Components and supplies
Arduino Nano R3
DT-06 Wireless WiFi Serial Port Transparent Transmission Module TTL To WiFi
ESP8266 ESP-01
Apps and platforms
Zip containing Jee Labs ESP Link Firmware V3.0.14 and Expressif Flash tool
Project description
Code
Demo Command - Response Terminal Interface
arduino
LoadMaster MPPT PV Hotwater controller can be remotely interrogated using a Serial 'Command Response Terminal Interface. This Demo provides a basic idea of the code concepts inloved. Take a look at the Loadmaster project code to see how this interface method can be used to set RTC values etc
1/*This is an Example of a Serial Command-response interface. 2 Arduino's Serial data can be transparently carried over Wifi using a DT-06 (or ESP8266-01) 3 Wifi Modules are loaded with esp-link firmware 4 BLE (HM-10) wireless links also work well. 5 6 Check Baud on the WifI module is set to match this program 7 8 Tested using excellent Android 'Serial WiFI Terminal' and 'Serial Bluetooth Apps' by Kai Moriche. 9 10 Sending a '?' +(CRLF) character will cause the Arduino to display a list of serial menu options 11 Sending a 'L 1' Turns the Nanos onboard LED On, L 2 turns it Off (COMMANDS USE CAPITAL LETTERS) 12 Sending 'W 23' would save a new Temperature setting of 23 to the EEPROM 13 14 Dated : 10th Jam 2020 15 V1.01 16 17 Hardware ////////////////////////////////////////////////////////////////////////// 18 19 This code uses the main serial port of the Arduino - shared by the USB socket on a Nano. 20 When programming you MUST disconnect the DT-06 Wifi module connected to Tx & Rx to avoid data conflicts 21 For the Demo, Power the Arduino from its 5V pins or use a USB 'power only' source. 22*/ 23 24 25 26#include <EEPROM.h> //1024 Byte EEPROM 27 28byte LED = 13; //The Nano's on-board LED 29int Volts_ADC = A1; //We will display volts on A1 when requested 30 31float Volts = 0; 32byte TempSet = 0; //Illustrating a non volatile setting configured via the serial connection 33 34unsigned long msec = 0; 35unsigned long Lastmsec = 0; 36unsigned long UpdateInterval = 1000; 37boolean OutputData = false; 38 39//Variables used in Serial CLI and Message Parsing 40const byte numChars = 30; // Maximum Char length of received serial messages terminated in a Linefeed. 41char receivedChars[numChars]; 42char RxdSerialMessage[numChars] = {0}; // variables to hold the parsed data 43 44int RxdInt1 = 0; 45int RxdInt2 = 0; 46float RxdFloat2 = 0; // Option to receive and use float values within command strings 47int RxdInt3 = 0; 48int RxdInt4 = 0; 49int RxdInt5 = 0; 50char CommandChar = 0; 51boolean NewData = false; 52 53 54 55//************************************ MAIN PROGRAM START - SETUP ******************************* 56void setup() 57{ 58 59 Serial.begin(9600); // Configue Hardware Serial. 60 Serial.flush(); // Clears the Serial RX buffer 61 62 TempSet = EEPROM.read(2); //Reads a saved setup value from EEPROM address location 2 63 64 pinMode(LED, OUTPUT); 65 digitalWrite(LED, LOW); //Set Nanos onboard LED initially off 66 67 68} 69 70//*********************************** MAIN PROGRAM LOOP ************************************** 71void loop() 72{ 73 74 SerialRxWithEndMarker(); //Check for data message in serial buffer 75 //messages seperated by NewLine char 76 77 if (NewData == true) { 78 parseData(); // Function to Split message into command and space seperated values 79 //showParsedData(); // FOR TEST ONLY! see what Character command and values are received 80 81 HandleCommand(); //Routine to identify & manage different received command characters 82 } 83 84 msec = millis(); // We use the millis millisecond runtime counter to schedule specific tasks 85 86 if ((msec - Lastmsec) > UpdateInterval) { //The Code below is executed evert MPPT update interval - 100ms) 87 88 if (OutputData == true) { 89 Serial.print(F("Volts on A1 = ")); 90 Serial.print(0.004887 * analogRead(Volts_ADC)); // read the Volts input A1 91 Serial.println("Volts"); 92 } 93 94 Lastmsec = msec; 95 96 } 97} 98 99//****************************PROGRAM MAIN LOOP END ************************************ 100//****************************SUBROUTINES FOLLOW *************************************** 101 102void HandleCommand (void) 103// The first character within a received serial message (from SerialRxWithEndMarker CR/LF) is extracted by the ParseData Subroutine 104// this routine identifies and handles the specific command request. 105{ 106 107 switch (CommandChar) { 108 109 case '?': // receiving a ? character will display the Serial Terminal command Menu 110 111 ClearTerminal (); 112 113 Serial.println(F("Serial Command Response Demo V1.0")); 114 Serial.println(F("--- Command list: ---")); 115 Serial.println(""); 116 Serial.println(F("? - Show this Menu!")); 117 Serial.println(F("V - Stream A1 Voltage")); 118 Serial.println(F("L - Control LED")); 119 Serial.println(F("S - Show Rxd message 'S 123 -456 54 67'etc")); 120 Serial.print(F("W - Set Limit")); 121 Serial.print(F(" (Currently ")); 122 Serial.print(TempSet); 123 Serial.println(F("°C )")); 124 break; 125 126 127 case 'V': //Turns on streaming of Voltage reading on A1 128 129 ClearTerminal (); 130 Serial.println(F("Request to Output Voltage has been Received")); 131 OutputData = true; 132 133 break; 134 135 136 case 'L': //Calls routine to turn LED on or OFF depending on Rxint1 value 137 138 SetLED(); 139 break; 140 141 case 'S': //Calls routine to display all values in Receive command string 142 143 showParsedData(); 144 break; 145 146 case 'W': //Calls routine to set temp limit 0 to 70C and save in EEPROM 147 148 SetTemp(); 149 break; 150 } 151} 152 //******************************************************************************************************************************************************** 153 // Serial print commands used to Clear Telnet Terminal Screen and position Cursor to Home position 154 155 void ClearTerminal (void) 156 { 157 Serial.write(27); // ESC command 158 159 Serial.print("[2J"); // Clear Screen...actually fills screen with carriage returns so earlier terminal data is not lost. 160 Serial.write(27); 161 Serial.print("[H"); // Cursor to Home position 162 } 163 164 165 166//**************************************************************************************** 167 168void SetTemp(void) // Serial command W sets and stores the target temperaturein EEPROM 169{ 170 ClearTerminal (); //Clears Serial Terminal Screen and positions Cursor at Home position 171 172 if (RxdInt1 == 0) { 173 Serial.print(F(" Current Temp limit is ")); 174 Serial.print(TempSet); 175 Serial.println(F("°C")); 176 177 Serial.println(F("Set the °C limit using 'W HW' where HW= 1 to 70")); 178 } 179 else { 180 if (RxdInt1 > 0 && RxdInt1 < 71) { 181 TempSet = RxdInt1; 182 Serial.print(F(" Temperature limit has been set to ")); 183 Serial.print(TempSet); 184 Serial.println(F("°C")); 185 186 EEPROM.write(2, TempSet); //Save temperature threshold to EEPROM address 2. 187 188 } 189 190 Serial.print("Temperature Limit = "); 191 Serial.print(TempSet); 192 Serial.println("°C"); 193 194 } 195} 196 197//************************* 198void SetLED (void) // Serial command sets and stores the target water temperature 199{ 200 ClearTerminal (); //Clears Serial Terminal Screen and positions Cursor at Home position 201 202 if (RxdInt1 == 2) { 203 Serial.print(F("Turn LED off")); 204 digitalWrite(LED, LOW); //LED off 205 } 206 else if (RxdInt1==1){ 207 Serial.print(F("Turn LED On")); 208 digitalWrite(LED, HIGH); //LED On 209 } 210 else{ 211 Serial.println(F("To Turn the LED ON send 'L 1'")); 212 Serial.println(F("To Turn LED off send 'L 2'")); 213 } 214} 215 216 217//******************************************************************************************************************************************* 218 219void SerialRxWithEndMarker() { 220 //("expects to receive strin of characters terminated in a LF. Max buffer size is currently 30 chars, text or Integer and an optional floating point value seperated by a comma"); 221 //("Enter data in this style "C/I 24.7 CRLF " C/I maybe a text command String or Integer value, after the space should be a float value ); 222 // You can ommit the comma and Float value if not required 223 //Note the parsing methods are now implemented in the functions specific to commands 224 225 static byte ndx = 0; 226 char endMarker = '\n'; 227 char rc; 228 229// if (Serial.available() > 0) { 230 while (Serial.available() > 0 && NewData == false) { //reads in new characters from serial buffer 231 rc = Serial.read(); 232 233 if (rc != endMarker) { //Looks for a new line code to end the message 234 receivedChars[ndx] = rc; 235 ndx++; 236 if (ndx >= numChars) { 237 ndx = numChars - 1; 238 } 239 } 240 else { 241 receivedChars[ndx] = '\\0'; // terminate the string a new serial message has been received 242 ndx = 0; 243 NewData = true; 244 245 } 246 } 247} 248 249 250//**************************************************************************************************** 251void parseData() { 252 253 // split the data into its parts 254 char * strtokIndx; // this is used by strtok() as an index 255 256 strtokIndx = strtok(receivedChars, " "); // get the first part of string before the first space Char 257 strcpy(RxdSerialMessage, strtokIndx); // copy it to RxdSerial message - extracts text string at start of a message if required 258 259 CommandChar = receivedChars[0]; //First Char in the initial command string is used to identify the Command 260 261 strtokIndx = strtok(NULL, " "); // this continues where the previous call left off 262 RxdInt1 = atoi(strtokIndx); // convert the next part of command upto next space to an integer 263 264 strtokIndx = strtok(NULL, " "); 265 RxdInt2 = atoi(strtokIndx); // convert this part to an Int - NOTE Currently Float values are not used in any commands 266 //RxdFloat2 = atof(strtokIndx); // If you want to recieve Floats, - NOTE Currently Float values are not used in any commands 267 268 strtokIndx = strtok(NULL, " "); 269 RxdInt3 = atoi(strtokIndx); // convert this part to a float - NOTE Currently Float values are not used in any commands 270 271 strtokIndx = strtok(NULL, " "); 272 RxdInt4 = atoi(strtokIndx); // convert this part to a float - NOTE Currently Float values are not used in any commands 273 274 strtokIndx = strtok(NULL, " "); 275 RxdInt5 = atoi(strtokIndx); // convert this part to a float - NOTE Currently Float values are not used in any commands 276 277 NewData = false; // The last received message has been identified handled 278 279 OutputData = false; // Stop Outputting Data values if a new message is received, 280 281} 282 283 284 285 286 287 288 289//******************************************************************************************************************* 290 291void showParsedData() { 292 // Used for testing only to see how command and integer values are extracted 293 294 Serial.print("Initial CommandChar "); 295 Serial.println(CommandChar); 296 Serial.print("RxdInt1 = "); 297 Serial.println(RxdInt1); 298 Serial.print("RxdInt2 = "); 299 Serial.println(RxdInt2); 300 Serial.print("RxdInt3 = "); 301 Serial.println(RxdInt3); 302 Serial.print("RxdInt4 = "); 303 Serial.println(RxdInt4); 304 Serial.print("RxdInt5 = "); 305 Serial.println(RxdInt5); 306 307}
Comments
Only logged in users can leave comments
stevetearle
0 Followers
•0 Projects
0