Comportamento anomalo sketch

ciao
sono in laboratorio cercando di fare un upgrade software e hardware di un datalogger che riceve dati via radio con un HC12
ci sono un trasmettitore di temperatura e un ricevitore lato ricevitore mi sono imbattuto in questo problema dove il setup viene continuamente ripetuto
questo il ricevitore

//data 220721
//master
//per ricezione dati htu21d + termocoppia K

//from termometri distribuiti >> unità centrale memorizza

#include <SPI.h>
//#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 32 // OLED display height, in pixels
#define OLED_RESET     4 // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

// libreries
//-------------------------------HC12 radio
#include <SoftwareSerial.h>
const byte HC12RxdPin = 2;                      // "RXD" Pin on HC12
const byte HC12TxdPin = 3;                      // "TXD" Pin on HC12
const byte HC12SetPin = 6;                      // "SET" Pin on HC12
SoftwareSerial Radio_HC12(HC12TxdPin, HC12RxdPin); // RX nano to HC-12 TX Pin, TX nano to HC-12 RX Pin

char SLAVE_START;//carattere di start codice stazione SLAVE
char MASTER_START;//carattere di start stazione MASTER
char END;// carattere di end trasmissione
char rx;
byte index;
int const maxdim = 36;
char stringa[maxdim];

//-------------------per la parte orologio RTC
#include <Wire.h>
#include <TimeLib.h>
#include <DS1307RTC.h>

//---------------------Scheda SD
#include <SPI.h>
#include <SD.h>
byte chipSDSelect;
File datafile;

char logfile; // contenitore per nome file di log

byte sensorNumTot;
char id_sensor[8];//vettore codice stazione aggiungere le stazioni se serve

byte i, j;//contatori

//sezione delay con millis()
unsigned long previousMillis;        // will store last time LED was updated
unsigned long currentMillis;
long interval;

void setup()
{
  Serial.begin(9600);                       // Open serial port to computer
  Wire.begin();

//  //--------------------SSD1306 sezione oled
//  // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
//  if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) 
//  {
//    Serial.println(F("SSD1306 allocation failed"));
//    for (;;); // Don't proceed, loop forever
//  }
//  //Show initial display buffer contents on the screen --
//  // the library initializes this with an Adafruit splash screen.
//  display.display();
//  delay(2000); // Pause for 2 seconds
//
//  //Clear the buffer
//  display.clearDisplay();
//  display.display();
//  delay(2000);

  //------------------------HC12
  Radio_HC12.begin(9600);// Open serial port to HC12
  pinMode(HC12SetPin, OUTPUT);
  digitalWrite(HC12SetPin, HIGH);
  delay(500);
  Serial.println("HC12 ready:");

  //------------------------Scheda SD
  chipSDSelect = 5;
  pinMode(chipSDSelect, OUTPUT);
  Serial.println("Initializing SD card...");
  
//--------------------------led allarm
  pinMode(7, OUTPUT);// led card not present
  pinMode(8, OUTPUT);// led no RTC
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);

  if (!SD.begin(chipSDSelect))// see if the card is present and can be initialized:
  {
    Serial.println("Card failed, or not present 01");// don't do anything more
    digitalWrite(7, HIGH);
    while (1);
  }
  Serial.println("SD card initialized.");

  logfile = "datalog.txt"; // contenitore per nome file di log

  SLAVE_START = '<';  //carattere inizio trasmissione stazione SLAVE
  MASTER_START = '#'; //carattere di start stazione MASTER
  END = '>';          // carattere di end trasmissione

  sensorNumTot = 3;

  id_sensor[0] = SLAVE_START; //carattere inizio trasmissione stazione SLAVE
  id_sensor[1] = 'a'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[2] = 'b'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[3] = 'c'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[4] = 'd'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[5] = 'e'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[6] = END; //caratte fine trasmissione
  id_sensor[7] = '\0'; //carattere null

  Serial.println(id_sensor);

  // id_sensor[8] = {SLAVE_START, '1', '2', '3', '4', '5', END, '\0'};

  // riceve e tratta i dati dalla radio
  char stringa[maxdim] = {0}; //il buffer di appoggio della trasmissione
  byte index = 0;

  interval = 3000;//millis intervallo delle interrogazioni delle stazioni
  //120000 = 6 min
  //100000 = 5 min
  //140000 = 7 min
  //80000 = 4 min

  previousMillis = 0;
  i = 0;
  rx = {0};
  index = 0;

  delay(1000);
}

void loop()
{
  currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    i++;
    Serial.print(id_sensor[0]);       // carattere di start codice stazione SLAVE
    Serial.print(id_sensor[i]);       //codice stazione TU
    Serial.println(id_sensor[6]);     // carattere di end trasmissione

    previousMillis = currentMillis;   // save the last time
    //-------------------send to TX
    Radio_HC12.print(id_sensor[0]);   // carattere di start codice stazione SLAVE
    delay(5);
    Radio_HC12.print(id_sensor[i]);   //codice stazione TU
    delay(5);
    Radio_HC12.println(id_sensor[6]); // carattere di fine trasmissione

    if (i == sensorNumTot)
    {
      i = 0;
    }
  }
  //--------------------receive from TX
  while (Radio_HC12.available())
  {
    rx = Radio_HC12.read(); //sono sicuro che esista un carattere dal leggere, altrimenti non sarebbe stata chiamata

    if (rx == MASTER_START)//carattere inizio trasmissione da TX
    {
      //      Serial.println("inizio RX");
      index = 1;
      stringa[0] = rx;//contiene il carattere start dalla TX
      return;
    }

    if (index > 0 && index < maxdim-2)
    {
      stringa[index++] = rx;
    }
  }//parentesi aggiunta
  
//-------------------------------write SD
  if (rx == END)
  {
    datafile = SD.open("datalog.txt", FILE_WRITE);    //apre file

    //    Serial.print("sizeof(stringa)");
    //    Serial.println(sizeof(stringa));

    if (datafile)   //if the file is available, write to it:
    {
      digitalWrite(7, LOW);   // turn the LED OFF
      //   Serial.println("scrivo su file data ora e dati");
      tmElements_t tm;

      //-----------------------RTC
      if (RTC.read(tm))
      {
        digitalWrite(8, LOW);   // turn the LED OFF
        if (tm.Hour < 10)       //scrive ora
        {
          datafile.print('0');
        }
        datafile.print(tm.Hour);
        datafile.print(':');    //separatore

        if (tm.Minute < 10)     //scrive minuto
        {
          datafile.print('0');
        }
        datafile.print(tm.Minute);
        datafile.print(':');    //separatore

        if (tm.Second < 10)     //scrive secondo
        {
          datafile.print('0');
        }
        datafile.print(tm.Second);
        datafile.print(' ');    //separatore

        datafile.print(tm.Day);                   //scrive giorno
        datafile.print('/');                      //separatore
        datafile.print(tm.Month);                 //scrive mese
        datafile.print('/');                      //separatore
        datafile.print(tmYearToCalendar(tm.Year));//scrive anno

        datafile.print(',');//separatore

        datafile.println(stringa);//scrive stringa dati da stazione TX

        datafile.close();//chiude file

        Serial.println(stringa);    //scrive stringa sulla seriale per controllo

        //-------------------------sezione oled
        display.clearDisplay();
        display.setTextSize(1);      // Normal 1:1 pixel scale
        display.setTextColor(SSD1306_WHITE); // Draw white text
        display.setCursor(0, 0);     // Start at top-left corner

        display.print(stringa[25]);
        display.print(stringa[26]);
        display.print(stringa[27]);
        display.print(stringa[28]);
        display.print(stringa[29]);
        display.print(stringa[30]);
        display.print(stringa[31]);
        display.println();

        display.display();
        delay(2000);
      }
      else
      {
        digitalWrite(8, HIGH);   // turn the LED on (HIGH is the voltage level)

        if (RTC.chipPresent())
        {
          Serial.println("The DS1307 is stopped.  Please run the SetTime");
          Serial.println("example to initialize the time and begin running.");
          Serial.println();
          digitalWrite(8, HIGH);
        }
        else
        {
          Serial.println("DS1307 read error!  Please check the circuitry");
          Serial.println();
          digitalWrite(8, HIGH);
        }
      }
    }
    else
    {
      Serial.println("Card failed, or not present 02");// don't do anything more
      digitalWrite(7, HIGH);   // turn the LED on
    }
  }
}

questo l output

SD card initialized.
<abcde>
<a>
#a,HC12 ready:
Initializing SD card...
SD card initialized.
<abcde>
<a>
#a⸮HC12 ready:
Initializing SD card...
SD card initialized.
<abcde>
<a>
#a,HC12 ready:
Initializing SD card...
SD card initialized.
<abcde>
<a>
#a,HC12 ready:
Initializing SD card...
SD card initialized.
<abcde>
<a>
#a⸮HC12 ready:
Initializing SD card...
SD card initialized.

questo il messaggio al termine dell upload

Sketch uses 23070 bytes (75%) of program storage space. Maximum is 30720 bytes.
Global variables use 1634 bytes (79%) of dynamic memory, leaving 414 bytes for local variables. Maximum is 2048 bytes.
Low memory available, stability problems may occur.

grazie per ogni suggerimento

... te lo dice pure ... sicuramente, come comincia a girare, cerca di allocare dinamicamente memoria (quella indicata è solo quella statica fissa ad inizio programma) e, non trovandola, va in crash e riparte.

O modifichi il programma per usare meno memoria (e la vedo dura usando delle SD) o ... cambi MCU e passi su qualche cosa con più SRAM.

Guglielmo

ciao
grazie
si immaginavo fosse quello il problema :face_with_diagonal_mouth: ma non sapevo come risolvere
ho trovato integrati che aumentano la SRAM
vedo di studiarli

... infatti ho scritto che devi cambiare MCU e non rimanere sul ATmega328P.

Se vuoi avere la quasi piena compatibilità, potresti provare la "Pro Midi 1284P" distribuita da Futura ed hai una scheda AVR che ha 128K di flash e ben 16 KB di SRAM.

Altrimenti ti sposti sulle Arduino MKR (occhio che lavorano a 3.3V) e su ATSAMD21(256KB di flash e 32KB di SRAM).

Guglielmo

Visto che per il display usi solo testo, prova ad usare la libreria U8x8 che non usa un buffer e quindi risparmia circa 1K di memoria, che non è poco.

Ciao, Ale.

Potrebbe essere un'idea :slight_smile: ... ma allora userei la ancora più semplice e compatta "SSD1306Ascii" ... rigorosamente SOLO testo :wink:

Guglielmo

@gpb01 @ilguargua
grazie per i suggerimenti
ho una mkr0 ma mi devo studiare come interfacciare l HC12
oled non faccio grafica solo numeri provo la libreria suggerita

Non dovresti aver problema ... l'HC12 lavora da 3.2V a 5.5V ... almeno da datasheet:
HC-12 english datasheets.pdf (528.4 KB)

Guglielmo

ciao grazie per le librerie
adesso lo sketch gira anche se ho ancora un problema di memoria
Adesso il problema è il collegamento su I2C dell OLED (0x3c) e del RTC (0x68) con un programma di scansione vedo solo l'OLED

Ciao
Un aggiornamento
Comprato e collegato uno schermo OLED SPI ma non visualizzo niente
Collegamenti ricontrollati, cercato in rete dove vedo che la chiamata agli slave OLED e SD è fatta dal pin CS.
Ho provato anche a caricare un semplice programma per il solo OLED ma non funziona, il fatto è che se sposto l'OLED su un'altra scheda e con lo stesso programma l'OLED funziona.
Non so cosa pensare

... che i collegamenti sono sbagliati ... metti lo schma dei collegamenti che stai usando e ... comunque NON capisco perché usare un OLED SPI invece che I2C ... cercando di aggirare i problemi invece che capirli e risolverli !

Guglielmo

ciao
Difficile fare una foto ci sono tanti fili
Ho ricontrollato i collegamenti + di una volta e sono corretti ho seguito il pinout della nano fornito dal sito
La compilazione da sempre un avviso di bassa memoria rimanente forse è questo
Sono passato ad un SPI perchè caricando lo sketch di uno scanner I2C vedo solo l'OLED ma non la SD
Comunque adesso come suggerito sto provando a passare alla MKR0 ma incontro questo errore

Arduino: 1.8.19 (Windows 10), Board: "Arduino MKRZERO"
RX_mkr0_K_hc12_HTU21D_oled:19:10: fatal error: SoftwareSerial.h: No such file or directory

 #include <SoftwareSerial.h>

          ^~~~~~~~~~~~~~~~~~

compilation terminated.

exit status 1

SoftwareSerial.h: No such file or directory

This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

lo sketch

//data 220721
//master con mkr0
//per ricezione dati htu21d + termocoppia K 
//comunicazione con HC12
//memorizza su SD

//from termometri distribuiti >> unità centrale memorizza

#include <SPI.h>  // SD
#include <Wire.h> // OLED I2C, RTC DS1307

//--------------------------OLED I2C
//#include <Wire.h>
#include "SSD1306Ascii.h"
#include "SSD1306AsciiWire.h"
#define I2C_ADDRESS 0x3C  // 0X3C+SA0 - 0x3C or 0x3D
#define RST_PIN -1        // Define proper RST_PIN if required
SSD1306AsciiWire oled;    //nome display

//-------------------------------HC12 radio
#include <SoftwareSerial.h>
const byte HC12RxdPin = 2;                      // "RXD" Pin on HC12
const byte HC12TxdPin = 3;                      // "TXD" Pin on HC12
const byte HC12SetPin = 6;                      // "SET" Pin on HC12
SoftwareSerial Radio_HC12(HC12TxdPin, HC12RxdPin); // RX nano to HC-12 TX Pin, TX nano to HC-12 RX Pin

char SLAVE_START;//carattere di start codice stazione SLAVE
char MASTER_START;//carattere di start stazione MASTER
char END;// carattere di end trasmissione
char rx;
byte index;
int const maxdim = 36;
char stringa[maxdim];

//-------------------orologio RTC DS1307
#include <TimeLib.h>
#include <DS1307RTC.h>

//---------------------Scheda SD
#include <SD.h>
const int chipSelect = SDCARD_SS_PIN;//board mkr0
//byte chipSDSelect; //board nano
File datafile;

char logfile; // contenitore per nome file di log

byte sensorNumTot;
char id_sensor[8];//vettore codice stazione aggiungere le stazioni se serve

byte i, j;//contatori

//sezione delay con millis()
unsigned long previousMillis;        // will store last time LED was updated
unsigned long currentMillis;
long interval;

void setup()
{
  Serial.begin(9600);                       // Open serial port to computer
  Wire.begin();
delay(500);
  //-----------------------OLED I2C
  Wire.setClock(400000L);
#if RST_PIN >= 0
  {
    oled.begin(&Adafruit128x64, I2C_ADDRESS, RST_PIN);
  }
#else // RST_PIN >= 0
  {
    oled.begin(&Adafruit128x64, I2C_ADDRESS);
  }
#endif // RST_PIN >= 0

  //-------------------OLED set font
  oled.setFont(Adafruit5x7);
  //  oled.set2X();
  // oled.set2X();

  //------------------------HC12
  Radio_HC12.begin(9600);// Open serial port to HC12
  pinMode(HC12SetPin, OUTPUT);
  digitalWrite(HC12SetPin, HIGH);
  delay(500);
  Serial.println("HC12 ready:");

  //------------------------Scheda SD
  //  chipSDSelect = 5;
  //  pinMode(chipSDSelect, OUTPUT);
  Serial.println("Initializing SD card...");

  //--------------------------led allarm
  pinMode(7, OUTPUT);// led card not present
  pinMode(8, OUTPUT);// led no RTC
  digitalWrite(7, LOW);
  digitalWrite(8, LOW);

  Serial.println("initialing SD card...");
  if (!SD.begin(chipSelect))// see if the card is present and can be initialized:
  {
    Serial.println("Card failed, or not present...");// don't do anything more
    digitalWrite(7, HIGH);
    while (1);
  }
  Serial.println("SD card initialized...");

  logfile = "datalog.txt"; // contenitore per nome file di log

  SLAVE_START = '<';  //carattere inizio trasmissione stazione SLAVE
  MASTER_START = '#'; //carattere di start stazione MASTER
  END = '>';          // carattere di end trasmissione

  sensorNumTot = 3;

  id_sensor[0] = SLAVE_START; //carattere inizio trasmissione stazione SLAVE
  id_sensor[1] = 'a'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[2] = 'b'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[3] = 'c'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[4] = 'd'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[5] = 'e'; //aggiungere le stazioni se serve e aggiornare indice vettore
  id_sensor[6] = END; //caratte fine trasmissione
  id_sensor[7] = '\0'; //carattere null

  Serial.println(id_sensor);

  // id_sensor[8] = {SLAVE_START, '1', '2', '3', '4', '5', END, '\0'};

  // riceve e tratta i dati dalla radio
  char stringa[maxdim] = {0}; //il buffer di appoggio della trasmissione
  byte index = 0;

  interval = 3000;//millis intervallo delle interrogazioni delle stazioni
  //120000 = 6 min
  //100000 = 5 min
  //140000 = 7 min
  //80000 = 4 min

  previousMillis = 0;
  i = 0;
  rx = {0};
  index = 0;

  delay(1000);
}

void loop()
{
  currentMillis = millis();

  if (currentMillis - previousMillis >= interval)
  {
    i++;
    Serial.print(id_sensor[0]);       // carattere di start codice stazione SLAVE
    Serial.print(id_sensor[i]);       //codice stazione TU
    Serial.println(id_sensor[6]);     // carattere di end trasmissione

    previousMillis = currentMillis;   // save the last time
    //-------------------send to TX
    Radio_HC12.print(id_sensor[0]);   // carattere di start codice stazione SLAVE
    delay(5);
    Radio_HC12.print(id_sensor[i]);   //codice stazione TU
    delay(5);
    Radio_HC12.println(id_sensor[6]); // carattere di fine trasmissione

    if (i == sensorNumTot)
    {
      i = 0;
    }
  }
  //--------------------receive from TX
  while (Radio_HC12.available())
  {
    rx = Radio_HC12.read(); //sono sicuro che esista un carattere dal leggere, altrimenti non sarebbe stata chiamata

    if (rx == MASTER_START)//carattere inizio trasmissione da TX
    {
      //      Serial.println("inizio RX");
      index = 1;
      stringa[0] = rx;//contiene il carattere start dalla TX
      return;
    }

    if (index > 0 && index < maxdim - 2)
    {
      stringa[index++] = rx;
    }
  }//parentesi aggiunta

  //-------------------------------write SD
  if (rx == END)
  {
    datafile = SD.open("datalog.txt", FILE_WRITE);    //apre file

    //    Serial.print("sizeof(stringa)");
    //    Serial.println(sizeof(stringa));

    if (datafile)   //if the file is available, write to it:
    {
      digitalWrite(7, LOW);   // turn the LED OFF
      //   Serial.println("scrivo su file data ora e dati");
      tmElements_t tm;

      //-------------------orologio RTC DS1307
      if (RTC.read(tm))
      {
        digitalWrite(8, LOW);   // turn the LED OFF
        if (tm.Hour < 10)       //scrive ora
        {
          datafile.print('0');
        }
        datafile.print(tm.Hour);
        datafile.print(':');    //separatore

        if (tm.Minute < 10)     //scrive minuto
        {
          datafile.print('0');
        }
        datafile.print(tm.Minute);
        datafile.print(':');    //separatore

        if (tm.Second < 10)     //scrive secondo
        {
          datafile.print('0');
        }
        datafile.print(tm.Second);
        datafile.print(' ');    //separatore

        datafile.print(tm.Day);                   //scrive giorno
        datafile.print('/');                      //separatore
        datafile.print(tm.Month);                 //scrive mese
        datafile.print('/');                      //separatore
        datafile.print(tmYearToCalendar(tm.Year));//scrive anno

        datafile.print(',');//separatore

        datafile.println(stringa);//scrive stringa dati da stazione TX

        datafile.close();//chiude file

        Serial.println(stringa);    //scrive stringa sulla seriale per controllo

        //-------------------------sezione oled
        display.clearDisplay();
        display.setTextSize(1);      // Normal 1:1 pixel scale
        display.setTextColor(SSD1306_WHITE); // Draw white text
        display.setCursor(0, 0);     // Start at top-left corner

        display.print(stringa[25]);
        display.print(stringa[26]);
        display.print(stringa[27]);
        display.print(stringa[28]);
        display.print(stringa[29]);
        display.print(stringa[30]);
        display.print(stringa[31]);
        display.println();

        display.display();
        delay(2000);
      }
      else
      {
        digitalWrite(8, HIGH);   // turn the LED on (HIGH is the voltage level)

        if (RTC.chipPresent())
        {
          Serial.println("The DS1307 is stopped.  Please run the SetTime");
          Serial.println("example to initialize the time and begin running.");
          Serial.println();
          digitalWrite(8, HIGH);
        }
        else
        {
          Serial.println("DS1307 read error!  Please check the circuitry");
          Serial.println();
          digitalWrite(8, HIGH);
        }
      }
    }
    else
    {
      Serial.println("Card failed, or not present 02");// don't do anything more
      digitalWrite(7, HIGH);   // turn the LED on
    }
  }
}

NON c'è la SoftwareSerial, devi definire tu una nuova porta seriale usando SERCOM ... studiati QUESTO tutorial e poi QUESTO (devi essere registrato sul sito di Adafruit).

Guglielmo

... e mi sembra anche normale! Il display OLED SSD1306 è un display I2C, le SD sono delle unità che funzionano sul bus SPI quindi NON puoi sperare di vedere le SD sul I2C ... :roll_eyes:

Ma dedicare un po' di tempo a studiare i vari bus ed a capire come funzionano ... no ???

Guglielmo

Tutorial SPI: QUESTO e QUESTO

Tutorial I2C: QUESTO e QUESTO

Buono studio!

Guglielmo

ciao
hai ragione è l RTC che non vedo con lo scanner I2C
collegamenti ricontrollati + volte ma con la nano il display non funziona
anche la mkr0 il display OLED I2C o SPI da solo non funzionano, provato anche un LCD i2c niente,
smonto tutto e ricomincio da capo

Le resistenze di pull-up, sul bus I2C, ci sono? L'alimentazione dei moduli? fai uno schema dei collegamenti che stai facendo ...

Guglielmo

ciao
Un aggiornamento
Provato singolarmente OLED SPI funziona mentre OLED I2C no probabilmente bruciato durante i precedenti test, LCD I2C funziona
Rimontato tutto e OLED SPI +SD non funziona, le librerie suggerite hanno migliorato la quantità di memoria disponibile, ma non abbastanza probabilmente il problema di memoria segnalato in compilazione influenza
Domanda come faccio a collegare un HC12 ad un MKR0? ho cercato in rete ma non ho trovato schemi

grazie

Hai studiato come creare una seconda seriale con SERCOM? ... una volta che hai la seconda seriale il HC-12 lo colleghi come su qualsiasi altro Arduino ... t'ho già allegato il datasheet (post #9) e puoi vedere che lavora da 3.2V a 5.5V.

Guglielmo

P.S.: ma lo schema dei collegamenti dov'è???

ciao
Domani posto schema
Si ho letto la SERCOM ma la devo rileggere non ci ho capito molto
Hc12 conosco e gia
Grazie