Mantenere dati in memoria NodeMCU ESP8266

Salve, vi chiedo aiuto per un progetto, un contatore di visitatori che mi trasmette anche i dati in rete, questo codice lo trovato in rete e per le mie esigenze funziona più che bene, unico difetto che non sono riuscito a modificare per il mio scopo è quello che non mantiene i dati in memoria; esempio se conta 10 visitatori e nel frattempo va via l'alimentazione oppure il segnale internet mi si azzera, volevo far si che mantiene i dati in memoria finchè non sono io a volerli resettare dal pulsante reset della scheda oppure creando un pulsante apposito per il reset, cosi avrò sempre i dati in memoria e avrò su internet anche un grafico con la percentuale di visite in ingresso e uscita. allego lo sktch grazie a chiunque può dedicarmi 1 minuto per aiutarmi.
(premetto che con la programmazione sono quasi a 0 tutto quello che riesco a fare è per pura passione e hobby)

#include "UbidotsESPMQTT.h"
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
 
#define TOKEN "*********************************" // Your Ubidots TOKEN
#define WIFINAME "************" //Your SSID
#define WIFIPASS "*************" // Your Wifi Pass
 
#define SCREEN_WIDTH 128    // OLED display width, in pixels
#define SCREEN_HEIGHT 64    // OLED display height, in pixels
#define OLED_RESET -1       // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
#define inSensor 14
#define outSensor 12
 
#define relay 0
 
int inStatus;
int outStatus;
 
int countin = 0;
int countout = 0;
 
int in;
int out;
int now;
 
Ubidots client(TOKEN);
 
void callback(char* topic, byte* payload, unsigned int length)
{
  Serial.print("Message arrived [");
  Serial.print(topic);
  Serial.print("] ");
  for (int i = 0; i < length; i++)
  {
    Serial.print((char)payload[i]);
  }
  Serial.println();
}
 
 
void setup()
{
  client.setDebug(true); // Pass a true or false bool value to activate debug messages
  Serial.begin(115200);
  client.wifiConnection(WIFINAME, WIFIPASS);
  client.begin(callback);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //initialize with the I2C addr 0x3C (128x64)
 
  pinMode(inSensor, INPUT);
  pinMode(outSensor, INPUT);
  pinMode(relay, OUTPUT);
  digitalWrite(relay, HIGH);
 
  Serial.println("Visitor Counter Demo");
  display.clearDisplay();
  display.setTextSize(2);
  display.setTextColor(WHITE);
  display.setCursor(20, 20);
  display.print("Visitor");
  display.setCursor(20, 40);
  display.print("Counter");
  display.display();
  delay(3000);
 
 
}
 
void loop()
{
  if (!client.connected())
  {
    client.reconnect();
  }
 
  inStatus =  digitalRead(inSensor);
  outStatus = digitalRead(outSensor);
  if (inStatus == 0)
  {
    in = countin++;
  }
 
  if (outStatus == 0)
  {
    out = countout++;
  }
 
  now = in - out;
 
  if (now <= 0)
  {
    digitalWrite(relay, HIGH);
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(0, 15);
    display.print("No Visitor");
    display.setCursor(5, 40);
    display.print("Light Off");
    display.display();
    Serial.println("No Visitors! Light Off");
    delay(500);
  }
  else
  {
    digitalWrite(relay, LOW);
 
    display.clearDisplay();
    display.setTextColor(WHITE);
 
    display.setTextSize(1);
    display.setCursor(15, 0);
    display.print("Current Visitor");
    display.setTextSize(2);
    display.setCursor(50, 15);
    display.print(now);
 
    display.setTextSize(1);
    display.setCursor(0, 40);
    display.print("IN: ");
    display.print(in);
 
    display.setTextSize(1);
    display.setCursor(70, 40);
    display.print("OUT: ");
    display.print(out);
 
    display.display();
 
    Serial.print("Current Visitor: ");
    Serial.println(now);
    Serial.print("IN: ");
    Serial.println(in);
    Serial.print("OUT: ");
    Serial.println(out);
    delay(500);
  }
  int relaystatus = digitalRead(relay);
  client.add("in", in);
  client.add("out", out);
  client.add("now", now);
  client.add("Light Status", relaystatus);
  client.ubidotsPublish("ESP8266");
  client.loop();
  Serial.println();
  delay(100);
}

Gli ESP8266 NON sono dotati di una EEPROM (che, comunque, NON può essere aggiornata in continuazione perché, queste memorie riscrivibili, hanno comunque un numero di cicli di scrittura limitato) per cui occorre usare altre tecniche ...

... se NON scrivi in continuazione puoi o utilizzare una parte della Flash del ESP dedicandola al FileSystem LittleFS oppure cercare qualche libreria che simula una EEPROM nella flash ... però ribadisco ... il numero di scritture della Flash è abbastanza limitato (credo, nel caso del ESP, massimo 100'000 scritture) prima che si danneggi e NON pensare quindi di potre scrivere in continuazione.

Se ti serve scrivere in continuazione ti serve usare un supporto esterno ... o un chip di memoria dedicato (FRAM, NVSRAM, ecc) o ... un banale modulo RTC con il DS1307 che ha una parte di RAM (quindi ci scrivi e leggi quanto ti pare) che è alimentata dalla batteria del RTC e che conserva le informazioni anche in caso di mancanza di alimentazione primaria.

Guglielmo

in casa mi trovo il modulo tiny rtc i2c credo che possa andare bene?, ma non saprei proprio come aggiungerlo allo sktch

Si, credo che quel modulo sia basato sul DS1307 che mette a disposizione 56 bytes di memoria RAM non volatile (grazie alla batteria che deve essere presente).

Per aggiungerlo al tuo programma dovrai decidere COSA salvare, QUANDO salvare e poi collegare il modulo sul bus I2C ed usare magari una libreria per la sua gestione ... ad esempio la libreria RTClib di Adafruit, tra i cui esempi ne trovi propio uno che si chiama "ds1307nvram" e che mostra l'utilizzo della libreria per salvare e leggere dati dalla memoria RAM non volatile del DS1307.

Guglielmo

ho aggiungere la libreria, e ho visto anche l'esempio "ds1307nvram", ma sono comunque in alto mare perchè non so dove collegare sul Nodemcu i pin SCL - SDA del modulo, e non so come aggiungere le line di codice allo sktch; le cose da salvare che mi interessano che non vadano cancellate sono in e out degli ingressi che devono essere aggiornate continuamente e salvate.

ciao...la faccio semplice...ti crei due funzioni...una lettura ed una scrittura; quella di lettura la richiami quando necessario (su comando seriale, su pressione pulsante etc) quella in scrittura dopo aver letto tutti gli ingressi ed impostato tutte le uscite che ti interessano....

Questi i pin normalmente utilizzabili del ESP8266 ...

Guglielmo

il problema è che i pin D1 e D2 sono già usati dal display

... ovvio, è un BUS I2C ... sarà il caso che ti leggi un tutorial su come funziona il bus I2C ... QUI. :roll_eyes:

Guglielmo

quindi posso collegare insieme il display e il modulo rtc? usando i stessi pin

Se hai studiato quel tutorial avrai capito che puoi collegarci quanti dispositivi vuoi (nei limiti del bus I2C), purché ciascun dispositivo abbia un "indirizzo" differente.

I display OLED da 0.96" hanno normalmente indirizzo 0x3C mentre i DS1307 hanno normalmente indirizzo 0x68.

Guglielmo

si mi è più chiaro, purtroppo non posso mettermi a studiare perchè nella vita faccio tutt’altro e sono tutto il giorno impegnato, come ripeto è un hobby e lo sempre coltivato da autodidatta, anche se per quanto riguarda la programmazione purtroppo sono a 0 non è facile capire quando non c'è nessuno che te lo spiega, soprattutto questo tipo di argomenti, ma comunque amo fare dei piccoli progetti e cimentarmi nel realizzare dispositivi elettronici che mi servono, magari trovando sktch già pronti su internet e modificarli quando serve ma in minima parte anche perchè grandi modifiche non so farle :slight_smile: quindi ringrazio chiunque vorrà aiutarmi modificandomi lo sktch (anche perchè da solo non so dove mettere mano) e insieme magari riusciremo nel mio intento, altrimenti vi ringrazio comunque per il tempo che mi avete dedicato finora.

Comincia con il chiartiti quello che ti ho già chiesto ...

... una volta che ti sarai chiarito questo potrai proseguire con il mettere le mani nel codice. :wink:

Guglielmo

credo che bisogna salvare i valori letti da queste due line
#define inSensor 14
#define outSensor 12
che sarebbero in e out; e quando salvarli credo bisogna salvarli in continuazione cosi da mantenere sempre i valori reali in memoria

Non ci siamo capiti ...

COSA = quali sono le variabili esatte che vuoi salvare, QUANDO = la condizione nel programma di quando salvarle (il punto del programma in cui necessita fare il salvataggio) ... se non riesci ad identificare queste cose ... è un problema ... :roll_eyes:

Guglielmo

faccio davvero fatica a comprendere perchè per me sono cose che non conosco, io più che chiedere un aiuto nel modificare lo sktch e farvi capire cosa voglio fare, più di questo non riesco, me la cavo nella parte dell'elettronica collegamenti ecc, ma con il codice sono a 0 altrimenti non chiedevo un aiuto sul forum, e spero che in tutto il forum qualcuno che sappia dove e quali mettere di varianti ci sarà perchè io non lo so :sweat_smile:, se c'è qualcuno che riesce a perdere 10 minuti per questo sktch ne sarei davvero felice :slightly_smiling_face: altrimenti vi ringrazio comunque ma credo sia inutile continuare perchè non ci stò capendo niente :face_with_spiral_eyes:

Emmm ... ma lo hai letto bene il REGOLAMENTO, al punto 16.1 ?

Tenete sempre presente che qui sul forum nessuno scrive software per conto terzi o realizza schemi su ordinazione, ma si aiuta chi viene qui a correggere/ottimizzare il software che lui scrive o gli schemi che lui realizza .

Insomma, noi possiamo aiutare, ma l'utente DEVE fare lo sforzo di trovare il tempo di studiare almeno le basi ... nel punto 16.1 sono elencati una serie di pdf ed un ottimo libro ... purtroppo, se è una passione, il tempo occorre dedicarcelo ... altrimenti che passione è ???

Guglielmo

Ciao.
Nello sketch ci sono 3 variabili:
in = dovrebbero essere gli ingressi
out = dovrebbero essere le uscite
now = per differenza dovrebbero essere le presenze
Il COSA sono queste 3 variabili, o forse solo l'ultima (decidi tu).
Per il QUANDO direi che potrebbe andare bene il punto in cui invii i dati al server (terzultima istruzione dello sketch).
Questo può essere un punto di partenza.
Non ho sottomano la libreria del DS... Partendo da quella trova le istruzioni che salvano e leggono in memoria. Poi inserirle nello sketch è il meno.

ciao, la variabile now dovrebbe essere quella cerchiata nella foto; a me interessa salvare in e out, e vorrei che in caso di interruzione dell'alimentazione oppure in assenza di internet, alla prima riconnessione a internet aggiorna i dati sul server, perchè cosi com'è mi ritorna sempre a 0
Senza titol0o

Ok, il COSA adesso è chiaro (in e out).
Il QUANDO è altrettanto chiaro:

  • salvi quando invii i dati
  • leggi una volta alla fine del setup() e dentro la prima if dopo il reconnect()

Manca il COME. Hai guardato nell'esempio del DS come salvano e leggono le info?