Buona sera a tutti. pongo una domanda a chi è più esperto di me. mi sto cimentando con arduino per fare una centralina acquario. nella rete ho trovato uno sketc per le luci e uno per la temperatura. sono riuscito a unire i due programmi e quando lo carico su arduino funziona tuto bene tranne che per una cosa: in void loop ho dovuto togliere il delay del sensore temperatura se no mi bloccava tutto, e senza un ritardo nell\' acquisizione dati del sensore lm35 ho uno sfarfallamento nella lettura temperatura e nella fase on off del relay. secondo voi è fattibile riuscire a ritardare la lettura del sensore usando millis al posto di delay? è una settimana che ci provo ma non ci riesco. se qualcuno può indirizzarmi ve ne sarei grato.
Non è obbligatorio usare il paracadute, ma ricorda, lo puoi fare una volta sola.
sistemato l\'allegato code, un pò di logica però F.G.
Non è obbligatorio usare il paracadute, ma ricorda, lo puoi fare una volta sola.
picmicro675
postato il: 16.03.2017, alle ore 21:07
La sezione dovrebbe essere PIC MICRO: Comunque ...
Delay() è bloccante, che vuol dire che sin tanto che non è trascorso il determinato periodo sta li ad aspettare. Con millis() si fa in modo che avviene una verifica e quando ha raggiunto tale periodo esegue il resto del codice. Per cui se la condizione non è vera, l' istruzione passa a quella successiva a millis().
Prova questo
int sampling(void)
/* campionamento della lettura analogica. Si rielvano 60 campioni
* poi si fa la media
*/
{
for (byte = i; i << 60; i++) {
reading += analogRead(sensorPin);
}
return reading / i;
}
void loop()
{
// attesa di 2 secondi prima di prendere una nuova campionatura
if (millis() > (lastmillis + 2000)) {
int celsius = sampling / 2;
}
lcd.setCursor(0, 0);
lcd.print("Temperatura: ");
lcd.setCursor(0,1);
lcd.print(celsius);
lcd.print((char)223);
lcd.print("C");
if (celsius >28) {
digitalWrite(7,HIGH);
lcd.print(" ON");
}
else {
digitalWrite(7,LOW);
lcd.print(" OFF");
}
delay(500);
lcd.clear();
}
Comunque non è chiaro cosa intendi per fare la lettura del sensore.
Io ho messo una funzione che fa una media di 60 campioni, l' aggiornamento del valore avviene ogni 2000 millisecondi , per avere un valore ottimale. Il ritardo in fondo dovrebbe rimanere, per non forzare troppo l' aggiornamento del display.
Comunque non riesco a capire se hai una conversione proporzionale al valore letto su piedino analogico.
int sampling(void)
/* campionamento della lettura analogica. Si rielvano 60 campioni
* poi si fa la media
*/
{
uint8_t i=0;
for ( ; i << 60; i++) {
reading += analogRead(sensorPin);
}
return reading / i;
}
void loop()
{
// attesa di 2 secondi prima di prendere una nuova campionatura
if (millis() > (lastmillis + 2000)) {
celsius = sampling() / 2;
}
lcd.setCursor(0, 0);
lcd.print("Temperatura: ");
lcd.setCursor(0,1);
lcd.print(celsius);
lcd.print((char)223);
lcd.print("C");
if (celsius >28) {
digitalWrite(7,HIGH);
lcd.print(" ON");
}
else {
digitalWrite(7,LOW);
lcd.print(" OFF");
}
delay(500);
lcd.clear();
}
Anno nuovo, forum nuovo.
Mi sa che lascio.
guzzj
postato il: 16.03.2017, alle ore 21:35
Praticamente avrei bisogno che la temperatura venisse letta solo ogni tot secondi o minuti, per non avere al raggiungimento dei 28 gradi un continuo on off sul Pin del relay.
Non è obbligatorio usare il paracadute, ma ricorda, lo puoi fare una volta sola.
guzzj
postato il: 16.03.2017, alle ore 22:56
Grazie picmicro ma anche solo eseguendo il tuo codice la temperatura mi rimane fissa a -1 gradi. posto il codice completo(spero di far giusto) in cui ho unito il codice temperatura. la stringa delay del codice temperatura non la posso usare se no si impalla il resto.
// include the libraries:
#include <LiquidCrystal.h>
#include <Wire.h>
#include <Button.h>
#include <EEPROM.h>
#include <EEPROMVar.h>
// set the relais
int reading = 0;
int sensorPin = A3;
int relay =1;
// set the RTC's I2C address
#define DS1307_I2C_ADDRESS 0x68
// create the LCD
LiquidCrystal lcd(8, 7, 5, 4, 16, 2);
// set up backlight
int bkl = 6; // backlight pin
byte bklIdle = 50; // PWM value for backlight at idle
byte bklOn = 70; // PWM value for backlight when on
int bklDelay = 10000; // ms for the backlight to idle before turning off
unsigned long bklTime = 0; // counter since backlight turned on
// create the menu counter
int menuCount = 1;
int menuSelect = 0;
//create the plus and minus navigation delay counter with its initial maximum of 250.
byte btnMaxDelay = 200;
byte btnMinDelay = 25;
byte btnMaxIteration = 5;
byte btnCurrIteration;
// create the buttons
Button menu = Button(12,PULLDOWN);
Button select = Button(13,PULLDOWN);
Button plus = Button(14,PULLDOWN);
Button minus = Button(15,PULLDOWN);
// LED variables. These control the behavior of lighting. Change these to customize behavoir
int minCounter = 0; // counter that resets at midnight.
int oldMinCounter = 0; // counter that resets at midnight.
int oneLed = 9; // pin for channel 1
int twoLed = 10; // pin for channel 2
int threeLed = 11; // pin for channel 3
int fourLed = 3; // pin for channel 4
int oneVal = 0; // current value for channel 1
int twoVal = 0; // current value for channel 2
int threeVal = 0; // current value for channel 3
int fourVal = 0; // current value for channel 4
// Variables making use of EEPROM memory:
EEPROMVar<int> oneStartMins = 750; // minute to start this channel.
EEPROMVar<int> onePhotoPeriod = 720; // photoperiod in minutes for this channel.
EEPROMVar<int> oneMax = 100; // max intensity for this channel, as a percentage
EEPROMVar<int> oneFadeDuration = 60; // duration of the fade on and off for sunrise and sunset for
// this channel.
EEPROMVar<int> twoStartMins = 810;
EEPROMVar<int> twoPhotoPeriod = 600;
EEPROMVar<int> twoMax = 100;
EEPROMVar<int> twoFadeDuration = 60;
// variables to invert the output PWM signal,
// for use with drivers that consider 0 to be "on"
// i.e. buckpucks. If you need to provide an inverted
// signal on any channel, set the appropriate variable to true.
boolean oneInverted = false;
boolean twoInverted = false;
boolean threeInverted = false;
boolean fourInverted = false;
/*
int oneStartMins = 1380; // minute to start this channel.
int onePhotoPeriod = 120; // photoperiod in minutes for this channel.
int oneMax = 100; // max intensity for this channel, as a percentage
int oneFadeDuration = 60; // duration of the fade on and off for sunrise and sunset for
// this channel.
int twoStartMins = 800;
int twoPhotoPeriod = 60;
int twoMax = 100;
int twoFadeDuration = 15;
int threeStartMins = 800;
int threePhotoPeriod = 60;
int threeMax = 100;
int threeFadeDuration = 30;
int fourStartMins = 800;
int fourPhotoPeriod = 120;
int fourMax = 100;
int fourFadeDuration = 60;
*/
/****** LED Functions ******/
/***************************/
//function to set LED brightness according to time of day
//function has three equal phases - ramp up, hold, and ramp down
int setLed(int mins, // current time in minutes
int ledPin, // pin for this channel of LEDs
int start, // start time for this channel of LEDs
int period, // photoperiod for this channel of LEDs
int fade, // fade duration for this channel of LEDs
int ledMax, // max value for this channel
boolean inverted // true if the channel is inverted
) {
int val = 0;
//fade up
if (mins > start || mins <= start + fade) {
val = map(mins - start, 0, fade, 0, ledMax);
}
//fade down
if (mins > start + period - fade && mins <= start + period) {
val = map(mins - (start + period - fade), 0, fade, ledMax, 0);
}
//off or post-midnight run.
if (mins <= start || mins > start + period) {
if((start+period)%1440 < start && (start + period)%1440 > mins )
{
val=map((start+period-mins)%1440,0,fade,0,ledMax);
}
else
val = 0;
}
if (val > ledMax) {
val = ledMax;
}
if (val < 0) {
val = 0;
}
//button hold function
int btnCurrDelay(byte curr)
{
if(curr==btnMaxIteration)
{
btnCurrIteration = btnMaxIteration;
return btnMaxDelay;
}
else if(btnCurrIteration ==0)
{
return btnMinDelay;
}
else
{
btnCurrIteration--;
return btnMaxDelay;
}
}
// format a number of minutes into a readable time (24 hr format)
void printMins(int mins, //time in minutes to print
boolean ampm //print am/pm?
) {
int hr = (mins%1440)/60;
int mn = mins%60;
if(hr<10){
lcd.print(" ");
}
lcd.print(hr);
lcd.print(":");
if(mn<10){
lcd.print("0");
}
lcd.print(mn);
}
// format hours, mins, secs into a readable time (24 hr format)
void printHMS (byte hr,
byte mn,
byte sec //time to print
)
{
//reset plus & minus acceleration counters if the button's state has changed
if(plus.stateChanged())
{
btnCurrDelay(btnMaxIteration);
}
if(minus.stateChanged())
{
btnCurrDelay(btnMaxIteration);
}
//turn the backlight off and reset the menu if the idle time has elapsed
if(bklTime + bklDelay < millis() && bklTime > 0 ){
analogWrite(bkl,bklIdle);
menuCount = 1;
lcd.clear();
bklTime = 0;
}
if(menuCount == 3){
//set start time for channel one
lcd.setCursor(0,0);
lcd.print("Canale A Inizio");
lcd.setCursor(0,1);
printMins(oneStartMins, true);
Non è obbligatorio usare il paracadute, ma ricorda, lo puoi fare una volta sola.
picmicro675
postato il: 17.03.2017, alle ore 08:59
Quando i listati sono lunghi, meglio caricarli su file hosting o propria pagina e dare il link. È scomodo da leggere nel browser., anche il topico diventa difficile da leggere.
Noterai che la larghezza non dovrebbe superare le 80 colonne, altrimenti il listato diventa scomodo anche da leggere.
La gestione dell' RTC è alquanto voluminosa, c'è la sua libreria che migliora la leggibilità del codice.
Ci faccio uno studio.
Anno nuovo, forum nuovo.
Mi sa che lascio.
gironico
postato il: 17.03.2017, alle ore 12:25
se il programma luci ti va bene, premesso che non ho letto bene il codice in quanto leggerlo cosi nn ci capisco molto, ora non posso copiarlo e passarlo sull'ide....
Consiglio veloce e indolore:
Usi la rtcSw, un bottino ma chi se ne frega.... per esempio al 30imo secondo di ogni minuto ti fai la misura della temperatura.... Un po' tende ad oscillare di suo lm35... infilaci una capacità e già ti migliora...
fai un ciclo di 10 misure e poi fai la media....
Proprio giorni fa ho fatto un'alba tramonto con ardu per l'acquario della mia figlia....promesso che quando ho tempo lo pubblico e vedrai che ci aggiungi al volo la misura della temperatura
chiaramente usando else appena hai una lettura oscillante che ti riporta appena sotto i 28 ti stacca il relè... ti basta che ti misuri 27.5 C e hai già il problema
Gia cosi risolvi il problema abbastanza bene... ti torna?
Questo è il modo più semplice.... per esempio potresti creare variabili di comodo della serie che se sei arrivato a temperatura cambi stato alla variabile e fai partire il conteggio dei millis su un'altra variabile che fino a per esempio 10mila millis il relè non commuterà anche se avviene la condizione di gradi <28
altro consiglio, ho visto che fai uso esagerato della funzione lcdclear();
impara a sovrascrive e non a cancellare ogni volta... il tempo di reflesh di questo tipo di lcd è molto lento... affievolisce le scritte e ti risponde in ritardo...
Fammi sapere se ti migliora o ti può andar bene il discorso...
Come utente anonimo puoi leggere il contenuto di questo forum ma per aprire una discussione
o per partecipare ad una discussione esistente devi essere registrato ed accedere al sito