strano blocco dell'esecuzione del codice

ciao a tutti, vi scrivo perchè ho riscontrato un problema strano nel mio progetto da portare
in maturità, in pratica si tratta di una mini serra con il controllo di temperatura e luminosità
e un servo che va a fare dell’ombra alle piante quando la luminosità inizia ad aumentare troppo.
il codice funziona bene fino a quando non gli apro la porta seriale e gli do il comando “d” per
attivare il debug errori, appena provo mi blocca l’esecuzione dell’intero programma( non aggiorna
nemmeno più l’lcd) e non capisco il motivo, a me non sembra ci sia nulla di sbagliato, vi lascio guardare a voi
(lo sketch è 26.322 byte una volta compilato)

/* pin utilizzati arduino uno
A0 --> trasduttore luminosità
4 --> selezione sdcard(CS)
5 --> servomotore
11, 12, 13 --> sdcard
sul bus i2c:
- lcd 20x4
- rtc
- mcp9808
*/


#include <Wire.h>
#include "RTClib.h"
#include <SD.h>
#include <Servo.h>
#include "Adafruit_MCP9808.h"
#include <LiquidCrystal_I2C.h>
#define CS 4

int input_carattere;
int pin_lux = A0;
byte pin_servo= 5;
byte pin_backlight= 10;
byte servo_angolo, servo_percentuale;
float rawRange = 1024; // 3.3v
float logRange = 5.0; // 3.3v = 10^5 lux
int old_valore_grezzo = 0;
long previousMillis = 0;  
long interval = 10000; // variabile utilizzata per aggiornare 
                       // dati su sd e posizione servo
boolean avvio_servo = false, avvio_sd = false, debug = false;

/* inizializzazione varie librerie  */
RTC_DS1307 rtc;
Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);
Servo myservo;


char buffer_lcd[50];
char buffer_sd[60];
char buffer_temp[10];
char buffer_lux[20];
 
void setup () {
    
    Serial.begin(9600); // inizializzo libreria per la comunicazione con la porta seriale
    analogReference(EXTERNAL);
    pinMode(pin_backlight, OUTPUT);
    myservo.attach(pin_servo);
    myservo.write(0);
    Wire.begin(); // inizializzo libreria per la comunicazione I2C
    rtc.begin(); // inizializzo libreria per la comunicazione con l'RTC
    lcd.begin(20,4); // inizializzo libreria per la comunicazione con il display 20x4
    pinMode(CS, OUTPUT);
    pinMode(10, OUTPUT);
    
    
    lcd.setCursor(0,0);
    lcd.print("Inizializzo SDcard");
    lcd.setCursor(0,1);
    if (!SD.begin(CS)) {
    lcd.print("Non trovo la SD!");
    // don't do anything more:
    return;
  }
    lcd.print("SDcard ok!");
    delay(2000);
    lcd.clear();
    
    
    lcd.setCursor(0,0);
    lcd.print("Inizializzo MCP9808");
    lcd.setCursor(0,1);
    if (!tempsensor.begin()) {
    lcd.print("Non trovo MCP9808!");
    while (1);
  }
  lcd.print("MCP9808 ok!");
  delay(2000);
  lcd.clear();
    


   
}
 
void loop () {
    DateTime now = rtc.now();
    unsigned long currentMillis = millis();
    
    if (Serial.available() > 0) { //Se sono presenti dati nel buffer
    input_carattere = Serial.read();
    delay(2);
    
    if (input_carattere == 'd'){ debug = true; Serial.println("Debug errori attivato!"); }
    if (input_carattere == 'i'){ }
    }
    
   
    
      // leggo la temperatura e la luminosità
      float temp = tempsensor.readTempC();
      int valore_grezzo = analogRead(pin_lux);
      

       if(currentMillis - previousMillis > interval) {
       avvio_servo = true;  // abilito il while che prosegue nel codice una volta ogni 10 secondi (interval = 10000ms)
       avvio_sd = true;
       previousMillis = currentMillis; // salvo in tempo trascorso dall'ultima volta che ho avviato il ciclo while     
       }
       
       while(avvio_servo){
        if(debug == true){Serial.println("Inizio ciclo while!");}
         
         if(valore_grezzo > old_valore_grezzo){ servo_angolo = servo_angolo+30; if(servo_angolo>=180){servo_angolo = 180;} }                                    
         if(valore_grezzo < old_valore_grezzo){ if(servo_angolo!=0){servo_angolo = servo_angolo-30;} }
         
         myservo.write(servo_angolo);
         delay(20);
         
         old_valore_grezzo = valore_grezzo;
        if(debug == true){Serial.println("Fine ciclo while!");}
         avvio_servo = false;
       }
        
        servo_percentuale = map(servo_angolo, 0, 180, 0, 100); // con la funzione map trasformo il valore dei gradi del servo in percentuale
                                                               // da visualizzare sul display lcd e da salvare sulla sd
        
        while(avvio_sd){
         
        sprintf(buffer_sd,  "%02d/%02d/%d %02d:%02d:%02d %d ", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second(), servo_percentuale );
        // qua creo la formattazzione da scrivere a video e sulla sulla sd della data e dell'ora con la % di chiusura del servo
       
        dtostrf(temp, 2, 2, buffer_temp); // funzione utilizzata per inserire la variabile a virgola mobile "temp" nel "buffer_temp"
        dtostrf(RawToLux(valore_grezzo), 5, 1, buffer_lux); // funzione utilizzata per inserire la variabile a virgola mobile "RawToLux" nel "buffer_lux"
        
        if(debug == true){ 
         Serial.print( buffer_sd );
         Serial.print( buffer_temp );
         Serial.print(" ");
         Serial.println( buffer_lux );
        }
         
      File myfile = SD.open("datalog.txt", FILE_WRITE);
         if (myfile) {
          if(debug == true){ Serial.println("Inizio scrittura buffer su SD!"); }
          myfile.print(buffer_sd);
          myfile.print( buffer_temp );
          myfile.print(" ");
          myfile.println( buffer_lux );
          myfile.close();
          if(debug == true){ Serial.println("Fine scrittura buffer su SD!"); }
         }     
         else { Serial.println("error opening data.log"); } 
   
    avvio_sd = false;
  }
        
        
        if(debug == true)
        {
         Serial.print("servo angolo  ");
         Serial.print(servo_angolo);
      
         Serial.print("  valore grezzo ");
         Serial.print(valore_grezzo);
         
         Serial.print("   old valore grezzo ");
         Serial.println(old_valore_grezzo);  
        }
       

      
      sprintf(buffer_lcd,  "%02d/%02d/%d %02d:%02d:%02d", now.day(), now.month(), now.year(), now.hour(), now.minute(), now.second());
     // qua creo la formattazzione da scrivere sull'lcd della data e dell'ora 
      lcd.setCursor(0,0);
      lcd.print(buffer_lcd);
      lcd.setCursor(0,1);
      lcd.print("Temp. serra:");
      lcd.setCursor(13,1);
      lcd.print(temp);
      lcd.setCursor(18,1);
      lcd.write(223); // questa linea crea il simbolo del grado nel display lcd, il valore 223 è dato dal libreria standard 
                      // precaricata nel controller hd44780 presente nel display
      lcd.setCursor(19,1);
      lcd.print("C");
      lcd.setCursor(0,2);
      lcd.print("Lux serra:");
      lcd.setCursor(11,2);
      lcd.print("        "); // questa linea di codice serve a "pulire" una singola porzione di lcd
      lcd.setCursor(11,2);
      lcd.print(RawToLux(valore_grezzo));
      lcd.setCursor(0,3);
      lcd.print("Chiusura serra:");
      lcd.setCursor(16,3);
      lcd.print("   "); // questa linea di codice serve a "pulire" una singola porzione di lcd
      lcd.setCursor(16,3);
      lcd.print(servo_percentuale);
      lcd.setCursor(19,3);
      lcd.print("%");
      delay(1000);    
      
}


// funzione utilizzata per traformare il valore letto dal trasduttore di luminosità in lux
float RawToLux(int raw)
{
  float logLux = raw * logRange / rawRange;
  return pow(10, logLux);
}

se avete qualche delucidazione da darmi sono tutto orecchie e occhi, grazie.

Tu sai vero che, ogni volta tu apri la seriale del PC per dargli un comando, Arduino UNO fa RESET ...

Guglielmo

sisi lo so, ma ora ho notato che lasciandolo acceso per una decina di minuti si blocca
nello stesso modo che fa come se gli dessi il comando "d"...

gpb01:
Tu sai vero che, ogni volta tu apri la seriale del PC per dargli un comando, Arduino UNO fa RESET ...

Guglielmo

ho provato con la libreria memoryFree e mi da che ho libero 204byte su 2kb....
forse è troppa poca? :disappointed_relieved:

usa la macro F()

su ogni print o prinfln di un testo aggiungi F():

lcd.print("Inizializzo SDcard");
diventa
lcd.print(F("Inizializzo SDcard"));

fatto cosí il testo non viene copiato dalla flasch in RAM prima di essere trasmesso ma non passa per la RAM.

Ciao Uwe

uwefed:
usa la macro F()

su ogni print o prinfln di un testo aggiungi F():

lcd.print("Inizializzo SDcard");
diventa
lcd.print(F("Inizializzo SDcard"));

fatto cosí il testo non viene copiato dalla flasch in RAM prima di essere trasmesso ma non passa per la RAM.

Ciao Uwe

Credo che la tua soluzione sia fantastica, non sapevo nemmeno della sua esistenza. per ora sembra andare tutto bene
(te lo dirò con sicurezza tra una decina di minuti)inoltre sempre con la libreria memoryfree ora mi da liberi 554byte su 2kb...
ti dovrò offrire una birra :smiley:

biohazard91:
non sapevo nemmeno della sua esistenza.

Perché non si leggono i Reference :wink:

You can pass flash-memory based strings to Serial.print() by wrapping them with F(). For example :
Serial.print(F(“Hello World”))

(te lo dirò con sicurezza tra una decina di minuti)inoltre sempre con la libreria memoryfree ora mi da liberi 554byte su 2kb...

Se hai tempo, puoi leggerti questi articoli che ho scritto sulla memoria dei microcontrollori e su alcuni sistemi per risparmiare risorse: