[Risolto] Controllo remoto non mi fa più funzionare keypard 4x4

Ciao a tutti,
ho notato che dopo aver richiamato il controllo remoto la tastiera 4x4 non funziona più, l’unico pulsante che rimane funzionanente è il cancelletto(#)… tutti gli altri non danno nessuna risposta… l’unico modo per farla rifunzionare è riavviando arduino… da profano sembra come che vada persa l’inizializzazione della tastiera, ma non capisco il perchè… mi sapete aiutare?

le parti di codice interessate sono:

void pulsantiera()

void inviodati()

grazie

codice.txt (93.9 KB)

aggiungo un'altra domanda,

nell'estratto sotto(codice completo più in basso):

key = kpd.waitForKey();
      Serial.println(key);
      code [1] = key;
      if (code[1] == '*') {
        code[0] = ' ';
        code[1] = ' ';
        code[2] = ' ';
        Serial.println("codice annullato");
      }

se arrivo a questo punto dove code [1] è uguale ad esempio a '9' ,perchè non ho cancellato il precedente carattere memorizzato in code [1](notavo ora che se sbaglio ha digitare tre cifre che non sono tra quelli negli if sotto non assegno mai nessun valore a code e mi porto dietro gli ultimi digitati) cosa farà il codice? da come sto interpretando io e da come dovrebbe essere dopo che ho assegnato un valore a code[0], arduino aspetta finchè non premo il tasto ' * '(per esempio) e appena lo premo code[1] dovrebbe venir modificato da '9' a ' * ', è corretto? oppure avendo già code[1] un valore assegnato( il 9) in automatico if (code[1] == '*') { sarà sempre falso?

il codice pulsantiera completa... stento a crederci che il controllo remoto possa invalidare il funzionamento della tastiera, non vorrei che invece c'è qualche errore che trascurando nel codice pulsantiera....

come sempre grazie

void pulsantiera() {
  char key = kpd.getKey();
  if (key) {
    wdt_disable();
    code [0] = key;
    if (code[0] == '*') {
      code[0] = ' ';
      code[1] = ' ';
      code[2] = ' ';
      Serial.println("codice annullato");
    }
    else {
      Serial.println(key);
      kpd.setDebounceTime(2);
      lcd.setCursor(7, 1);
      lcd.print('K');
      key = kpd.waitForKey();
      Serial.println(key);
      code [1] = key;
      if (code[1] == '*') {
        code[0] = ' ';
        code[1] = ' ';
        code[2] = ' ';
        Serial.println("codice annullato");
      }
      else {
        kpd.setDebounceTime (2);
        key = kpd.waitForKey();
        Serial.println(key);
        code [2] = key;
        if (code[2] == '*') {
          code[0] = ' ';
          code[1] = ' ';
          code[2] = ' ';
          Serial.println("codice annullato");
        }
      }
    }
    wdt_enable(WDTO_8S);
    lcd.setCursor(7, 1);
    lcd.print(' ');
  }
  if (( (code[0] == '0') && (code[1] == 'A') && (code[2] == '#') ) && stato_pulsanteSX == 0)  {
    stato_pulsanteSX = 1;
    Serial.println("PROVA1");
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if (( (code[0] == '0') && (code[1] == 'A') && (code[2] == '#') ) && stato_pulsanteSX == 1)  {
    stato_pulsanteSX = 0;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }

  if (( (code[0] == '0') && (code[1] == 'B') && (code[2] == '#') ) && stato_pulsanteCENTRO == 0)  {
    stato_pulsanteCENTRO = 1;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if (( (code[0] == '0') && (code[1] == 'B') && (code[2] == '#') ) && stato_pulsanteCENTRO == 1)  {
    stato_pulsanteCENTRO = 0;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }

  if (( (code[0] == '0') && (code[1] == 'C') && (code[2] == '#') ) && stato_pulsantePICCOLA == 0)  {
    stato_pulsantePICCOLA = 1;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if (( (code[0] == '0') && (code[1] == 'C') && (code[2] == '#') ) && stato_pulsantePICCOLA == 1)  {
    stato_pulsantePICCOLA = 0;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }

  if (( (code[0] == '0') && (code[1] == 'D') && (code[2] == '#') ) && stato_pulsanteSXCE == 0)  {
    stato_pulsanteSXCE = 1;
    stato_pulsanteSX = 1;
    stato_pulsanteCENTRO = 1;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if (( (code[0] == '0') && (code[1] == 'D') && (code[2] == '#') ) && stato_pulsanteSXCE == 1)  {
    stato_pulsanteSXCE = 0;
    stato_pulsanteSX = 0;
    stato_pulsanteCENTRO = 0;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '1') && (code[2] == '#') )  {
    count_chiusureSX = 0;
    count_chiusureCENTRO = 0;
    count_chiusurePICCOLA = 0;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '2') && (code[2] == '#') )  {
    ricordavalorestatopioggia = 0;
    attiva_ricordavalorestatopioggia = false;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '3') && (code[2] == '#') )  {
    CHIUDITENDAGRANDESX = true;
    Serial.println("PROVA2");
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '4') && (code[2] == '#') )  {
    CHIUDITENDAGRANDECENTRO = true;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '5') && (code[2] == '#') )  {
    CHIUDITENDAGRANDEPICCOLA = true;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '6') && (code[2] == '#') )  {
    stapiovendo = true;
    startingTimePioggia2 = millis();
    Rotations = 50;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '7') && (code[2] == '#') )  {
    wdt_disable();
    connessioneinternet();
    wdt_enable(WDTO_8S);
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '0') && (code[1] == '8') && (code[2] == '#') )  {
    avvio_ventola_per_check = true;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }

  if ( (code[0] == '0') && (code[1] == '9') && (code[2] == '#') )  {
    verificariavvioWD = true;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '1') && (code[1] == '0') && (code[2] == '#') )  {
    count_problemibme = 0;
    lcd.setCursor(13, 1); campovuoto();
    lcd.setCursor(12, 1); campovuoto();
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
  if ( (code[0] == '1') && (code[1] == '1') && (code[2] == '#') )  {
    avvioLCDinitdopochiusura = millis();
    LCDinitdopochiusura = true;
    code[0] = ' ';
    code[1] = ' ';
    code[2] = ' ';
  }
}

Ho fatto delle prove con la seriale collegata, non ho trovato problemi ne tantomeno me ne ha dati ... con la scusa ho aggiunto la parte che se inserisco tre caratteri che non rientrano negli if di interesse mi cancella i caratteri inseriti.. per il resto nn so che dire... non trovo errori per quelle che sono le mie conoscenze...

ho continuato con le prove e credo proprio che perda la definizione della mappa della tastiera...

altre prove effettuate:

  • con la seriale attiva il problema non è mai sorto

  • dopo 2/3 chiamate da remoto non si è mai presentato il problema... dopo una decina si..(non è cmq sistematico, diciamo random)

  • i tasti: 3 - 6 - 9 - # - A - B - C - D continuano a funzionare correttamente

  • alla pressione degli altri non succede nulla, il codice non entra nell' if (key) {

per ovviare mi vinene in mente di ricreare la tastiera ogni volta che finisco la trasmissione in remoto...

i pin usati nell'arduino mega sono questi:

byte rowPins[ROWS] = { 29, 28, 27, 26 }; // Riga0,1,2,3.
byte colPins[COLS] = { 25, 24, 23, 22}; // Colonna0,1,2,3

mentre se volessi provare a ricreare la tastiera dopo ogni chiamata da remoto è sufficente mettere questo corretto?

// Definizione mappa della tastiera
char keys[ROWS][COLS] = {
  {'1', '2', '3', 'A'},
  {'4', '5', '6', 'B'},
  {'7', '8', '9', 'C'},
  {'*', '0', '#', 'D'}
};
byte rowPins[ROWS] = { 29, 28, 27, 26 }; // Riga0,1,2,3.
byte colPins[COLS] = { 25, 24, 23, 22}; // Colonna0,1,2,3
// Creazione della tastiera
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

non serve rimettere anche:

const byte ROWS = 4; // Quattro righe
const byte COLS = 4; // Quattro colonne

Ciao di nuovo,

Sto continuando con le prove:

  • pur ridefinendo la tastiera dopo ogni invio dati del cobtrollo remoto il problema di ripresenta

Più tardi modificherò i pin al quale la tastiera si collega... anche se mi pare evidente che se all'inizio tutto funziona e poi no,con cadenza casuale difficile credere che siano i pin ad essere il problema..

  • ho verificato la tastiera e funziona

Credo proprio che mi sto concentrando ulla parte sbagliata... nessuno che mi può aiutare??

Cambiati i due pim che comandano le due colonne incriminare, ovvero pin 25 e 24 ... il problema persiste... altra prova che sto facendo è quella di non utilizzare il controllo remoto per un paio si giorni per vedere se il problema si presenta ugualmente...

In attesa di chiarire il punto sopra, sto ragionando sul motivo,pin apparte che ho già provato a cambiare, cosa nn può farmi funzionare solo mezza tastiera...

Idee? Suggerimenti? Ci può essere qualcosa nel loop xhe mi sfancula la tastiera a cui nn sto pensando???

Siete tutti in ferie ppure è un problema cosi particolare che nemmeno una mezza idea vi viene!?!?! O peggio ancora son ignorato!?!?!? :frowning: :stuck_out_tongue:

Ignorato no, ma quasi. Il tuo programma l'ho visionato ma è difficile da seguire.
In gergo si dice che è "gonfio". Troppe variabili. Usi una convenzione tua per i nomi delle variabili comprensibile solo a te. Mettere le mani in quel programma per me è impossibile, serve una profonda ristrutturazione.

Io proverei con gli esempio della libreria keypad per vedere se funziona la tastiera. Poi proverei ad integrare il controllo remoto, se vanno entrambe continuerei ad aggiungere pezzi di programma.

Prova a scrivere altri sketch da usare come unita di test e quindi non modificare questo.

Inoltre ho visto che ci sono almeno due librerie keypad, una è questa, l'altra quella standard mi pare sia differente internamente. Tu quale hai installato?

PS: Stai usando 1% delle potenzialità del linguaggio, non sei il solo tutti così fanno, la parola chiave
struct del C++ non la usa nessuno, per non parlare di class. In sostanza vuoi costruire un castello con secchio e paletta anche se disponi di una impresa di costruzioni.

Ciao.

Maurotec:
... Stai usando 1% delle potenzialità del linguaggio, non sei il solo tutti così fanno, la parola chiave
struct del C++ non la usa nessuno, per non parlare di class ...

Per carità Mauro, lascia stare queste cose ... è un utente veramente "base" e ... come tale ... non incasinargli la vita con classi, strutture, ecc. ecc. perché non ne esce più. Basterebbe che usasse bene tutte le potenzialità di base del 'C' e che il codice fosse più strutturato.

Concordo invece pienamente con te sul fatto che il programma sia illegibile, impossibile da seguire, scritto mettendo assieme pezzi qua e la e raffazzonandolo ... va buttato e riscritto completamente in modo molto ma molto più ordinato.

simosere:
O peggio ancora son ignorato!?!?!?

I motivi ti sono stati ampiamente descritti ...
...ho i miei dubbi che qualcuno ti aiuterà con quel groviglio di programma ... ::slight_smile:

Guglielmo

Ciao Maurotec,

so bene che il codice che sto usando non è formalmente corretto,elegante e strutturato come si deve, sono molto alle prime armi...

Il codice è in uso da circa 2 anni e mezzo, con alcune implementazioni fatte nel tempo, nessuna implementazione è stata inserita senza aver verificato che nn impattasse quello che già c'era.. quello quindi che voglio dire è che se c'e' qualcosa che da fastidio alla tastiera a livello software c'era gia' e nn dava problemi nel funzionamento.... quindi secondo il mio ragionamento (ammesso che sia corretto) è capire cosa potrebbe dar fastidio alla tasiera, invalidare dopo un po' solo due colonne su quattro(cosa mai può farlo? I pin improvvisamente non funzionano piu!?!?) andare a indagare li...in maniera assoluta dico...

Ora sono da cell, come faccio a capire quale libreria ho installato? Perché ce ne sono due con lo stesso nome??

@ Gugliemo, ok ho capito, a questo punto cercherò di inventarmi qualcosa.. purtroppo per me non sono in grado di fare di meglio al momento, questo è il codice... pensavo che in base ai problemi riportati potevo cmq ricevere imput su dove provare ad andare a verificare...

quindi secondo il mio ragionamento (ammesso che sia corretto) è capire cosa potrebbe dar fastidio alla tasiera, invalidare dopo un po' solo due colonne su quattro(cosa mai può farlo?

L'unico modo (anche quando il programma è scritto benissimo) è di isolare porzioni di codice e testarle se funziona vuole dire che l'hardware non ha problemi e nemmeno il software, se non funziona ti ritrovi a cercare il problema in quella porzione di programma isolata e non su tutto il codice del programma.

Ora mi pare di capire si vuole che l'applicazione possa interagire tramite due interfacce, 1) terminale seriale, 2) terminale remoto.

Solitamente quando si ha questa necessità si fa confluire il tutti tramite una interfaccia a comandi "trasparente".
Trasparente vuole dire che all'applicazione non importa da dove arrivi il comando.

Per carità Mauro, lascia stare queste cose ... è un utente veramente "base" e ... come tale ... non incasinargli la vita con classi, strutture, ecc. ecc. perché non ne esce più.

Il senso è: il programma sembra volere fare troppe cose impiegando solo 1% delle potenzialità del linguaggio.
Detto in altri termini o studi e impari oppure devi accontentarti delle funzionalità dell'attuale implementazione.

Mettere le mani in quel codice è un incubo proprio perché il bug c'è (ci sarà) ma non si vede e scovarlo in quel groviglio è una impresa.

va buttato e riscritto completamente in modo molto ma molto più ordinato.

Oddio non si butta niente, va messo da parte e si inizia un nuovo sketch anche più sketch, cosa che è ancora fattibile e lo si fa frequentemente durante lo sviluppo. Come dire; "buona la prima"... non capita mai.

Ciao.

simosere:
Ciao a tutti,
... l'unico pulsante che rimane funzionanente è il cancelletto(#)...

io mi stavo domandando

  1. come fai a sapere che l'unico pulsante funzionante è il cancelletto, dato che non testi mai il cancelletto da solo, da cosa lo capisci che lui va e gli altri no?

e poi, ma si tratta di filosofia
2) ti rendi conto vero che se tu ti fossi messo a studiare il 'C' adesso avresti un programma molto meno incasinato, molto più leggibile, funzionante e che ti avrebbe richiesto infinitamente meno tempo per essere scritto? che la somma dei tempi di studio e programmazione sarebbe stata probabilmente meno della metà del tempo che ci hai perso dietro finora, e non ne sei ancora uscito?

il mio consiglio è (S)troncare senza alcuna pietà il tuo programma e ri-partire da capo
questa volta "dopo" aver imparato dagli errori

se vuoi io ci sono

simosere:
capire cosa potrebbe dar fastidio alla tasiera, invalidare dopo un po’ solo due colonne su quattro(cosa mai può farlo?

Ipotesi: un’area di memoria che si sporca per superamento dei bordi di un array o qualcosa di simile

Standardoil:
avresti un programma molto meno incasinato, molto più leggibile, funzionante e che ti avrebbe richiesto infinitamente meno tempo per essere scritto

Ma soprattutto, cosa più importante, infinitamente meno complesso da controllare e correggere.
Ho l’impressione che di tutti quei flag e variabili temporali ne potrebbero bastare meno di un terzo, forse anche meno.

Ciao standardoil,

Per il primo punto funzuonano tutti i pulsanti della colonna 3 e 4... lo so perché il tasto che digito lo stampo sul display e quelli funzionano tutti...

Per il punto due io rispondo presente, ma non sono al momento nella condizione di potermici dedicare attivamente e devo far funzionare questo... è l'ultimo passo per ritenerlo concluso, questa pulsantiera ha sostituito la precedente che era troppo macchinosa nel funzionamento ma funzionava... tornare a quella è il piano b... vorrei intanto far lavorare tutto bene e nel mentre senza pensieri applicarmi per farlo da capo... come dire sono al 99% e nn posso finirlo...

Apprezzo la tua disponibilità. Anzi grazie, sei stato sempre duro nei commenti e ci siamo anche beccati avvolte... mi sorprendo... grazie!!!

Voi come macro aree cosa verifichereste? Poi me lo spulcio io...

per claudio FF

bella ipotesi, magari potrebbe essere quella ringbuffer che è usata ma non inclusa

della quale trovo comunque solo il puntoH (potrebbe essere una single_file_lib, ci guarderò)
e che sembra comunque che il buffer circolare non sia mai svuotato, ci devo guardare bene

simosere:
Ciao standardoil,

Per il punto due io rispondo presente, ma non sono al momento nella condizione di potermici dedicare attivamente e devo far funzionare questo... è l'ultimo passo per ritenerlo concluso, questa pulsantiera ha

risposta sbagliata

grazie comunque per l'apprezzamento

Ipotesi: un'area di memoria che si sporca per superamento dei bordi di un array o qualcosa di simile

Nulla che posso gestire io nel codice però...è una cosa direttamente correlata alla libreria mi sembra di capire...

char code[4];
char command[4];
byte keyCounter = 0;

void setup() {
    code[3] = '\0';           // aggiunge terminatore stringa
    command[3] = '\0';   // aggiunge terminatore stringa
}

// pulisce l'array code[] e annulla il comando 
void clearKeyCode() {
    keyCounter = 0;
    memset(code, ' ', 3); // pulisce l'array code[]
    
}

boolean pulsantiera() {
  
    char key = kpd.getKey();
    if (key == NO_KEY) {
        return false;
    }
    if (key == '*') { // questo carattere '*' annulla il comando
        clearKeyCode();
        Serial.println("codice annullato");
   } else {
        code[keyCounter] = key; // salva key in code[]
        keyCounter++;  // incrementa il contatore di caratteri
   } 
   if (keyCounter == 3) { // quando keyCounter arriva a 3
       if (code[2] != '#') {   // se code[2] non contiene il carattere '#' annulla il comando
           clearKeyCode();
           Serial.println("codice invalido"); 
       } else {
           memcpy(command, code, 3); // copia code[] in command[]
           clearKeyCode();                     // annulla il comando
           return true;                             // restituisce true
       }
    }
    return false;
} // end boolean pulsantiera()

void loop() {
    if (pulsantiera()) {
        Serial.println(command);
        if (strcmp(command, "12#") == 0) {  // restituisce 0 se command è uguale a "12#\0"
            Serial.println("comando 12 accettato);     
        } 
    }
}

Il codice sopra non è testato né compilato, per cui potrebbe non funzionare.
Da notare che sia code che command ora sono stampabili con Serial.println()
poiché sono C string e possono anche essere comparate con strcmp().

L'obbiettivo del codice si basa sul concetto di "publicazione" di un comando.
La pubblicazione avviene quando pulsantiera restituisce true e allora command[]
contiene un nuovo comando. Non serve azzerare command.

Io per ragioni mie non lo farei così o meglio preferirei avere dei comandi numerici, al posto di
stringhe.

Provatelo voi, poiché io non ho al momento la possibilità e non avendo la tastiere dovrei anche scrivere
del codice per simularla.

Ciao.

Maurotec grazie del supporto…

Wow che differenza con il mio… oltre ha essere evidentemente più compatto e formalmente corretto, cosa fa di più rispetto allo schifo del mio???scusa la domanda ma vorrei capire…

scusa la domanda ma vorrei capire...

Ma perché funziona?

Comunque, cosa fa in più non lo so, credo che le if (strcmp... siano più compatte e sbrigative di if (code[0] = ...
Inoltre puoi stampare il comand. Inoltre non importa chi pubblica command ad esempio da remoto puoi pubblicare 12# e funziona comunque. Si chiama interfaccia a comandi generica (anche se ha un doppio buffer).

Poi cosa non fa, o meglio esce subito dopo la chiamata se key == NO_KEY, quindi è veloce e non c'è neanche bisogno di watchdog.

Ciao.

Nn posso provarlo ora… ma sicuramente funzionerà!!! :wink:

Chiedevo nella speranza che avevi identificato qualche cosa che creava il problema sopra descritto delle due colonne che si perdono per strada… per un’attimo ci ho sperato… :slight_smile: