Nuovo adepto, primi problemi

Salve a tutti,
sono melagodo e ho ricevuto da pochi giorni il mio starter kit con Arduino Uno. Che dire…non sono del settore, e non si sa bene come sia arrivato ad appassionarmi ad Arduino, ma che divertimento!! :slight_smile:

Per evitare di farmi idee sbagliate, ed approfittando del forum, ho delle domande da fare.

-Progetto 02 - Interfaccia per astronave
Nessun problema col codice, lo capisco. Ma sono un po’ in difficoltà sulla logica dei collegamenti dei led.
A pag. 24 del manuale viene presentato il collegamento di base di un led (solo alimentazione). Per come “leggo” il circuito, l’ordine è: 5V–>resistenza da 220ohm–>anodo–>GND.
Nel progetto 02, quando è ora di comandare i led da arduino, l’ordine diventa: pin digitale–>anodo–>resistenza da 220ohm–>GND.
Stesso discorso per l’interruttore.

Insomma, la domanda è: per quale motivo la resistenza viene inizialmente collegata “a monte” del led/interruttore, e poi “a valle”?

  • Progetto 03 - Amorometro
    Ho effettuato i collegamenti come indicato e cominciato a scrivere il codice. Riesco correttamente a rilevare i dati del sensore di temperatura da monitor seriale, tuttavia - nonostante il sensore sia lontano da componenti che potrebbero riscaldarsi, ho delle letture non proprio stabili.
ADC: 141  Volt: 0.69  Gradi: 18.85
ADC: 142  Volt: 0.69  Gradi: 19.34
ADC: 141  Volt: 0.69  Gradi: 18.85
ADC: 142  Volt: 0.69  Gradi: 19.34
ADC: 141  Volt: 0.69  Gradi: 18.85
ADC: 142  Volt: 0.69  Gradi: 19.34
ADC: 141  Volt: 0.69  Gradi: 18.85
ADC: 142  Volt: 0.69  Gradi: 19.34
ADC: 142  Volt: 0.69  Gradi: 19.34
ADC: 141  Volt: 0.69  Gradi: 18.85
ADC: 142  Volt: 0.69  Gradi: 19.34

Ho controllato e ricontrollato i collegamenti e il codice (copiato pari pari, a parte l’utilizzo di nomi variabili più comodi), ma mi pare tutto a posto…

-ultima domanda. Questione SPAZI in fase di scrittura codice.
Dato che sto imparando da zero, e per evitare di prendere brutte abitudini, come devo comportarmi con gli spazi?

Es. if(t1>t2){ oppure if(t1 > t2){
int i=1; oppure int i = 1;?
for(i=1;i<5;i++){ oppure for (i = 1; i<5; i++)?
E via dicendo…

Mille grazie a tutti per l’aiuto :slight_smile:

mela

ciao melagodo,

innanzitutto dovresti presentarti qui: http://forum.arduino.cc/index.php?topic=113640.0

per le tue domande: -la resinstenza "a monte" o "a valle" del led è la stessa cosa, l'importante è che ci sia! :) -la lettura "instabile" è assolutamente normale visto che varia di un punto + o -. -riguardo agli spazi nel codice penso sia una cosa soggettiva ma è meglio che ti risponda un programmatore.

ciao pippo72

Benvenuto melagodo ...

  1. la resistenza e messa in SERIE per limitare la corrente che scorre nel LED. Essendo in SERIE la puoi mettere sia prima che dopo, l'effetto non cambia ... l'importante che la corrente (I) sia limitata ... legge di Ohm ... I = V / R ;)

  2. come ti è stato detto, è del tutto normale, quei sensori hanno ... un ampia tolleranza e quindi ... due letture danno sempre valori diversi .. nei limiti della tolleranza :)

  3. L'inserimento degli SPAZI è del tutto ininfluente per il compilatore (li ignora), ma ... non lo è per chi legge ... quindi, ti consiglio di metterli ... gli occhi di chi leggono ringrazieranno per il minor sforzo XD Ricorda anche gli incolonnamenti e le indentature ben fatte e ... nel IDE, dal menu Tools, la voce Auto Format ... ti metterà a posto molte cose ;)

Guglielmo

Per la resistenza in serie al led, decidi tu dove metterla, visto che è un circuito di tipo serie non è importante la sequenza, sovente per convenzione si usa la R dopo la sorgente di alimentazione positiva, poi il carico (led).

Per l'interruttore o pulsante la resistenza assolve ad un compito leggermente differente dal quella usate con il led. Il pulsante viene usato come dispositivo di input, mentre il led di base è un dispositivo di output, già questa differenza ci suggerisce che non posso fare le stesse assunzioni fatte per l'uno e applicarle all'altro.

La R sul pulsante, serve a fornire ad un pin di ingresso un determinato livello di tensione che può essere prossima a Vcc o a GND, rispettivamente si usa una R di pull-up (tiralo su), o pull-down( tiralo giù).

Se usi una pull-down (tiralo giù) il pin con il pulsante rilasciato deve essere portato giù (verso GND) attraverso la resistenza, premendo il pulsante al pin dovrà arrivare una tensione positiva prossima a Vcc.

Se invece usi una pull-up con il pulsante rilasciato deve essere portato su (verso Vcc) attraverso la resistenza, premendo il pulsante al pin dovrà arrivare una tensione negativa prossima a GND.

Ciò che cambia è la logica di rilevamento, che nel caso di pull-up il pulsante risulta premuto solo quando il pin è prossimo a GND, quindi se digitalRead(nPin, LOW) è vero il pulsante è premuto.

Nel caso di pull-down il pulsante risulta premuto se digitalRead(nPin, HIGH) è vero il pulsante è premuto.

I valori temperatura sono anzi abbastanza stabili, se vuoi puoi provare a fare un media su 10 valori letti e visualizzare questa che dovrebbe apparire più stabile.

Il codice sorgente: Scrivilo il modo che sia maggiormente leggibile, metti gli spazi quando c'è alta concentrazione di codice, cioè es a+5*2/0.1*a+2; e difficilmente leggibile, usa le parentesi e gli spazi al fine di renderlo più leggibile: (a+5) * (2/0.1) * (a+2), se necessario anche ( a+5 ) * ( 2/0.1 ) * ( a+2 );

Occhio alla precedenza implicita degli operatori * / + - ecc, usa le parente per forzare la precedenza.

Scrivi sempre una istruzione per rigo, incluso dichiarazioni e inizializzazione, prenditi tutti gli spazi che vuoi, scrivi nomi di variabili lunghi quanto vuoi tanto la dimensione del firmware non aumenta.

gpb01, mi ha anticipato.

Ciao.

Approvo quello scritto dagli altri. :grin: :grin:

La incertezza di un numero dei valori letti in analogico é normale (141 e 142). È un errore fisiologico del convertitore oltre a una piccola instabilitá della tensione. Per avere numeri piú ripetibili puoi leggere piú volte e fare la media aritmetica. Ciao Uwe

Nel C / C++ è la punteggiatura la parte più importante , dimenticarsi una virgola , un punto e virgola , una parentesi, un = invece di == , un & invece di && etc...... significa bloccare la compilazione o un risultato differente da quello desiderato

Nel C / C++ è la punteggiatura la parte più importante , dimenticarsi una virgola , un punto e virgola , una parentesi, un = invece di == , un & invece di && etc...... significa bloccare la compilazione o un risultato differente da quello desiderato

Parole Sante! ho perso tutta la mattine a capire perchè un programma che avevo modificato non mi funzionava, me la prendevo con tutte le cose difficili, prova qui, e prova la, ma alla fine, il problema era alla base, la parte più elementare, avevo dichiarato ed inizializzato un'array multidimensionale (array[2][16]) ed avevo usato le parentesi tonde per separare i dati delle due righe, mentre avrei dovuto usare quelle graffe!! nessun errore di compilazione e 1/2 giornata persa per una banalità! Quindi mi accodo ai preziosi consigli dati fin ora!!

Buon divertimento!

Grazie a tutti delle risposte, farò tesoro dei vostri consigli. Siete stati davvero uno più chiaro dell’altro!

Primo problema “reale”. Sto cercando di realizzare un semplice termostato; mi mancano alcuni componenti (i relé in primis) ma ho già cominciato a scrivere il codice.

Ecco quello che ho partorito fino ad ora (è il mio primo codice, non mangiatemi :P)

//parametri di temperatura impostati
float temperatura_da_mantenere = 25.0;
float temperatura_tolleranza = 2.0;
float temperatura_incrementale = 0;
float temperatura_media = 0;
int contatore_media_temp = 0;

//sensore e relè
const int sensore_temperatura = A0;
const int relay_riscaldamento = 2;

void setup()
{
	pinMode(relay_riscaldamento, OUTPUT); //imposto il pin del relè come output
	digitalWrite(relay_riscaldamento, LOW);
}

void loop()
{
	 //leggo il valore del sensore e lo converto in gradi
	 int valore_sensore_temperatura = analogRead(sensore_temperatura);
	 float voltage_sensore_temperatura = (valore_sensore_temperatura/1024.0) * 5.0;
	 float temperatura = (voltage_sensore_temperatura - .5) * 100;

	 temperatura_incrementale = temperatura_incrementale + temperatura; //aggiungo la media T  
	 contatore_media_temp++;	//aggiorno il contatore per la T media

	 if(contatore_media_temp == 15) 
		{	
			//se hai fatto 15 letture, calcola la media e resetta i contatori
			temperatura_media = temperatura_incrementale/15;

			contatore_media_temp = 0;		   
		    temperatura_incrementale = 0;
		}

	 //se temperatura inferiore a quella fissata meno la tolleranza: attiva relè; altrimenti disattiva
	 if(temperatura_media < (temperatura_da_mantenere - temperatura_tolleranza))
	 {
	 	digitalWrite(relay_riscaldamento, HIGH);		     
	 }
	 else 
	 {
	 	digitalWrite(relay_riscaldamento, LOW);
	 }

	 delay(1000);

}

Ora vorrei complicarmi un po’ la vita. Per evitare continue attivazioni e disattivazioni del relè, vorrei che il relè scattasse quando la temperatura è inferiore a quella impostata meno la tolleranza (come sopra quindi), ma che rimanesse HIGH fino a che la temperatura non torna a quella impostata (senza considerare quindi la tolleranza).

Esempio pratico.
temperatura_da_mantenere: 20 °C;
temperatura_tolleranza: 1°C;
temperatura rilevata: 19 °C.

Per come lo ho scritto io, il relè scatterebbe a t<19°C (20-1), ma appena sorpassati i 19 andrebbe su LOW, e continuerebbe ad accendere/spegnere la fonte di riscaldamento.

Ho pensato a un if dentro ad un altro, all’uso di while, ma non trovo un modo logico per esprimere quanto vorrei che succedesse.

Consigli? Non mi serve codice pronto da copia/incollare, meglio una spiegazione :slight_smile:
Probabilmente la domanda è banale e mi sono scervellato per 2 giorni per una schioccezza, ma proprio non ne esco :confused:

grazie a tutti!

Consigli? Non mi serve codice pronto da copia/incollare, meglio una spiegazione smiley
Probabilmente la domanda è banale e mi sono scervellato per 2 giorni per una schioccezza, ma proprio non ne esco :confused:

C’è una valutazione errata del problema, cioè non si tratta di una sciocchezza.

Modellare il comportamento del termostato tradizionale non è un problema da sottovalutare, in realtà
ogni problema non lo è, per cui bisogna documentarsi, analizzare ed infine scrivere codice che si
comporti quanto più possibile come un termostato.

Il SETPOINT è la temperatura desiderata. Il termostato può essere adatto ad applicazioni che producono un
innalzamento della temperatura quando il termostato ha il contatto chiuso, oppure quando chiuso ci sarà una riduzione della temperatura, questo è il caso di un frigorifero o cella di congelamento.
Quindi ci sono due comportamenti da modellare:

  • Termostato in modo COLD (freddo)
  • Termostato in modo HOT (caldo)
    La temperatura differenziale o isteresi di intervento del termostato contribuisce a calcolare la temperatura di
    intervento e di rientro. La temperatura di intervento avviene quando il termostato chiude due contatti che alimentano il dispositivo di condizionamento della temperatura. Qui il termine “condizionamento” deve essere interpretato con il significato principe, cioè condizionare una temperatura attuale al fine di incrementarla o ridurla.
    Il rientro è l’opposto del rientro, cioè quando i contatti del termostato non alimentano il dispositivo di condizionamento.

Il differenziale come parametro utente ha un valore assoluto, mentre il differenziale da usare nel calcolo è
differenziale/2.
es parDiff = 2, setpoint = 40 °C, termostato tipo HOT:
temperatura di intervento = setpoint - (parDiff / 2)
temperatura di rientro = setpoint + (parDiff / 2)

Nel codice conviene calcolarsi prima parDiff / 2 e aggiornare questo valore quando l’utente cambia il parDiff
con il termostato in corsa.

Qualcosa tipo:

currentTemperature = readSensor();
tDiff = parDiff / 2; 
if ( currentTemperature > ( setpoint + tDiff) ) {
     SwitchOff();   // apre i contatti
     //  Nota che se mode == COLD al posto di SwitchOff ci va SwitchOn, che accende quello che diciamo farà freddo
} else if (currentTemperature < ( setpoint - tDiff) {
     SwitchOn();   // chiude i contatti
     //  Nota che se mode == COLD al posto di SwitchOn ci va SwitchOff, che spegne quello che diciamo farà freddo
}

Io eviterei di usare float per i calcoli, preferendo il tipo int o più grande int32_t, userei float solo per stampare
il valore. Quindi la temperatura float la moltiplichi per 100 e converti il valore a tipo int.

Es: 25.75 * 100 = 2575 che sta in un tipo “int” anziche float, questo fa risparmiare tempo di calcolo e spazio in memoria e in più permette alle if di fare confronti con gli interi.

Nota che: Il codice è in ciclo, quindi esegue le if anche quando non c’è necessità, cioè se il termostato è on è inutile eseguire la if che accende il termostato in quanto è già acceso, stessa cosa quando è spento. Quindi il codice da eseguire dovrebbe essere quello che può modificare lo stato portandolo dallo stato attuale a quello opposto.

Ciao.

Grazie mille per l’esauriente risposta Mauro!

Forse non mi ero spiegato bene, ma avrei voluto che la temperatura di intervento fosse effettivamente

  • per il riscaldamento: x-1, mentre quella di rientro fosse x.
  • per il raffreddamento: x+1, con quella di rientro sempre x.

Ad ogni modo la tua idea di basare le if sullo stato del relè mi ha fatto arrivare a questa conclusione

	 //accende il riscaldamento
	 if(relay_riscaldamento == LOW)
	 {
	 	if(temperatura_media < (temperatura_da_mantenere - tolleranza))
	 	{
	 		digitalWrite(relay_riscaldamento, HIGH);
	 	}
	 }
	 

	 //spegne il riscaldamento
	 if(relay_riscaldamento == HIGH)
	 {
	 	if(temperatura_media > temperatura_da_mantenere)
	 	{
	 		digitalWrite(relay_riscaldamento, LOW);
	 	}
	 }

	 delay(1000);

Come ti sembra? Spero di aver capito bene ciò che intendevi…

Tengo comunque presente il tuo ragionamento se dovesse capitarmi di dover utilizzare temperature di intervento/rientro pari a t = ± x.

Quanto alla questione dei float, considerando che vorrei collegare monitor che visualizzi una cifra decimale, e server web integrato che la riporti su un banale html, mi consigli comunque di fare i calcoli con int e di dividere nuovamente per 100 ogni volta che devo dare un print.lcd o serial.print ecc?