Vai al contenuto
PLC Forum


controllo pid con arduino


roberto8303

Messaggi consigliati

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


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

#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

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

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:(:wallbash:

Link al commento
Condividi su altri siti

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

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

#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

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

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

#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

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:lol:

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

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:wallbash: devo rivedere la mappatura per il pwm

 

Link al commento
Condividi su altri siti

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

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

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

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

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

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

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

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

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

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

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

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 account

Accedi

Hai già un account? Accedi qui.

Accedi ora
×
×
  • Crea nuovo/a...