Salve a tutti, mi sono avvicinato da poco ad Arduino e dopo vari esperimenti di base per capire il funzionamento e il linguaggio di Arduino ho iniziato il primo progetto vero e proprio. Sto costruendo un incubatrice. Per la parte hardware/costruttiva nessun problema e tutto sommato neppure con quella dello sketch tranne due problemi che ho incontrato e che a causa delle mie scarse conoscenze non so come arginare. in sintesi l’incubatrice deve svolgere 4 funzioni:
mantenere la temperatura impostata
mantenere l’umidità impostata
mantenere la ventilazione impostata
girare le uova.
ho basato la stesura del programma sulla funzione millis() cosi da far eseguire ad Arduino delle azioni ad intervalli prestabiliti e l’input dei valori di temperatura, umidità e ventilazione tramite potenziometri.
il primo problema nasce dal fatto che io vorrei acquisire valori dal potenziometro per l’impostazione della temperatura desiderata con un numero decimale (es. 37.7) e non ci riesco! ho provato con la funzione map(analogRead(0),0,1023,20,40) ma mi ritornano solo valori interi anche impostando la variabile del tipo float.
Il secondo rompicapo ce l’ho col girauova. Questo è un servo che dovrebbe compiere da 16 a 180 gradi in 2 ore e tornare indietro in altre 2 ore continuamente. In un altro progetto in cui arduino doveva solo fare questo lavoro ho utilizzato il ciclo for in questo modo e funzionava benissimo.
{
for(pos_girauova = 16; pos_girauova < 180; pos_girauova += 1)
{girauova.write(pos_girauova);}
for(pos_girauova = 180; pos_girauova >=16; pos_girauova -= 1)
{girauova.write(pos_girauova);}
}
Ora avendo strutturato tutto col millis questo for mi blocca il ciclo?
Come posso fare diversamente?
Ho pensato di far aumentare di un grado la posizione del servo ogni tot secondi sempre utilizzando millis
if(time>girauova_time+40000)
{
pos_girauova += 1;
girauova.write(pos_girauova);
}
Ma non saprei come fermarlo a 180 gradi e poi farlo tornare indietro!
problema 1: Arduino - Map spiega che map restituisce solo numeri interi. Usa un altro metodo: fal la lettura analogica poi applichi una semplice operazione tipo "valoreSet = Valoreminimo+ LetturaAnalogica*(ValoreMassimo-ValoreMinimo)/1024
problema 2:
(prendilo con le molle perchè potrei sbagliarmi)
il loop rimane bloccato finchè il ciclo for non viene eseguito completamente. Converrebbe incrementare una variabile ad ogni loop e muovere il servo di conseguenza, oppure lavorare direttamente con il millis.
per il 2: prima di tutto ti sei dimenticato di aggiornare il valore di girauova_time una volta entrato nell’if al tempo attuale.
facciamo due conti:
180° in 2 ore sono 1° ogni 40 secondi
in oltre il “girauova” ha due stati: incremento(diciamo true) e decremento(diciamo false)
quindi
if (millis() - last_update >= 40000){ //se sono passati 40second dall'ultimo aggiornamento
last_update = millis(); //salviamo il tempo di ultima esecuzione
if (stato_girauova){
//gira in senso orario
pos_girauova++;
if (pos_girauova >= 180){
stato_girauova = false;
}
}else{
pos_girauova--;
if (pos_girauova <= 0){
stato_girauova = true;
}
}
girauova.write(pos_girauova);
}
tapirinho:
Usa un altro metodo: fal la lettura analogica poi applichi una semplice operazione tipo "valoreSet = Valoreminimo+ LetturaAnalogica*(ValoreMassimo-ValoreMinimo)/1024
Ottimo!! questa soluzione funziona alla grande: ottengo due cifre dopo la virgola. succede però una cosa strana che ho notato gia altre volte. la cifra dei centesimi non è costante nelle varie letture anche se non tocco il potenziometro.. diciamo che varia di +-2 unità. come posso risolverlo? Se invece volessi troncare alla prima cifra decimale?
Per quanto riguarda la soluzione di lesto al problema del girauova, ho provato velocizzando il tutto mettendo 400ms al posto dei 40000.. il servo fa il suo lavoro in maniera perfetta per 5-6 corse dopodichè impazzisce e fa avanti e indietro velocissimo sulla zona piu o meno dei 70-110°!!
vi ringrazio davvero tanto per la vostra disponibilità e cortesia!
mostra il codice completo, maagri c'è qualcosa d'altro che tiene impegnato il loop e sfori i tempi.
per il fatto dell'analog che sballa è normale, un solizione può essere quella di tagliare uno o due bit dalla lettura analogica, oopure fare la media di 5/10 leture
sì, però occhio che la print è solo visualizzazione, matematicamente lo tiene.
prova con un
girauova.attach(9, 1000, 2000);
e cambia il 1000/2000 per fare in modo che il servo lavori senza sforzare mai (in pratica regoli l’angolo massimo richiesto non sia maggiore dell’angolo reale, purtroppo di default arduino usa valori molto ampi, il che fa surriscaladre i servo e anche bruciare)
ho cercato ma non ci ho capito molto, ho trovato solo questo
float troncato=((float)((int)(f*{10^N})))/{10^N}; //Per la N-esima decimale
ma non so bene se può andare.
quello che dici tu è se voglio visualizzare una sola cifra, mi sta bene, ma a me occorre proprio avere una variabile con un solo decimale. cioè io acquisisco il valore dal potenziometro per impostare la temperatura, non mi occorre impostare una temperatura con 6 cifre dopo la virgola, me ne basta una ed è quello che vorrei fare. non so se sono riuscito a spiegarmi
lesto:
e cambia il 1000/2000 per fare in modo che il servo lavori senza sforzare mai (in pratica regoli l'angolo massimo richiesto non sia maggiore dell'angolo reale, purtroppo di default arduino usa valori molto ampi, il che fa surriscaladre i servo e anche bruciare)
con cosa dovrei sostituire 1000/2000? cosa stano ad indicare?
scusa ma non ho capito!!
devi cambiare 1000 e 2000, di default arduino uisa qualcosa tipo
girauova.attach(9, 500, 2500);
se vuoi un solo decimale in modo semplice (che poi è il metoo che hai trovato, "srotolato" e con N=1):
float valore = 1.123456789;
valore = valore *10; //così diventa 11.23456789, salvo arrotondament dei float
valore = (int)valore; //così togliamo la parte decimale; diventa 11
valore = valore/10; //così ridivividiamo per 10, ritorna 1.1 salvo arrotondamenti dei float
per un solo decimale l'arrotondamento float non dovrebbe fare casini
mi da la lista delle ampiezze dell'angolo... ora impazzisce diversamente cioè invece di fare avanti e indietro velocissimo solo su un piccolo angolo ora ad un certo punto comincia ad andare alla massima velocità però facendo tutta la corsa! che stranezza!
si, ma tu hai definito un servo che ha dei parametri ben definiti, cioè
minimo=1000
massimo=2000
secondo quanto descritto nel reference. Sei sicuro che siano i parametri giusti per il tuo servo?
già Lesto ti aveva detto di modificarli
lesto:
girauova.attach(9, 1000, 2000);
devi cambiare 1000 e 2000, di default arduino uisa qualcosa tipo