Modificare codice per aggiungere funzione

Titolo un pò generico ma non mi è venuto meglio. Espongo brevemente. Ho un codice, del famoso cronografo balistico realizzato qualche tempo fa con il vostro aiuto, nel quale vorrei inserire alcune funzioni.

  1. il codice, che funziona benissimo, nell'attuazione mi chiede di inserire un dato (peso in grammi) per poi poter effettuare una seconda azione (sparo). L'interazione è con pulsanti e visualizzazione su LCD display. Ora dopo l'inserimento del dato, il display rimane sulla visualizzazione del dato inserito. Vorrei quindi inserire un blocco che, una volta inserito il peso, pulisca lo schermo e quindi mostri la videata dell'azione successiva...ad esempio "Pronto".
    Ho provato ad inserire il nuovo codice ma, ovviamente, girando in continuazione non si "blocca";
  2. una seconda funziona è un reset SENZA dover premere necessariamente il reset hardware;
    Sto studiando;
  3. la possibilità di annullare/non ritenere valida una lettura "invariata" ovvero ripetere gli stessi dati del tiro precedente una seconda volta che indicano chiaramente una lettura errata.
    Ho fatto qualche prova...esito negativo. Di seguito posto il codice che ho limitato, alle parti di interesse essendo abbastanza lungo sperando che sia comprensibile.
    Potete darmni qualche indicazioni sul corretto approccio?
    Grazie
...omissis

void setup()
{
  t1 = 0;
  t2 = 0;
  Serial.begin(9600);
  //Serial.println("Pronto ... ");
  //
  EIFR |= bit(INTF0);
  EIFR |= bit(INTF1);
  //
  attachInterrupt(digitalPinToInterrupt(2), ISR0, RISING);
  attachInterrupt(digitalPinToInterrupt(3), ISR1, RISING);
  {
    avvio();
    warning();
  }
}
void loop()
{
  // --------- ins peso -------------------

  if (digitalRead(wUp))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      weight += 0.001;
    }
    {
      weightIns();
    }
  }
  if (digitalRead(wDown))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
     }
    weightIns();
   }
 
 // -------- misurazione -----------------------

  if ((t1 == 0) && (t2 != 0))
  {
    //Serial.println("Errore ENTRATA");
    clearAndEnable();
    {
      entryError(); // rimanda al void per errore sensore entrata
    }
  }
  else if ((t1 != 0) && ((micros() - t1) > MAXTIME))
  
  {
    // Serial.println("Errore USCITA");
    clearAndEnable();
    {
      exitError();  // rimanda al void errore sensore uscita
    }
  }

 else if ((t1 != 0) && (t2 != 0))
  {
    deltaT = t2 - t1;
    Serial.print("Tempo misurato : ");
    Serial.print(deltaT);
    Serial.println(" microsec.");
    clearAndEnable();

    mpsSpeed = (0.12 * 1000000) / deltaT;    // s = v * t, v = s / t ;
    joule = ((mpsSpeed * mpsSpeed * weight) / 2) / 1000; // joule = v * v * pesokg : 2
    // weight in kg
 
   
// -------------- void per display LCD -----------------

void avvio() {
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("- SuperCrono");
  lcd.setCursor(1, 2);
  lcd.print("ver.3f ");
  delay(1500);
 // lcd.clear();
 // lcd.setCursor(0, 0);
 // lcd.print("Peso impostato :");
 // lcd.setCursor(0, 2);
 // lcd.print("grammi ");
 // lcd.print(weight,3); // se si vogliono 3 decimali
 // lcd.print(weight);
 // delay(2500);
 // lcd.clear();
 // lcd.setCursor(0, 0);
 // lcd.print("m/s : ");
 // lcd.print(mpsSpeed);
 // lcd.setCursor(0, 1);
 // lcd.print("Joule : ");
 // lcd.print(joule);
}
void warning() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Verificare il peso,");
  lcd.setCursor(0, 1);
  lcd.print("...oppure, sparare!");
  lcd.setCursor(0, 3);
  lcd.print("grammi: ");
  lcd.setCursor(9, 3);
  lcd.print(weight,3);
  //lcd.print(joule);
}
void weightIns() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Inserire peso");
  lcd.setCursor(0, 1);
  lcd.print("...e sparare.");
  lcd.setCursor(0, 3);
  lcd.print("grammi: ");
  lcd.setCursor(9, 3);
  lcd.print(weight, 3);  // se si vogliono 3 decimali
  //lcd.print(weight);
 // delay(1000);
 // lcd.clear();
 // lcd.print("Hallo");
}
void shootDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("vel m/s  : ");
  lcd.print(String(mpsSpeed));
  //lcd.print("tiro num : ");
  //lcd.print(contaSpari + 1);
  
  lcd.setCursor(0, 1);
  lcd.print("diff m/s : ");
  lcd.print(deltaMS);
  //lcd.print("vel m/s  : ");
  //lcd.print(String(mpsSpeed));
  
  lcd.setCursor(0, 2);
  lcd.print("Joule    : ");
  lcd.print(joule);
  //lcd.print("diff m/s : ");
  //lcd.print(deltaMS);
  
  lcd.setCursor(0, 3);
  lcd.print("tiro num : ");
  lcd.print(contaSpari + 1);
  //lcd.print("Joule    : ");
  //lcd.print(joule);
}
void avgDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Medie rilevate");
  lcd.setCursor(0, 2);
  lcd.print("vel m/s : ");
  lcd.print(mpsSpeed);
  lcd.setCursor(0, 3);
  lcd.print("Joule   : ");
  lcd.print(joule);
  //delay(3500);
  //warning();
}
void entryError() {
  lcd.clear();                           // se c'è un errore nel tiro dopo la schermata media
  lcd.setCursor(0, 0);
  lcd.print("- Tiro non valido -");
  lcd.setCursor(0, 2);
  delay(300);  // la scritta "error" si sovrappone e rimane la prima riga.
  lcd.print(" - errore entrata -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore entrata -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore entrata -");
}
void exitError() {
  lcd.clear();                           // se c'è un errore nel tiro dopo la schermata media
  lcd.setCursor(0, 0);
  lcd.print("- Tiro non valido -");
  lcd.setCursor(0, 2);                   // la scritta "error" si sovrappone e rimane la prima riga.
  delay(300);
  lcd.print(" - errore uscita -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore uscita -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore uscita -");
}
void record() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Log tiri - m/s");
  lcd.setCursor(0, 1);
  lcd.print("t1 ");
  lcd.print(tiri2[0]);
  lcd.setCursor(10, 1);
  lcd.print("t4 ");
  lcd.print(tiri2[3]);
  lcd.setCursor(0, 2);
  lcd.print("t2 ");
  lcd.print(tiri2[1]);
  lcd.setCursor(10, 2);
  lcd.print("t5 ");
  lcd.print(tiri2[4]);
  lcd.setCursor(0, 3);
  lcd.print("t3 ");
  lcd.print(tiri2[2]);
}
void nullError() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("tiro nullo");
}
void start() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("vel m/s  :");
  lcd.setCursor(0, 1);
  lcd.print("Joule    :");
}

Dunque, il passaggioda una schermata all'altra sono riuscito ad ottenerla tramite l'inserimento dei una nuova condizione (pressione di entrambi i tasti per untemppo superiore a 500ms)...però non mi piace ora di DOVER premere i pulsanti e vorrei che lo facess in automatico dopo uncerto tempo....ho provato ma gira sempre....dove sbaglio?
Ho provato anche con due cicli else...stesso risultato.
Dovrei usare il timeout?

Ciao @vince59,
se per cortesia riesci a fornire qualche informazione in più riguardo al progetto forse qualcosa potrò ditri... Magari postando anche l'intero codice....

Alan

Ecco la porzione di codice di interesse. Il resto non serve perchè sto testando questo e gira correttemente.
In pratica dopo il ciclo di avvio appare la schermata per inserimento peso. Ora, una volta inserito il peso, il display rimane sulla schermata richiamata dallo specifico "void" e rimane in attesa del successivo input.
Vorrei invece far si che:

  • dopo due secondi si portasse sulla schermata definita dal void "reStart"...in attesa dell'inpiut successivo;
    OPPURE (soluzione meno preferita)
  • premendo un tasto, richiamare la funzione void "reStart"...e rimanere in attesa dell'input sucessivo.
    Non fate caso se il codice appare confuso, ma come avrete capito sto provando diverse soluzioni e quindi di volta in volta attvo le linee di interesse.
#include <LiquidCrystal_I2C.h>
#include <Wire.h>

//LiquidCrystal_I2C lcd(0x27, 16, 2);  // LCD PICCOLO
LiquidCrystal_I2C lcd(0x3F, 20, 4);    // LCD GRANDE

// --------- costanti

#define MAXTIME 1000000UL      // tempo massimo di 1sec oltre il quale la misurazione rileva errore in uscita
//#define LENGHT 0.12          // 12 cm distanza
const int wUp = 6;
const int wDown = 7;
//const int restart = 5;
int switchState = 5;


// ---------- variabili

volatile unsigned long t1, t2;
unsigned long deltaT;

long previousMillis = 0;  // prova millis
long previousMillis1 = 0;  // prova millis
long previousMillis2 = 0;  // prova millis
long interval = 250;      // delay per rimbalzo tasto
long interval2 = 1000;      // delay per rimbalzo tasto
long waitTime = 250;  // delaytest per cambio schermo
double mpsSpeed, joule, weight = 0.470, deltaTMedia, tiri[2], deltaMS, tiri2[5]; // aggiungere uno 0 al weight se si vogliono 3 decimali
byte contaSpari, contaSpari1, contaSpari2, num;

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


void setup()
{
  pinMode(5, INPUT);
  {
    avvio();
    warning();
  }
}
void loop()
{
  switchState = digitalRead(5);
 
  // --------- ins peso -------------------

  if (digitalRead(wUp))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      delay(250);
      weight += 0.001;
    }
    {
      weightIns();
    }
  }
  if (digitalRead(wDown))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      delay(250);
      weight -= 0.001; // aggiungere uno 0 se si vogliono 3 decimali
    }
    {
      weightIns();
    }
  }
}
  // ------------- test cambio su schermata "start" dopo inserimento peso ------------------
/*
  // if (digitalRead(wUp) && digitalRead(wDown)) // se rileva pressione (HIGH) sui tasti esegue il ciclo
  // if (digitalRead(wUp) == LOW && digitalRead(wDown)== LOW)
  // if (digitalRead(restart))
  // if (switchState == HIGH)
  {
    unsigned long currentMillis1 = millis();
   if (currentMillis1 - previousMillis1 > waitTime)
   {
     previousMillis1 = currentMillis1;
    //  reStart();
   }
 {
      // clearAndEnable();
   //   delay(500);
   //   reStart();
    }
  }
*/
  // ---------------test reset -----------------------
  /*
    if (digitalRead(restart))
    {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      //weight -= 0.001; // aggiungere uno 0 se si vogliono 3 decimali
    }
    //clearAndEnable();
    //reStart();
    }

  */
  // -------- misurazione -----------------------

  // ------------ test per annullare lettura uguale -------------
  /*
     else if ((t1 == 0) && ((t2 == 0)))
     {
     // Serial.println("Errore tiro NULLO");
     clearAndEnable();
     {
       nullError();  // rimanda al void errore tiro nullo
     }
    }
  */
 // ------------ calcolo differenza m/s sul tiro -----------------

 // ------------------------ media ------------------------------

 // ------------------ void per display LCD ----------------------

void avvio() {
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("- SuperCrono by NV -");
  lcd.setCursor(1, 2);
  lcd.print("ver.3f - 17.mag.21");
  delay(1500);
 }
void warning() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Verificare il peso,");
  lcd.setCursor(0, 1);
  lcd.print("...oppure, sparare!");
  lcd.setCursor(0, 3);
  lcd.print("grammi: ");
  lcd.setCursor(9, 3);
  lcd.print(weight, 3);
  //lcd.print(joule);
}
void weightIns() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Inserire peso");
  lcd.setCursor(0, 1);
  lcd.print("...e sparare.");
  lcd.setCursor(0, 3);
  lcd.print("grammi: ");
  lcd.setCursor(9, 3);
  lcd.print(weight, 3);  // se si vogliono 3 decimali
}
void shootDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("vel m/s  : ");
  lcd.print(String(mpsSpeed));
  lcd.setCursor(0, 1);
  lcd.print("diff m/s : ");
  lcd.print(deltaMS);
  lcd.setCursor(0, 2);
  lcd.print("Joule    : ");
  lcd.print(joule);
  lcd.setCursor(0, 3);
  lcd.print("tiro num : ");
  lcd.print(contaSpari + 1);
}
void avgDisplay() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Medie rilevate");
  lcd.setCursor(0, 2);
  lcd.print("vel m/s : ");
  lcd.print(mpsSpeed);
  lcd.setCursor(0, 3);
  lcd.print("Joule   : ");
  lcd.print(joule);
}
void entryError() {
  lcd.clear();             // se c'è un errore nel tiro dopo la schermata media
  lcd.setCursor(0, 0);
  lcd.print("- Tiro non valido -");
  lcd.setCursor(0, 2);
  delay(300);     
  lcd.print(" - errore entrata -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore entrata -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore entrata -");
}
void exitError() {
  lcd.clear();                           
  lcd.setCursor(0, 0);
  lcd.print("- Tiro non valido -");
  lcd.setCursor(0, 2);                   
  delay(300);
  lcd.print(" - errore uscita -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore uscita -");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print("                    ");
  delay(300);
  lcd.setCursor(0, 2);
  lcd.print(" - errore uscita -");
}
void record() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Log tiri - m/s");
  lcd.setCursor(0, 1);
  lcd.print("t1 ");
  lcd.print(tiri2[0]);
  lcd.setCursor(10, 1);
  lcd.print("t4 ");
  lcd.print(tiri2[3]);
  lcd.setCursor(0, 2);
  lcd.print("t2 ");
  lcd.print(tiri2[1]);
  lcd.setCursor(10, 2);
  lcd.print("t5 ");
  lcd.print(tiri2[4]);
  lcd.setCursor(0, 3);
  lcd.print("t3 ");
  lcd.print(tiri2[2]);
}
void nullError() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("tiro nullo");
}
void reStart() {
  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("vel m/s  : ");
  lcd.print("0,00");

  lcd.setCursor(0, 1);
  lcd.print("diff m/s : ");
  lcd.print("0,00");

  lcd.setCursor(0, 2);
  lcd.print("Joule    : ");
  lcd.print("0,00");

  lcd.setCursor(0, 3);
  lcd.print("tiro num : ");
  lcd.print("0");
}

@vince59 : ... e si che sei da un po' sul forum :imp:

... devi editare il tuo post qui sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona la parte di codice e premi l'icona </> nella barra degli strumenti per contrassegnarla come codice. Così com'è, inoltre, non è leggibile ... assicurati di averlo correttamente indentato nell'IDE prima di inserirlo (questo lo si fa premendo ctrlT su un PC o cmd T su un Mac all'intero del IDE). Grazie.

Guglielmo

Ciao Gug, scusa...con il nuovo layout mi sono confuso. :innocent: :unamused: :unamused: :smirk:
Rimediato prontamente!!!!

1 Like

...però mi dovete aiutare.
Gug...istradami e se necassrio cazziami pure! :crazy_face: :stuck_out_tongue_winking_eye:

Non sono entrato nel merito del tuo porgramma, però un paio di indicazioni te le do ...

  1. se vuoi rimanere in un punto fisso del codice crei una while sempre vera da cui esci con una break.
...
while (true) {
   ...
   // da qui NON esci se non eseguendo una istruzione break, esempio:
   if ( condizione_di_uscita ) break;
   ...
   ...
}
...
  1. se vuoi realmente ripartire in modo corretto da sofware, l'unica è attivare i watchdog, dove vuoi il reset, per un tempo breve (es. WDTO_15MS che sono 15 msec) e metteti subito dopo in un loop chiuso come quello di prima senza fare nulla ... passati i 15 msec. il watchdog scatta e ti resetta in modo pulito la MCU.

Non so se sono stato utile ... :roll_eyes:

Guglielmo

Gug, il codice su cui sto lavorando è quello del famoso cronografo balistico che mettemmo a punto qualche tempo fa e che per me fu un bell'esercizio in cui mi premiasti per aver utilizzato la funzione memset. Tengo quel post in un quadretto ad imperitura memoria :innocent:
Passo subito a studiare e vedere cosa riesco a cavare.
Un caro saluto con grande stima e profondo odio :sunglasses: :nerd_face:

1 Like

Niente...l'unico modo in cui riesco a fargli fare quanto richiesto (eseguire una routine) è mediante due condizioni...ovvero i due tasti premuti contemporaneamente...con le ovvie difficoltà pratiche del caso. Tutto il resto mi manda la routine in ciclo continuo ...ed è ovvio che sia così. Il blocco di codice su cui sto smanettando...dalla linea che recita ---test cambio schermata

void loop()
{
  // --------- ins peso -------------------

  if (digitalRead(wUp))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      delay(250);
      weight += 0.001;
    }
    {
      weightIns();
    }
  }
  if (digitalRead(wDown))
  {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > interval)
    {
      previousMillis = currentMillis;
      delay(250);
      weight -= 0.001; // aggiungere uno 0 se si vogliono 3 decimali
    }
    {
      weightIns();
    }
  }

  // ------------- test cambio schermata "start" dopo inserimento peso ------------------

  if (digitalRead(wUp) && digitalRead(wDown)) // se rileva pressione (HIGH) sui tasti esegue il ciclo
    // if (digitalRead(wUp) == LOW && digitalRead(wDown)== LOW)
    // if (digitalRead(restart)
    // if (switchState == HIGH)
    // while (digitalRead(restart))
  {
    // lcd.clear();
    // reStart();
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis > waitTime)
    {
      previousMillis = currentMillis;
    }

    //if ((digitalRead(restart))== LOW)
    //break;
    reStart();
    // {
    // clearAndEnable();
    // delay(500);
    // reStart();
    // }
  }
}

// ---------------test reset -----------------------
/*
  if (digitalRead(restart))
  {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval)
  {
    previousMillis = currentMillis;
    //weight -= 0.001; // aggiungere uno 0 se si vogliono 3 decimali
  }
  //clearAndEnable();
  //reStart();
  }

...ho risolto il problema con il pulsante aggiuntivo...mi vergogno un pò a dirlo ma vi era un errore hardware, in pratica la sezione della millefori su cui montavo il pulsante non aveva alimentazione, ma ci ho messo un pò a realizzare...troppe cose fatte in fretta.
Rimane però l'esercizio del cambio schermata automaticamente dopo un certo tempo.