3x Arduino + ESP32 with ESP-NOW - c++
The configuration on "machine" looks like this:
Computer with custom app WPF C#, have connected ESP32-sender.
On other side of room there is ESP32 as recaiver that have connected to it 3 arduino due, that controls a lot of stepper motors.
My problem is, that if I send a single command all works great. Directly on other side it executes.
The problem starts when there is a lot of commands to send. ESP32 starts to makes Delivery fail status and after that moment all further commands are lost.
That's the code of Master-ESP connected to PC.
Which arduino to send is decide by one of the symbols on begin of message "!,#,#"
#include <esp_now.h>
#include <WiFi.h>
#include <Wire.h>
uint8_t broadcastAddress[] = {0x94, 0xB9, 0x7E, 0xD0, 0x93, 0x64};
String inMess;
typedef struct Message {
char a[100];
} Message;
// Variable to store if sending data was successful
String success;
Message message;
Message send_message;
esp_now_peer_info_t peerInfo;
char incoming;
String full = "";
bool text_done = false;
bool sended = false;
// Callback when data is sent
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
//Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success*" : "Delivery Fail*");
if (status ==0){
success = "Delivery Success :)";
text_done = false;
full = "";
sended = false;
}
else{
success = "Delivery Fail :(";
delay(10);
sended = false;
Serial.println(success);
}
}
// Callback when data is received
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&message, incomingData, sizeof(message));
Serial.println(message.a);
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK){
Serial.println("Failed to add peer");
return;
}
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
if(Serial.available() > 0 && !text_done){
incoming = Serial.read();
if(incoming == '\n'){
text_done = true;
full.trim();
full.toUpperCase();
}
if(text_done == false){
full += incoming;
}
}
if(text_done){
if(full[0] != '!' && full[0] != '#' && full[0] != '#'){ //check if text is worth sending to other esp
text_done = false;
full = "";
}
}
if(text_done){
if(!sended){
full.toCharArray(send_message.a,sizeof(send_message));
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &send_message, sizeof(send_message));
if (result == ESP_OK) {
//Serial.println("Sent success*");
sended = true;
}
else {
Serial.println("Error sending*");
delay(10);
}
}
}
}
That's the code of recaiver ESP
#include <esp_now.h>
#include <WiFi.h>
#include <SoftwareSerial.h>
#include <Wire.h>
SoftwareSerial worker;
SoftwareSerial tool;
//Serial2 is Table, software serials are others
uint8_t broadcastAddress[] = {0x7C, 0x9E, 0xBD, 0x4B, 0x47, 0xA4};
String outMess;
String outMessTable;
String outMessTool;
String inMess;
typedef struct Message {
char a[100];
} Message;
String success;
Message message;
Message send_message;
bool sended = true;
String again_message = "";
esp_now_peer_info_t peerInfo;
void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) {
//Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
if (status == 0) {
success = "Delivery Success :)";
sended = true;
again_message = "";
}
else {
success = "Delivery Fail :(";
sended = false;
delay(5);
}
}
void OnDataRecv(const uint8_t * mac, const uint8_t *incomingData, int len) {
memcpy(&message, incomingData, sizeof(message));
Serial.println(message.a);
sendTo((String)message.a);
}
void setup() {
// Init Serial Monitor
Serial.begin(115200);
Serial2.begin(115200, SERIAL_8N1, 16, 17);
//rx tx
worker.begin(57600, SWSERIAL_8N1, 25, 26, false);
if (!worker) {
Serial.println("Invalid SoftwareSerial pin configuration, check config");
while (1) {
delay (1000);
}
}
//rx tx
tool.begin(57600, SWSERIAL_8N1, 32, 33, false);
if (!tool) {
Serial.println("Invalid SoftwareSerial pin configuration, check config");
while (1) {
delay (1000);
}
}
// Set device as a Wi-Fi Station
WiFi.mode(WIFI_STA);
Serial.println(WiFi.macAddress());
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Trasnmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, broadcastAddress, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
// Register for a callback function that will be called when data is received
esp_now_register_recv_cb(OnDataRecv);
}
void loop() {
// Set values to send
if(sended){
if (worker.available() > 0) {//!
char t = worker.read();
if(t == '\n'){
outMess.trim();
sendToEsp(outMess,"!");
outMess = "";
}
else{
outMess += t;
}
}
}else{
if(again_message.length()>0){
delay(10);
sendToEsp(again_message.substring(1),again_message.substring(0,1));
}else{
sended = true;
}
}
if(sended){
if (tool.available() > 0) {//#
char t = tool.read();
if(t == '\n'){
outMessTool.trim();
sendToEsp(outMessTool,"#");
outMessTool = "";
}
else{
outMessTool += t;
}
}
}else{
if(again_message.length()>0){
delay(10);
sendToEsp(again_message.substring(1),again_message.substring(0,1));
}else{
sended = true;
}
}
if(sended){
if (Serial2.available() > 0) { //#
char t = Serial2.read();
if(t == '\n'){
outMessTable.trim();
sendToEsp(outMessTable,"#");
outMessTable = "";
}else{
outMessTable += t;
}
}
}else{
if(again_message.length()>0){
delay(10);
sendToEsp(again_message.substring(1),again_message.substring(0,1));
}else{
sended = true;
}
}
if(Serial.available() > 0){
outMess = Serial.readStringUntil('\n'); //read command from pc
outMess.trim(); // remove uneccesery spaces
sendTo(outMess);
}
}
void sendToEsp(String text, String which){
String mess = which + text;
again_message = mess;
mess.toCharArray(send_message.a,sizeof(send_message));
esp_err_t result = esp_now_send(broadcastAddress, (uint8_t *) &send_message, sizeof(send_message));
if (result == ESP_OK) {
// Serial.println("Sent with success");
}
else {
Serial.println("Error sending the data");
sended = true;
again_message = "";
}
}
void sendTo(String outMess){
Serial.print("=");
Serial.print(outMess);
if(outMess[0] == '!'){ //worker
worker.enableTx(true);
worker.println(outMess.substring(1));
worker.enableTx(false);
Serial.println("send to worker");
}
if(outMess[0] == '#') {//table
Serial2.println(outMess.substring(1));
Serial.println("send to table");
}
if(outMess[0] == '#'){ //tool
tool.enableTx(true);
tool.println(outMess.substring(1));
tool.enableTx(false);
Serial.println("send to tool");
}
}
If I send one message with a delay of writing next one by hand it works great.
If the message is sended via c# very fast, esp32 is handling first few of them then losing on sending or recaiving, sometimes both of esp32 sometimes only one.
How could I prevent that to make stable connection ?
Related
Is it possible to make a sip call over gprs with a SIM800 module?
I have an Asterisk server on cloud and I want ESP32 devices to register as SIP clients and make a VoIP call over GPRS via SIM800 module. AT commands of SIM800 module allows me to make a GPRS connection and I can send http request and send MQTT messages. However, I couldn't find a way to connect to VoIP server, if possible. My current code establises MQTT connection over GPRS and make calls over GSM but cannot connect to Asterisk: // ESP32 Configuration #define TINY_GSM_MODEM_SIM800 #define SerialMon Serial #define SerialAT Serial2 #define TINY_GSM_DEBUG SerialMon #define GSM_AUTOBAUD_MIN 9600 / #define GSM_AUTOBAUD_MAX 38400 #define TINY_GSM_USE_GPRS true #define PhoneNumber "xxxxxxxxxxxxxxx" #define rcSwitchInterruptPin 35 #define ENABLE_SIM800C 22 #define BUTTON_PIN 33 #define SOS_BUTTON_ID0 4236140 #define SOS_BUTTON_ID1 4236132 #define SOS_BUTTON_PIN 27 // GPRS internet settings, specific to your SIM card const char apn[] = "internet"; const char gprsUser[] = ""; const char gprsPass[] = ""; // MQTT settings const char *broker = "broker.emqx.io"; const int mqttPort = 1883; const char * clientID = "esp32-client"; const char * mqttUser = "acido"; const char * mqttPassword = "12345678"; #include <TinyGsmClient.h> #include <PubSubClient.h> #include <SPI.h> #include <Wire.h> #include <PubSubClient.h> #include <elapsedMillis.h> #include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); TinyGsm modem(SerialAT); TinyGsmClient client(modem); PubSubClient mqtt(client); uint32_t lastReconnectAttempt = 0; void mqttCallback(char *, byte *, unsigned int); boolean mqttConnect(); void DRE_switch(); elapsedSeconds serialLogSeconds; unsigned int serialLog_Interval = 3; elapsedSeconds sinyalBekletme; unsigned int sinyalBekletme_Interval = 3; elapsedSeconds sosDelay; unsigned int sosDelay_Interval = 3; elapsedSeconds kapiacikDelay; unsigned int kapiacikDelay_Interval = 3; elapsedSeconds kapiKapaliDelay; unsigned int kapiKapaliDelay_Interval = 3; elapsedSeconds gazDelay; unsigned int gazDelay_Interval = 3; elapsedSeconds pirDelay; unsigned int pirDelay_Interval = 3; elapsedSeconds dumanDelay; unsigned int dumanDelay_Interval = 3; void setup() { mqtt.setKeepAlive(60); // Set console baud rate SerialMon.begin(9600); while (!SerialMon) delay(10); // !!!!!!!!!!! mySwitch.enableReceive(35); pinMode(BUTTON_PIN, INPUT_PULLDOWN); pinMode(ENABLE_SIM800C, OUTPUT); digitalWrite(ENABLE_SIM800C, HIGH); delay(3000); digitalWrite(ENABLE_SIM800C, LOW); // !!!!!!!!!!! TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX); delay(6000); // Restart takes quite some time // To skip it, call init() instead of restart() // if (!modem.restart()) { if (!modem.init()) { DBG("Failed to restart modem, delaying 10s and retrying"); // restart autobaud in case GSM just rebooted TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX); return; } String modemInfo = modem.getModemInfo(); SerialMon.print("setup: Modem Info: "); SerialMon.println(modemInfo); SerialMon.print("setup: Waiting for network..."); if (!modem.waitForNetwork()) { SerialMon.println("setup: fail, wait 5 seconds"); delay(5000); return; } SerialMon.println("setup: success"); if (modem.isNetworkConnected()) SerialMon.println("setup: Network connected"); #if TINY_GSM_USE_GPRS // GPRS connection parameters are usually set after network registration SerialMon.print(F("setup: Connecting to apn: ")); SerialMon.print(apn); if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { SerialMon.println("setup: GPRS Connecting fail, wait 5 seconds"); delay(5000); return; } SerialMon.println("setup: GPRS success"); if (modem.isGprsConnected()) { SerialMon.println("setup: GPRS connected"); } #endif // MQTT Broker setup mqtt.setServer(broker, mqttPort); mqtt.setCallback(mqttCallback); } void loop() { bool result; // check if we're connected to network if (!modem.isNetworkConnected()) { SerialMon.println("loop: modem disconnected"); if (!modem.waitForNetwork(180000L, true)) { SerialMon.println("loop: modem fail, wait 10 sec"); delay(10000); return; } if (modem.isNetworkConnected()) { SerialMon.println("loop: Modem re-connected"); } // And make sure GPRS/EPS is still connected if (!modem.isGprsConnected()) { SerialMon.println("loop: GPRS disconnected!"); SerialMon.print(F("loop: Connecting to apn:")); SerialMon.print(apn); if (!modem.gprsConnect(apn, gprsUser, gprsPass)) { SerialMon.println("loop: GPRS fail, wait 10 sec"); delay(10000); return; } if (modem.isGprsConnected()) { SerialMon.println("loop: GPRS reconnected"); } } } // check if we're connected to MQTT if (!mqtt.connected()) { SerialMon.println("loop: === mqtt not connected ==="); // Reconnect every 10 seconds uint32_t t = millis(); if (t - lastReconnectAttempt > 10000L) { lastReconnectAttempt = t; if (mqttConnect()) { lastReconnectAttempt = 0; } } return; } if (digitalRead(BUTTON_PIN) == HIGH) { Serial.println("BUTONA BASILDI"); result = modem.callNumber(PhoneNumber); DBG("Call:", result ? "OK" : "fail"); } // Check RF signals and publish to MQTT if (mySwitch.available()) { int num = mySwitch.getReceivedValue(); Serial.print("Num: "); Serial.print(num); Serial.print(" Protocol: "); Serial.println(mySwitch.getReceivedProtocol()); if (sosDelay >= sosDelay_Interval) { if (num == 4236132) // SOS { Serial.println("SOS Butonuna Basıldı."); DRE_switch(); mqtt.publish("CMR/ESP32s/SENSOR/SOS", "SOS"); // Publish message. result = modem.callNumber(PhoneNumber); DBG("Call:", result ? "OK" : "fail"); } else { mqtt.publish("CMR/ESP32s/SENSOR/SOS", "0"); // Publish message. } sosDelay = 0; } if (pirDelay >= pirDelay_Interval) { if (num == 8330345) { DRE_switch(); Serial.println("HAREKET ALGILANDI."); mqtt.publish("CMR/ESP32s/SENSOR/PIR", "HAREKET ALGILANDI"); // Publish message. } else { mqtt.publish("CMR/ESP32s/SENSOR/PIR", "0"); // Publish message } pirDelay = 0; } if (kapiacikDelay >= kapiacikDelay_Interval) { if (num == 5729285) // Kapi acilinca gelen sinyal { DRE_switch(); Serial.println("KAPI AÇILDI."); mqtt.publish("CMR/ESP32s/SENSOR/KAPIACIK", "1"); // Publish message. } else { mqtt.publish("CMR/ESP32s/SENSOR/KAPIACIK", "0"); // Publish message } kapiacikDelay = 0; } if (kapiKapaliDelay >= kapiKapaliDelay_Interval) { if (num == 5729294) // Kapi kapaninca gelen sinyal { DRE_switch(); Serial.println("KAPI KAPANDI."); mqtt.publish("CMR/ESP32s/SENSOR/KAPIKAPALI", "1"); // Publish message. } else { mqtt.publish("CMR/ESP32s/SENSOR/KAPIKAPALI", "0"); // Publish message } kapiKapaliDelay = 0; } if (gazDelay >= gazDelay_Interval) { if (num == 12607491) { DRE_switch(); Serial.println("Gas Algılandı."); mqtt.publish("CMR/ESP32s/SENSOR/GAS", "GAS ALGILANDI"); // Publish message. } else { mqtt.publish("CMR/ESP32s/SENSOR/GAS", "0"); // Publish message } gazDelay = 0; } if (dumanDelay >= dumanDelay_Interval) { if (num == 79974) { DRE_switch(); Serial.println("Duman Algılandı ."); mqtt.publish("CMR/ESP32s/SENSOR/DUMAN", "DUMAN ALGILANDI"); // Publish message. } else { mqtt.publish("CMR/ESP32s/SENSOR/DUMAN", "0"); // Publish message } dumanDelay = 0; } } // end if mySwitch.available modem.maintain(); mqtt.loop(); // Handling MQTT on the background. } // end of loop boolean mqttConnect() { // Connect to MQTT Broker SerialMon.print("mqttConnect: MQTT trying to connect: "); SerialMon.print(broker); // Connect to MQTT Broker with password protected boolean status = mqtt.connect(clientID, mqttUser, mqttPassword); // boolean status = mqtt.connect(clientID); // without password if (status == false) { SerialMon.println("mqttConnect: MQTT Connection Fail"); return false; } SerialMon.println("mqttConnect: *** MQTT CONNECTED *** "); mqtt.publish("topic/akes", "Client connection started"); mqtt.subscribe("topic/akes"); // subscribe to topic return mqtt.connected(); } void mqttCallback(char *topic, byte *payload, unsigned int len) { // Handle message arrived SerialMon.print("mqttCallback: Message arrived ["); SerialMon.print(topic); SerialMon.print("]: "); SerialMon.write(payload, len); SerialMon.println(); } void DRE_switch() { // Disable Reset Enable function for RF module mySwitch.disableReceive(); mySwitch.resetAvailable(); mySwitch.enableReceive(rcSwitchInterruptPin); }
PubSubClient ESP32 disconnected while receive message
I create a project to receive message from MQTT. My full code is here https://github.com/kamshory/OTP-Mini/blob/main/Server/Server.ino WiFiClient espClient; PubSubClient client(espClient); void setup() { char * mqttServer = "192.168.1.3"; client.setServer(mqttServer, 1883); client.setCallback(mqttCallback); } void mqttCallback(const char* topic, byte* payload, unsigned int length) { Serial.print("Message arrived on topic: "); Serial.print(topic); Serial.print("Message: "); char * mqttTopic = "sms"; String messageTemp; for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); messageTemp += (char)payload[i]; } Serial.println(); // Feel free to add more if statements to control more GPIOs with MQTT // If a message is received on the topic esp32/output, you check if the message is either "on" or "off". // Changes the output state according to the message if (String(topic) == String(mqttTopic)) { } } void mqttReconnect() { Serial.print("WiFi status = "); Serial.println(WiFi.status()); char * clientId = "php"; char * mqttUsername = "user"; char * mqttPassword = "pass"; char * mqttTopic = "sms"; // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection "); // Attempt to connect if (client.connect(clientId, mqttUsername, mqttPassword)) { Serial.println("connected"); // Subscribe boolean sub = client.subscribe("sms"); Serial.println(sub); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } When ESP32 publish a message in a topic, the message is received by subscriber (I create the subscriber with Java). But when it try to receive the message with callback, the client is disconnected. I try to debug with edit library on file PubSubClient.cpp boolean PubSubClient::loop() { if (connected()) { unsigned long t = millis(); if ((t - lastInActivity > MQTT_KEEPALIVE*1000UL) || (t - lastOutActivity > MQTT_KEEPALIVE*1000UL)) { if (pingOutstanding) { this->_state = MQTT_CONNECTION_TIMEOUT; _client->stop(); return false; } else { buffer[0] = MQTTPINGREQ; buffer[1] = 0; _client->write(buffer,2); lastOutActivity = t; lastInActivity = t; pingOutstanding = true; } } if (_client->available()) { uint8_t llen; uint16_t len = readPacket(&llen); uint16_t msgId = 0; uint8_t *payload; if (len > 0) { lastInActivity = t; uint8_t type = buffer[0]&0xF0; if (type == MQTTPUBLISH) { if (callback) { uint16_t tl = (buffer[llen+1]<<8)+buffer[llen+2]; /* topic length in bytes */ memmove(buffer+llen+2,buffer+llen+3,tl); /* move topic inside buffer 1 byte to front */ buffer[llen+2+tl] = 0; /* end the topic as a 'C' string with \x00 */ char *topic = (char*) buffer+llen+2; // msgId only present for QOS>0 if ((buffer[0]&0x06) == MQTTQOS1) { msgId = (buffer[llen+3+tl]<<8)+buffer[llen+3+tl+1]; payload = buffer+llen+3+tl+2; callback(topic,payload,len-llen-3-tl-2); buffer[0] = MQTTPUBACK; buffer[1] = 2; buffer[2] = (msgId >> 8); buffer[3] = (msgId & 0xFF); _client->write(buffer,4); lastOutActivity = t; } else { payload = buffer+llen+3+tl; callback(topic,payload,len-llen-3-tl); } } } else if (type == MQTTPINGREQ) { buffer[0] = MQTTPINGRESP; buffer[1] = 0; _client->write(buffer,2); } else if (type == MQTTPINGRESP) { pingOutstanding = false; } } else if (!connected()) { // readPacket has closed the connection return false; } } return true; } return false; } The type value is 208 which is MQTTPINGRESP not 48 which is MQTTPUBLISH. So, where is the problem? Is my library or my code? I download library from https://www.arduino.cc/reference/en/libraries/pubsubclient/
Arduino compiler failing with error code - invalid types 'int[int]' for array subscript
Quite a bit of untested code but the only thing really concerning me at the moment is my DISPLAY variable. I don't see how it is much different than my FONT array (which works fine) yet DISPLAY is the one that gets 'invalid types 'int[int]' for array subscript' I should be able to index an array of integers with integers (at least I have been with FONT). #include <WiFiNINA.h> #include <NTPClient.h> #include <WiFiUdp.h> #include "font.h" const int PIXEL_WIDTH = 30; const int PIXEL_HEIGHT = 5; int DISPLAY[PIXEL_HEIGHT][PIXEL_WIDTH] = {}; bool MILI_TIME = false; String FORMATTING[2] = {"LONGS","SHORTH:LONGM"}; char ssid[] = "REMOVED"; // your network SSID (name) between the " " char pass[] = "REMOVED"; // your network password between the " " int keyIndex = 0; // your network key Index number (needed only for WEP) int status = WL_IDLE_STATUS; // connection status WiFiServer server(80); // server socket WiFiClient client = server.available(); WiFiUDP ntpUDP; NTPClient timeClient(ntpUDP); int ledPin = LED_BUILTIN; void setup() { Serial.begin(9600); pinMode(ledPin, OUTPUT); while (!Serial); // dont do anything until there is a serial connection enable_WiFi(); connect_WiFi(); server.begin(); printWifiStatus(); timeClient.begin(); timeClient.setTimeOffset(-14400); } void loop() { timeClient.update(); client = server.available(); if (client) { printWEB(); } preRender(); } void preRender(){ String FILLED_FORMATTING[2] = FORMATTING; for(int i=0;i<2;i++){ FILLED_FORMATTING[i].replace("LONGH",leadWithZero(timeHours())); FILLED_FORMATTING[i].replace("LONGM",leadWithZero(timeMinutes())); FILLED_FORMATTING[i].replace("LONGS",leadWithZero(timeSeconds())); FILLED_FORMATTING[i].replace("SHORTH",timeHours()); FILLED_FORMATTING[i].replace("SHORTM",timeMinutes()); FILLED_FORMATTING[i].replace("SHORTS",timeSeconds()); } int x = 0; for(int i=0;i<FILLED_FORMATTING[0].length();i++){ int c_ID = charID(FILLED_FORMATTING[0][i]); if(c_ID < 38){ for(int j=0;j<5;j++){ DISPLAY[j][x] = FONT[c_ID][j][0]; x += 1; DISPLAY[j][x] = FONT[c_ID][j][1]; x += 1; DISPLAY[j][x] = FONT[c_ID][j][2]; x += 1; if(i != FILLED_FORMATTING[0].length()){ DISPLAY[j][x] = 0; x += 1; } } } } x = PIXEL_WIDTH-1; for(int i=FILLED_FORMATTING[1].length()-1;i>=0;i--){ int c_ID = charID(FILLED_FORMATTING[1][i]); if(c_ID < 38){ for(int j=0;j<5;j++){ DISPLAY[j][x] = FONT[c_ID][j][0]; x -= 1; DISPLAY[j][x] = FONT[c_ID][j][1]; x -= 1; DISPLAY[j][x] = FONT[c_ID][j][2]; x -= 1; if(i != 0){ DISPLAY[j][x] = 0; //<----------- compiler error here, and ofc all instances above x -= 1; } } } } } int charID(char c){ for(int i=0;i<FONT_ID.length();i++){ if(FONT_ID[i] == c){ return i; } } return 40; } String timeHours(){ if(MILI_TIME){ return String(timeClient.getHours()); } else{ return convFromMili(timeClient.getHours()); } } String timeMinutes(){ return String(timeClient.getMinutes()); } String timeSeconds(){ return String(timeClient.getSeconds()); } String leadWithZero(String t){ if(t.length() < 2){ t = "0"+t; return t; } } String convFromMili(int t){ if(t > 12){ t -= 12; }else if(t == 0){ t += 12; } String ts = String(t); return ts; } void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID()); // print your board's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip); // print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); Serial.print("To see this page in action, open a browser to http://"); Serial.println(ip); } void enable_WiFi() { // check for the WiFi module: if (WiFi.status() == WL_NO_MODULE) { Serial.println("Communication with WiFi module failed!"); // don't continue while (true); } String fv = WiFi.firmwareVersion(); if (fv < "1.0.0") { Serial.println("Please upgrade the firmware"); } } void connect_WiFi() { while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); status = WiFi.begin(ssid, pass); delay(10000); } } void printWEB() { if (client) { // if you get a client, Serial.println("new client"); // print a message out the serial port String currentLine = ""; // make a String to hold incoming data from the client while (client.connected()) { // loop while the client's connected if (client.available()) { // if there's bytes to read from the client, char c = client.read(); // read a byte, then Serial.write(c); // print it out the serial monitor if (c == '\n') { // if the byte is a newline character // if the current line is blank, you got two newline characters in a row. // that's the end of the client HTTP request, so send a response: if (currentLine.length() == 0) { // HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK) // and a content-type so the client knows what's coming, then a blank line: client.println("HTTP/1.1 200 OK"); client.println("Content-type:text/html"); client.println(); //create the buttons client.print(WiFi.getTime()); client.print("<br>"); client.print(timeClient.getEpochTime()); client.print("<br>"); client.print(timeClient.getFormattedTime()); client.print("<br>"); client.print(timeClient.getDay()); client.print("<br>"); client.print(timeClient.getHours()); client.print("<br>"); client.print(timeClient.getMinutes()); client.print("<br>"); client.print(timeClient.getSeconds()); client.print("<br>"); client.print("<div style=\"display:block;padding-left:calc(50% - 150px);margin-bottom:50px\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">ON</div></div>"); client.print("<div style=\"display:block;padding-left:calc(50% - 150px)\"><div style=\"background-color:#e3e3e3;width:300px;height:120px;font-size:50px;text-align:center;padding-top:50px\">OFF</div></div>"); // The HTTP response ends with another blank line: client.println(); // break out of the while loop: break; } else { // if you got a newline, then clear currentLine: currentLine = ""; } } else if (c != '\r') { // if you got anything else but a carriage return character, currentLine += c; // add it to the end of the currentLine } if (currentLine.endsWith("GET /H")) { digitalWrite(ledPin, HIGH); } if (currentLine.endsWith("GET /L")) { digitalWrite(ledPin, LOW); } if (currentLine.endsWith("%VAL")) { // Trim 'GET /' and '%VAL' currentLine.remove(0,5); currentLine.remove(currentLine.indexOf("%"),4); Serial.println(currentLine); Serial.println(); } } } // close the connection: client.stop(); Serial.println("client disconnected"); } } font.h: int FONT[37][5][3] = {{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,0},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{0,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,0},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,0,1},{0,0,1},{0,0,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,1,0},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,1,0},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,1,1},},{{1,1,1},{1,0,0},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,0},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,1},{1,0,1},{1,0,1},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{1,1,1},},{{0,0,1},{0,0,1},{0,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{1,0,0},{1,0,0},{1,0,0},{1,0,0},{1,1,1},},{{1,1,1},{1,1,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,0},{1,0,1},{1,0,1},{1,0,1},{1,0,1},},{{1,1,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,1,1},{1,0,1},{1,1,1},{1,0,0},{1,0,0},},{{1,1,1},{1,0,1},{1,0,1},{1,1,0},{0,0,1},},{{1,1,1},{1,0,1},{1,1,0},{1,0,1},{1,0,1},},{{0,1,1},{1,0,0},{0,1,0},{0,0,1},{1,1,0},},{{1,1,1},{0,1,0},{0,1,0},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,0,1},{1,1,1},},{{1,0,1},{1,0,1},{1,0,1},{0,1,0},{0,1,0},},{{1,0,1},{1,0,1},{1,0,1},{1,1,1},{1,1,1},},{{1,0,1},{1,0,1},{0,1,0},{1,0,1},{1,0,1},},{{1,0,1},{1,0,1},{1,1,1},{0,0,1},{1,1,1},},{{1,1,1},{0,0,1},{0,1,0},{1,0,0},{1,1,1},},{{0,0,0},{0,1,0},{0,0,0},{0,1,0},{0,0,0}}}; String FONT_ID = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ:"; did check - int D[5][30]; void setup() { } void loop() { D[0][0] = 0; } and of course its fine, so I'm just wondering where I went wrong in the mess above? and yes there's a good bit of mess/debugging stuff
Simple solution... don't use DISPLAY as a variable it seems. Changing to DISPLAY_ fixed it, figured the variable was defined as a normal integer somewhere... just not in my code.
WDT reset cause 4 after reinstalling Arduino
I try to control my LED strip with an Android app. I reinstalled the Arduino IDE since I didn't like the Windows-store version. The serial monitor broke for whatever reason so I switched back to the Windows-store version. But now I'm getting a WDT reset error, which I can't seem to overcome. I'm also using Adafruit_NeoPixel and wherever I put "ledstrip.begin" or "ledstrip.show" seems to break it. #include <ESP8266WiFi.h> #include <Adafruit_NeoPixel.h> byte RED = 14; byte GREEN = 12; byte BLUE = 13; byte PIN_COUNT = 20; Adafruit_NeoPixel ledstrip = Adafruit_NeoPixel(PIN_COUNT, 6, NEO_RGB + NEO_KHZ800); //(num of leds, ) WiFiServer server(port); void setup() { Serial.begin(115200); delay(10); ledstrip.begin(); Serial.print("Connecting to: "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); byte tries; while (WiFi.status() != WL_CONNECTED) { delay(500); tries++; Serial.println("."); if (tries == 5) { Serial.println("Connection failed"); return; } } Serial.println("\nWiFi connected"); server.begin(); Serial.println("Server URL: "); Serial.print(WiFi.localIP()); } void print_tokens(char* strings) { byte index = sizeof(strings); for (int n = 0; n < index; n++) { Serial.println(strings[n]); } } char *tokenize_request(String request) { char requestArray[1024]; char *ptr = NULL; byte index = 0; char *strings[10]; strcpy(requestArray, request.c_str()); ptr = strtok(requestArray, ";"); while (ptr != NULL) { strings[index] = ptr; index++; ptr = strtok(NULL, ";"); } return *strings; } void loop() { WiFiClient responder = server.available(); if (!responder) { return; } while (!responder.available()) { delay(1); } String request = responder.readStringUntil('#'); char *strings[10] = {tokenize_request(request)}; print_tokens(*strings); int mode = atoi(strings[0]); int R = atoi(strings[1]); int G = atoi(strings[2]); int B = atoi(strings[3]); if (mode == 1) { ledstrip.setPixelColor(5, R, G, B); } if (mode == 0) { ledstrip.setPixelColor(5, 0, 0, 0); } ledstrip.show(); delay(1); Serial.println("------------------------------------------------------------------"); } Serial monitor output:
how can I display/save the value of what return an AT command
Good day all! I am working on a project with Arduino UNO and a SIM908. I am trying to understand the AT command. When I enter Serial.print("AT") Serial.println("AT+CGPSSTATUS?"); Serial retuen a value and I would like to save that value into a buffer char buffer[size] I do not want to have other string than the return value of an AT command. I also red that document SIM908 AT Command Manual_V1.01 At the page 13, you can read (NB. < CR>< LF> : I added a space after the first <, other there are not display) The "AT" or "at" prefix must be set at the beginning of each Command line. To terminate a Command line enter < CR>. Commands are usually followed by a response that includes. "< CR>< LF>< CR>< LF>" Throughout this document, only the responses are presented, < CR>< LF> are omitted intentionally Then, I am asking how I can "extract" the response between < CR>< LF> and < CR>< LF> Looking at this exemple (let me know if I am wrong), how can I detect the < CR>< LF> void setup() { char buffer[200]; Serial.println("AT+CGPSSTATUS?"); } void loop() { if (Serial.available()) { // HERE I SHOULD CHECK IF CR ANF LF Serial.write(Serial.read()); // AND SAVE IT IN buffer. IS'T NOT? } } } Do you see what I means? How could you help me to store in a buffer, only the return value of an AT command? Many thank for your help
It's very interresting what you show me. Here is how I adapt my code I adapted my code and by the way I created a file for testing Serail while we send a AT command. The concern function are loop() and read_AT_string(). (I renamed the read_String to read_AT_string(). Here my code and I explain, after the issue, regardin your proposal #include <SoftwareSerial.h> int baud_rate = 9600; int pin_gsm = 3; int pin_gps = 4; int pin_power = 5; //int pin_dtr = 6; boolean debug = true; boolean raedy_to_go = false; // Reading String #define BUFFERSIZE 200 char buffer[BUFFERSIZE]; char inChar; int index; void setup() { Serial.begin(baud_rate); delay(5000); // Wait for 5sec after begin if(debug) { Serial.println(F("\n****************************")); Serial.println(F("STARTING SYSTEM Read AT stream")); Serial.println(F("******************************")); } pinMode(pin_gsm,OUTPUT); // Set the pins pinMode(pin_gps,OUTPUT); pinMode(pin_power,OUTPUT); powerUpSim908: if(powerUpSim908()) { delay(1000); if(gps_power()){ gsm_enable(); raedy_to_go = true; if(debug) { Serial.println(F("\n****************************")); Serial.println(F("READY TO GO\n")); Serial.println(F("****************************\n")); } } else { raedy_to_go = false; if(debug) { Serial.println(F("\nNOT READY TO GO.\nGPS could not be power\nRestart the module\nor/and check the battery level.\n")); } goto powerUpSim908; } } else { raedy_to_go = false; if(debug) { Serial.println(F("\nNOT READY TO GO.\nCheck the battery level.\n")); } }; } void loop() { /* if (Serial.available()) { Serial.print("Character received: "); Serial.write(Serial.read()); Serial.println(""); } */ if(raedy_to_go) { read_AT_string("AT",5000); delay(10000); } } char read_AT_string(char* command, int timeout) { unsigned long previous; previous = millis(); Serial.println(F("\nDISPLAY BUFFER:")); index=0; Serial.println(command); do { if(Serial.available() > 0) // Don't read unless // there you know there is data { Serial.println("1"); if (Serial.peek() == 13) // check if CR (without reading) { Serial.println("13"); if(Serial.available() > 0) { Serial.read(); // read and ignore if (Serial.peek()==10) // then check if LF (without reading) { Serial.println("10"); if(index < Serial.readBytesUntil(13, buffer, BUFFERSIZE-1)) // One less than the size of the buffer array { Serial.println("b"); inChar = Serial.read(); // Read a character buffer[index] = inChar; // Store it index++; // Increment where to write next buffer[index] = '\0'; // Null terminate the string } } } } } }while(((millis() - previous) < timeout)); Serial.println(buffer); buffer[0]='\0'; Serial.println(F("END DISPLAY BUFFER")); } /* FUNCTION */ boolean powerUpSim908(void) { if(debug) { Serial.println(F("Powering up SIM908")); } boolean turnedON = false; //uint8_t answer=0; int cont; for (cont=0; cont<3; cont++) { digitalWrite(pin_power,HIGH); delay(1500); digitalWrite(pin_power,LOW); Serial.println(F("Checking if the module is up")); if(sendATcommand("AT", "OK", 5000)) { cont = 4; // Leave the loop turnedON = true; } else { turnedON = false; if(debug) { Serial.println(F("\nTrying agin to turn on SIM908")); } }; } if(turnedON) { if(debug) { Serial.println(F("Module is tunrned up\n")); } } else { if(debug) { Serial.println(F("Module is NOT tunrned ON\n")); } } return turnedON; } boolean sendATcommand(char* ATcommand, char* expected_answer, unsigned int timeout) { uint8_t x=0; bool answer=false; //åchar response[100]; //buffer[0]='\0'; unsigned long previous; //memset(response, '\0', 100); // Initialice the string //Serial.println(response); delay(100); while( Serial.available() > 0) Serial.read(); // Clean the input buffer if (ATcommand[0] != '\0') { Serial.println(ATcommand); // Send the AT command } x = 0; previous = millis(); index=0; do { if(Serial.available() > 0) // there you know there is data { if(index < BUFFERSIZE-1) // One less than the size of the array // Same as buffer size { inChar = Serial.read(); // Read a character buffer[index] = inChar; // Store it index++; // Increment where to write next //Serial.println(index); buffer[index] = '\0'; // Null terminate the string } } }while(((millis() - previous) < timeout)); if(strstr(buffer,"NORMAL POWER DOWN") != NULL) { answer = false; } else if (strstr(buffer, expected_answer) != NULL) // check if the desired answer (OK) is in the response of the module { /* Serial.println(F("### BUFFER")); Serial.println(buffer); Serial.println(F("### END BUFFER")); */ answer = true; } else { answer = false; } if(debug) { if(answer) { //Serial.println(F("Expected answer : OK!\n")); } else { //Serial.println(F("Expected answer : KO!\n")); }; } return answer; } void gps_enable(void) { if(debug) { Serial.println(F("\nEnabling GPS ...")); } digitalWrite(pin_gps,LOW); //Enable GPS mode digitalWrite(pin_gsm,HIGH); //Disable GSM mode delay(2000); } void gsm_enable(void) { if(debug) { Serial.println(F("\nEnabling GSM ...")); } digitalWrite(pin_gsm,LOW); //Enable GSM mode digitalWrite(pin_gps,HIGH); //Disable GPS mode delay(2000); } /* UTILISTIES */ /* GPS */ boolean gps_power(void) //turn on GPS power supply { /* Serial.println("AT"); delay(2000); */ boolean gpspwr = false; boolean gpsrst = false; if(sendATcommand("AT+CGPSPWR=1","OK",2000)) { gpspwr = true; if(debug) { Serial.println("turn on GPS power supply => OK"); } } else { if(debug) { Serial.println("turn on GPS power supply => KO"); } }; //delay(1000); if(sendATcommand("AT+CGPSRST=1","OK",2000)) { gpsrst = true; if(debug) { Serial.println("reset GPS in autonomy mode => OK"); } } else { if(debug) { Serial.println("reset GPS in autonomy mode => KO"); } }; //reset GPS in autonomy mode delay(1000); if(gpspwr && gpsrst) { return true; }else { return false; } } At the read_AT_string, the first if(Serial.peek()==13) always return false. 1 is printed, but '13' is not, then I supposed if(Serial.peek()==13) return false Here is what is printed within 5 sec AT DISPLAY BUFFER: 1 1 1 1 1 1 1 1 1 [...] // It prints 1 until now 1 END DISPLAY BUFFER
Here a piece of code to detect and remove CR+LF (Attention: if A CR is read but it's not followed by a LF, it is removed as well): if (Serial.peek()==13) { // check if CR (without reading) Serial.read(); // read and ignore if (Serial.peek()==10) // then check if LF (without reading) Serial.read(); } To read the rest of the response from Serial you could use: buffer[Serial.readBytesUntil(13, buffer, 199)]=0; // readbytes returns the number of bytes read You then have to discard the ending CRLF (same as above). Edit There are several issues with the code that you've posted in a separate answer. When you powerUpSim908() you have to be aware that the gsm module may send unrequested data (see documentation, chapter 1.4): Note: A HEX string such as "00 49 49 49 49 FF FF FF FF" will be sent out through serial port at the baud rate of 115200 immediately after SIM908 is powered on. The string shall be ignored since it is used for synchronization with PC tool. Only enter AT Command through serial port after SIM908 is powered on and Unsolicited Result Code "RDY" is received from serial port. This means that before you send anything, you have to discard this data by reading it. I guess this is why you don't get CRLF when reading the response: you first get the HEX string or "RDY". Then readBytesUntil() reads as many bytes as available (maxi 199 in my example above), stores them in the buffer. It stops reading when it encounters the byte 13 (i.e.CR). There is no need to loop on an index. The function returns the number of chars that could be read, and it doesn't put an ending 0 at the end of the buffer (i.e. no valid C string). If you want to use the function in another way than what I proposed, you must store the length returned, because you have no other way to find it out later on.