Progetto incubatrice (problemini!!!)

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!

grazie mille per l’attenzione e l’aiuto!
Gabriele

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.

Ciao

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? :smiley:

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°!! :astonished:

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

#include <Servo.h>  //include librerie per servo e lcd

Servo girauova;         
int pos_girauova = 90;     
int girauova_time = millis();
boolean stato_girauova;
void setup() 
{   
  girauova.attach(9);   
}  
  
void loop() 
{  
 if (millis() - girauova_time >= 40) //se sono passati 40second dall'ultimo aggiornamento
   {
     girauova_time = millis(); //salviamo il tempo di ultima esecuzione
  
   if (stato_girauova)
   {
     pos_girauova++;
     if (pos_girauova >= 180)
     {
       stato_girauova = false;
     }
   }
   else{
       pos_girauova--;
       if (pos_girauova <= 16)
       {
         stato_girauova = true;
       }
   }
   girauova.write(pos_girauova);

}
}

non credo perchè per provare ho messo sullo sketch solo il codice per il servo senza tutto il resto.

se è normale ok allora,però mi sarebbe più comodo ottenere un valore con un solo decimale. è complicato toncarlo?

se vuoi visualizzare una sola cifra dopo la virgola, fai

Serial.print(numero,1)

(l'ho letto da un vecchio post di Lesto :stuck_out_tongue: )

comunque fare due ricerche con google non fa mai male.. ]:slight_smile:

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!! :roll_eyes:

girauova.attach(9, 1000, 2000);

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

ah ok, quindi mettendo 1000/2000 ho già cambiato, pensavo dicessi a me di cambiare questo valore!
ora provo!!

per il troncamento perfetto! tutto chiaro!!

grazie mille!!

niente, impazzisce uguale!!!

se ogni volta che fai una write scrivi anche il valore via seriale, da serial monitor cosa ottieni?

ah ok, quindi mettendo 1000/2000 ho già cambiato, pensavo dicessi a me di cambiare questo valore!
ora provo!!

niente, impazzisce uguale!!!

e leggere il reference??
http://arduino.cc/en/Reference/ServoAttach

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!

se levo la stringa Serial.println(girauova) ri-impazzisce solo intorno ai 90°!!

tapirinho:
e leggere il reference??
Arduino - ServoAttach

già letto ma senza giovamento!! ci trovi qualcosa che fa al caso mio che mi è sfuggito?

scusa, forse ho capito male:
che valori metti in quel comando? forse è meglio se ripubblichi lo sketch…

metto la posizione del servo!

#include <Servo.h> 

Servo girauova;         
int pos_girauova = 90;           
int girauova_time = millis();
boolean stato_girauova;
void setup() 
{   
 girauova.attach(9, 1000, 2000);  
 Serial.begin(9600);
 }  
  
void loop() 
{  
 if (millis() - girauova_time >= 40)
   {
     girauova_time = millis(); 
  
   if (stato_girauova)
   {
     pos_girauova++;
     if (pos_girauova >= 180)
     {
       stato_girauova = false;
     }
   }
   else{
       pos_girauova--;
       if (pos_girauova <= 16)
       {
         stato_girauova = true;
       }
   }
   girauova.write(pos_girauova);
   Serial.println(pos_girauova);
}
}

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

girauova.attach(9, 500, 2500);