Menu che non scorrono

Buongiorno a tutti, sono alla fine di un progetto ma ho un problema, presumo sullo sketch, tutte le altre funzioni vanno bene, cerco di spiegarlo,
Esp32 s2 mini
display 7789
un pulsante
circuito di carica della batteria
Con il pulsante faccio ON e OFF con autoritenuta, una volta acceso, mi da i dati di un sensore e lo stato della batteria, con lo stesso pulsante scorro nelle varie pagine, se invece tengo premuto spengo, fin qui tutto ok
Se collego il circuito della batteria per caricarla o per alimentarla da powerbank, il display mi segnala che sono alimentato da fonte esterna con la scritta "Chrg" e lo scorrimento dell'icona della batteria, il problema è in questo momento, quando è in questo stato non riesco più a scorrere le pagine e non capisco perchè
se potete darmi un aiuto questo è lo sketch
Grazie infinite

#include <SPI.h>
#include <Wire.h>
#include "SPIFFS.h"
#include <TFT_eSPI.h>
#include "DEFINES.h"
#include <Adafruit_ADS1X15.h>   
#include "RunningAverage.h"
#include <Arduino.h>
#include <Pangodream_18650_CL.h>
#include <Adafruit_INA219.h> 
#include <TJpg_Decoder.h>
//------------------------------------------------------------------------------------------------
//    INIZIALIZE LIBRARY
//------------------------------------------------------------------------------------------------
TFT_eSPI tft = TFT_eSPI();
#define RA_SIZE 16
RunningAverage RA(RA_SIZE);
Adafruit_INA219 ina219; // Declare and instance of INA219
#define I2C_ADDRESS_1  0x48
Adafruit_ADS1115 ads;
Pangodream_18650_CL BL;
char *batteryImages[] = {"/battery_01.jpg", "/battery_02.jpg", "/battery_03.jpg", "/battery_04.jpg", "/battery_05.jpg"};
//-----------------------------Calculate MOD (Maximum Operating Depth)----------------------------

float cal_mod (float percentage, float ppo2 = 1.4) {
  return 10 * ( (ppo2 / (percentage / 100)) - 1 ); 
}
//------------------------------------------------------------------------------------------------
void beep() {
    tone(buzzer, 700, 50);                        // Suono attivo per 50mS
}
//------------------------------------------------------------------------------------------------
int read_sensor(int adc = 0) {
  int16_t millivolts = 0;
  double currentmv = 0;
  millivolts = ads.readADC_Differential_0_1();
  millivolts = abs(millivolts);
  RA.addValue(millivolts);
  currentmv = RA.getAverage();
  currentmv = abs(currentmv);
  return currentmv; 
}

//------------------------------------------------------------------------------------------------

void setup(void) {                    
  Serial.begin(115200); 
  
  pinMode(charge,INPUT); 
  pinMode(pinButton, INPUT_PULLUP);
  pinMode(mosfetPin, OUTPUT);
  
  digitalWrite(mosfetPin, LOW);
  
  //pinMode(P_ROSSO, OUTPUT);

  // Accendo led rosso
  // digitalWrite(P_ROSSO, HIGH);
  delay(1000); //tempo ritardo in accensione
  digitalWrite(mosfetPin, HIGH);
  //Spengo led rosso
  //digitalWrite(P_ROSSO, LOW);
  Serial.println("STARTED!");
  
  Serial.print("Running: Setup\n");
  Serial.println(F("Inizializing FS..."));
  if (SPIFFS.begin()){
      Serial.println(F("done."));
  }else{
      Serial.println(F("fail."));
  }
  File testFile = SPIFFS.open(F("/Datas.txt"), "r");
  if (testFile){
      Serial.println("Read file content!");
      testFile.seek(0, SeekSet);
      page   = testFile.readString().toInt();
      testFile.seek(10, SeekSet);
      oxVmax = testFile.readString().toInt();
      testFile.close();
  }else{
      Serial.println("Problem on read file!");
  }
  // Init 
  ads.begin();      // ads1115 start
  ina219.begin();
  RA.clear();       // Clear the Running Avarage
  tft.begin();
  tft.setSwapBytes(true);
  TJpgDec.setJpgScale(1);
  TJpgDec.setCallback(tft_output);
  
    
  ads.setGain(GAIN_SIXTEEN);
  multiplier = 0.0078125F; 
  
      tft.setRotation(2);
      tft.fillScreen(TFT_BLACK);
      tft.setTextSize(2);
      tft.setTextFont(4); 
      tft.setTextColor(0x4BC5);     
      tft.fillRect(5,90,230,50, 0xFFAD);    // blocco GIALLO
      tft.fillRect(5,87,230,10, 0x07E0 );   // blocco dove vengono scritte le situazioni
      tft.fillRect(5,130,230,10, 0x07E0 );  // blocco dove vengono scritte le situazioni
      tft.setCursor(70,95);
      tft.print("EAN");
      tft.setTextColor(TFT_GREEN);
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.setCursor(30,40);
      tft.print("Analizzatore");
      tft.setCursor(70,180);
      tft.print("Nitrox");
  delay(3000);
  pinMode(buzzer, OUTPUT);
  
 
}
//------------------------------------------------------------------------------------------------
void FILEWriteInt(int p_address, int p_value)
{
   File testFile = SPIFFS.open(F("/Datas.txt"), "w");
   testFile.seek(p_address, SeekSet);
   testFile.print(p_value);
   testFile.close();
}
unsigned int FILEReadInt(int p_address)
{
  File testFile = SPIFFS.open(F("/Datas.txt"), "r");
  testFile.seek(p_address, SeekSet);
  int value = testFile.readString().toInt();
  testFile.close();
  return value;
}
//------------------------------------------------------------------------------------------------
int calibrate(double oxGas) {
    Serial.print("calibrating for sampleling gas : ");
    Serial.print(oxGas);
    Serial.print(" % Oxygen\n");
    Serial.print("oxVair: ");
    Serial.print(oxVact);
    Serial.print("  ");
    Serial.print("oxVair: ");
    Serial.print(oxVair);
    Serial.print("  ");
    Serial.print("oxV1atm: ");
    Serial.print(oxV1atm);
    Serial.print("\n");
    // Azzera la media corrente in modo da poter ricominciare da capo
    RA.clear();
    tft.fillScreen(TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextFont(4); 
    tft.setTextColor(TFT_CYAN, TFT_BLACK);
    tft.setCursor(10,40);
    tft.print("   CALIBRAZIONE");
    tft.setCursor(10,70);
    tft.print("    AUTOMATICA");
    tft.setCursor(50,200);
    tft.setTextSize(1);
    tft.setTextFont(4);
    tft.setTextColor( TFT_GREEN, TFT_BLACK);
    tft.print(oxGas);
    tft.print(F(" oxygen"));
  int bar = 1; 
  for (int cx = 0; cx <= RA_SIZE; cx++) {
    tft.drawRect(10, 119, 210, 27,  TFT_WHITE);
    tft.fillRect(11, 120, cx*13, 25,  TFT_GREEN);
    delay(200);   
    result = read_sensor(0);
    delay(50);  
  }
  beep();
  result = RA.getAverage();
  result = abs(result);   
  Serial.print("Calibration value o2: ");
  Serial.print(result);
  Serial.print("\n");
  if (result <= milivolt_low_error) {
    Serial.print("result <= milivolt_low_error\n");
    errorState=1;
    return 0;
  } else {
  tft.fillScreen(TFT_BLACK);
    active = 0;    
    if( oxGas == 20.90 ) {
    Serial.print("oxGas == 20.9\n");
      // This is the 100% linear value of the milivolts expected
      // From the sensor in 1 bar o2 == 100 % oxygen
      oxV1atm = 1/0.209 * result * multiplier;      
      Serial.print("Theoretical linear 100% o2 voltage level: ");
      Serial.print(oxV1atm);
      Serial.print(" mV \n");          
    } else if( oxGas == 100.00 ) {
      Serial.print("oxGas == 100.0\n");
      //Serial.print("Voltage level for 100% o2 : ");
      //Serial.print(result * multiplier);
      //Serial.print(" mV \n");
      FILEWriteInt(10, result);
    }
    return result;
  }
}
//------------------------------------------------------------------------------------------------
void ina219values()  {
//Acquisizione dei valori dal sensore
  shuntvoltage = ina219.getShuntVoltage_mV(); //Legge la tensione tra V e V +. Questa è la caduta di tensione misurata ai capi del resistore shunt. Il valore è espresso in mV
  busvoltage = ina219.getBusVoltage_V(); //Legge la tensione tra GND e V. Questa è la tensione totale vista dal circuito in esame. (Tensione di alimentazione - tensione shunt). Il valore è in Volt.
  current_mA = ina219.getCurrent_mA(); //Legge la corrente, ricavata tramite la legge di Ohm dalla tensione shunt misurata. Il valore è in mA.
  power_mW = ina219.getPower_mW();
  loadvoltage = busvoltage + (shuntvoltage / 1000); //Calcola la tensione sul carico
  energy = energy + loadvoltage * current_mA / 3600;
  Serial.print("Bus Voltage:   "); Serial.print(busvoltage); Serial.println(" V");
  Serial.print("Shunt Voltage: "); Serial.print(shuntvoltage); Serial.println(" mV");
  Serial.print("Voltage:  "); Serial.print(loadvoltage); Serial.println(" V");
  Serial.print("Current:       "); Serial.print(current_mA); Serial.println(" mA");
  Serial.print("Power:         "); Serial.print(power_mW); Serial.println(" mW");
  Serial.print("");
}
//------------------------------------------------------------------------------------------------
void error(int e) {
  beep();
  delay(200);  
  oxVact = read_sensor(0);
  oxVact = oxVact * multiplier;
  
    tft.setTextColor(TFT_RED, TFT_BLACK);
    tft.setTextSize(3);
    tft.setTextFont(4); 
    tft.setCursor(30,30);
    tft.print("X");
    tft.setTextColor(TFT_RED, TFT_BLACK);
    tft.setTextSize(1);
    tft.setTextFont(4);
    tft.setCursor(100,40);
    tft.print("SENSOR ");
    tft.setTextSize(1);
    tft.setTextFont(4);
    tft.setCursor(100,70);
    tft.print("ERROR");
  if ( e == 1 ) {
     tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
     tft.setTextSize(1);
     tft.setTextFont(4);
     tft.setCursor(40,140);
     tft.print("Voltage LOW");
   } else if ( e == 2 ) {
     tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
     tft.setTextSize(1);
     tft.setTextFont(4);
     tft.setCursor(2,140);
     tft.print("Voltage High");
   } else {
     tft.setTextColor(TFT_MAGENTA, TFT_BLACK);
     tft.setTextSize(1);
     tft.setTextFont(4);
     tft.setCursor(2,140);
     tft.print("Unknown Err");
   }   
  tft.setCursor(60, 200);
  tft.setTextSize(1);
  tft.setTextFont(4);
  tft.print(oxVact , 2);
  tft.print(" mV ");
  if (oxVact > milivolt_low_error && oxVact < milivolt_high_error ) {
    errorState = 0;
    oxVair = 0;
    result_max = 0;
  } 
}
byte countDigits(int num){
  byte count=0;
  while(num){
    num=num/10;
    count++;
  }
  return count;
}
//------------------------------------------------------------------------------------------------
void batteryMonitor(){ 
 battPcrt = (busvoltage-6.8)/.014+.5;
  if(battPcrt>100) battPcrt=100;
  if(battPcrt<0) battPcrt=0;
    if (digitalRead(charge) == HIGH)
    //if (false)
    { 
        for(int i=0; i< ARRAY_SIZE(batteryImages); i++){
        drawingBatteryIcon(batteryImages[i]);
        tft.setTextColor(TFT_WHITE,  TFT_BLACK);
        tft.setCursor(150, 4);
        tft.setTextSize(1);
        tft.setTextFont(2); 
        tft.print(" Chrg ");
        //drawingText("Chrg"); 
        //delay(400);  
        vTaskDelay(500);   
      }
    }else{
        int imgNum = 0;
       // int battPcrt = BL.getBatteryChargeLevel();
        if(battPcrt >=80){
          imgNum = 3;
        }else if(battPcrt < 80 && battPcrt >= 50 ){
          imgNum = 2;
        }else if(battPcrt < 50 && battPcrt >= 20 ){
          imgNum = 1;
        }else if(battPcrt < 20 ){
          imgNum = 0;
        }     
        drawingBatteryIcon(batteryImages[imgNum]);
        char buf[10] = {0};
        tft.setTextColor(TFT_WHITE,  TFT_BLACK);
        tft.setTextSize(1);
        tft.setTextFont(2); 
        sprintf(buf,"%3i %%",battPcrt);
        tft.setTextPadding(tft.textWidth("000 %",2));
        tft.setTextDatum(TR_DATUM); //se vuoi rimanere allineato a dx
        tft.drawString(buf,190,4,2); // cambia x,y (150,3) al bisogno
      //tft.print("Never Used Stack Size: ");
      //tft.println(uxTaskGetStackHighWaterMark(NULL));    
    }
}
//------------------------------------------------------------------------------------------------
void drawingBatteryIcon(String filePath){
   TJpgDec.drawFsJpg(ICON_POS_X, 0, filePath);
}
void drawingText(String text){
  tft.fillRect(ICON_POS_X-70, 0, 20, ICON_HEIGHT, TFT_BLACK);
  tft.setTextDatum(5);
  tft.setTextSize(1);
  //tft.setTextFont(2); 
  tft.drawString(text, ICON_POS_X-2, STATUS_HEIGHT_BAR/2, 4);
}
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap)
{
  if ( y >= tft.height() ) return 0;
  tft.pushImage(x, y, w, h, bitmap);
  return 1;
}
//------------------------------------------------------------------------------------------------
void header(float result) {     
      tft.setTextSize(1);
      tft.setTextFont(6);
      tft.setTextColor(TFT_YELLOW);   
      tft.setCursor(50, 40);
      tft.print(result, 1);     
}
//------------------------------------------------------------------------------------------------
void analysing(int x, int cal, int cal100) {
  int mod = 0;  
  oxVact = read_sensor(0);
 //Serial.print("Oxygen = ");   
  if (cal100 > 0 ) {
    result = 20.9 + 79.1*(oxVact - cal)/(cal100 - cal);
    
  } else {
   result = (float(oxVact)/float(cal) )*20.9; 
   
  }
  oxVact = oxVact*multiplier;
  if (result > 99.9) result = 99.9;
  if (oxVact < milivolt_low_error || result <= 0  ) {
    tft.fillScreen(TFT_BLACK);
    errorState=1;
  } else if ( oxVact > milivolt_high_error ) {
    tft.fillScreen(TFT_BLACK);
    errorState=2; 
  } else   
    if (result >= result_max) {
      result_max = result;
    }
//-------------------------------------------------------PAGINA 0 MAX -------------------------------
    if ( page == 0 ) {
      batteryMonitor();
      tft.setTextSize(1);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setTextFont(6);    
      tft.setCursor(70, 40);
      tft.print((float) result, 1); 
      tft.fillRect(70,120,4,100, TFT_BLUE);   //linea di divisione
      tft.fillRect(170,120,4,100, TFT_BLUE);  //linea di divisione
      tft.fillRect(2,100,238,4, TFT_MAGENTA); //linea di divisione
      tft.fillRect(70,165,100,4, TFT_BLUE);   //linea di divisione
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.setCursor(95, 130);
      tft.print("Max"); 
      tft.setCursor(95,180);
      tft.print(result_max, 1);
      tft.print(" ");      
    }
//-------------------------------------------------------PAGINA 1 MOD-------------------------------
    // MOD Display
    if ( page == 1 ) {
      batteryMonitor();
      tft.setTextSize(1);
      tft.setTextFont(6); 
      tft.setTextColor(TFT_WHITE, TFT_BLACK);   
      tft.setCursor(70, 40);
      tft.print((float) result, 1);      
      // Print table with MOD 1.4 and 1.6 ppO2
      tft.fillRect(70,120,4,100, TFT_BLUE);    //linea di divisione verticale
      tft.fillRect(140,120,4,100, TFT_BLUE);   //linea di divisione verticale
      tft.fillRect(210,120,4,100, TFT_BLUE);   //linea di divisione verticale
      tft.fillRect(2,100,238,4, TFT_MAGENTA);  //linea di divisione orrizontale
      tft.fillRect(70,165,140,4, TFT_BLUE);    //linea di divisione orrizontale
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.setCursor(90, 130);
      tft.print("1.4");
      tft.setCursor(160, 130);
      tft.print("1.6 ");
      tft.setCursor(2, 180);
      tft.print("MOD");     
      tft.setCursor(90, 180);
      tft.print(floor(cal_mod(result, 1.4)),0);
      tft.print(" ");      
      tft.setCursor(160, 180);
      tft.print(floor(cal_mod(result, 1.6)),0);
      tft.print(" ");      
    }
//-------------------------------------------------------PAGINA 2 RISULTATO IN GRANDE-------------------------------    
    if ( page == 2 ) {
     batteryMonitor();
      tft.setTextSize(1);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setTextSize(2); 
      tft.setTextColor(TFT_CYAN,TFT_BLACK);   
      tft.setCursor(20, 90);
      tft.setTextFont(6);
      tft.print((float) result, 1);   
    }
//-------------------------------------------------------PAGINA 3 informazione tecniche-------------------------------   
    // Questa pagina non viene salvata nella EEPROM
    if ( page == 3 ) {
      tft.fillRect(95,37,3,160, TFT_YELLOW); //linea di divisione verticale
      tft.fillRect(2,37,220,3, TFT_YELLOW);  //linea di divisione orrizontale
      tft.setCursor(5, 10);
      tft.setTextColor(TFT_WHITE, TFT_BLACK);
      tft.setTextSize(1);
      tft.setTextFont(4);
      tft.print("INFO");     
      tft.setCursor(0, 50);
      tft.setTextColor(0xfffc41,  TFT_BLACK);
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.print("Cell");
      tft.setCursor(120, 50);
      tft.print( oxVact , 2); 
      tft.print(" mV");
      tft.setCursor(0, 90);
      tft.setTextColor(0xfffc41,  TFT_BLACK);
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.print("Batt");
      tft.setCursor(120, 90);
      tft.print(busvoltage , 2);
      tft.print(" V ");
      tft.setCursor(0, 130);
      tft.setTextColor(0xfffc41,  TFT_BLACK);
      tft.setTextSize(1);
      tft.setTextFont(4); 
      tft.print("Batt");
      tft.setCursor(120, 130);
      tft.print(battPcrt);
      tft.print(" % ");
      tft.setCursor(0, 170);
      if (cal100 > 0 ) {
        tft.print("refmix");
        tft.setCursor(120, 170);
        tft.print("Aria + o2");       
      } else {
        tft.print("refmix");
        tft.setCursor(120, 170);
        tft.print("Aria    ");
      }
      tft.setTextColor(TFT_SKYBLUE, TFT_BLACK);
      tft.setCursor(0, 210);
      tft.setTextSize(1);
      tft.setTextFont(2); 
      tft.print("Firmw 1.8");
    }
  }
//------------------------------------------------------------------------------------------------
void max_clear() {
  result_max = 0;
  beep();
  //battVolt.clear();
  active = 0;
}


//------------------------------------------------------------------------------------------------
void ON_OFF(){
  if (digitalRead(pinButton) == LOW && t == 0) {
    t = millis();
    // Debounce software...
    delay(50);
    // Accendo led rosso
//    digitalWrite(P_ROSSO, HIGH);
    Serial.println("Inizio sequenza ");
    Serial.print(t); Serial.println("...");
    tmrLast = millis();
  }
  if (digitalRead(pinButton) == HIGH && t > 0) {
    //Spengo led rosso
//    digitalWrite(P_ROSSO, LOW);
    t = 0;
    Serial.println(" (annullata)");
    tmrLast = millis();
  }
  //tempo ritardo in spegnimento
  // Verifico anche il tempo totale
  if((t > 0 && millis() - t > 2000) || millis() - tmrLast > INATTIVITA*1000 ) {
    digitalWrite(mosfetPin, LOW);       

    // Simulo lo spegnimento....
 //   digitalWrite(P_ROSSO, LOW);
    Serial.println("*** SPENTO ***");
    while (1) { };

  }
}
//------------------------------------------------------------------------------------------------
void loop(void) {  
    ON_OFF();
     
    ina219values();
    int current = digitalRead(pinButton); 
  if (current == LOW && previous == HIGH && (millis() - firstTime) > 200) {
    firstTime = millis();
    active = 17;
  }
  millis_held = (millis() - firstTime);
  secs_held = millis_held / 1000;
  if (millis_held > 2) {
    if (current == HIGH && previous == LOW) {
      if (millis_held <= 400) {
       page++;
        if ( page >= 4 ) {
          page = 0;
        }
        if ( page != 3 ) { 
          FILEWriteInt(0, page);
        }      
        tft.fillScreen(TFT_BLACK);
      }
      if (millis_held >= 400 && millis_held < 5000 ) {
        
        oxVact = read_sensor(0);
        oxVact = oxVact*multiplier;
        if ( (oxVact > (oxV1atm - 10) ) &&  oxVair > 0) {
          oxVmax = calibrate(100.00);
        }
        else {
          //max_clear();
          oxVair = calibrate(20.90);
        }
      }    
      if (millis_held >= 5000 ) {
         //Serial.print("Clear  100% o2\n");
        // max_clear();
         oxVmax=0;
         //EEPROMWriteInt(2, 0);
         FILEWriteInt(10, 0);
         oxVair = calibrate(20.90);
      }     
    }
  }
  previous = current;
  prev_secs_held = secs_held;
  if ( errorState > 0 ) {
    tft.fillScreen(TFT_BLACK); 
    while(errorState > 0){
      error(errorState);
      }
  } else { 
   //calibrazione forzata all'avvio
    if (oxVair == 0) {
      oxVair = calibrate(20.90);
    }
    analysing(0, oxVair, oxVmax);
  }
  active++;
 }

Nessuna idea??

Secondo me perchè rimani bloccato nel for() delle icone in crescendo troppo tempo senza leggere il pulsante. Prova a togliere il for(), e sostituisci "i" con una variabile static, es:

void batteryMonitor(){ 
 static int i = 0;
 battPcrt = (busvoltage-6.8)/.014+.5;
  if(battPcrt>100) battPcrt=100;
  if(battPcrt<0) battPcrt=0;
    if (digitalRead(charge) == HIGH)
    //if (false)
    { 
        //for(int i=0; i< ARRAY_SIZE(batteryImages); i++){
        drawingBatteryIcon(batteryImages[i]);
        i++;
        if(i == ARRAY_SIZE(batteryImages)) i = 0;
[etc]

A questo punto puoi anche togliere (o ridimensionare) il delay() .

Ciao, Ale.

@ilguargua
Ciao e grazie, ho fatto come hai detto tu, se tolgo il delay le pagine scorrono anche quando sono in ricarica ma la rotazione delle icone della batteria è troppo veloce e fastidiosa, se riporto il delay al valore ottimale non scorrono più le pagine

Allora togli il delay() e fai un timer con millis() come fai da altre parti. Se non vuoi alterare più di tanto il codice, aggiungi un controllo subito all'inizio della funzione:

void batteryMonitor(){ 
 static uint32_t lst_print = 0;
if(millis() - lst_print < 500) return;
lst_print = millis();
 battPcrt = (busvoltage-6.8)/.014+.5;
  if(battPcrt>100) battPcrt=100;
[etc]

Ciao, Ale.

2 Likes

GRAZIE!!!! Funziona

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.