Here is the circuit showing how a Web Server on an STM32F103C8T6 can be used to control a Relay Switch:
The Fritzing code used to create that diagram/image can be downloaded here.
An ENC28J60 ethernet module is used to connect the STM32F103C8T6 (BluePill) to a network.
Here is the source code for the sketch to load into the STM32F103C8T6 (BluePill):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 |
/* Web Server A simple web server that shows the value of the analog input pins. blinks the built in LED, or toggles a Relay Switch (check the comments) From: earl@microcontrollerelectronics.com Also Demonstrates checking the ENC28J60 and keeping it from freezing. ENC28J60 STM32F103 SCK PA5 SO PA6 SI PA7 CS PA4 RST PA0 VCC - 5V GND - GND --ENC28J60-- CLK INT WOL SO SI SCK CS RESET VCC GND +-----------------[USB]-----------------+ [SS2|PB12] | [31] [Gnd] | [SCK2|PB13] | [30] +---+ [Gnd] | [MISO2|PB14] | [29] +-----+ |0 0| [3V3] | [MOSI2|PB15] | [28] |Reset| |x x| [Reset] | [PA8] | [27] +-----+ |1 1| [ 0] | [PB11|SDA2|RX3] [TX1|PA9] | [26] +---+ [ 1] | [PB10|SCL2|TX3] [RX1|PA10] | [25] ^ ^ [33] | [PB1] [USB-|PA11] | [24] Boot1--+ | [ 3] | [PB0|A0] [USB+|PA12] | [23] Boot0----+ [ 4] | [PA7|A1|MOSI1] [PA15] | [20] [ 5] | [PA6|A2|MISO1] [PB3] | [19] +-----------+ [ 6] | [PA5|A3|SCK1] [PB4] | [18] | STM32F103 | [ 7] | [PA4|A4|SS1] [PB5] | [17] | Blue Pill | [ 8] | [PA3|A5|RX2] [SCL1|PB6] | [16] +-----------+ [ 9] | [PA2|A6|TX2] [SDA1|PB7] | [15] [10] | [PA1|A7] [PB8] | [32] [11] | [PA0|A8] [PB9] | [PB9] [12] | [PC15] | [5V] +---------------+ [13] | [PC14] | [Gnd] | ST-Link | [14] | [PC13|LED] | [3V3] |3V3 DIO CLK GND| [Vbat]| +-------------+---+---+---+-------------+ | | | | */ #define BOARD_SPI1_NSS_PIN PA4 #define BOARD_SPI1_SCK_PIN PA5 #define BOARD_SPI1_MISO_PIN PA6 #define BOARD_SPI1_MOSI_PIN PA7 #include <libmaple/iwdg.h> #include <SPI.h> #include <UIPEthernet.h> // ..utility\Enc28J60Network.h file - //move readReg() subroutine def from private to public #define NET_ENC28J60_EIR 0x1C #define NET_ENC28J60_ESTAT 0x1D #define NET_ENC28J60_ECON1 0x1F #define NET_ENC28J60_EIR_RXERIF 0x01 #define NET_ENC28J60_ESTAT_BUFFER 0x40 #define NET_ENC28J60_ECON1_RXEN 0x04 #define NET_ENC28J60_CHECK_PERIOD 5000UL #define iwdg_init_ms(N) iwdg_init(IWDG_PRE_256,((N)/5)) #define pinLED PC13 #define pinSwitch PA15 #define ETH_RS_PIN PA0 byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; IPAddress ipdns(192, 168, 0, 1); IPAddress ip(192, 168, 0, 150); IPAddress gateway(192, 168, 0, 1); IPAddress subnet(255, 255, 255, 0); EthernetServer server = EthernetServer(80); String cdata = ""; unsigned long timer; void setup() { disableDebugPorts(); Serial.begin(115200); pinMode(pinLED, OUTPUT); pinMode(pinSwitch, OUTPUT); digitalWrite(pinLED,LOW); digitalWrite(pinSwitch,LOW); eth_reset(); iwdg_init_ms(4000); timer = millis(); } void eth_reset() { pinMode(ETH_RS_PIN, OUTPUT); digitalWrite(ETH_RS_PIN, LOW); delay(100); digitalWrite(ETH_RS_PIN, HIGH); pinMode(ETH_RS_PIN, INPUT); Ethernet.begin(mac, ip, ipdns, gateway, subnet); server.begin(); Serial.print(F("WEB server is at ")); Serial.println(Ethernet.localIP()); Serial.print(F("DNS server is at ")); Serial.println(Ethernet.dnsServerIP()); } void loop() { iwdg_feed(); Ethernet.maintain(); if ((millis() - timer) > NET_ENC28J60_CHECK_PERIOD) { // Enc28J60 is Enc28J60Network class that is defined in Enc28J60Network.h // readReg() subroutine must be moved from private to public members area in utility\Enc28J60Network.h // ENC28J60 ignore all incoming packets if ECON1.RXEN is not set uint8_t stateEconRxen = Enc28J60.readReg((uint8_t) NET_ENC28J60_ECON1) & NET_ENC28J60_ECON1_RXEN; // ESTAT.BUFFER rised on TX or RX error // I think the test of this register is not necessary - EIR.RXERIF state checking may be enough uint8_t stateEstatBuffer = Enc28J60.readReg((uint8_t) NET_ENC28J60_ESTAT) & NET_ENC28J60_ESTAT_BUFFER; // EIR.RXERIF set on RX error uint8_t stateEirRxerif = Enc28J60.readReg((uint8_t) NET_ENC28J60_EIR) & NET_ENC28J60_EIR_RXERIF; Serial.println("---REGS---"); Serial.println(stateEconRxen,HEX); Serial.println(stateEstatBuffer,HEX); Serial.println(stateEirRxerif,HEX); if (!stateEconRxen || (stateEstatBuffer && stateEirRxerif)) { Serial.println ("ENC28J60 reinit"); // Enc28J60.init(netConfig->macAddress); eth_reset(); } timer = millis(); } EthernetClient client = server.available(); if (client) { Serial.println(F("\n--Client Connected--\n")); cdata = ""; Serial.println(cdata); while (client.connected()) { if (client.available()) { char c = client.read(); Serial.write(c); cdata.concat(c); if (cdata.indexOf("\r\n\r\n") > 0) { Serial.print(F("Buffer Length: ")); Serial.println(cdata.length()); client.println(F("HTTP/1.1 200 OK")); client.println(F("Content-Type: text/html")); client.println(F("Connection: close")); if(cdata.indexOf("Analog") > 0) client.println(F("Refresh: 5")); client.println(); client.println(F("<!DOCTYPE HTML>")); client.println(F("<html>")); client.println(F("<body>")); client.println(F("<br><br><center><H1>STM32F103C8T6 WEB Server</H1></center>")); if ( (cdata.indexOf("LED") > 0) || (cdata.indexOf("led") > 0) ) { digitalWrite(pinLED,!digitalRead(pinLED)); if (digitalRead(pinLED)) client.println(F("<center><br><br><br><br><H1>LED OFF!</H1></center>")); else client.println(F("<center><br><br><br><br><H1>LED ON!</H1></center>")); client.println(F("</body>")); client.println(F("</html>")); break; } if (cdata.indexOf("switch") > 0) { digitalWrite(pinSwitch,!digitalRead(pinSwitch)); if (digitalRead(pinSwitch)) client.println(F("<center><br><br><br><br><H1>Switch ON! </H1></center>")); else client.println(F("<center><br><br><br><br><H1>Switch OFF!</H1></center>")); client.println(F("</body>")); client.println(F("</html>")); break; } if(cdata.indexOf("Analog") > 0) { client.println(F("<table border=1 cellspacing=4 cellpadding=4>")); client.println(F("<tr><th>Analog</th><th>Value</th></tr>")); for (int analogChannel = 0; analogChannel < 4; analogChannel++) { int sensorReading = analogRead(analogChannel); client.print(F("<tr><td>")); client.print(analogChannel); client.print(F("</td><td>")); client.print(sensorReading); client.println(F("</td></tr>")); } client.println(F("</table>")); client.println(F("</body>")); client.println(F("</html>")); break; } client.println(F("<center><br><br><br><br><H1>Unknown Command!</H1></center>")); client.println(F("</body>")); client.println(F("</html>")); break; } } } client.stop(); Serial.println(F("\n--Client Disconnected--")); timer = millis(); } } |
This is an updated and enhanced sketch from a previous post on a WEB server using both the BluePill (STM32F103C8T6) and the ENC28J60 module. It seems the UIPEthernet library has changed since then. I had to add these lines to the code to define the correct pin settings:
1 2 3 4 |
#define BOARD_SPI1_NSS_PIN PA4 #define BOARD_SPI1_SCK_PIN PA5 #define BOARD_SPI1_MISO_PIN PA6 #define BOARD_SPI1_MOSI_PIN PA7 |
The source code has the IP address and network settings for the ENC28J60 ethernet module hard coded. Those settings may need changed for use on a different network.
The relay switch can be attached to any number of AC type low current devices and turned ON/OFF by accessing the WEB server. (The relay switch can possibly handle low current DC devices as well). I used a 2N3904 NPN transistor in my circuit to allow the STM32F103CT6 to turn the relay OFF and ON. This circuit also has a red LED to visually show when the relay is ON or OFF.
The WEB server accepts several ‘commands’:
http://192.168.0.150/led
http://192.168.0.150/analog
http://192.168.0.150/switch
‘LED’ toggles the internal LED On/Off, ‘analog’ displays the analog values of the first 4 analog pins and ‘switch’ toggles the relay On/Off. So now you know how a Web Server on an STM32F103C8T6 can be used to control a Relay Switch.
Recent Comments