roberto8303 Inserito: 29 ottobre 2016 Segnala Share Inserito: 29 ottobre 2016 Buongiorno, stavo pensando di utilizzare arduino uno per controllare la velocità di una ventola di pc 12v con filo giallo della tacho per avere il riferimento di retroazione della velocita. Poi, voglio dare un riferimento set point di velocità ed rallentando la ventola con le mani voglio che il mio arduino aumenti la velocità affinchè la porti al piu vicino valore di set point. avevo pensato di iniziare in questo modo, il segnale della tacho è un pwm con frequenza di 50hz quando sono a 1400 rpm e quindi proporzionale alla velocità a 750 ho impulsi a 25hz Ho usato una libreria freqcount e leggo bene la velocità, il problema nasce quando voglio implementare il mio pid in un void a timer diciamo di 20ms, se importo un timer del contatore interno, non mi funziona piu' il conteggio della frequenza con la libreria dedicata. Stavo pensando, come posso contare manualmente dal void chiamato a tempo di 20ms la velocità della ventolina? in modo da svolgere tutto il programma insieme misura della retroazione piu controllo. Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 29 ottobre 2016 Segnala Share Inserita: 29 ottobre 2016 Arduino ha 3 timer interni. Timer0 è usato per le librerie di temporizzazzione, ed è meglio non toccarlo. Rimangono Timer 1 e 2. Le librerie che usi per misurare la frequenza impiegano timer1 come base tempi e timer2 come contatore (o viceversa). Dovresti modificare il timer di libreria della base tempi per ricavare il clock a 20ms. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 29 ottobre 2016 Autore Segnala Share Inserita: 29 ottobre 2016 #define ledPin 12 void setup() { pinMode(ledPin, OUTPUT); pinMode(led,OUTPUT); // initialize timer1 noInterrupts(); // disable all interrupts TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 2560; // compare match register 16MHz/256/2Hz TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt interrupts(); // enable all interrupts } ISR(TIMER1_COMPA_vect) // timer compare interrupt service routine { digitalWrite(ledPin, digitalRead(ledPin) ^ 1); // toggle LED pin } void loop() { Ho usato il timer1 ed ho sul pin un onda quadra di 20ms ho caricato nel OCR1A 2560 , adesso come faccio a leggere la frequenza che ho sul pin 2 della ventola? una volta conosciuta la velocita in rpm posso continuare con le formule del pid Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 29 ottobre 2016 Segnala Share Inserita: 29 ottobre 2016 Il pin2 a cosa è connesso? Se è l'ingresso al timer2 (non ricordo se il timer 2 può funzionare come contatore di impulsi eserni) usi un multiplo di questa tempo, facendo un contaore, per esempio di 10 interrupt, per leggere il timer/counter 2. Altrimenti devi invertire tra loro i 2 contatori: il timer1 conteggia la frequenza esterna, mentre il 2 funge da base tempi per richiamare il PID e per leggere il contatore. Attenzione che se la freqeunza massima è 50Hz per avere un minimo di precisione devi avere una base tempi di almeno 1". Se questa è la cadenza del conteggio è inutile fare il PID più veloce. Di solito con queste frequenze si fa una misura di periodo, ovvero quanto dura un periodo del segnale. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 29 ottobre 2016 Autore Segnala Share Inserita: 29 ottobre 2016 ho fatto cosi, ho misurato gli impulsi nel tempo con millis direttamente dal void irs chiamato dal timer ogni 2ms e risco a leggere bene la velocità. Se cerco di portare il timer a 20ms non ottengo una lettura precisa della velocità perche sicuramente gli impulsi vengono letti con ritardo #define ledPin 13 boolean impulso = 0; boolean memoria = 0; unsigned int pulseCount = 0; unsigned long time0 = 0; unsigned long timeT = 0; unsigned long rpm = 0; void setup() { pinMode(ledPin, OUTPUT); pinMode(7, INPUT); Serial.begin(57600); // initialize timer1 noInterrupts(); // disable all interrupts TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 128; // compare match register 16MHz con 128 in contatore ottengo 2ms chiamata void isr TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt interrupts(); // enable all interrupts } ISR(TIMER1_COMPA_vect) // timer ogni 2ms { digitalWrite(ledPin, digitalRead(ledPin) ^ 1); //pin prova misura frequenza impulso = digitalRead(7); if (impulso == LOW) { memoria = 1;} if (impulso== HIGH && memoria== 1 && pulseCount == 0) { time0 = millis();} if (impulso == HIGH && memoria == 1) { pulseCount = (pulseCount + 1); memoria = 0;} if (pulseCount == 100) {// setto il contatore a 100 per rilevare impulsi ad una frequenza bassa timeT = millis(); rpm = 100000/(timeT-time0)*60/2; Serial.print("rpm = "); Serial.print(rpm); Serial.println(" Hz"); pulseCount = 0; memoria = 0; } } void loop() { } adesso viene il bello, continuo nel void timer a svolgere il controllo? nel mio pid devo inserire solo la parte P+I? da dove inizio sono arrugginito Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 29 ottobre 2016 Autore Segnala Share Inserita: 29 ottobre 2016 sul pin 7 ho l uscita della ventola tacho e leggo gli impulsi ho fatto per 60 e poi /2 e ho gli rpm di consegna, ora monto il drive motor shield l298p per pilotare la ventola con il pwm e vediamo se funziona ancora tutto in manuale Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 29 ottobre 2016 Autore Segnala Share Inserita: 29 ottobre 2016 ok funziona, adesso ho eseguito un operazione per stampare sulla seriale l errore cioe errore=setpoint-rpm effettivi e vedo che l errore vale tra 100 e anche -30. Adesso devo prendere la variabile errore e moltiplicarla per un kp diciamo di 0,5 la metto in una variabile chiamata proporzionale e poi sommo all uscita cioe uscita=uscita+proporzionale. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 29 ottobre 2016 Autore Segnala Share Inserita: 29 ottobre 2016 #define ledPin 13 boolean impulso = 0; boolean memoria = 0; unsigned int pulseCount = 0; unsigned long time0 = 0; unsigned long timeT = 0; unsigned long rpm = 0; int setpoint=0; int uscita=0; int uscita1=0; int errore; float proporzionale; int proporzionale1; void setup() { pinMode(3,OUTPUT); pinMode(ledPin, OUTPUT); pinMode(7, INPUT); Serial.begin(57600); // initialize timer1 noInterrupts(); // disable all interrupts TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 128; // compare match register 16MHz con 128 in contatore ottengo 2ms chiamata void isr TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt interrupts(); } // enable all interrupts ISR(TIMER1_COMPA_vect) // timer ogni 2ms { digitalWrite(ledPin, digitalRead(ledPin) ^ 1); //pin prova misura frequenza setpoint=950;// set point errore=setpoint-rpm; //calcolo l errore in giri al minuto proporzionale=errore*0.95; //la parte proporzionale in rpm per kp =0,95 proporzionale1=map(proporzionale,0,1800,30,255); // riporto in mappa l errore in rpm proporzionale*Ki in punti per il pwm uscita= map(setpoint,380 ,1800,30 ,255); // riporto in mappa il setpoin in giri al minuto in punti per il pwm if(setpoint<=rpm){ // se il setpoint è minore degli rpm effettivi allora diminuisco il riferimento di velocita uscita1=uscita-proporzionale1;} if(rpm<=setpoint){ // se gli rpm effettivi sono minore del setpoint allora aumento il riferimento di velocita uscita1=uscita+proporzionale1;} if (uscita1>=250){ //limiti min max per l uscita pwm uscita1=250;} if (uscita1<=30){ uscita1=30;} analogWrite(3,uscita1); //metto in uscita1 il pwm finito di correzione proporzionale impulso = digitalRead(7); // impulso della tacho filo giallo ventola if (impulso == LOW) { memoria = 1;} if (impulso== HIGH && memoria== 1 && pulseCount == 0) { time0 = millis();} if (impulso == HIGH && memoria == 1) { pulseCount = (pulseCount + 1); memoria = 0;} if (pulseCount == 100) {// setto il contatore a 100 per rilevare impulsi ad una frequenza bassa timeT = millis(); rpm = 100000/(timeT-time0)*60/2; Serial.print("rpm = "); Serial.print(rpm); Serial.print(" Hz errore="); Serial.println(proporzionale1); pulseCount = 0; memoria = 0;} } void loop() { } ci sono, con kp 0,95 ottengo un oscillazione con set point di 950rpm da 838 a 1050 rpm non è un buon regolatore tutt altro, se inserisco la parte integrativa risolvo qualcosa?qual è la foruma per l' integrativo? Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 30 ottobre 2016 Segnala Share Inserita: 30 ottobre 2016 Quote ci sono, con kp 0,95 ottengo un oscillazione con set point di 950rpm da 838 a 1050 rpm non è un buon regolatore tutt altro, se inserisco la parte integrativa risolvo qualcosa?qual è la foruma per l' integrativo? Dovresti rileggerti il mio tutorial dovre torovi anche la funzione completa già scritta in un linguaggio simile a quello di arduino. Il guadagno proporzionale deve (annullare) ridurre l'errore istantaneo. Per prima cosa il tempo di campionamento della velocità reale deve essere uguale a quello di campionamento del regolatore, secondariamente il regolatore deve essere attivato sempre con il medesimo periodo. Non ho letto il tuo sketch, anche perchè non usando la funzione "code" risulta difficoltoso da leggere. I prossimi inseriscili nella funzione code, quella del pulsante con l'icona "<>". Comunque se leggi la velcoità con la funzione millis() hai dei problemi di sincronismo tra misura e regolazione. Io ti suggerirei di tenere l'interrupt a 10ms contare almeno 10 interrupts prima di chiamare la funzione PID. Tieni anche presente che seriale ed anche display I2C rallentano molto il programma. Poi per tarare cresci lentamente il Kp e dovresti notare una diminuzione dell'errore. Per trovare il Kp ottimale dovreti dare un gradino di velocità ed osservare che la velocità vada a regime senza sovra elongazione. Da ultimo, ma non ultimo, il PWM con frequenza di default va bene per pilotare LEDs, non per motori. Io vado con PWM a circa 4kHz per ottenere risultati decenti con il 298. L'integrale serve solo per azzerare l'errore. Se la velocità non è stabile non serve l'integrale per stabilizzarla. Se lo fa è solo un mascheramento di un problema che poi si può ripresentare sotto forma di oscillazioni ad alcune velocità. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 Ma il pwm risiede nel void irs chiamato ogni 2,5ms quindi non e alla frequenza base di 490hz cosa si intende chiamare la funzione pid ogni 10 interrupt? ulltimo potresti indicarmi dove trovo il tuo codice scritto nel tutorial? Grazie Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 #define ledPin 13 boolean impulso = 0; boolean memoria = 0; unsigned int pulseCount = 0; unsigned long time0 = 0; unsigned long timeT = 0; unsigned long rpm = 0; int setpoint=0; int uscita=0; int uscita1=0; int errore; float proporzionale; int proporzionale1; void setup() { pinMode(3,OUTPUT); pinMode(ledPin, OUTPUT); pinMode(7, INPUT); Serial.begin(57600); // initialize timer1 noInterrupts(); // disable all interrupts TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; OCR1A = 256; // compare match register 16MHz con 128 in contatore ottengo 2ms chiamata void isr TCCR1B |= (1 << WGM12); // CTC mode TCCR1B |= (1 << CS12); // 256 prescaler TIMSK1 |= (1 << OCIE1A); // enable timer compare interrupt interrupts(); } // enable all interrupts ISR(TIMER1_COMPA_vect) // timer ogni 2ms { digitalWrite(ledPin, digitalRead(ledPin) ^ 1); //pin prova misura frequenza setpoint=950;// set point errore=setpoint-rpm; //calcolo l errore in giri al minuto proporzionale=errore*0.15; //la parte proporzionale in rpm per kp =0,95 proporzionale1=map(proporzionale,0,1200,30,255); // riporto in mappa l errore in rpm proporzionale*Ki in punti per il pwm uscita= map(setpoint,380 ,1800,30 ,255); // riporto in mappa il setpoin in giri al minuto in punti per il pwm if(setpoint<=rpm){ // se il setpoint è minore degli rpm effettivi allora diminuisco il riferimento di velocita uscita1=uscita-proporzionale1;} if(rpm<=setpoint){ // se gli rpm effettivi sono minore del setpoint allora aumento il riferimento di velocita uscita1=uscita+proporzionale1;} if (uscita1>=254){ //limiti min max per l uscita pwm uscita1=254;} if (uscita1<=10){ uscita1=10;} analogWrite(3,uscita1); //metto in uscita1 il pwm finito di correzione proporzionale impulso = digitalRead(7); // impulso della tacho filo giallo ventola if (impulso == LOW) { memoria = 1;} if (impulso== HIGH && memoria== 1 && pulseCount == 0) { time0 = millis();} if (impulso == HIGH && memoria == 1) { pulseCount = (pulseCount + 1); memoria = 0;} if (pulseCount == 100) {// setto il contatore a 100 per rilevare impulsi ad una frequenza bassa timeT = millis(); rpm = 100000/(timeT-time0)*60/2; pulseCount = 0; memoria = 0;} } void loop() { Serial.print("rpm = "); Serial.print(rpm); Serial.print(" Hz errore="); Serial.println(uscita1); } Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 30 ottobre 2016 Segnala Share Inserita: 30 ottobre 2016 Il codice lo trovi come listato di esempio nel tutorial stesso. E' scritto in pseudo "C", quindi molto simile al linguaggio di arduino. Quote Ma il pwm risiede nel void irs chiamato ogni 2,5ms quindi non e alla frequenza base di 490hz E' anche peggio, perchè la sua freqeunza è di 400Hz Dovresti passare ad arduino mega che ha 5 timer ed usare l'uscita di PWM legata al timer2 settato in modo avere la frequenza base di 4kHz circa. In una discussione di Luigi Marchi, ho riportato un link di settorezero che spiega bene l'uso dei timer di arduino per impieghi in PWM, dovresti leggere anche tu quell'articolo. Quote cosa si intende chiamare la funzione pid ogni 10 interrupt? nell funzione ISR(TIMER1_COMPA_vect) // timer ogni 2ms fai un contatore come, ad esempio, int cnt = 20; ----- if (cnt > 0) { cnt--; } else { cnt = 20; pid(); } Poi scrivi la funzione pid che verrà richiamata ogni 40ms se lasci il timer così, però io il timer lo porterei a 10 ms e richiamerei la funzione ogni 200 ms Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 nooo scusa ho ricaricato il timer da avere 250us e con kp a 0,5 ottengo circa ogni tre secondi una variazione di tensione sulla ventola da 11volt quindi riferimento al max a 7 volt per un secondo e poi risale qualcosa non va e non solo qualcosa mi sa gli errori piu grandi sono nella conversione tra pwm ed rpm cioe dò riferimento di set poin 700 e la ventola va a 1200rpm devo rivedere la mappatura per il pwm Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 allora non posso continuare, se resto il timer a 250us il conteggio sulla tacho per avere il riferimento di velocità non posso farlo escono dei numeri sballati forse perche c e anche millis devo risolvere prima questo Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 potrei costruire un circuito elettronico che mi trasformi gli impulsi della ventola da 0 a 50hz in un segnale analogico 0-5 volt per entrare nell arduino? Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 30 ottobre 2016 Segnala Share Inserita: 30 ottobre 2016 250 µs sono una follia! gia 10 ms è esageratamente veloce. Si è forse neglio fare un convertitore frequenza tensione, però con frequenze così basse non è facile. Meglio sarebbe usare una scheda che ha più timer/counter. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 30 ottobre 2016 Autore Segnala Share Inserita: 30 ottobre 2016 quindi, il timer da 250us andrebbe anche bene per il pwm però da come ho capito per leggere il riferimento degli rpm e calcolare l errore occorre farlo ogni 10ms giusto? Stavo pensando non è che nel timer dovrei utilizzare micros e non millis? Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 31 ottobre 2016 Segnala Share Inserita: 31 ottobre 2016 250µs per il PWM di un controllo motore è esageratamente lento, son solo 400Hz, mentre come campionatore dell'anello di velocità in genere è quasi 100 volte troppo veloce. In questo caso bisogherebbe farlo 10.000 volte più lento. Io per controllare i motori uso le uscite 3 e 11 che corrispondono al timer2. Io ti consiglierei di usare un ingresso di inerrupt, non ricordo a memoria il pin corrispondente ma ce ne sono 2, per leggere l'impulso dell'encoder e misurare il tempo. Potresti leggerlo contemporaneamente con i 2 ingressi ed abilitarne uno per il fronte di salita e l'altro per il fronte di discesa, così misuri tutto il periodo esatto dell'impulso. Usi il timer 2 con il prescaler al minimo così da ottenere una freqeunza di PWM >4khz (se vuoi ti metto i settaggi per farlo). Poi usare il timer1 per avere un clock per richiamare il PID di circa 200ms che, per basse velocità sarebbe anche troppo veloce. Se il richiamo del PID è più veloce della misura di velocità o metti i guadagni bassissimi o vai in oscilalzione. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 31 ottobre 2016 Autore Segnala Share Inserita: 31 ottobre 2016 Quote 250µs per il PWM di un controllo motore è esageratamente lento, son solo 400Hz, intendevi 250ms? credo proprio di si Quote Se il richiamo del PID è più veloce della misura di velocità o metti i guadagni bassissimi o vai in oscilalzione. e se venisse richiamato nello stesso tempo in cui misuro? Quote Usi il timer 2 con il prescaler al minimo così da ottenere una freqeunza di PWM >4khz (se vuoi ti metto i settaggi per farlo). se puoi grazie Quote Potresti leggerlo contemporaneamente con i 2 ingressi ed abilitarne uno per il fronte di salita e l'altro per il fronte di discesa, così misuri tutto il periodo esatto dell'impulso. attachinterrupt(pin, void, CHANGE) è questa la funzione che legge il pin ed entra ogni volta nel void legato a questo interrupt, ma nel void dovrò avere un millis per contare gli rpm? come si fa a determinare la frequenza? cioè avviene l interrupt scatenato per il cambio stato del pin 3, entra nel void e da qui come faccio a misurare direttamente gli rpm? Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 31 ottobre 2016 Segnala Share Inserita: 31 ottobre 2016 i Quote ntendevi 250ms? credo proprio di si Scusa intendevo 2.5µs. E' l'effetto mattina presto. Son 4kHz e possono essere sufficienti. Quote e se venisse richiamato nello stesso tempo in cui misuro? Cosa intendi? Se, ad esempio, fai una misura di frequenza con base tempi 100ms, ad ogni acquisizione della frequenza (ogni 100 ms) dopo aver acquisito il valore lanci la funzione PID, fai una cosa corretta. Questo è il modo corretto quando la misura della variabile può essere sincrona con il lancio della funzione. La sequenza corretta è acquisizione, messa in uscita del valore di riferimento calcolato in precedenza, calcolo del nuovo valore di riferimento. Se la funzione e la misura non possono essere sincrone devi avere il periodo del campionamento della funzione pari al doppio dell'intervallo di tempo tra due misure nel caso pessimo. Ad esempio se usi una misura di periodo e imponi che il perido più lungo da misurare sia <=100 ms, la funzione di regolazione la puoi lanciare solo ogni 200 ms + e. Oggi se ho tempo e voglia ti recupero il codice per il settaggio del PWM sul timer2 ed il codice per la misura dell'impulso ad interrupt. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 31 ottobre 2016 Autore Segnala Share Inserita: 31 ottobre 2016 ok quando vuoi voglio prima misurare per bene la velocità della ventola se no è inutile andare avanti Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 31 ottobre 2016 Segnala Share Inserita: 31 ottobre 2016 Ti metto il codice promesso /* I 4 motori si collegano ad una scheda K_298 per controllarne il movimento. I motori sono collegati in serie 2 a 2. Le uscite PWM di arduino, P3 e P11, sono collegati rispettivamente agli ingressi ENA e ENB. Se sono a livello "0" i motori sono fermi indipendentemente dallo stato degli altri 2 comandi. P2, P4 per il motore A, e P10, P9 per il motore B, sono connessi agli ingressi In1, In2 e In3, In4 rispettivamente. Con le coppie al medesimo livello i motori sono bloccati. Con i_enb_A, i_av_ind_B = HIGH e i_av_ind_A, i_av_ind_A = LOW si ha la marcia avanti. Invertendo gli stati si ha la marcuia indietro. */ int EchoPin = 6; //Ingresso misura --------------- void setup() { --------------- noInterrupts(); TCCR1A = 0; TCCR1B = 0; TCNT1 = 6491; TCCR1B |= (1 << CS12); TIMSK1 |= (1 << TOIE1); TCCR2B = TCCR2B & 0b11111000 | 0b10; /* Si imposta il fattore di divisione del prescaler; in questo caso il timer usato è il timer 2 che con prescaler diviso per 1 genera una frequenza di 31.250 Hz */ icnt = 20; ---------- interrupts(); } ISR (TIMER1_OVF_vect) { TCNT1 = 64911; //ricarica timer per 10 ms //digitalWrite(imarca, digitalRead(imarca)^1); icnt--; if (icnt == 0) { icnt = 20; flgacq = HIGH; } } void loop() { -------------------- cmh = (pulseIn(EchoPin, HIGH)); //leggo il tempo (in ms) in cui il pin EchoPin sta alto cml = (pulseIn(EchoPin, LOW)); //Se metto l'opzione LOW leggo il tempo in cui sta basso } Se connetti la tachimetrica digitale all'ingresso Echopin avrai i 2 tempi, la cui somma ti da il periodo. Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 31 ottobre 2016 Autore Segnala Share Inserita: 31 ottobre 2016 int giri = 0; int rpm = 0; unsigned long unsecondo= 0; int cnt; void setup() { Serial.begin(57600); noInterrupts(); attachInterrupt(0, rpm_fan, FALLING); TCCR1A = 0; TCCR1B = 0; TCNT1 = 6491; TCCR1B |= (1 << CS12); TIMSK1 |= (1 << TOIE1); TCCR2B = TCCR2B & 0b11111000 | 0b10; /* Si imposta il fattore di divisione del prescaler; in questo caso il timer usato è il timer 2 che con prescaler diviso per 1 genera una frequenza di 31.250 Hz */ cnt=20; interrupts(); } ISR (TIMER1_OVF_vect) { TCNT1 = 64911; //ricarica timer per 10 ms cnt=cnt-1; analogWrite(3,125); if (cnt<=0){ // posso scrivere qui le formule per ricavare l errore e quindi il pid? Se il cnt arriva a 0 scrivo il programma e ricarico il cnt a 20 quindi esco dal if e aspetto altri 20ms per rientrarci cnt=20; } } void loop(){ if (millis() - unsecondo == 1000){ // detachInterrupt(0);// rpm = giri * 60/2; // Serial.print("RPM =\t"); Serial.print(rpm); // Serial.print("\t Hz=\t"); // Serial.println(giri); // giri = 0; // unsecondo = millis(); // attachInterrupt(0, rpm_fan, FALLING); // } } void rpm_fan(){ giri++; } sono riuscito a leggere bene la velocita della ventola con interrupt sul cambio stato del pin. Nel programma però del timer è giusto come ho scritto nel commento centrale? Link al commento Condividi su altri siti More sharing options...
Livio Orsini Inserita: 1 novembre 2016 Segnala Share Inserita: 1 novembre 2016 ISR (TIMER1_OVF_vect) { TCNT1 = 64911; //ricarica timer per 10 ms cnt=cnt-1; if (cnt<=0){ // posso scrivere qui le formule per ricavare l errore e quindi il pid? Se il cnt arriva a 0 scrivo il programma e ricarico il cnt a 20 quindi esco dal if e aspetto altri 20ms per rientrarci analogWrite(3,125); cnt=20; } Devi mettere nell'interrupt anche la scrittura dell'uscita. Con questi dati l'interrupt lo hai ogni 200ms, va bene se la misura del periodo più lungo della tachimetrica è <100ms Link al commento Condividi su altri siti More sharing options...
roberto8303 Inserita: 1 novembre 2016 Autore Segnala Share Inserita: 1 novembre 2016 Si ma perche nel void isr non riesco a leggere la variabile rpm e nemmeno a stampare sulla seriale?? A questo punto sto pensando di utilizzare due arduino uno che legge la tachimetrica e mi da in proporzione il segnale analogico e lo mando ad un altro Arduino dove leggo l ingresso in tensione e calcolo il pid Link al commento Condividi su altri siti More sharing options...
Messaggi consigliati
Crea un account o accedi per commentare
Devi essere un utente per poter lasciare un commento
Crea un account
Registrati per un nuovo account nella nostra comunità. è facile!
Registra un nuovo accountAccedi
Hai già un account? Accedi qui.
Accedi ora