Iniziano i problemi... con Arduino.

Ciao a tutti, ho scritto anche sulla pagina FB di Arduino ma chiedo anche qui, non si sa mai :-)

Sto scrivendo uno sketch per automatizzare la chiusura della tenda da

la luce de sole, quello che ho fatto fin'ora funziona ma... al reset o

istante, a volte va a zero altre va al massimo o "inf" e spesso manda a

Non capisco dove sbaglio, il sensore hall attiva l'interrupt che legge i millisecondi e fa la sottrazione trovando il periodo fra un interrupt e

fila tutto liscio.

Dove caspita sbaglio?

Ringrazio per l'eventuale aiuto.

int relechiusura = 13; // comando rele chiusura su pin 13 int releapertura = 12; // comando rele apertura su pin 12 int finecorsa = 11; // fine corsa tenda chiusa su pin 11 volatile int state = LOW; // set per interrupt unsigned long tempo_1 = 0; // tempo iniziale in mS float tempo = 0; // differenza fra tempo iniziale e tempo dell'interrupt

float frequenza = 0; // frequenza interrupt in Hz in base al tempo int valorepotsetvento = 0; // valore del potenziometro da 0 a 1023 unsigned long setvento = 0; // variabile dove memorizza il valore del set del vento int potsetvento = A0; // ingresso del potenziometro int termoresistenza = A1; // ingresso termoresistenza int lucesole = 0; //imposta valore iniziale lucesole int setluce = 0; // imposta valore iniziale setluce int potsetluce = A2; // ingresso potenziometro set luce

void setup() { pinMode (relechiusura, OUTPUT); pinMode (releapertura, OUTPUT); pinMode (finecorsa, INPUT_PULLUP); digitalWrite(relechiusura, LOW); //mette l'uscita bassa digitalWrite(releapertura, LOW); //mette l'uscita bassa attachInterrupt(0, periodo, FALLING); //intervento interrupt su pin 2 attiva "periodo" su lettura del segnale a massa

}

void periodo() //ciclo interrupt { unsigned long tempo_2 = millis(); //assegna a tempo_2 il valore attuale in millisecondi

tempo = (tempo_2 - tempo_1); //tempo trascorso in mS fra i due interrupt che corrisponde a mezzo giro o 0,5m/S frequenza = ((1/tempo)*1000); //frequenza interrupt 4 interrupt corrispondono a 1 m/S

tempo_1 = tempo_2; //mette il tempo iniziale uguale al tempo finale per prepararlo alla prossima sottrazione }

void loop() {

finecorsa = digitalRead(11); //legge finecorsa

{ digitalWrite(relechiusura, LOW); //disattiva relechiusura setvento = 1000; //mette setvento a 1000 per bloccare il rele di chiusura } else { valorepotsetvento = analogRead(potsetvento); //legge il valore del potenziometro setvento=((valorepotsetvento/0.64)*0.036); //calcola il set del vento in km/h

superiore al set

digitalWrite (relechiusura, HIGH); //attiva il rele di chiusura } }

--
Saluti da Drizzt. 


www.agidone.altervista.org 
http://www.tappezzeriagraziella.com/ 
MAI PIU' OPEL IN VITA MIA!!!!
Reply to
Drizzt do'Urden
Loading thread data ...

unsigned long tempo = 1;

usa tutti unsigend long anche per le altre variabili relative a millis.

nella funzione "periodo".

Reply to
Franco Af

Il 02/09/2019 13:42, alfio ha scritto:

Reply to
drizzt

Il 02/09/2019 13:57, Franco Af ha scritto:

non funziona se metto unsigned long, mi da risultato zero.

che casino. :-(

Reply to
drizzt

Il 02/09/2019 13:42, alfio ha scritto:

il giochetto girava li attorno, era il consiglio giusto ma per farlo funzionare ho dovuto fare una piccola modifica, aiutato da un amico, ora funziona pefettamente, ho settato una variabile "conta" a 2:

void periodo() { unsigned long tempo_2 = millis();

tempo = (tempo_2 - tempo_1); //tempo trascorso in mS fra i due

if(conta) conta--;

else

{

frequenza = ((1/tempo)*1000); //frequenza interrupt 4 interrupt corrispondono a 1 m/S

tempo_1 = tempo_2; //mette il tempo iniziale uguale al tempo finale per prepararlo alla prossima sottrazione } }

Reply to
Drizzt do'Urden

Il 02/09/19 16:59, drizzt ha scritto:

Vedi questa rielaborazione... non servono cosi` tanti calcoli:

//-------------------------------------------------------------------- // COSTANTI (andrebbero scritte in maiuscolo) //--------------------------------------------------------------------

const byte relechiusura = 13; // rele` attivo HIGH const byte releapertura = 12; // rele` attivo HIGH const byte finecorsa = 11; // premuto == LOW const byte potsetvento = A0; // imposta velocita` max vento

//-------------------------------------------------------------------- // VARIABILI GLOBALI //--------------------------------------------------------------------

volatile float velocita = 0.0; unsigned long inizio; byte conta = 1;

//-------------------------------------------------------------------- // GESTORE INTERRUPT //-------------------------------------------------------------------- void periodo() { unsigned long adesso = millis(); if (conta) { conta--; } //un giro a vuoto else { unsigned long trascorso = adesso - inizio; if (trascorso) { velocita = 900.0 / trascorso; } //km/h } inizio = adesso; //tempo inizio prossima misura }

//-------------------------------------------------------------------- // FUNZIONI DI SUPPORTO PER LETTURA/SCRITTURA INGRESSI/USCITE //--------------------------------------------------------------------

bool tendaChiusa() { return digitalRead(finecorsa) == LOW; }

void fermaChiusura() { digitalWrite(relechiusura, LOW); }

void avviaChiusura() { digitalWrite(relechiusura, HIGH); }

float setVento() { return analogRead(potsetvento) * 0,05625; } //km/h

//--------------------------------------------------------------------

void setup() { pinMode (relechiusura, OUTPUT); pinMode (releapertura, OUTPUT); pinMode (finecorsa, INPUT_PULLUP); digitalWrite(relechiusura, LOW); //rele` inizialmente spento digitalWrite(releapertura, LOW); //rele` inizialmente spento attachInterrupt(0, periodo, FALLING); }

//--------------------------------------------------------------------

void loop() { if (tendaChiusa()) { fermaChiusura(); } else if (velocita > setVento()) { avviaChiusura(); } }

Reply to
Claudio_F

programmazione. Ti consiglio ogni volta che hai a che fare con arduino di aprire comunque la seriale e stampare i valore dubbi. Per fare questo conviene sempre una macro che attivi le sezioni giuste se sei in fase di sviluppo. In pratica il tuo scheletro diventa qualcosa di simile a quanto sotto.

Nota che si tratta di macro e non delle istruzioni di linguaggio. Gli essenzialisti mi diranno che bastava #ifdef ma facendo come sotto puoi dare diversi valori alla macro e attivare differenti livelli di debug che servono prima o poi. Se prendi questa buona abitudine un giorno

A questo punto, nell'IDE di arduino vai nel menu "serial monitor" e vedrai l'effetto delle istruzioni di stampa che mandi alla seriale.

Quando lo sketch sta a posto, poni MYSKETCH_DEBUG pari a 0

casini evitati se serve la seriale per il normale funzionamento del programma).

#define MYSKETCH_DEBUG 1

// .....

void setup () { #if( MYSKETCH_DEBUG > 0 ) // apro la seriale Serial.begin (9600); #endif }

void ab_qualcosa () { unsigned long time1 = 42, time2 = 42 ; unsigned long casino ;

#if( MYSKETCH_DEBUG > 0 ) if( time1 == time2 ) { Serial.print("err. div. 0: time1,2 = ") ; Serial.println(time1) ; } #endif

casino = 422 / ( time2 - time1 ) ; }

--
- Thanks for introducing me to minimalims. 
- It's the least I could do.
Reply to
Archaeopteryx

pt

Per inciso:

frequenza = ((1/tempo)*1000);

frequenza = 1000.0f / tempo;

oppure:

frequenza = 1000 / (float)tempo;

vello di compilatore in una singola moltiplicazione (le divisioni sono cost ose, e se ci sono divisioni per costanti si possono esprimere come la molti plicazione per il reciproco della costante);

2) diversamente dagli altri linguaggi di programmazione, quando fai operazi oni con argomenti interi viene effettuata l'operazione su interi, anche se

eri. Facciamo che tempo sia uguale a 20ms, avresti ((1/20) * 1000), ma la p

razioni float, almeno uno degli operatori deve essere un float. Scrivendo 1

000.0f oppure (float)tempo stai forzando uno dei due argomenti a float, e q
--
marimbarza
Reply to
marimbarza

Il 02/09/2019 20:05, marimbarza ha scritto:

quelle variabili le ho dovute fare tutte float altrimenti mi dava come risultato sempre 0.

--
Saluti da Drizzt. 


www.agidone.altervista.org 
http://www.tappezzeriagraziella.com/ 
MAI PIU' OPEL IN VITA MIA!!!!
Reply to
Drizzt do'Urden

Il 02/09/2019 19:20, Claudio_F ha scritto:

ecco, proprio pulito come mi piace, provvedo e speriamo di non incasinare tutto :-)

--
Saluti da Drizzt. 


www.agidone.altervista.org 
http://www.tappezzeriagraziella.com/ 
MAI PIU' OPEL IN VITA MIA!!!!
Reply to
Drizzt do'Urden

Il 02/09/2019 19:47, Archaeopteryx ha scritto:

rimedio al disguido, sapevo che il problema era il conteggio del tempo ma ho avuto bisogno di aiuto per metterlo a posto, pure con i calcoli, quelli che facevo andavano bene ma non erano ottimizzati.

Comunque sono soddisfatto, ero sulla strada della rinuncia ma poi ci ho provato e comincio a capire qualcosa, pian pianino :-)

--
Saluti da Drizzt. 


www.agidone.altervista.org 
http://www.tappezzeriagraziella.com/ 
MAI PIU' OPEL IN VITA MIA!!!!
Reply to
Drizzt do'Urden

Asp... c'e` un errorone in questa riga:

float setVento() { return analogRead(potsetvento) * 0,05625; } //km/h

Quella virgola *deve* ovviamente essere un punto (il compilatore non lo segnala come errore perche' la sintassi e` comunque corretta, ma indica un'altra -brutta- cosa chiamata comma operator...)

Reply to
Claudio_F

Il 02/09/19 20:19, Drizzt do'Urden ha scritto:

E' probabile che lavorando con gli interi le divisioni perdessero tutti i decimali...

Infatti con l'aritmetica intera scrivere (1 / T) * 1000 e` *molto* diverso da scrivere 1000 / T mentre in floating point i risultati sono gli stessi.

Reply to
Claudio_F

Ottimo, ne sono contento.

--
- Thanks for introducing me to minimalims. 
- It's the least I could do.
Reply to
Archaeopteryx

Il 02/09/2019 20:35, Claudio_F ha scritto:

Ho fatto altre prove e mettendo tutte le variabili della funzione come

che l'indicazione del vento sia 13,55 o 14 non cambia nulla. Quando mi mettete la pulce nell'orecchio indago per capire :-)

unsigned long tempo_1 = 0; // tempo iniziale in mS unsigned long tempo = 0; // differenza fra tempo iniziale e tempo dell'interrupt

unsigned long frequenza = 0; // frequenza interrupt in Hz in base al tempo

Reply to
Drizzt do'Urden

Il 02/09/2019 13:57, Franco Af ha scritto:

Ho fatto altre prove e mettendo tutte le variabili della funzione come

che l'indicazione del vento sia 13,55 o 14 non cambia nulla. Quando mi mettete la pulce nell'orecchio indago per capire

unsigned long tempo_1 = 0; // tempo iniziale in mS unsigned long tempo = 0; // differenza fra tempo iniziale e tempo dell'interrupt

unsigned long frequenza = 0; // frequenza interrupt in Hz in base al tempo

Reply to
Drizzt do'Urden

infatti non dovrebbero darti problemi.

sempre variabili dichiarate volatili, altrimenti in alcune situazioni potresti avere problemi. volatile unsigned long tempo = 0;

Reply to
Franco Af

Come da subject, poi in certi momenti mi si ottunde il

scenario-sketch?

--
- Thanks for introducing me to minimalims. 
- It's the least I could do.
Reply to
Archaeopteryx

Il 03/09/2019 16:28, Archaeopteryx ha scritto:

Ti dico come l'ho pensata: gli interrupt non guardano in faccia a nessuno, fermano il programma in un punto e lo riprendono, quindi per calcolare un tempo vanno bene, sempre se quell'interruzione non danneggia il resto del programma ma nel mio caso non ho tempi stretti.

--
Saluti da Drizzt. 


www.agidone.altervista.org 
http://www.tappezzeriagraziella.com/ 
MAI PIU' OPEL IN VITA MIA!!!!
Reply to
Drizzt do'Urden

oercion in C, altrimenti impazzisci dietro a bug apparentemente assurdi.

Reply to
marimbarza

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.