[RISOLTO] Recupero dati non corretto da un Array

Salve ragazzi getto la spugna e chiedo aiuto a voi.
Premettendo che sto cercando di decodificare i telecomandi IR senza la famosissima libreria di “Ken Shirriff” e ahimè senza oscilloscopio.
Stavo scrivendo un Sketch che mi tirasse fuori la scala dei tempi del segnale (alto e basso) per poter fare un grafico in excel.
Telecomando Sony e un Ricevitore Demodulatore IR TSOP2438 collegato ad Arduino UNO.
Il primo sketch utilizzava dei serial print ma lavorando nell’ordine dei microsecondi ho paura che i serial print ritardino troppo il programma.
Stavo cercando di migliorarlo ed anziché ogni volta durante lo sketch usare il serialprint volevo scrivere i dati letti su un array per poi, una volta uscito dal loop di raccolta dati, stamparli su seriale.
Il programma sembra funzionare, sembra scrivere correttamente i dati nell’array però quando vado a recuperarli sono sballati.

//
//Definizioni Variabili
//
unsigned long T;   //Variabile Tempo
int clk=2000;      //Ciclo in microsecondi
long M=0;   //Variabile azzeramento ciclo
long OFF;
long ON;
byte ps=8;          //Segnale prelevato da Ricevitore Demodulatore IR TSOP2438
byte s;           //Stato Segnale
int x= -1;         //Variabile per condizioni
byte of;
byte y=0;
int timeout=2500;
int on[]={
};
int off[]={
};
//
//Setup
//
void setup(){
  Serial.begin(9600);
  pinMode(ps,INPUT);
  Serial.println("Ready: ");         //Programma Pronto
  }
//
//Programma
//
void loop(){  
  s=digitalRead(ps);


  if (s==0 && OFF<timeout){                         //Se 0 sta ricevendo 
    s=digitalRead(ps);               //Leggo segnale
    y=1;

    T=micros();
    M=T;
    while (s==0){                     //Fino a che il segnale è 0
      T=micros();                    //Aggiornamento Tempo
      s=digitalRead(ps);             //Lettura segnale per uscita dal ciclo      
      ON=T-M;                        //ON misura per quanto tempo è stato acceso
    }

    T=micros();
    M=T;                             //Azzero il contatore
    while (s==1 && OFF<timeout){                     //Fino a che il segnale è 1
      T=micros();                    //Aggiorno Tempo
      s=digitalRead(ps);             //Leggo segnale      
      OFF=T-M;                       //OFF misura per quanto tempo è stato spento   
    }


    if (x<50){
    x++;
    Serial.println(x);
    on[x]=ON;
    Serial.println(on[x]);
    off[x]=OFF;
    Serial.println(off[x]);
    }
  }
  else{
    if (y==1){
      
      while (of<=x){
        int a=on[of];
        Serial.println(of);
        int b=off[of];
        Serial.println(of);
      Serial.println(a);
      Serial.println(b);
      of++;
      }
      y=0;
      OFF=0;
      of=0;
      x=-1;
      delay(1000);
    }
  }
}

dovrebbe vedersi in allegato una lettura su seriale
I tempi al momento sono sballati per via dei serial print infatti gli unici giusti sono, o almeno dovrebbero, i valori scritti su array[0] (lo “start” del segnale).
Nell’allegato:

  • nel primo blocco i serial print in fase di scrittura
  • nel secondo blocco i serial print in fase di lettura

Se potete darci un occhio mi farebbe comodo mi basta capire perché non recupera correttamente i dati XD

In linguaggio C gli array non vengono controllati se scrivi "oltre" la loro dimensione.
Questo è una "cavolata":

int on[]={};

In questo modo crei un array vuoto, senza elementi. Poi comunque tu scrivi nell'array senza che ci sia spazio per gli elementi.
Te lo fà fare, ma stai scrivendo in zone di memoria non ammesse.

Devi per forza dimensionare gli array
int on[100]; Facendo attenzione di accedere agli elementi da 0 a 99 (in questo esempio)

Oppure devi usare l'allocazione dinamica, ma è un'altra storia. Tu stavi cercando di fare allocazione dinamica (ammessa ad esempio in Basic) ma con una sintassi errata per il C.

P.S. Se i dati letti sono dei byte, int è 2 byte, uno spreco.

Premetto che è la prima volta che li utilizzo quindi potrebbero esserci moolti errori "cavolata".....l'array lo compilo finché legge i dati quindi non devo dichiararlo subito?

P.S. Se non lo scrivo così non compila il programma

nid69ita:
P.S. Se i dati letti sono dei byte, int è 2 byte, uno spreco.

Arrivo ad un valore di on[0] di 2400 quindi mi sembra giusto int

ZG84:
Premetto che è la prima volta che li utilizzo quindi potrebbero esserci moolti errori "cavolata"

Non c'e' problema.

DEVI dichiararne la dimensione subito. Non basta dichiararlo come nome. E' il numero di elementi che lo compongono che è importante.

Quando dichiari una variabile semplice (int x;) dichiari una variabile ma anche "allochi" una cella di memoria di dimensione del tipo che utilizzi: x=12;
Quando dichiari un array DEVI dire quanti elementi lo compongono. int arr[5]; vuol dire 5 celle di memoria (in realtà 10 byte) e quindi potrai avere le celle da 0 a 4.
Se non lo fai lo spazio di memoria NON viene creato. Il C non controlla che tu scrivi dove non potresti (un linguaggio tipo il basic controlla).
Non controlla neppure se vai oltre l'ultimo elemento, esempio di prima:

int arr[5];
arr[6]=12;

Il C non ti dà errore, son cavoli tuoi controllare di non uscire dalla dimensione.

Si ho capito come utilizzare l'array in maniera "classica" ma il problema e che io non so quanti dati verranno scritti nell'array per quello l'ho dichiarato così.
L'array lo compila durante il ciclo if mentre durate il ciclo else dovrebbe recuperare i dati.
La cosa strana e che quando vado a fare la lettura subito dopo la scrittura il dato è corretto mentre quando vado a fare la lettura a fine ciclo non recupera i dati in modo corretto.

Perchè se l'array viene scritto senza una zona di memoria pre-allocata allora non c'e' sicurezza che i dati non vengano "persi".
Non sai quanti saranno gli elementi a priori ?

@ZG84 : Il tuo metodo E' SBAGLIATO in C ed il fatto che, casualmente, quando vai a fare la lettura subito dopo la scrittura il dato è corretto, è solo fortuna ... perché si vede che ... non hai sovrascritto ancora nulla ...

Il C non effettua alcun controllo sugli array ... se tu lo definisci di 1 elemento e poi scrivi nell'elemento 100 ... lui te lo fa fare, peccato che va a sovrascrivere chissà cosa senza alcun controllo !!! :astonished:

Se ti serve allocare dinamicamente dello spazio, esistono apposite funzioni per farlo ...
... guardati la malloc(), realloc() e free() (sono descritte QUI ... fanno parte della stdlib di AVR) ma fai molta attenzione ... su una MCU non hai "garbage collection" e quindi ... TUTTA la gestione della memoria così allocata è da fare da parte del tuo programma.

Uomo avvisato ... :grin: :grin: :grin:

Guglielmo

Ti faccio un esempio di allocamento dinamico della memoria e un esempio in C classico di tale uso:

Allocazione dinamica della memoria di un array di int:

int numeroElementi = 12, i;
int *arrayInt;
/* Alloco dinamicamente (sizeof ( int ) * numeroElementi) byte per l'array 
arrayInt = (int*) malloc ( sizeof ( int ) * numeroElementi );
/* Inizializzo gli elementi dell'array con il valore 0 */
for ( i = 0; i < numeroElementi; i ++ ) {
    arrayInt[i] = 0;
}
/* Adesso disalloco la memoria */
free ( arrayInt );

Adesso ti faccio di utilizzo pratico in C “classico”:

#include <stdio.h>
#include <stdlib.h>

int main ( ) {
    int n, *array, i;
    printf ( "Inserisci il numero di elementi del vettore: " );
    scanf ( "%d", &n );
    /* Riempio il vettore */
    for ( i = 0; i < n; i ++ ) {
        printf ( "elemento %d = ", i );
        scanf ( "%d", &array[i] );
    }
    /* Adesso stampo tutti gli elementi dell'array moltiplicati per 2 */
    for ( i = 0; i < n; i ++ ) {
        printf ( "Il doppio dell'elemento con indice %d è: %d", i, array[i] * 2 );
    }
    /* Per disallocare la memoria */
    free ( array );
    return 0;
}

Spero ti sia abbastanza chiaro come utilizzare e a cosa serve l’allocamento dinamico della memoria
Ciao :smiley:

ps: per altre informazioni più dettagliate guarda questo link: malloc - C++ Reference

@Duecce : ... troppo facile ... ]:smiley:

... lui neanche sa QUANTI elementi gli servono (... anche perché altrimenti allocherebbe direttamente l'array non ti pare :wink:) ... quindi il primo lo può allocare con la malloc(), ma poi deve continuare a fare realloc() ... e ... hai idea del casino che può venire fuori su una piccola MCU come quella di Arduino vero ??? :wink:

Guglielmo

Si scusa hai completamente ragione, nella fretta non ho guardato il codice, comunque ora che l’ho visto, secondo me ti conviene fare un’altra cosa, dovresti fare una specie si quantizzazione, intanto inizializzi l’array nel modo giusto, e poi dovresti controllare quando l’array è pieno, e a quel punto forzi la scrittura su terminale, altrimenti potresti utilizzare una lista al posto di un array, così non hai più problemi, però come già accennato dagli altri su arduino fare una cosa del genere è come mangiarsi la memoria.
Io opterei per la prima soluzione che ti ho detto, cioè quella di limitare il numero di elementi dell’array e forzare la scrittura quando è pieno, e poi ripartire.
Ciao :smiley:

Difatti .... XD

La RAM di Arduino è quella che è, per cui comunque non potrebbe andare avanti all'infinito e allora ... comunque che dimensioni l'array per il MASSIMO numero degli elementi e via ... tanto di più non ce ne stanno :grin: :grin: :grin:

Guglielmo

Son di nuovo qua ho risolto grazie ai suggerimenti.....per il momento l'allocamento dinamico :fearful: e fuori dalla mia portata...si insomma sarà il terzo programma forse quarto che faccio per Arduino quindi mi studio l'occorrente man mano che mi serve perché purtroppo non ho tempo di dedicarmi a tempo pieno allo studio del linguaggio di programmazione.

Diciamo che ho risolto ipotizzando quanti elementi serviranno e quindi anziché dichiarare erratamente:

int on[]={};

che effettivamente, documentandomi meglio sull'inizializzazione degli Array, non sta ne in cielo ne in terra :*

dichiarando

int on[50];

Non perde più i dati per strada :smiley:
Adesso sistemo un po il programma perché gli avevo fatto diverse modifiche nel tentativo di riuscire a recuperare i dati per esempio l'array era uno solo in principio scriveva i risultati uno dietro l'altro.
Adesso posso proseguire tranquillamente per la mia impresa folle XD
Impostando la variabile x non ci sono problemi di scrittura lettura fuori dall'array.

Grazie a nid69ita, gpb01, Duecce delle dritte e dell'interessamento