Problema urgentissimo, funzione in C

Ciao, ho uno strano problema nel funzionamento di questo codice. Se uso la funzione void inserimento tramite insCodice funziona. Se invece la uso tramite cambiaPin mi va in loop il display con dei quadratini. Ho usato questo metodo perché i puntatori non li so usare ma ripeto che funziona se accedo alla funzione in determinati modi:

#include <LiquidCrystal.h>
#include <IRremote.h>


char codice[4]={'1', '2', '3', '4'};
int stato = 0; // acceso o spento
const int sensoreMovimento =  2; // pin del sensore di movimento
const int sensoreInfrarossi = 13; // pin del sensore infrarossi
const int buzzer = 12; // pin del buzzer
const int rosso = 9; // pin per il led rosso
const int verde = 10; // pin per il led verde
const int blu = 11; // pin per il led blu

LiquidCrystal lcd(3, 4, 5, 6, 7, 8);

IRrecv irrecv(sensoreInfrarossi);

decode_results results;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver

  pinMode(sensoreMovimento,INPUT);

  pinMode(buzzer, OUTPUT);
  
  pinMode(rosso, OUTPUT);
  pinMode(verde, OUTPUT);
  pinMode(blu, OUTPUT);  
  
  lcd.begin(16, 2);
}

void loop() {
  if(stato == 0){
        lcd.print("Allarme spento");
        lcd.setCursor(0, 1);
        lcd.print("1)Cambia pin");
    setColor(0, 0, 255);  // led blu
    if (irrecv.decode(&results)) {
        if(results.value == 0xFFA25D){
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Inserisci codice");
          bool ins=insCodice(codice);
          if(ins){
            stato=1;
            lcd.clear();
        }  
        }
        else if(results.value == 0xFF30CF){
          lcd.clear();
          cambiaPin(codice);
        }
       irrecv.resume(); // Receive the next value
    
    
  }
  delay(200);
  lcd.clear();
  }

  if(stato == 1){

    lcd.setCursor(0, 0);
    lcd.print("Allarme attivo!");
    setColor(0, 255, 0);  // verde
    if(motionDetected()){
      tone(buzzer, 1000, 3000);
    }
    if (irrecv.decode(&results)) {
        if(results.value == 0xFFA25D){
        stato=0;
        lcd.clear();
        lcd.print("Allarme spento");
        lcd.setCursor(0, 1);
        lcd.print("1)Cambia pin");
        }
       irrecv.resume(); // Receive the next value
    }

    
    
  }
  

}


  void setColor(int red, int green, int blue)
  {
    #ifdef COMMON_ANODE
      red = 255 - red;
      green = 255 - green;
      blue = 255 - blue;
    #endif
    analogWrite(rosso, red);
    analogWrite(verde, green);
    analogWrite(blu, blue);  
  }
  

  void cambiaPin(char codice[]){
    char nuovoPin[4];
    lcd.print("Ins. pin attuale");
    bool test=insCodice(codice);
    if(test){
      lcd.clear();
      lcd.print("Nuovo pin");
      delay(2000);
      insert(nuovoPin);
      strcpy(codice, nuovoPin);
    }
    else{
     lcd.clear();
     lcd.print("Pin errato!");
     delay(2000);
     lcd.clear();
     return;
    }
  }

  bool insCodice(char codice[]){
  char cod[4];
  inserimento(cod);
    if(codice[0] == cod[0] && codice[1] == cod[1] &&
        codice[2] == cod[2] && codice[3] == cod[3])
        return true;
    else
        return false;
    
  }

  
  void inserimento(char ritorno[]){
    irrecv.resume();
    int i=2;
    int j;
    char inserimento[4]={' ', ' ', ' ', ' '};
    while(results.value != 0xFF906F){
      j=0;
      if (irrecv.decode(&results)) {
          if(results.value == 0xFF6897){
            lcd.setCursor(i, 1);
            lcd.write('0');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '0';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF30CF){
            lcd.setCursor(i, 1);
            lcd.write('1');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '1';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF18E7){
            lcd.setCursor(i, 1);
            lcd.write('2');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '2';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF7A85){
            lcd.setCursor(i, 1);
            lcd.write('3');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '3';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF10EF){
            lcd.setCursor(i, 1);
            lcd.write('4');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '4';
                break;
              }
              j++;
            }
          }
  
          if(results.value == 0xFF38C7){
            lcd.setCursor(i, 1);
            lcd.write('5');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '5';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF5AA5){
            lcd.setCursor(i, 1);
            lcd.write('6');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '6';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF42BD){
            lcd.setCursor(i, 1);
            lcd.write('7');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '7';
                break;
              }
              j++;
            }
          }
          
          else if(results.value == 0xFF4AB5){
            lcd.setCursor(i, 1);
            lcd.write('8');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '8';
                break;
              }
              j++;
            }
          }
          
          else if(results.value == 0xFF52AD){
            lcd.setCursor(i, 1);
            lcd.write('9');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '9';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFFA857){
            i-=4;
            lcd.setCursor(i, 1);
            lcd.write(' ');
          }
          
       irrecv.resume();
    }
  
    } //fine while
    strcpy(ritorno, inserimento);
  }

    boolean motionDetected(){
       if(digitalRead(sensoreMovimento)==HIGH){
        return true;
       }else{
        return false;
       } 
   }

Premetto, che fare intendere, “questo il programma dimmi dove è l’errore” è una cosa molto superficiale…

Comunque vedo un “anomalia”, gli array di char, in linguaggio c, sono array particolari perché usati per gestire le stringhe.

In C, la dimensione di un array di char, deve essere NumeroElementi+1, perché verrà aggiunto il carattere terminatore stringa ‘\0’.

Nel tuo caso char array[4], dovrebbe essere char array[5], in modo da prevedere il terminatore…

Non puoi dichiarare una funzione in questo modo "void inserimento(char ritorno)".
Se non sei capace di usare i puntatori dichiara l'array "ritorno" come variabile globale, p.e. "char ritorno[20];", ovviamente la dichiarazione deve trovarsi esterna alle funzioni e il numero tra le deve essere pari almeno al numero massimo previsto di elementi più uno.

Non puoi dichiarare una funzione in questo modo "void inserimento(char ritorno)".

In che senso? mi sembra corretto, è un modo per passare un array ad una funzione,

void inserimento(char ritorno) o void inserimento(char *ritorno) "si usano" allo stesso modo, senza parlare di distinzione tra array e puntatori :slight_smile:

torn24:
In che senso? mi sembra corretto, è un modo per passare un array ad una funzione,

Assolutamente no, non puoi dichiarare un array nel prototipo della funzione, gli array puoi solo passarli tramite puntatori o sotto forma di variabili globali, sicuramente il compilatore in quel punto gli mette delle warning perché sebbene viene compilato sicuramente crea problemi.

Be io ho usato spesso la formula prototipo(int array) e non mi ha dato mai errori, forse dipende da che standard ANSI C si usa, magari non era possibile con lo standard originale.

Da link, sembrerebbe possibile

http://www.diit.unict.it/users/michele/didattica/fondamenti/fondamenti/lingC_2.html

Molti compilatori C accettano la sintassi con le quadre. Non bello da vedere ma funziona senza warning. Nessun errore perchè il compilatore lo tratta poi come se fosse un puntatore. Se poi è standard ANSI, non sò.

Per le stringhe... mi pare che il programma NON le usa, ovvero ha si array di char ma sono effettivamente semplici vettori di caratteri, non c'e' bisogno di un elemento in più per il terminatore.
TRANNE qui: strcpy(ritorno, inserimento);
Non la puoi usare !! Se hai array di char NON terminati da NULL non puoi usare le varie istruzioni strxxx() !!!!!
Fai come per gli if con 4 test, copia elemento per elemento (4 righe) oppure un piccolo for

Ho messo globali le variabili array e ammetto che mi risulta più comodo ma il problema persite e sembra non essere causato dai char array. Quando entra in cambia pin e incontra inserimento() il programma si riavvia dopo aver fatto il delay(2000) e il display torna alla grafica principale. Perché invece se uso inserimento da insCodice() funziona perfettamente?

Ragazzi, il problema è solo uno e probabilmente è piccolissimo. L'ho girata e rigirata in tutti i modi ma se uso inserimento() in cambiaPin() non funziona. Solo lì!!!! Incredibile, non capisco :confused:

astrobeed:
Assolutamente no, non puoi dichiarare un array nel prototipo della funzionde

Ahhhhhh, caro astro, qua mi scadi! K&R, paragrafo 5.3, “Pointers and Arrays”:

As formal parameters in a function definition
char s;
and
char *s;
are equivalent; we prefer the latter because it says more explicitly that the parameter is a pointer. When an array name is passed to a function, the function can at its convenience believe that it has been handed either an array or a pointer, and manipulate it accordingly. It can even use both notations if it seems appropriate and clear.

... stiamo filosofeggiando ::slight_smile: , comunque, in effetti, mi pare che anche le norme MISRA C-2012 proibiscano solo l'uso della parola "static" all'interno delle dimensioni dell'array quando passato come parametro:

Rule 17.6
The declaration of an array parameter shall not contain the "static" keyword between the

... vero pure che l'esempio che segue ... non brilla per chiarezza :confused:

Guglielmo

Ragazzi, invece di discutere su come si usano gli array di caratteri potete aiutarmi concretamente?
Ditemi come vi posso aiutare per essere più chiaro… Ripeto che la funzione inserimento() funziona se entro da insCodice() ma non funziona se entro da cambiaPin()

Vi allego come ho ritoccato il programma con le variabili globali:

#include <LiquidCrystal.h>
#include <IRremote.h>


char codice[5]={'1', '2', '3', '4'};
char cod[5];
char inserito[5];
int stato = 0; // acceso o spento
const int sensoreMovimento =  2; // pin del sensore di movimento
const int sensoreInfrarossi = 13; // pin del sensore infrarossi
const int buzzer = 12; // pin del buzzer
const int rosso = 9; // pin per il led rosso
const int verde = 10; // pin per il led verde
const int blu = 11; // pin per il led blu

LiquidCrystal lcd(3, 4, 5, 6, 7, 8);

IRrecv irrecv(sensoreInfrarossi);

decode_results results;

void setup() {
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver

  pinMode(sensoreMovimento,INPUT);

  pinMode(buzzer, OUTPUT);
  
  pinMode(rosso, OUTPUT);
  pinMode(verde, OUTPUT);
  pinMode(blu, OUTPUT);  
  
  lcd.begin(16, 2);
}

void loop() {
  if(stato == 0){
        lcd.print("Allarme spento");
        lcd.setCursor(0, 1);
        lcd.print("1)Cambia pin");
      setColor(0, 0, 255);  // led blu
    if (irrecv.decode(&results)) {
        if(results.value == 0xFFA25D){
          lcd.clear();
          lcd.setCursor(0, 0);
          lcd.print("Inserisci codice");
          bool ins=insCodice();
          if(ins){
            stato=1;
            lcd.clear();
        }  
        }
        else if(results.value == 0xFF30CF){
          lcd.clear();
          lcd.print("Ins. pin attuale");
          bool test=insCodice();
          if(test){
            lcd.clear();
            lcd.print("Nuovo pin");
            cambiaPin();
          }
          else{
            lcd.clear();
            lcd.print("Pin errato!");
            delay(2000);
            lcd.clear();
          }
        }
       irrecv.resume(); // Receive the next value
    
    
  }
  delay(200);
  lcd.clear();
  }

  if(stato == 1){

    lcd.setCursor(0, 0);
    lcd.print("Allarme attivo!");
    setColor(0, 255, 0);  // verde
    if(motionDetected()){
      tone(buzzer, 1000, 3000);
    }
    if (irrecv.decode(&results)) {
        if(results.value == 0xFFA25D){
        stato=0;
        lcd.clear();
        lcd.print("Allarme spento");
        lcd.setCursor(0, 1);
        lcd.print("1)Cambia pin");
        }
       irrecv.resume(); // Receive the next value
    }

    
    
  }
  

}


  void setColor(int red, int green, int blue)
  {
    #ifdef COMMON_ANODE
      red = 255 - red;
      green = 255 - green;
      blue = 255 - blue;
    #endif
    analogWrite(rosso, red);
    analogWrite(verde, green);
    analogWrite(blu, blue);  
  }
  

  void cambiaPin(){
      delay(2000);
      inserimento();
      Serial.println("a");
      codice[0]=inserito[0];
      codice[1]=inserito[1];
      codice[2]=inserito[2];
      codice[3]=inserito[3];
  }

  bool insCodice(){
  inserimento();
    if(codice[0] == inserito[0] && codice[1] == inserito[1] &&
        codice[2] == inserito[2] && codice[3] == inserito[3])
        return true;
    else
        return false;
    
  }

  
  void inserimento(){
    irrecv.resume();
    int i=2;
    int j;
    char inserimento[5]={' ', ' ', ' ', ' '};
    inserito[0]='0';
    inserito[1]='0';
    inserito[2]='0';
    inserito[3]='0';
    while(results.value != 0xFF906F){
      j=0;
      if (irrecv.decode(&results)) {
          if(results.value == 0xFF6897){
            lcd.setCursor(i, 1);
            lcd.write('0');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '0';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF30CF){
            lcd.setCursor(i, 1);
            lcd.write('1');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '1';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF18E7){
            lcd.setCursor(i, 1);
            lcd.write('2');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '2';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF7A85){
            lcd.setCursor(i, 1);
            lcd.write('3');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '3';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF10EF){
            lcd.setCursor(i, 1);
            lcd.write('4');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '4';
                break;
              }
              j++;
            }
          }
  
          if(results.value == 0xFF38C7){
            lcd.setCursor(i, 1);
            lcd.write('5');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '5';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF5AA5){
            lcd.setCursor(i, 1);
            lcd.write('6');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '6';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFF42BD){
            lcd.setCursor(i, 1);
            lcd.write('7');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '7';
                break;
              }
              j++;
            }
          }
          
          else if(results.value == 0xFF4AB5){
            lcd.setCursor(i, 1);
            lcd.write('8');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '8';
                break;
              }
              j++;
            }
          }
          
          else if(results.value == 0xFF52AD){
            lcd.setCursor(i, 1);
            lcd.write('9');
            i+=4;
            while(j<4){
              if(inserimento[j] == ' '){
                inserimento[j] = '9';
                break;
              }
              j++;
            }
          }
  
          else if(results.value == 0xFFA857){
            i-=4;
            lcd.setCursor(i, 1);
            lcd.write(' ');
          }
          
       irrecv.resume();
    }
  
    } //fine while

    inserito[0]=inserimento[0];
    inserito[1]=inserimento[1];
    inserito[2]=inserimento[2];
    inserito[3]=inserimento[3];
  }

    boolean motionDetected(){
       if(digitalRead(sensoreMovimento)==HIGH){
        return true;
       }else{
        return false;
       } 
   }

Comunque se è possibile qualcuno mi può passare un suo contatto, sempre se è disponibile a perdere dieci minuti, per usare una chat più veloce visto che devo risolvere il problema entro stasera?

SukkoPera:
Ahhhhhh, caro astro, qua mi scadi! K&R, paragrafo 5.3, "Pointers and Arrays":

Hai ragione, mi sa tanto che sto cominciando a invecchiare. :smiley:

Vidal23:
il programma si riavvia dopo aver fatto il delay(2000)

Il che presuppone che il software va in crash, dopo la delay hai "strcpy(codice, nuovoPin);" se non correttamente formattati gli array, p.e. manca lo 0x00 alla fine di nuovoPin, questa riga di codice può mandare in overflow la ram con tutte le conseguenze del caso.
Non vedo la funzione insert() nel codice che hai postato, il problema potrebbe essere proprio lei visto che viene invocata esclusivamente dove va in blocco il programma e scrive su un array, se non mette il terminatore 0x00 ecco la causa del blocco.

astrobeed:
Il che presuppone che il software va in crash, dopo la delay hai "strcpy(codice, nuovoPin);" se non correttamente formattati gli array, p.e. manca lo 0x00 alla fine di nuovoPin, questa riga di codice può mandare in overflow la ram con tutte le conseguenze del caso.
Non vedo la funzione insert() nel codice che hai postato, il problema potrebbe essere proprio lei visto che viene invocata esclusivamente dove va in blocco il programma e scrive su un array, se non mette il terminatore 0x00 ecco la causa del blocco.

La funzione insert() non c'è più e nemmeno strcopy, ho postato il nuovo programma.
Comunque non capisco perché non funziona solo se accedo a inserimento() da cambiaPin()

Vado a memoria, a me pare di ricordare dei problemi quando si mette la irrecv.resume(); in posti non adeguati.
Non ricordo neppure dove lo avevo letto, forse sul sito dell'autore della IRRemote.
Di quelle chiamate ne hai due dentro ad inserimento. Prova a commentarne una e poi l'altra. E' un tentativo.
Parlando con @Guglielmo, in un altro thread secondo lui non cambia nulla. Eppure io ricordo qualcosa.

Un riavvio vuol dire che va in crash. Sicuro che passando da cambiaPin non scordi di azzerare una variabile globale ?
Cosa fanno nella inserimento() quei vari cicli while per i vari tasti da 0 a 9 ? Perchè i lo aumenti di 4 ? Non l'ho capito.
Riempi il codice della inserimento() di Serial.println() in vari punti con dentro 1, poi 2, poi 3 e da serial monitor cerca di capire "quando" va in crash (e quindi in che punto) in base alle println() che ha fatto.

Suggerimenti in generale:

  1. Usa CTRL+T nel codice che indenta meglio di quel che hai fatto. Una fatica bestiale a capire dove finiscono i tuoi cicli. Le graffe non bisogna "nasconderle".
  2. gli array rimettili con dimensione 4, questo di sicuro almeno un warning lo da:
char codice[5]={'1', '2', '3', '4'};     // brutto, cosa viene messo nella 5° cella ??
  1. i pin definiscili con const byte e non const int
  2. i tasti IR definiscili in testata con dei nomi più leggibili, esempio:
    #define KEY_0 0xFF6897
    #define KEY_9 0x....