Iniziano i problemi... con Arduino.

Sep 02, 2019 26 Replies

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

unsigned long tempo = 1;

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

nella funzione "periodo".

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

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

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

che casino. :-(

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 } }

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(); } }

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.

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

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

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

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

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...)

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.

Ottimo, ne sono contento.

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

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

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

infatti non dovrebbero darti problemi.

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

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.

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

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

Join the Discussion

Have something to add? Share your thoughts — no account required.

Didn't find your answer?

Ask the community — no account required