Consigli primi passi misurazione resistenze

Buongiorno a tutti,
innanzi tutto mi scuso per i termini magari non troppo corretti,
ho letto diversi post sul forum e so che si tratta di un tema trito e ritrito,
ma la mia richiesta non è rivolta solo alla misurazione, ma piuttosto al metodo in generale,
la mia esigenza nasce dal voler misurare delle impedenze variabili di tre segnalatori di livello posti all’interno di tre serbatoi, il mio desiderio è quello di utilizzare dei misuratori di livello commerciali, questi misuratori variano la restenza al variare del livello del liquido contenuto, per fare questo leggendo nei vari post ho riscontrato diverse opinioni anche differenti e dopo alcune valutazioni ho pensato di:

  • utilizzare la tensione interna dell’Arduino uno 1.1 V come valore di riferimento
  • scartare le prime letture della tensione di riferimento per evitare errori visto che verrà usata anche per altro in seguito
  • delle misure effettuate fare una media sui 10 valori rilevati
  • arrotondare il valore calcolato della resistenza

Vorrei sottoporvi quanto ho composto per consigli e commenti, ho appena iniziato a studiare il linguaggio di programmazione e quindi quello che ho composto non è tutta farina del mio sacco, ma si tratta di parti copiate e adattate, spero abbastanza bene.

Ho allegato sia lo schema di prova che lo sketch, dove le resistenze segnate in verde sono le resistenze note di riferimento e quelle segnate in blu sono quelle da misurare,
ho eseguito lo sketch e funziona, ho misurato i valori con un multimetro e sono abbastanza corrispondenti, ma vorrei sapere se il lavoro è buono, o è solo fortuna che i valori siano abbastanza corrispondenti alla realtà.

Grazie a tutti in anticipo per i commenti e le correzioni.

Misurazione_resistenze_per_livelli_serbatoi_con_riferimento_int.ino (3.3 KB)

ciao
non è fortuna, è un lavoro fatto bene

se ho ben capito tu hai

  1. misurato il riferimento ADC (cosa che fanno in pochi)
  2. misurato le resistenze campione (cosa che fanno altri pochi)
  3. calcolato le resistenza con le buone vecchie formule dell'elettrotecnica

nulla di sbagliato in questo, anzi tanto di cappello

non mi è però chiaro perché arrotondi il valore calcolato
e perché lo dividi per 10

invece
un paio di consigli, se mi permetti

  1. non serve scartare le prime 100 letture, serve di scartare la "prima" lettura dopo aver cambiato ingresso, non le prime 100 in assoluto

  2. inutile usare una variabile intera per conservare un numero di piedino, ancora di più usare una varabile intera per conservare il valore di una macro, usa direttamente la macro

  3. i commenti servono a spiegare quello che si fa, ma tradurre in italiano lo statement appena scritto è inutile, è sempre possibile farlo

i commenti servono per spiegare a cosa serve quello che si sta facendo

esempio

    volt3=analogRead(pin2);//leggo il valore e lo scrivo alla variabile volt3

non serve a nulla, lo vedo benissimo che leggi un valore e lo assegni a una variabile

mi servirebbe invece sapere come intendi gestirlo

  1. hai ripetuto tre volte lo stesso codice, con variabili trine e triplo "litania" di comandi
    usavi un ciclo for su un array di piedini e di variabili, scrivevi un programma più espandibile e più controllabile e modificabile
    ma questo convengo che è un passo ulteriore, non ho ben capito come te la cavi con la programmazione

  2. chiudere e riaprire subito una graffa non ha molto senso, a meno che tu non voglia "isolare" gruppi di variabili omonime, ma non mi sembra il tuo caso

Ducembarr innanzi tutto grazie per il tuo commento,
il mio post è stato scritto proprio per ricevere commenti di questo tipo,

  1. non serve scartare le prime 100 letture,
    non lo sapevo, ho letto alcuni post e pensavo fosse corretto, scarterò dunque solo la prima,

  2. inutile usare una variabile intera per conservare un numero di piedino, ancora di più usare una varabile intera per conservare il valore di una macro, usa direttamente la macro,
    mi pacerebbe sapere come fare, purtroppo il mio livello di programmazione è base, ho iniziato da pochi giorni,

  3. i commenti servono a spiegare quello che si fa, ma tradurre in italiano lo statement appena scritto è inutile, è sempre possibile farlo
    è un metodo che ho imparato ad usare quando iniziato a programma VBA e lo trascino per mia pura comodità, quando avrò imparato a leggere il codice con dimestichezza eliminerò gran parte dei commenti e terrò solo i più significativi, ma prima devo imparare quali sono

  4. hai ripetuto tre volte lo stesso codice
    si hai ragione proverò a ridurlo ma ancora non so come fare, ogni aiuto è ben accetto

  5. chiudere e riaprire subito una graffa non ha molto senso, a meno che tu non voglia "isolare" gruppi di variabili omonime, ma non mi sembra il tuo caso
    non lo sapevo, ho visto diversi sketch scritti così e pensavo fosse utile.

Ti ringrazio ancora per i consigli, e cercherò sicuramente di migliorare, sono alle prime armi.

criboe:
quando avrò imparato a leggere il codice con dimestichezza eliminerò gran parte dei commenti e terrò solo i più significativi, ma prima devo imparare quali sono

Chiaro, adesso stai annotando cosa fa la sintassi, poi a cosa servirà l’operazione.
Però… un commento dovrebbe essere almeno giusto :wink: Vediamo questa parte:

volt1 = analogRead(pin0); //leggo il valore e lo scrivo alla variabile volt1
int X1=0;
for (int i=0;i<=9; i++)//leggo 10 valori
X1=X1+volt1;//sommo le letture
volt1=X1/10;// faccio la media delle letture

Il commento “leggo 10 valori” è sbagliato, fai un ciclo di qualcosa, ma di cosa? Non di letture, ma solo di somma ripetuta di un valore (sempre lo stesso) con la variabile X1, in pratica moltiplichi per dieci il valore di ‘volt1’ letto prima del ciclo. E questo evidenzia un errore, o nel commento, o di logica: pensavi di fare una cosa mentre ne fai un’altra.

Questa era solo la premessa per dire che l’indentazione e le parentesi sono importanti(ssime) per vedere a colpo d’occhio cosa è subordinato/dipendente a/da cosa.

In particolare un’istruzione if/else/for/while esegue UNA istruzione, quella scritta appena dopo, oppure un blocco di istruzioni purché racchiuse tra graffe.

Se la scrittura era indentata, e magari anche con le parentesi per indicare esplicitamente e senza ambiguità il contenuto del for, l’errore sarebbe apparso subito evidente, all’interno del for non viene effettuata alcuna lettura ma solo una somma ripetuta:

volt1 = analogRead(pin0); //leggo il valore e lo scrivo alla variabile volt1
int X1 = 0;
for (int i=0; i<=9; i++)//leggo 10 valori
{
    X1 = X1 + volt1;//sommo le letture
}
volt1=X1/10;// faccio la media delle letture

criboe:
Ducembarr innanzi tutto grazie per il tuo commento,
il mio post è stato scritto proprio per ricevere commenti di questo tipo,

  1. inutile usare una variabile intera per conservare un numero di piedino, ancora di più usare una varabile intera per conservare il valore di una macro, usa direttamente la macro,
    mi pacerebbe sapere come fare, purtroppo il mio livello di programmazione è base, ho iniziato da pochi giorni,

.

guarda che non è come sai programmare, ma quanto "easy" sai pensare

in effetti hai faticato "di più" a inizializzare una variabile usando una macro

 int pin0=A0;//dichiaro il pin 0 assegnato all’ingresso analogico A0
    volt2=analogRead(pin1);//leggo il valore e lo scrivo alla variabile volt2

fa lo stesso lavoro di

volt2=analogRead(A0);

con una variabile in meno, oltretutto senza obbligare il compilatore a leggere una variabile e usarne il valore
infatti le macro sono risolte a compile-time e non passano per la memoria ram

questo l'ho detto per riallacciarmi ad un'altra discussione, dove viene consigliato di usare "const int" invece che #define...

se stai imparando impara bene,
non si usano variabili per valori costanti pre-conosciuti al momento della scrittura del programma, per quello ci sono le macro (ovvero le #define)
non si mettono commenti inutili, se spiega perché si fa qualcosa, non come, come lo si vede dal programma
si indenta bene (ma qui ognuno ha una "religione" differente)

Ducembarr:
questo l'ho detto per riallacciarmi ad un'altra discussione, dove viene consigliato di usare "const int" invece che #define...

In realtà il compilatore è piuttosto furbo ad ottimizzare e non c'è differenza di occupazione di memoria a livello di compilato.

Con il preprocessore puoi fare altri giochini simpatici che con il const non puoi fare, ma questo è un'altro discorso.

Guglielmo

Dettaglio ...
due programmini:

#define pin 13
void setup() {
   pinMode(13, OUTPUT);
}
void loop() {
  digitalWrite(13, HIGH);
  delay(500);
   digitalWrite(13, LOW);   
   delay(500);
}

... che usa la #define ...

const int pin=13;
void setup() {
   pinMode(pin, OUTPUT);
}
void loop() {
  digitalWrite(pin, HIGH);
  delay(500);
   digitalWrite(pin, LOW);   
   delay(500);
}

... che usa la const int ...

Ebbene, se andiamo a vedere l'occupazione di memoria con avr-size abbiamo per il primo esempio :

avr-size -C sketch_test1.cpp.elf
AVR Memory Usage
----------------
Device: Unknown
Program: 4818 bytes
(.text + .data + .bootloader)
Data: 155 bytes
(.data + .bss + .noinit)

... e per il secondo esempio :

avr-size -C sketch_test2.cpp.elf
AVR Memory Usage
----------------
Device: Unknown
Program: 4818 bytes
(.text + .data + .bootloader)
Data: 155 bytes
(.data + .bss + .noinit)

... ovvero ... identici valori.

Quale dei due preferire se non si debbono fare cose particolari a livello di preprocessore? Sicuramente la versione con 'const' che evita possibili sviste ed errori del tipo ...

#define pin 13;
void setup() {
    pinMode(pin, INPUT);
}
void loop() {
    digitalWrite(pin, HIGH);
    delay(500);
    digitalWrite(pin, LOW);
    delay(500);
}

... che, ovviamnete, in compilazione da un bell'errore :smiley:

Insomma, avr-gcc è piuttosto furbo ad ottimizzare e risparimare memoria quindi ... usiamo quello che veramente serve al momento giusto :wink:

Guglielmo

sarà

ma a me questo programma qui

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento



   Creato con IDE 1.8.10
*/


//#define pin 13
//byte pin = 13;
const byte pin = 13;



void setup()
{
   pinMode(pin, OUTPUT);
}
void loop()
{
   digitalWrite(pin, HIGH);
   delay(500);
   digitalWrite(pin, LOW);
   delay(500);
}

compilato nelle tre maniere mi dice due cose differenti

#define pin 13
Lo sketch usa 924 byte (2%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 9 byte (0%) di memoria dinamica, lasciando altri 2039 byte liberi per le variabili locali. Il massimo è 2048 byte.

byte pin=13;
Lo sketch usa 936 byte (2%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 9 byte (0%) di memoria dinamica, lasciando altri 2039 byte liberi per le variabili locali. Il massimo è 2048 byte.

const byte pin=13;
Lo sketch usa 924 byte (2%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 9 byte (0%) di memoria dinamica, lasciando altri 2039 byte liberi per le variabili locali. Il massimo è 2048 byte.

dove effettivamente la versione define e la versione const sono uguali

le cose si fanno interessanti se si comincia a fare qualcosa in più di creare e usare una variabile intera
con questo programma:

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento



   Creato con IDE 1.8.10
*/


//const char nome[] = "acqua";
//char nome[] = "acqua";
#define nome "acqua"


void setup()
{
   Serial.begin(9600);
}
void loop()
{
   Serial.println(nome);
   delay(500);
}

la cosa non sembra essere cambiata

const char nome[] = "acqua";
Lo sketch usa 1628 byte (5%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 194 byte (9%) di memoria dinamica, lasciando altri 1854 byte liberi per le variabili locali. Il massimo è 2048 byte.

stessa cosa per la define

char nome[] = "acqua";
Lo sketch usa 1646 byte (5%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 194 byte (9%) di memoria dinamica, lasciando altri 1854 byte liberi per le variabili locali. Il massimo è 2048 byte.

ma se si cambia il programma in:

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento



   Creato con IDE 1.8.10
*/


//const char nome[] = "acqua";
//char nome[] = "acqua";
#define nome "acqua"


void setup()
{
   Serial.begin(9600);
}
void loop()
{
   Serial.print("Valore della variabile: ");
   Serial.println(nome);
   Serial.print("Indirizzo della variabile: ");
   Serial.println((int) & nome);
   delay(500);
}

si ottiene per tutte tre le versioni la stessa occupazione

Lo sketch usa 1966 byte (6%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 246 byte (12%) di memoria dinamica, lasciando altri 1802 byte liberi per le variabili locali. Il massimo è 2048 byte.

ma, qui c'è la sorpresa:

in nessuna delle tre versioni ha la parola "acqua" allo stesso indirizzo, ad indicare che "comunque" una differenza esiste, anche se i programmi sembrano uguali

Caspita una marea di commenti interessanti,
grazie raccolgo tutti gli insegnamenti e mi ci metto subito al lavoro.

Ducembarr:
in nessuna delle tre versioni ha la parola "acqua" allo stesso indirizzo, ad indicare che "comunque" una differenza esiste, anche se i programmi sembrano uguali

... certo ch qualche differenza c'è ... ovviamnete il compilatore ottimizza le due cose seguendo due strade che ... portano però allo stesso risultato pratico.

Ripeto, cerca sul forum le discussioni passate, fatte quando c'era Astrobeed e troverai parecchi dettagli.

Guglielmo

hai link?

Ducembarr:
hai link?

… e se li avevo sottomano ti pare che non te li passavo ? :smiley: :smiley: :smiley: … tocca andare a cercare con … il “meraviglioso” motore di ricerca che abbiamo … ::slight_smile:

Guglielmo

In ogni caso, ricordo che la cosa si riassumeva così ...
... se usi un "const" viene creata una variabile di tipo costante sfruttando la flash, se usi #define viene sostituito il valore in fase di compilazione direttamente nell'espressione. Entrambe le cose usano la stessa occupazione di memoria.

La #define è molto comoda se fai, ad esempio macro o calcoli direttamente tra costanti che vengono tutti fatti a livello di preprocessore e non poi in fase di esecuzione.

Se vogliamo proprio cercare un vantaggio di una rispetto all'altra soluzione e probabilmente nella velocità di esecuzione del codice e non nel risparmio di memoria.

Nel caso della #define il valore è già sostituito al posto giusto nell'espressione che usa la costante, nel caso della "const" il valore si trova in flash e ocorre recuperarlo, operazione che richiede qualche ciclo macchina di più :slight_smile:

Credo sia tutto ... ::slight_smile:

Guglielmo

gpb01:
In ogni caso, ricordo che la cosa si riassumeva così ...
... se usi un "const" viene creata una variabile di tipo costante sfruttando la flash, se usi #define viene sostituito il valore in fase di compilazione direttamente nell'espressione. Entrambe le cose usano la stessa occupazione di memoria.

Guglielmo

temo la cosa non sia possibile

se io scrivessi:

const int lettura=analogRead(A0);

avrei una variabile costante che non può risiedere nella flash, essendo che viene conosciuta solo in esecuzione

la define potrebbe essere in flash, la const non dovrebbe andarci

dopo provo

eccolo qua

tagliato la testa al toro

a parte le ottimizzazioni che il compilatore fa alle volte

const e define sono concettualmente differenti

   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento
   Creato con IDE 1.8.10
*/

#define numero 1023

#ifdef numero
#else
const int numero = analogRead(A0);
#endif

void setup()
{
   Serial.begin(9600);
}
void loop()
{
   int valore = analogRead(A0);
   Serial.print("Valore della variabile: ");
   Serial.println(numero);
   delay(500);
}

se si commenta la define il programma viene compilato con una const int conosciuta solo in esecuzione

altrimenti usa una sostituzione

e infatti ci sono 2 byte di differenza di variabili globali tra un caso e l'altro

con la define
Lo sketch usa 1852 byte (5%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 212 byte (10%) di memoria dinamica, lasciando altri 1836 byte liberi per le variabili locali. Il massimo è 2048 byte.

con la const int
Lo sketch usa 1948 byte (6%) dello spazio disponibile per i programmi. Il massimo è 32256 byte.
Le variabili globali usano 214 byte (10%) di memoria dinamica, lasciando altri 1834 byte liberi per le variabili locali. Il massimo è 2048 byte.

ci sono anche quasi 100 byte in più di programma che non provengono dall'inclusione della analogRead, che è citata in tutti e due i casi
strano

sempre idee interessanti

/*
   Una nuova idea DDD
   Del Dinamico Duo

   Sentitevi liberi di copiare
   Sentitevi liberi di trarre ispirazione
   Sentitevi liberi di dare un cenno di ringraziamento
   Creato con IDE 1.8.10
*/

//#define numero 7

#ifdef numero
#else
const int numero = 7;
#endif



void setup()
{
   Serial.begin(9600);
}
void loop()
{
   Serial.print("Valore della variabile: ");
   Serial.println(numero);
   delay(500);
   int a = numero;
   int ritorno = 0;

   switch (a)
   {
      case numero:
         ritorno = 1;
         break;

      default:
         ritorno = 0;
         break;
   }
}



int selezione(const int numero)
{
   int a = numero;
   int ritorno = 0;

   switch (a)
   {
      case numero:
         ritorno = 1;
         break;

      default:
         ritorno = 0;
         break;
   }

   return ritorno;
}

questo codice non è compilabile

perché la const int argomento della funzione selezione() non è una "costante"
provare per credere

eppure lo stesso identico codice nella loop è compilabile

provare per credere

questo dimostra che il compilatore alle volte ottimizza, ma non è detto che lo faccia sempre, e anche quando lo fa non dovrebbe, secondo me

perché se io usassi quel pezzo di codice da un'altra parte mi tirerei addosso una valanga di problemi che non saprei da dove arrivano

astrobeed:
Vero però c'è una differenza sostanziale tra i due metodi, se usi un const viene creata una variabile di tipo
const byte pin 13;
digitalWrite(pin, HIGH);

Utilizzando "#define pin 13" la digitalWrite, dopo la compilazione, diventa equivalente a:

digitalWrite(13, HIGH);

trovato lo ho

min..ia

sembra quasi che lo avessi già letto, uguale al mio è
giurin giuretta non lo avevo letto prima

notevole, e dice anche le stesse cose che dico io

oltre ad aver misurato il tempo che serve per leggere la variabile const invece che avere la macro
187.5 ns, stando alle misure di Astrobeed

non ho idea di come abbia fatto, ma adesso me lo studio

edit

anche qui:

astrobeed:
Dipende da quello che devi fare con quel valore, se parliamo di pin sicuramente conviene la #define, ....

alla fine la logica ha sempre il sopravvento
se K&R non hanno messo "const" nel 'C' forse tutti i torti non li avevano...

T'avevo detto che Astrobeed aveva sviscerato la cosa ... :smiley:

Guglielmo

Ducembarr:
temo la cosa non sia possibile ...

Attento ... noi stavamo parlando dell'uso classico di dichiarazione di una costante, tu stai usando due possibilità che il C++ ti offre per le "const" e che dipendono dall'uso ...

Non ricordo bene tutta la spiegazione, ma mi sembra che in quel caso hai una costante calcolata, valida nello scopo della dichiarazione ma quella costante così calcolata NON può essere usata come una vera costante per, ad esempio, inizializzare le dimensioni di un array ... e non sono neanche sicuro con che versione del C++ la cosa sia possibile. Credo che con C++11 sia fattibile, ma non con C++98/03 ... mah ... NON sono un utilizzatore di C++ ed ho vaghi ricordi :smiley: :smiley: :smiley:

In 'C' comunque è fissato che ... "The result is implementation-defined if an attempt is made to change a const." ... quindi, dipende dall'implementazione del compilatore.

Guglielmo

Ducembarr:
se K&R non hanno messo "const" nel 'C' forse tutti i torti non li avevano...

... emmm ... veramente ce lo hanno messo eccome ... a cominciare dal capitolo 2.4 Declarations:

The qualifier const can be applied to the declaration of any variable to specify that its value will not be changed. For an array, the const qualifier says that the elements will not be altered.

... a proseguire nel paragrafo A.4.4 Type Qualifier

An object's type may have additional qualifiers. Declaring an object const announces that its value will not be changed; declaring it volatile announces that it has special properties relevant to optimization. Neither qualifier affects the range of values or arithmetic properties of the object. Qualifiers are discussed in Par.A.8.2.

... ed in un altra infinità di punti del libro :smiley:

Guglielmo