DELAY is crashing board if delay duration is greater than 30 seconds? - arduino

I have this variable, DELAY_INTERVAL, which I set to measure how long my arduino mega board will delay before submitting a request to my server again.
I've found that when this variable is set to 30 seconds my board runs fine but as soon as I set it to 45 seconds my board crashes.
I've inserted a bunch of printlns for debugging purposes:
void loop() {
Serial.print("Free RAM: ");
Serial.println(getFreeRam(), DEC);
Serial.println(1);
getEC();
Serial.println(2);
getPH();
Serial.println(3);
createPoint(ecSensorString, phSensorString);
Serial.println(4);
delay(DELAY_INTERVAL*1000);
Serial.println(5);
}
Note that this runs indefinitely for 30s but not 45s.
This is what the console outputs on 45s:
Free RAM: 6551
1
getEC:*OK
2
getPH:
3
a
postPointToServer:ec=*OK&ph=&interval=45s
b
c
d
e
f
g
h
4
<output monitor just stalls>
So I have identified that delay is the culprit here. But why and how can I solve this?
The rest of my code if anyone is interested.
void setup() {
//initRGB();
Serial.begin(9600);
ecSensorString.reserve(30);
phSensorString.reserve(30);
initSensors();
initWireless();
Serial.println("Setup Complete");
}
void loop() {
Serial.print("Free RAM: ");
Serial.println(getFreeRam(), DEC);
Serial.println(1);
getEC();
Serial.println(2);
getPH();
Serial.println(3);
createPoint(ecSensorString, phSensorString);
Serial.println(4);
delay(DELAY_INTERVAL*1000);
Serial.println(5);
}
void initWireless() {
/* Initialise the module */
if (!cc3000.begin()) {
Serial.println(F("Couldn't begin()! Check your wiring?"));
//displayRed();
while(1);
}
Serial.println(F("Initialization Complete"));
Serial.print(F("Attempting to connect to "));
Serial.println(WLAN_SSID);
if (!cc3000.connectToAP(WLAN_SSID, WLAN_PASS, WLAN_SECURITY)) {
Serial.println(F("Failed!"));
//displayRed();
while(1);
}
Serial.println(F("Wireless Connected!"));
/* Wait for DHCP to complete */
while (!cc3000.checkDHCP()) {
delay(100); // ToDo: Insert a DHCP timeout!
}
Serial.println(F("DHCP Requested!"));
if (IP_NOT_DOMAIN) {
ip = cc3000.IP2U32(IP_1, IP_2, IP_3, IP_4);
} else {
ip = 0;
// Try looking up the website's IP address
while (ip == 0) {
if (! cc3000.getHostByName(WEBSITE, &ip)) {
Serial.println(F("Couldn't resolve!"));
}
delay(500);
}
}
}
void initSensors() {
Serial2.begin(38400);
Serial3.begin(38400);
// Tell the EC sensors to stop continuous mode
Serial2.print("c,0\r");
// Tell the pH sensor to stop all readings
Serial3.print("E\r");
// TODO: EC sensor's first reading is always empty, possibly delay?
}
void createPoint(String ec, String ph) {
if (ec && ph) {
postPointToServer("ec=" + ec + "&ph=" + ph);
} else if (ec) {
postPointToServer("ec=" + ec);
} else if (ph) {
postPointToServer("ph=" + ph);
} else {
Serial.println("createPoint: null");
}
}
void postPointToServer(String data) {
Serial.println("a");
char interval_c[20];
sprintf(interval_c, "&interval=%ds", DELAY_INTERVAL);
data += interval_c;
Serial.print("postPointToServer:");
Serial.println(data);
Serial.println("b");
Adafruit_CC3000_Client www = cc3000.connectTCP(ip, PORT);
Serial.println("c");
if (www.connected()) {
www.fastrprint(F("POST ")); www.fastrprint(WEBPAGE); www.fastrprint(F(" HTTP/1.1\r\n"));
www.fastrprint(F("Host: ")); www.fastrprint(WEBSITE); www.fastrprint(F("\r\n"));
Serial.println("d");
String auth_raw = serial + ":" + token;
char auth_input[200];
char auth_output[200];
auth_raw.toCharArray(auth_input, auth_raw.length() + 1);
base64_encode(auth_output, auth_input, auth_raw.length());
www.fastrprint(F("Authorization: Basic ")); www.fastrprint(auth_output); www.fastrprint(F("\r\n"));
www.fastrprint(F("Content-Type: application/x-www-form-urlencoded")); www.fastrprint(F("\r\n"));
Serial.println("e");
char len_c[7];
itoa(data.length(), len_c, 10);
www.fastrprint(F("Content-Length: ")); www.fastrprint(len_c); www.fastrprint(F("\r\n"));
// Extra empty line for post arguments
www.fastrprint(F("\r\n"));
Serial.println("f");
char data_c[200];
data.toCharArray(data_c, data.length() + 1);
www.fastrprint(data_c); www.fastrprint(F("\r\n"));
www.fastrprint(F("\r\n"));
www.println();
//displayGreen();
} else {
Serial.println(F("Connection failed"));
//displayRed();
}
Serial.println("g");
www.close();
Serial.println("h");
}
void getEC() {
ecSensorString = "";
Serial2.print("r\r"); // Read only 1
char inchar;
while (Serial2.available()) {
inchar = (char)Serial2.read();
if (inchar != '\r') {
ecSensorString += inchar;
}
}
Serial.print("getEC:");
Serial.println(ecSensorString);
}
void getPH() {
phSensorString = "";
Serial3.print("R\r"); // Read only 1
char inchar;
while (Serial3.available()) {
inchar = (char)Serial3.read();
if (inchar != '\r') {
phSensorString += inchar;
}
}
Serial.print("getPH:");
Serial.println(phSensorString);
}

I've had the same problem.
Do you need to put an L at the end to make an explicit conversion of this constant into a long integer:
delay(DELAY_INTERVAL*1000L);

Related

Arduino MEGA, LCD and SSR is frozen after 24 hours

I'm going to tell you my problem with arduino.
I am making an access rfdi system to enable a water pump, the procedure is as follows: I bring the rfid keyring closer to the reader, I make a sql query to the server and if it returns the data, I enable the pump and later register that user is served water.
Everything works fine for 18-24 hours, after that time the screen freezes and the arduino doesn't respond in any way or run the program. To get it to work again I have to restart it.
Maybe I thought it was a memory problem, but I don't know. On build I have Sketch (18%) and memory (22%).
I don't know where the problem is.
#include <U8glib.h>
#include <SPI.h>
#include <EthernetENC.h>
#include <Wiegand.h> //PROTOCOLO P/ RFDI
#include <ArduinoJson.h>
U8GLIB_ST7920_128X64_1X u8g(6, 5, 4 ,7); //LCD Enable, RW, RS, RESET
#define FALSE 0
#define TRUE 1
long int rawToken;
char c;
char pageAdd[64];
char user[64];
int totalCount = 0;
String ID = "";
String readString = "";
String clientegraba = "";
String terrenograba = "";
bool inicio = true;
bool errorbit = false;
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// CONFIG IP ARDUINO
IPAddress ip(192,168,0,210);
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
// IP Y PUERTO SERVIDOR
IPAddress server(192,168,0,104);
char serverName[] = "192.168.0.104";
int serverPort = 80;
EthernetClient client;
WIEGAND wg;
void setup() {
Serial.begin(9600);
pinMode(34,OUTPUT); //OUT PUMP
digitalWrite(34,LOW);
welcome(); //PANTALLA BIENVENIDA
//GATE A
wg.D0PinA =2;
wg.D1PinA =3;
//GATE B
wg.D0PinB =18;
wg.D1PinB =19;
//GATE C
wg.D0PinC =20;
wg.D1PinC =21;
// Reader enable
wg.begin(TRUE, FALSE, FALSE); // wg.begin(GateA , GateB, GateC)
// disable SD SPI
pinMode(4,OUTPUT);
digitalWrite(4,HIGH);
// Start ethernet
Serial.println(F("Iniciando ethernet..."));
Ethernet.begin(mac, ip, gateway, gateway, subnet);
Serial.println(Ethernet.localIP());
delay(2000);
Serial.println(F("Listo"));
ingresellave();
}
void loop()
{
if(wg.available()){
errorbit = false;
espere(); //WAITING SCREEN
ID = String(wg.getCode()); //OBTIENE ID DE TARJETA
String data = "/test.php?cliente=" + ID; //CONCAT ID
sprintf(pageAdd,data.c_str(),totalCount);
Serial.println(pageAdd);
if(!getPage(server,serverPort,pageAdd)){
Serial.print(F("Falla "));
}else{
Serial.print(F("Paso "));
}
totalCount++;
Serial.println(totalCount,DEC);
}
if(ID != ""){
if(clientegraba != ""){
grabacarga(clientegraba,terrenograba);
}else{
if(errorbit == false){
noexiste();
delay(3000);
ID = "";
ingresellave();
}
}
}
delay(200);
}
byte getPage(IPAddress ipBuf,int thisPort, char *page)
{
int inChar;
char outBuf[128];
Serial.print(F("Conectando..."));
if(client.connect(ipBuf,thisPort) == 1){
Serial.println(F("Conectado"));
sprintf(outBuf,"GET %s HTTP/1.1",page);
client.println(outBuf);
sprintf(outBuf,"Host: %s",serverName);
client.println(outBuf);
client.println(F("Connection: close\r\n"));
}else{
error();
errorbit = true;
Serial.println(F("Error en servidor"));
return 0;
}
// connectLoop controls the hardware fail timeout
int connectLoop = 0;
boolean reader = false;
while(client.connected())
{
while(client.available())
{
String line = client.readStringUntil('\n');
if(reader){
StaticJsonBuffer<200> jsonBuffer;
JsonObject& datos = jsonBuffer.parseObject(line);
String apellido = datos["name"];
String cliente = datos["cliente"];
clientegraba = cliente;
long total = datos["total"];
long libres = datos["libres"];
String terreno = datos["terreno"];
terrenograba = terreno;
String costo = datos["costo"];
float price = costo.toFloat();
usuario(apellido,total,libres,price);
Serial.println("User: " + apellido);
Serial.println("Cliente: " + cliente);
Serial.println("Tarjeta: " + ID);
Serial.println("Terreno: " + terreno);
Serial.println("Costo: " + String(costo));
Serial.println("Total: " + String(total));
Serial.println("Libres: " + String(libres));
if(apellido != ""){
digitalWrite(34,HIGH); //PUMP START
delay(1000);
digitalWrite(34,LOW); //PUMP STOP
}
}
if(line == "\r") {
reader = true;
break;
}
// set connectLoop to zero if a packet arrives
connectLoop = 0;
}
connectLoop++;
// if more than 10000 milliseconds since the last packet
if(connectLoop > 10000)
{
// then close the connection from this end.
Serial.println();
Serial.println(F("Timeout"));
client.stop();
}
// this is a delay for the connectLoop timing
delay(1);
}
Serial.println();
Serial.println(F("Desconectando."));
// close client end
client.stop();
delay(100);
return 1;
}
void grabacarga(String cliente, String terreno){
String data = "/graba.php?cliente=" + cliente + "&tarjeta=" + ID + "&terreno='" + terreno + "'";
sprintf(pageAdd,data.c_str(),totalCount);
Serial.println(pageAdd);
if(!getPage(server,serverPort,pageAdd)) Serial.print(F("Falla "));
else Serial.print(F("Paso "));
totalCount++;
Serial.println(totalCount,DEC);
ID = "";
terrenograba = "";
clientegraba = "";
inicio = true;
delay(9000);
ingresellave();
}
void welcome() {
u8g.setRot180();
u8g.setFont(u8g_font_unifont);
u8g.firstPage();
do {
u8g.drawStr(18,22,"SISTEMA");
u8g.drawStr(15,50,"ACCESO RFID");
} while( u8g.nextPage() );
}
void ingresellave() {
u8g.setFont(u8g_font_unifont);
u8g.firstPage();
do {
u8g.drawStr(0,10,"COLOQUE EL BIDON");
u8g.drawStr(2,35,"Y LUEGO INGRESE");
u8g.drawStr(25,60,"UNA LLAVE");
} while( u8g.nextPage() );
}
void error() {
u8g.setFont(u8g_font_unifont);
u8g.firstPage();
do {
u8g.drawStr(40,10,"ERROR");
u8g.drawStr(33,35,"INTENTE");
u8g.drawStr(22,60,"NUEVAMENTE");
} while( u8g.nextPage() );
}
void espere() {
u8g.setFont(u8g_font_unifont);
u8g.firstPage();
do {
u8g.drawStr(25,35,"ESPERE...");
} while( u8g.nextPage() );
}
void usuario(String user, long total, long libres, float costo) {
u8g.firstPage();
do {
u8g.setFont(u8g_font_6x10);
u8g.drawStr(0,10,user.c_str());
String carga = "Carga:" + String(total) + "/" + String(libres);
u8g.setFont(u8g_font_unifont);
u8g.drawStr(15,33,carga.c_str());
if(total > libres){
long precio = total - libres;
float costototal = precio * costo;
Serial.println(costototal);
String valor = "Costo:$" + String(costototal);
u8g.drawStr(0,60,valor.c_str());
}
} while( u8g.nextPage() );
}
void noexiste(){
u8g.setFont(u8g_font_unifont);
u8g.firstPage();
do {
u8g.drawStr(34,22,"USUARIO");
u8g.drawStr(12,50,"NO REGISTRADO");
} while( u8g.nextPage() );
}
The system power is from a 12V 4.5A source and the Arduino Mega along with the screen(LCD12864A) are powered from the 5V pin through an external LM2596 regulator.
The screen data pins are connected to pins 4,5,6 and 7, the rfid reader to pins 2 and 3 and the water pump output is pin 34 which has a 2222a pnp transistor connected with a 1K base resistor, emitter to ground and collector to an SSR-24DA solid state relay.
Thank you.
After reading your comment mentioning wiegand malfunction, and the fact that it only malfunctioned after several hours of running well, I would try and see if it's overheating somehow, or try and reduce EMI by using EMI filter on the power supply and shielding the circuit board with aluminium box or the like.
Water pump can cause high EMI and voltage spike in the mains upon turning on or off.

Trying to understand ESP32 OTA over the GSM code

I am performing ESP32 OTA over the GSM. I have found some example code online, modified it slightly based on my board connections and was able to sucesfully perform a firmware update.
I use lilygo ESP32 GSM development board.
However, it frustrates me that I am not capable of understanding what really happens in the code at the low level. I really want to understand before I go any further with my project.
Full code for my OTA update:
#include <Update.h>
#define TINY_GSM_MODEM_SIM800
// Increase RX buffer
#define TINY_GSM_RX_BUFFER 1030
const char apn[] = "omnitel";
const char user[] = "omni";
const char pass[] = "omni";
#define MODEM_RST 5
#define MODEM_PWRKEY 4
#define MODEM_POWER_ON 23
#define MODEM_TX 27
#define MODEM_RX 26
#define LED_GPIO 13
#define LED_ON HIGH
#define LED_OFF LOW
#define SerialAT Serial1
#include <TinyGsmClient.h>
#include <CRC32.h>
#include "FS.h"
#include "SPIFFS.h"
#ifdef DUMP_AT_COMMANDS
#include <StreamDebugger.h>
StreamDebugger debugger(SerialAT, Serial);
TinyGsm modem(debugger);
#else
TinyGsm modem(SerialAT);
#endif
TinyGsmClient client(modem);
const char server[] = "myesptestserver.ddns.net";
const int port = 80;
const char resource[] = "/esp.bin"; //here de bin file
uint32_t knownCRC32 = 0x6f50d767;
uint32_t knownFileSize = 1024; // In case server does not send it
void setup()
{
SerialAT.begin(115200, SERIAL_8N1, MODEM_RX, MODEM_TX);
// Set console baud rate
Serial.begin(115200);
setupModem();
delay(10);
if (!SPIFFS.begin(true))
{
Serial.println("SPIFFS Mount Failed");
return;
}
SPIFFS.format();
listDir(SPIFFS, "/", 0);
// Set GSM module baud rate
delay(3000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
Serial.println("Initializing modem...");
modem.restart();
String modemInfo = modem.getModemInfo();
Serial.print("Modem: ");
Serial.println(modemInfo);
// Unlock your SIM card with a PIN
//modem.simUnlock("1234");
}
void loop()
{
Serial.print("Waiting for network...");
if (!modem.waitForNetwork())
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
Serial.print("Connecting to ");
Serial.print(apn);
if (!modem.gprsConnect(apn, user, pass))
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
Serial.print("Connecting to ");
Serial.print(server);
// if you get a connection, report back via serial:
if (!client.connect(server, port))
{
Serial.println(" fail");
delay(10000);
return;
}
Serial.println(" OK");
// Make a HTTP request:
client.print(String("GET ") + resource + " HTTP/1.0\r\n");
client.print(String("Host: ") + server + "\r\n");
client.print("Connection: close\r\n\r\n");
long timeout = millis();
while (client.available() == 0)
{
if (millis() - timeout > 5000L)
{
Serial.println(">>> Client Timeout !");
client.stop();
delay(10000L);
return;
}
}
Serial.println("Reading header");
uint32_t contentLength = knownFileSize;
File file = SPIFFS.open("/update.bin", FILE_APPEND);
while (client.available())
{
String line = client.readStringUntil('\n');
line.trim();
//Serial.println(line); // Uncomment this to show response header
line.toLowerCase();
if (line.startsWith("content-length:"))
{
contentLength = line.substring(line.lastIndexOf(':') + 1).toInt();
}
else if (line.length() == 0)
{
break;
}
}
timeout = millis();
uint32_t readLength = 0;
CRC32 crc;
unsigned long timeElapsed = millis();
printPercent(readLength, contentLength);
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
{
int i = 0;
while (client.available())
{
// read file data to spiffs
if (!file.print(char(client.read())))
{
Serial.println("Appending file");
}
//Serial.print((char)c); // Uncomment this to show data
//crc.update(c);
readLength++;
if (readLength % (contentLength / 13) == 0)
{
printPercent(readLength, contentLength);
}
timeout = millis();
}
}
file.close();
printPercent(readLength, contentLength);
timeElapsed = millis() - timeElapsed;
Serial.println();
client.stop();
Serial.println("stop client");
modem.gprsDisconnect();
Serial.println("gprs disconnect");
Serial.println();
float duration = float(timeElapsed) / 1000;
/*
Serial.print("Tamaño de Archivo: ");
Serial.println(contentLength);
Serial.print("Leido: ");
Serial.println(readLength);
Serial.print("Calculado. CRC32: 0x");
Serial.println(crc.finalize(), HEX);
Serial.print("Conocido CRC32: 0x");
Serial.println(knownCRC32, HEX);
Serial.print("Bajado en: ");
Serial.print(duration);
Serial.println("s");
Serial.println("Se genera una espera de 3 segundos");
for (int i = 0; i < 3; i++)
{
Serial.print(String(i) + "...");
delay(1000);
}
*/
//readFile(SPIFFS, "/update.bin");
updateFromFS();
// Do nothing forevermore
while (true)
{
delay(1000);
}
}
void appendFile(fs::FS &fs, const char *path, const char *message)
{
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if (!file)
{
Serial.println("Failed to open file for appending");
return;
}
if (file.print(message))
{
Serial.println("APOK");
}
else
{
Serial.println("APX");
}
}
void readFile(fs::FS &fs, const char *path)
{
Serial.printf("Reading file: %s\n", path);
File file = fs.open(path);
if (!file || file.isDirectory())
{
Serial.println("Failed to open file for reading");
return;
}
Serial.print("Read from file: ");
while (file.available())
{
Serial.write(file.read());
delayMicroseconds(100);
}
}
void writeFile(fs::FS &fs, const char *path, const char *message)
{
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if (!file)
{
Serial.println("Failed to open file for writing");
return;
}
if (file.print(message))
{
Serial.println("File written");
}
else
{
Serial.println("Write failed");
}
}
void listDir(fs::FS &fs, const char *dirname, uint8_t levels)
{
Serial.printf("Listing directory: %s\n", dirname);
File root = fs.open(dirname);
if (!root)
{
Serial.println("Failed to open directory");
return;
}
if (!root.isDirectory())
{
Serial.println("Not a directory");
return;
}
File file = root.openNextFile();
while (file)
{
if (file.isDirectory())
{
Serial.print(" DIR : ");
Serial.println(file.name());
if (levels)
{
listDir(fs, file.name(), levels - 1);
}
}
else
{
Serial.print(" FILE: ");
Serial.print(file.name());
Serial.print(" SIZE: ");
Serial.println(file.size());
}
file = root.openNextFile();
}
}
void deleteFile(fs::FS &fs, const char *path)
{
Serial.printf("Deleting file: %s\n", path);
if (fs.remove(path))
{
Serial.println("File deleted");
}
else
{
Serial.println("Delete failed");
}
}
void updateFromFS()
{
File updateBin = SPIFFS.open("/update.bin");
if (updateBin)
{
if (updateBin.isDirectory())
{
Serial.println("Directory error");
updateBin.close();
return;
}
size_t updateSize = updateBin.size();
if (updateSize > 0)
{
Serial.println("Starting update");
performUpdate(updateBin, updateSize);
}
else
{
Serial.println("Error, archivo vacío");
}
updateBin.close();
// whe finished remove the binary from sd card to indicate end of the process
//fs.remove("/update.bin");
}
else
{
Serial.println("no such binary");
}
}
void performUpdate(Stream &updateSource, size_t updateSize)
{
if (Update.begin(updateSize))
{
size_t written = Update.writeStream(updateSource);
if (written == updateSize)
{
Serial.println("Writes : " + String(written) + " successfully");
}
else
{
Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
}
if (Update.end())
{
Serial.println("OTA finished!");
if (Update.isFinished())
{
Serial.println("Restart ESP device!");
ESP.restart();
}
else
{
Serial.println("OTA not fiished");
}
}
else
{
Serial.println("Error occured #: " + String(Update.getError()));
}
}
else
{
Serial.println("Cannot beggin update");
}
}
void printPercent(uint32_t readLength, uint32_t contentLength)
{
// If we know the total length
if (contentLength != -1)
{
Serial.print("\r ");
Serial.print((100.0 * readLength) / contentLength);
Serial.print('%');
}
else
{
Serial.println(readLength);
}
}
void setupModem()
{
#ifdef MODEM_RST
// Keep reset high
pinMode(MODEM_RST, OUTPUT);
digitalWrite(MODEM_RST, HIGH);
#endif
pinMode(MODEM_PWRKEY, OUTPUT);
pinMode(MODEM_POWER_ON, OUTPUT);
// Turn on the Modem power first
digitalWrite(MODEM_POWER_ON, HIGH);
// Pull down PWRKEY for more than 1 second according to manual requirements
digitalWrite(MODEM_PWRKEY, HIGH);
delay(100);
digitalWrite(MODEM_PWRKEY, LOW);
delay(1000);
digitalWrite(MODEM_PWRKEY, HIGH);
// Initialize the indicator as an output
pinMode(LED_GPIO, OUTPUT);
digitalWrite(LED_GPIO, LED_OFF);
}
From what I understand, the following part of the code reads my binary file that is stored in the server and read it into SPIFFS memory:
while (readLength < contentLength && client.connected() && millis() - timeout < 10000L)
{
int i = 0;
while (client.available())
{
// read file data to spiffs
if (!file.print(char(client.read())))
{
Serial.println("Appending file");
}
//Serial.print((char)c); // Uncomment this to show data
//crc.update(c);
readLength++;
if (readLength % (contentLength / 13) == 0)
{
printPercent(readLength, contentLength);
}
timeout = millis();
}
}
Then the updateFromFS() function is executed, which checks whether the binary is all good and then calls another function performUpdate(updateBin, updateSize);
void updateFromFS()
{
File updateBin = SPIFFS.open("/update.bin");
if (updateBin)
{
if (updateBin.isDirectory())
{
Serial.println("Directory error");
updateBin.close();
return;
}
size_t updateSize = updateBin.size();
if (updateSize > 0)
{
Serial.println("Starting update");
performUpdate(updateBin, updateSize);
}
else
{
Serial.println("Error, archivo vacío");
}
updateBin.close();
// whe finished remove the binary from sd card to indicate end of the process
//fs.remove("/update.bin");
}
else
{
Serial.println("no such binary");
}
}
in the performUpdate(updateBin, updateSize), 2 functions from Arduino Update Library are being called ( Update.begin(updateSize) and Update.writeStream(updateSource) ) and that is where I cant follow anymore...
void performUpdate(Stream &updateSource, size_t updateSize)
{
if (Update.begin(updateSize))
{
size_t written = Update.writeStream(updateSource);
if (written == updateSize)
{
Serial.println("Writes : " + String(written) + " successfully");
}
else
{
Serial.println("Written only : " + String(written) + "/" + String(updateSize) + ". Retry?");
}
if (Update.end())
{
Serial.println("OTA finished!");
if (Update.isFinished())
{
Serial.println("Restart ESP device!");
ESP.restart();
}
else
{
Serial.println("OTA not fiished");
}
}
else
{
Serial.println("Error occured #: " + String(Update.getError()));
}
}
else
{
Serial.println("Cannot beggin update");
}
}
I have found this Update library source code :
https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/src/Updater.cpp
But it seems that this is beyond my knowledge to understand what really is going on in this code.
First of all, we pass only 1 variable to .begin method, but the function prototype requires more than that:
bool UpdateClass::begin(size_t size, int command, int ledPin, uint8_t ledOn, const char *label)
And then I am trying to understand what happens in function Update.writeStream(updateSource) but cant..
If anyone could shed some light here I would appreciate a lot! Thanks in advance...
The algorithm downloads the new firmware (.bin) from the cloud to the device's local memory and makes the firmware change with the UpdateClass library
(I see the texts in Spanish if you want we speak in Spanish)
Check the .h (only one argument required)
https://github.com/espressif/arduino-esp32/blob/master/libraries/Update/src/Update.h
/*
Call this to check the space needed for the update
Will return false if there is not enough space
*/
bool begin(size_t size=UPDATE_SIZE_UNKNOWN, int command = U_FLASH, int ledPin = -1, uint8_t ledOn = LOW, const char *label = NULL);
You could use the OTAdrive library and use it for OTA updates.
Check here for the esp32 gsm modem OTA example.

How to request for two different URL from Arduino one after another?

In the following code segment I am obtaining latitude, longitude, time, date and speed using GPS SKG13BL with Arduino UNO and then send it to the database via GSM module at every 5 secs. And if the speed (stored to s) returned by GPS is greater than 0, then an LED glows else will be low. After this code segment I am performing the database insertion by calling a URL. This works fine and obtains the results as I thought.
Code:
#include <NeoSWSerial.h>
//#include <SoftwareSerial.h>
#include <AltSoftSerial.h>
#include <NMEAGPS.h>
NeoSWSerial GSM(2, 3); // RX, TX: Connect TXD to RX & RXD to TX
static const int RXPin = 8, TXPin = 9; //when looking from antenna of gps , Last TTL pin is to be connected to 8 and second one to 9
AltSoftSerial gpsPort(RXPin, TXPin);
static const uint32_t GPSBaud = 9600;
NMEAGPS gps;
gps_fix fix;
uint8_t fixCount = 0;
char dt[15],tm[15],lati[10],longi[10],rno[13]="kl-05-jb-007";
//int block = 0;
enum _parseState {
PS_DETECT_MSG_TYPE,
PS_IGNORING_COMMAND_ECHO,
PS_HTTPPARA_RESPONSE,
PS_HTTPACTION_TYPE,
PS_HTTPACTION_RESULT,
PS_HTTPACTION_LENGTH,
PS_HTTPREAD_LENGTH,
PS_HTTPREAD_CONTENT
};
enum _actionState {
AS_IDLE,
AS_WAITING_FOR_RESPONSE
};
byte actionState = AS_IDLE;
unsigned long lastActionTime = 0;
int s;
byte parseState = PS_DETECT_MSG_TYPE;
char buffer[160],url[160];
byte pos = 0;
int contentLength = 0;
void resetBuffer() {
memset(buffer, 0, sizeof(buffer));
pos = 0;
}
void sendGSM(const char* msg, int waitMs = 500) {
GSM.println(msg);
while(GSM.available()) {
parseATText(GSM.read());
}
//delay(waitMs);
}
void setup()
{
GSM.begin(9600);
Serial.begin(9600);
gpsPort.begin(GPSBaud);
pinMode(13, OUTPUT); //pin 13 to be connected to positive of LED via a resistor
Serial.println(F("Hinder LOADING....."));
Serial.println(F("obtain gps and store data to database"));
Serial.println(F("Testing by : "));
Serial.println(F("Nikhil,Muthumani and Mathews"));
Serial.println();
sendGSM("AT+SAPBR=3,1,\"APN\",\"vodafone\"");
delay(500);
sendGSM("AT+SAPBR=1,1",3000);
delay(500);
sendGSM("AT+HTTPINIT");
delay(500);
sendGSM("AT+HTTPPARA=\"CID\",1");
delay(500);
}
void loop()
{
unsigned long now = millis();
while (gps.available( gpsPort )) {
fix = gps.read();
//Serial.println(F("b"));
// Once every 5 seconds...
if (++fixCount >= 5) {
//Serial.println(F("a"));
displayInfo();
if(s>0) // Change led state when speed greater than 0 or less than 0
digitalWrite(13, HIGH);
else
digitalWrite(13, LOW);
//send the next report if previous one is finished
if ( actionState == AS_IDLE ) {
sprintf(url, "AT+HTTPPARA=\"URL\",\"http://hinder.000webhostapp.com/HInsert.php?rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",rno,lati,longi,s,dt,tm );
sendGSM(url);
// lastActionTime = now;
parseState = PS_HTTPPARA_RESPONSE; // a new state
actionState = AS_WAITING_FOR_RESPONSE;
fixCount = 0;
}
}
}
/* if ((gps.statistics.chars < 10) && (millis() > 5000)) {
Serial.println( F("No GPS detected: check wiring.") );
while(true);
block=1;
}*/
while(GSM.available()) {
//lastActionTime = now;
parseATText(GSM.read());
}
}
void displayInfo()
{
Serial.print(F("Location: "));
if (fix.valid.location) {
dtostrf( fix.latitude(),7,5,lati);
//sprintf(lati,"%d",fix.latitude(),5);
Serial.print(lati);
Serial.print( ',' );
dtostrf( fix.longitude(),8,5,longi);
//sprintf(longi,"%d",fix.longitude(),5);
Serial.print(longi);
} else {
Serial.print(F("INVALID"));
}
Serial.print(F(" Speed: "));
if (fix.valid.speed) {
s=fix.speed_kph();
Serial.print(s);
Serial.print(F(" KMPH "));
} else {
Serial.print(F("INVALID"));
}
// Shift the date/time to local time
NeoGPS::clock_t localSeconds;
NeoGPS::time_t localTime;
if (fix.valid.date && fix.valid.time) {
using namespace NeoGPS; // save a little typing below...
localSeconds = (clock_t) fix.dateTime; // convert structure to a second count
localSeconds += 5 * SECONDS_PER_HOUR + 30 * SECONDS_PER_MINUTE; // shift timezone
localTime = localSeconds; // convert back to a structure
}
Serial.print(F(" Date : "));
if (fix.valid.date) {
sprintf(dt,"%02d/%02d/20%d",fix.dateTime.date,fix.dateTime.month,fix.dateTime.year);
Serial.print(dt);
} else {
Serial.print(F("INVALID"));
}
Serial.print(F(" Time : "));
if (fix.valid.time) {
if (localTime.hours>12)localTime.hours-=12;//To convert 24 hr format to 12 hr format
sprintf(tm,"%02d:%02d:%02d",localTime.hours,localTime.minutes,localTime.seconds);
Serial.print(tm);
//block=1;
} else {
Serial.print(F("INVALID"));
}
Serial.println();
}
void parseATText(byte b) {
buffer[pos++] = b;
if ( pos >= sizeof(buffer) )
resetBuffer(); // just to be safe
/*
// Detailed debugging
Serial.println();
Serial.print("state = ");
Serial.println(state);
Serial.print("b = ");
Serial.println(b);
Serial.print("pos = ");
Serial.println(pos);
Serial.print("buffer = ");
Serial.println(buffer);*/
switch (parseState) {
case PS_HTTPPARA_RESPONSE:
{
parseState = PS_DETECT_MSG_TYPE;
sendGSM("AT+HTTPACTION=0");
/* while(GSM.available()) {
//lastActionTime = now;
parseATText(GSM.read());
}*/
}
break;
case PS_DETECT_MSG_TYPE:
{
if ( b == '\n' )
resetBuffer();
else {
if ( pos == 3 && strcmp(buffer, "AT+") == 0 ) {
parseState = PS_IGNORING_COMMAND_ECHO;
}
else if ( b == ':' ) {
//Serial.print("Checking message type: ");
//Serial.println(buffer);
if ( strcmp(buffer, "+HTTPACTION:") == 0 ) {
Serial.println("Received HTTPACTION");
parseState = PS_HTTPACTION_TYPE;
}
else if ( strcmp(buffer, "+HTTPREAD:") == 0 ) {
Serial.println("Received HTTPREAD");
parseState = PS_HTTPREAD_LENGTH;
}
resetBuffer();
}
}
}
break;
case PS_IGNORING_COMMAND_ECHO:
{
if ( b == '\n' ) {
Serial.print("Ignoring echo: ");
Serial.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPACTION_TYPE:
{
if ( b == ',' ) {
Serial.print("HTTPACTION type is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_RESULT;
resetBuffer();
}
}
break;
case PS_HTTPACTION_RESULT:
{
if ( b == ',' ) {
Serial.print("HTTPACTION result is ");
Serial.println(buffer);
parseState = PS_HTTPACTION_LENGTH;
resetBuffer();
}
}
break;
case PS_HTTPACTION_LENGTH:
{
if ( b == '\n' ) {
Serial.print("HTTPACTION length is ");
Serial.println(buffer);
// now request content
GSM.print("AT+HTTPREAD=0,");
GSM.println(buffer);
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
}
}
break;
case PS_HTTPREAD_LENGTH:
{
if ( b == '\n' ) {
contentLength = atoi(buffer);
Serial.print("HTTPREAD length is ");
Serial.println(contentLength);
Serial.print("HTTPREAD content: ");
parseState = PS_HTTPREAD_CONTENT;
resetBuffer();
}
}
break;
case PS_HTTPREAD_CONTENT:
{
// for this demo I'm just showing the content bytes in the serial monitor
Serial.write(b);
contentLength--;
if ( contentLength <= 0 ) {
// all content bytes have now been read
parseState = PS_DETECT_MSG_TYPE;
resetBuffer();
Serial.print("\n\n\n");
actionState = AS_IDLE;
}
}
break;
}
}
Now I need a modification in this as, when the speed is greater than 0, along with the glowing of the LED, a variable flag (int flag=0; declared globally) is incremented. And flag is set to 0 when the speed is equal to 0. And if the flag value becomes 2 (i.e when speed is greater than 0 for two consecutive readings) I want to send latitude, longitude, date, time and speed at that instant to another database which is also done by calling a URL (url1). And after that I want to send that to the usual database by calling its URL (url).
I did a modification as follows :
if(s>0) // Change led state when speed greater than 0 or less than 0
{
digitalWrite(13, HIGH);
flag++;
}
else
{
digitalWrite(13, LOW);
flag=0;
}
if(flag==2)
{
sprintf(url1, "AT+HTTPPARA=\"URL\",\"http://speed.000webhostapp.com/HInsert.php?rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",rno,lati,longi,s,dt,tm );
sendGSM(url1);
parseState = PS_HTTPPARA_RESPONSE; // a new state
actionState = AS_WAITING_FOR_RESPONSE;
}
This doesn't obtain result as I thought. Can anyone help me. Is it possible to have flag variable working this way in loop(). Is there a problem with my usage of flag or is it another problem.
It is bit tough to make arduino request for two URLs as we would have to handle two separate request and its responses, either the two request would merge in and wont obtain required result or the code would become large that arduino-uno wont be able to handle.
So i found an easy way for doing that, i.e to request for the second PHP page from the first PHP page (which is requested by arduino itself). The only difference between these two request was that the second one need an extra variable. I passed along with the first request so it was available for making request from first page.
I changed arduino code as follows :
First I modified the portion making the check - just after the displayinfo();, as I mentioned in the question, added a flag bit to it. So it become like this :
if(s>0) // s is speed
{
digitalWrite(13, HIGH); //if speed exceeds limit then LED is set to HIGH
flag++;
}
else
{
digitalWrite(13, LOW);
flag=0;
}
The URL for request from arduino was added with the flag variable too. (For the request for second page).
sprintf(url, "AT+HTTPPARA=\"URL\",\"http://hinder.000webhostapp.com/HInsert.php?flag=%d&rno=%s&lat=%s&lng=%s&speed=%d&date=%s&time=%s\"",flag,rno,lati,longi,s,dt,tm );
In the PHP code I added following lines :
if ( $flag == 2 )
{
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://masp203.000webhostapp.com/RTO.php?rno=".$rno."&date=".$date."&time=".$time."&speed=".$speed."&street=".$street."" );
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
This worked just the way I wanted it to be.
Hope this helps some one.

Arduino: If/Else issues

Situation: I have a webpage that has two buttons on it. One sends to the PubNub channel a JSON string of {"lightRight":"1"} and one sends {"lightRight":"0"}, regardless of what I do in the Arduino Sketch I cannot make it into the "on" portion of the void light function.
I know from the serial output of the arduino that I am receiving communication from the web page. If I flip my boolean values to off then I am able to get the "LED HIGH" output but then no longer can I get the "led low".
The code I am trying to adapt can be found here.
https://gist.github.com/ianjennings/ada8fb1a91a486a0c73e
It is very possible I have hacked out to much code from the examples that is why I am including it, but running the stock code I cannot seem to get this to work.
I am not a developer, so I am very sorry if I do not call things as their proper terms. I will learn from correction.
#include <PubNub.h>
#include <SPI.h>
#include <EthernetV2_0.h>
#include <string.h>
#include <Servo.h>
byte mac[] = { MAC was here };
byte gateway[] = { Gate was here };
byte subnet[] = { Sub was here };
IPAddress ip(IP was here);
char pubkey[] = "Key was here";
char subkey[] = "Key was here";
char channel[] = "Channel was here";
int lightRight = 5;
int lightRoom = 6;
int lightGarage = 7;
int i;
EthernetClient *client;
#define W5200_CS 3
#define SDCARD_CS 4
void setup()
{
pinMode(SDCARD_CS,OUTPUT);
digitalWrite(SDCARD_CS,HIGH);
Serial.begin(9600);
Serial.println("Serial set up");
while (!Ethernet.begin(mac)) {
Serial.println("Ethernet setup error");
blink(1000, 999999);
delay(1000);
}
Serial.println("Ethernet set up");
PubNub.begin(pubkey, subkey);
Serial.println("PubNub set up");
pinMode(lightRight, OUTPUT);
pinMode(lightRoom, OUTPUT);
pinMode(lightGarage, OUTPUT);
// blink(100, 5);
reset();
}
//void flash(int ledPin)
//{
// for (int i = 0; i < 3; i++) {
// Serial.println("flash");
// digitalWrite(ledPin, HIGH);
// delay(100);
// digitalWrite(ledPin, LOW);
// delay(100);
// }
//}
void loop()
{
Ethernet.maintain();
PubSubClient *client;
Serial.println("waiting for a message (subscribe)");
client = PubNub.subscribe(channel);
if (!client) {
Serial.println("subscription error");
return;
}
String messages[10];
boolean inside_command = false;
int num_commands = 0;
String message = "";
char c;
while (client->wait_for_data()) {
c = client->read();
if(inside_command && c != '"') {
messages[num_commands] += c;
}
if(c == '"') {
if(inside_command) {
num_commands = num_commands + 1;
inside_command = false;
} else {
inside_command = true;
}
}
message += c;
}
client->stop();
for (i = 0; i < num_commands; i++){
int colonIndex = messages[i].indexOf(':');
String subject = messages[i].substring(0, colonIndex);
String valueString = messages[i].substring(colonIndex + 1, messages[i].length());
boolean value = false;
if(valueString == "1") {
value = true;
}
if(subject == "lightRight") {
light(lightRight, value);
}
if(subject == "lightRoom") {
light(lightRoom, value);
}
if(subject == "lightGarage") {
light(lightGarage, value);
}
if(subject == "blink") {
blink(100, valueString.toInt());
}
Serial.println(subject);
Serial.println(value);
}
Serial.print(message);
Serial.println();
delay(2000);
}
void light(int ledPin, boolean on) {
if(on) {
digitalWrite(ledPin, HIGH);
Serial.println("LED HIGH");
} else {
digitalWrite(ledPin, LOW);
Serial.println("led low");
}
}
void reset() {
Serial.println("Void reset");
light(lightRight, false);
light(lightRoom, false);
light(lightGarage, false);
}
void on() {
Serial.println("Void on");
light(lightRight, true);
light(lightRoom, true);
light(lightGarage, true);
}
void off() {
Serial.println("Void off");
light(lightRight, false);
light(lightRoom, false);
light(lightGarage, false);
}
void blink(int delayn, int count) {
for (int j=0; j <= count; j++){
on();
delay(delayn);
off();
delay(delayn);
}
}
That example expects the PubNub publish to be "lightRight:1" and not {"lightRight": "1"}.

How to get numbers from sd card?

I am bad at coding. I have a file called Test.cal in sd card contained 6 numbers. 20,21,22,23,24,25
But I do not know how to get this six number. Can someone help me ? Below is my own thought about the coding.
#include <SD.h>
float meterTemp[6];
String theLines[15];
File myFile;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(53, OUTPUT);
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// re-open the file for reading:
myFile = SD.open("Test.cal");
if (myFile) {
//I want to put the file numbers into array, meterTemp[6], not inclduing comma, so when I get meterTemp[0]=-32, and so on.
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop()
{
// nothing happens after setup
}
#include <SD.h>
float meterTemp[6];
String theLines;
File myFile;
String filename="Test.cal";
int line=0;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(53, OUTPUT);
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// re-open the file for reading:
myFile = SD.open("Test.cal");
if (myFile) {
Serial.println("test.txt:");
;
// read from the file until there's nothing else in it:
while (myFile.available()) {
Serial.write(myFile.read());
theLines=readFile(filename,line);
Serial.println(theLines);
}
// close the file:
myFile.close();
} else {
// if the file didn't open, print an error:
Serial.println("error opening test.txt");
}
}
void loop()
{
// nothing happens after setup
}
String readFile(String filename, int line)
{
char s[20];
char FileName[sizeof(filename)];
filename.toCharArray(FileName, sizeof(FileName));
File myFile = SD.open(FileName,FILE_READ);
if(myFile)
{
String recived = "";
int cur = 0;
char ch;
while (myFile.available())
{
ch = myFile.read();
if(ch == ',')
{
cur++;
if(cur == line)
{
myFile.close();
return String(recived);
}
}
else
{
recived += ch;
}
}
}
return "";
}
String readFile(String filename, int line)
{
char FileName[sizeof(filename)];
filename.toCharArray(FileName, sizeof(FileName));
File myFile = SD.open(FileName,FILE_READ);
if(myFile)
{
String recived = "";
int cur = 0;
char ch;
while (myFile.available())
{
ch = myFile.read();
if(ch == '\n')
{
cur++;
if(cur == line)
{
myFile.close();
return String(recived);
}
}
else
{
recived += ch;
}
}
}
return "";
}
It is from Arduino Visual code generator.Replace "\n" with your char

Resources