If you read my last post on Solar Power System Monitoring with an Arduino you might be wondering if that circuit could be enhanced a bit. Say, change the LCD to an OLED and add wireless (WEB server) capability?
I was not happy to have to go out and look at the device when I wanted to see the info. So I did enhance it a bit. I changed the LCD to an OLED for more info in case I did happen to be where the device is and I added a wireless module (an ESP8266). The wireless module has a WEB server so I can just connect wireless via a browser and see the info.
Since the ESP8266 needs 3 Volts, I also changed the ‘arduino’ I was using. I switched to an STM32F103C8T6 (BluePill) since it can take 5 Volts and output 3 Volts. This new circuit still uses the LM7805 voltage regulator to take the 14 Volt input and then output 5 Volts. It also keeps the SN75176BP for the RS485 protocol conversion. If you have not read the previous post, you can find more details there on those components.
Here is what the circuit wiring looks like:
You can get the Fritzing code for this circuit here.
Here is what the circuit looks like (top and front side view):
The left side has the STM32F103C8T6 and the RJ11 connector. The right side has the ESP8266, the OLED, the SN75176BP and the LM7805. The LM7805 has a heat sink on it since it gets a bit hot. The STM32F103C8T6, ESP8266, OLED and SN75176BP are all in sockets for easy (re)placement. This circuit has all the ‘messy’ wiring and soldering on the bottom (hidden from view). In my previous post I still had all the components on a breadboard.
Here is the code to load into the STM32F103C8T6 (using the Arduino IDE):
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 216 217 218 |
/* PA9/PA10 Serial PB10/PB11 Serial2 PA2/PA3 Serial1 I2C1 SDA PB7 I2C1 SCL PB6 +-----------------[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]| +-------------+---+---+---+-------------+ | | | | */ #include <Adafruit_GFX.h> #include <Adafruit_SSD1306_STM32.h> #define OLED_RESET PB4 Adafruit_SSD1306 display(OLED_RESET); String sbuffer = ""; char connectionId; #define MAXBUFFER 512 #define DE PB12 #define ESP8266_RESET PB8 uint32_t last_millis = 0; uint32_t timer = 0; unsigned int bl = 0; float volts = 0.0; int amps = 0; unsigned char Buffer[MAXBUFFER + 1]; unsigned char SBuffer[MAXBUFFER + 1]; char data[256]; char DcV[10]; // Serial -> host PC // Serial1 -> RS485 SN75176 // Serial2 -> ESP8266 void setup() { display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3D (for the 128x64) display.display(); Serial.begin(115200); Serial2.begin(115200); Serial1.begin(19200); pinMode(DE, OUTPUT); digitalWrite(DE, LOW); display.clearDisplay(); display.display(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println("Setting up ESP8266.."); display.display(); Serial.println("Setting up ESP8266..."); init_server(); Serial.println("Setup Done!"); display.clearDisplay(); display.display(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println("Setup Done!"); display.display(); last_millis = millis(); } void init_server() { sendData("AT+RST\r\n", 5000, (String)"jump to run", 1); sendData("AT+RESTORE\r\n", 5000, (String)"ready", 1); sendData("AT+GMR\r\n", 5000, (String)"OK", 1); sendData("AT+CWMODE=2\r\n", 5000, (String)"OK", 1); String cmd = "AT+CWSAP=\"ESP8266\",\"\",6,0\r\n"; sendData(cmd, 5000, (String)"OK", 1); sendData("AT+CIFSR\r\n", 5000, (String)"OK", 1); sendData("AT+CIPMUX=1\r\n", 5000, (String)"OK", 1); sendData("AT+CIPSERVER=1,80\r\n", 5000, (String)"OK", 1); } void get_serial_data() { while (Serial1.available() > 0) { if (bl > MAXBUFFER) bl = 0; Buffer[bl] = Serial1.read(); ++bl; last_millis = millis(); } while (Serial2.available() > 0) { char c = Serial2.read(); sbuffer.concat(c); Serial.write(c); } } void loop() { get_serial_data(); /* if (Serial.available()) { digitalWrite(DE,HIGH); Serial1.write(Serial.read()); digitalWrite(DE,LOW); } */ timer = millis() - last_millis; if ( (timer > 30) && (bl > 15) ) { for (int i = 0; i < bl; ++i) SBuffer[i] = Buffer[i]; bl = 0; display.clearDisplay(); display.display(); display.setTextSize(2); display.setTextColor(WHITE); display.setCursor(0, 0); display.println("Magnum Inverter"); display.setTextSize(1); // Left in for Debugging // sprintf(data,"%02X%02X%02X%02X%02X%02X%02X%02X",SBuffer[0],SBuffer[1],SBuffer[2],SBuffer[3],SBuffer[4],SBuffer[5],SBuffer[6],SBuffer[7],SBuffer[8]); sprintf(data, "S%02X F%02x M%02X R%02X", SBuffer[0], SBuffer[1], SBuffer[14], SBuffer[10]); display.println(data); volts = ( ((unsigned char)(SBuffer[2]) * 256) + (unsigned char)(SBuffer[3]) ) / 10.0; dtostrf(volts, 5, 2, DcV); amps = ((unsigned char)(SBuffer[4]) * 256) + (unsigned char)(SBuffer[5]); sprintf(data, "%s5Vdc %3dA", DcV, amps); display.println(data); display.display(); } if (sbuffer.indexOf("busy") != -1) init_server(); if (sbuffer.indexOf("+IPD,") != -1) { timer = millis() + 500; while (millis() < timer) get_serial_data(); int pos = sbuffer.indexOf(",CONNECT"); if (pos != -1) pos -= 1; if (sbuffer[pos] == 0x0d) connectionId = sbuffer[pos + 2]; else connectionId = sbuffer[pos]; Serial.println(connectionId, HEX); String webpage = F("<!DOCTYPE HTML>\n<html>\n<body>\n<H1>Magnum Inverter</H1>\n"); // Left in for Debugging // sprintf(data,"%02X%02X%02X%02X%02X%02X%02X%02X",SBuffer[0],SBuffer[1],SBuffer[2],SBuffer[3],SBuffer[4],SBuffer[5],SBuffer[6],SBuffer[7],SBuffer[8]); sprintf(data, "S%02X F%02x M%02X R%02X", SBuffer[0], SBuffer[1], SBuffer[14], SBuffer[10]); webpage += "<H2>"; webpage += data; webpage += "</H2>"; volts = ( ((unsigned char)(SBuffer[2]) * 256) + (unsigned char)(SBuffer[3]) ) / 10.0; dtostrf(volts, 5, 2, DcV); amps = ((unsigned char)(SBuffer[4]) * 256) + (unsigned char)(SBuffer[5]); sprintf(data, "%s5Vdc %3dA", DcV, amps); webpage += "<H2>"; webpage += data; webpage += "</H2>"; webpage += F("<script>setTimeout(function(){window.location.reload(1);},5000);</script>\n"); webpage += F("</body>\n</html>"); String cipSend = "AT+CIPSEND="; cipSend += connectionId; cipSend += ","; cipSend += webpage.length(); cipSend += "\r\n"; sendData(cipSend, 2000, (String)"OK", 1); sendData(webpage, 2000, (String)"SEND OK", 1); String closeCommand = "AT+CIPCLOSE="; closeCommand += connectionId; closeCommand += "\r\n"; sendData(closeCommand, 2000, (String)"OK", 1); } } void sendData(String command, const int timeout, String msg, boolean flag) { Serial2.print(command); display.clearDisplay(); display.display(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(0, 0); display.println(command); display.display(); long int time = millis() + timeout; while (time > millis()) { get_serial_data(); if (sbuffer.indexOf(msg) != -1) break; } if (sbuffer.indexOf(msg) == -1) { long int time1 = millis() + 500; while ( time1 > millis()) { get_serial_data(); if (sbuffer.indexOf(msg) != -1) break; } } get_serial_data(); display.println(sbuffer); display.display(); if (flag) sbuffer = ""; } |
I am using the Adafruit GFX and SSD1306 libraries to control the OLED. The ESP8266 is just connected via a serial connection and sent commands to set it up as an access point and WEB server.
The wireless access point name is just set to ESP8266. You can change it to anything you want. The IP address is 192.168.4.1, so just go to that IP address in a browser after connecting wirelessly. The WEB page will refresh every 5 seconds.
My next step is to enhance the code to display more info as it still only outputs the codes like the LCD version does. Here is a picture (photography is not my forte) of the device on top of one of my Lithium Batteries (from Deeds Solar Solutions).
Recent Comments