Lettura dati da pin analogici

Oggi stavo rivedendo la gestione dei pin analogici quando per errore ho cancellato dopo modifica uno sketch che avevo preparato.
Va beh, lo riscrivo ma al momento di testarlo inizio a leggere valori che non mi tornano.
Ho quindi buttato giù velocemente quattro righe in modo da leggere sul serial monitor i valori che effettivamente arduino mi passa:

unsigned long tempoPrecedente = 0;
unsigned long tempoPrecedente1 = 0;
unsigned long tempoPrecedente2 = 0;
unsigned long tempoPrecedente3 = 0;
unsigned long tempoPrecedente4 = 0;

void setup() {
  Serial.begin(9600);

}

void loop() {
  

if (millis() - tempoPrecedente > 5000) {
    tempoPrecedente = millis();
    int consumo_generale = analogRead(A0);
    int consumo_generale2 = (analogRead(A0)*100/1023);
    Serial.println(consumo_generale);
    Serial.println(consumo_generale2);
    Serial.println("--");
    
    }
    
    if (millis() - tempoPrecedente1 > 5100) {
    tempoPrecedente1 = millis();
    int sens_allagamento_lavastoviglie = analogRead(A1);
    int sens_allagamento_lavastoviglie2 = (analogRead(A1)*100/1023);
    Serial.println(sens_allagamento_lavastoviglie);
    Serial.println(sens_allagamento_lavastoviglie2);
    Serial.println("----");
    
    }

    if (millis() - tempoPrecedente2 > 5200) {
      tempoPrecedente2 = millis();
    int sens_allagamento_lavatrice = analogRead(A2);
    int sens_allagamento_lavatrice2 = (analogRead(A2)*100/1023);
    Serial.println(sens_allagamento_lavatrice);
    Serial.println(sens_allagamento_lavatrice2);
    Serial.println("------");
    
    }

    if (millis() - tempoPrecedente3 > 5300) {
      tempoPrecedente3 = millis();
    int sens_vasi_bagnati = analogRead(A3);
    int sens_vasi_bagnati2 = (analogRead(A3)*100/1023);
    Serial.println(sens_vasi_bagnati);
    Serial.println(sens_vasi_bagnati2);
    Serial.println("--------");
    
    }

    if (millis() - tempoPrecedente4 > 5400) {
      tempoPrecedente4 = millis();
    int sens_luminosita_rep_giorno = analogRead(A4);
    int sens_luminosita_rep_giorno2 = (analogRead(A4)*100/1023);
    Serial.println(sens_luminosita_rep_giorno);
    Serial.println(sens_luminosita_rep_giorno2);
    Serial.println("----------");
    
    }
}

Ok, lo sketch legge i valori dai pin analogici e mi indica valore in digitale ed in percentuale.
Non posso utilizzare delay e quindi utilizzo millis().

Consapevolissimo del fatto che durante il test ho lasciato i pin scollegati e quindi i valori sono ballerini, perché ottengo anche valori negativi???

Ecco cosa leggo ad esempio sul serial monitor:

336
-31
----
426
-22
------
406
-24
--------
304
174
--
120
120
----------
336
-31
--
341
-30
----
389
-26
------
387
-26
--------
372
-27
----------

Per ogni coppia, il primo rappresenta quanto letto sul pin analogico (valori da 0 a 1023), il secondo dovrebbe darmi il valore in percentuale

Vai in overflow su variabili signed :wink:

Usa unsigned long anche sulle variabili locali

Ciao,
prova a sostituire gli int della percentuale con un bel float. Ovviamente in parentesi metterai

float variabile_percentuale = float(analogRead(0))*100/1023

ciao, Giovicavalla

Grazie ragazzi!

Che ciufolo che sono!!!
Senza scomodare i float (non ho bisogno dei decimali) è bastato moltiplicare per "1023.0"

Sinceramente non riesco a comprendere il problema. Perché vado in overflow?
Perché risolvo moltiplicando per xxx.0?

Avevo affrontato il problema tempo fa ma non ricordo bene...

Grazie!

Tu allochi un int, che nella prima operazione, esempio 336*100 va in overflow,
Quindi se anche guardando il totale il numero venendo diviso per 1024 rientrerebbe in un int, l overflow è già avvenuto in precedenza.

Fainun cast a UL dei valori e dovresti risolvere

Testato:
Tu allochi un int, che nella prima operazione, esempio 336*100 va in overflow,
Quindi se anche guardando il totale il numero venendo diviso per 1024 rientrerebbe in un int, l overflow è già avvenuto in precedenza.

Prova conte ti ho detto a dichiarare unsigned long anche le altre variabili tipo sensore allagamenti

Ah, ecco, verissimo! E' la prima operazione (moltiplicazione) che mi frega :slight_smile:
Ovviamente con unsigned long nessun problema!

Ma approfondendo... Se faccio:

int sens_luminosita_rep_giorno2 = analogRead(A4) * (100/1023);

ottengo sempre 0. Perché divido 100 per 1023 che fa 0.09 ma essendo intero viene semplicemente recepito come 0. quindi analogRead(A4) * 0 è corretto che sia 0.

Se invece faccio così funziona:

int sens_luminosita_rep_giorno2 = analogRead(A4) * (100/1023.0);

Vediamo se ho capito... scrivendo di dividere per 1023.0 forzo l'operazione 100/1023.0 in float, esatto? Il risultato è 0.0977 che viene moltiplicato per analogRead che restituisce comunque un intero senza crearmi problemi...

Esatto?

Senza scomodare i float (non ho bisogno dei decimali) è bastato moltiplicare per "1023.0"

Ma stai proprio costringendo Arduino a usare dei float se aggiungi una posizione dopo la virgola.

Un int con segno interpreta i numer da 0 a 32767 come numeri positivi e dal 32768 al 65636 (usa il Bit piú alto come segno negativo) se calcoli un numero che é maggiore di 32767 (e minore di 65535) il bit 15 viene considerato il segno negativoe percui Ti esce dal calcolo un numero negativo.

Ciao Uwe

Un numero è di per se la dichiarazione di una variabile, se non si specifica nulla 10 significa allocare una int

Facendo cosi decidi tu che tipo deve essere la variabile numerica

byte consumo_generale2 = (analogRead(A0)*100UL/1023UL);

una cosa è l'operazione fra analogRead*100 altro è l'assegnazione del risultato a consumo_generale
L'operazione iniziale va memorizzata in una variabile che tu non hai esplicitamente dichiarato, viene scelta in automatico il tipo di dato, e se stai operando su due int viene allocato uno spazio int e nel tuo caso vai in overflow. Cosi invece con 100UL costringi ad allocare un UL e non hai problemi.
Il risultato finale invece rientrera sempre in un tipo byte quinddi quella puoi dichiararla byte

Credo che puoi dichiarare anche solo 100UL lasciando 1024 normale, perché basta uno dei tipi ad essere UL che viene allocato UL per il risultato

Sul 1024.0 stesso discorso, dichiari implicitamente float.
Pero visto che lasci normali gli altri due mi aspetterei comunque overflow sulla prima operazione ?

Qua si continua ad imparare ed è bellissimo.
Grazie!

Uwe, se io utilizzo

float sens_luminosita_rep_giorno2 = analogRead(A4) * (100/1023);

ottengo valori del tipo 32.15 - 12.54 - 41.33 (valori che ho inventato adesso).
Quindi se io dichiaro la mia variabile come float avrò numeri con decimali. Ci siamo.

Se invece utilizzo:

int sens_luminosita_rep_giorno2 = analogRead(A4) * (100/1023.0);

ottengo valori 32 - 13 - 41 (anche qua valori inventati).
Dichiaro la mia variabile un intero e quindi non ho decimali (e ci mancherebbe).

@Testato: anche lasciando gli altri come interi, moltiplicando per 1023.0 non ho overflow.

pero' cosi' hai cambiato le priorita' di esecuzione, con le parentesi. Quindi ora nel tuo caso fai prima 100/1023.0 e solo dopo moltiplichi per analogread, hai cambiato le carte in tavola :slight_smile:

e comunque consumi piu' risorse perche' fai operazioni float quando poi in realta' non ti servono.

Ti basta fare:
byte consumo_generale2 = (analogRead(A0)*100UL/1023UL);