Arduino Motor Shield PWM e interrupts

Buongiorno. Io sto costruendo un robot a quattro ruote con svariati sensori per il controllo. Uno dei controlli e la regolazione della velocità tramite un encoder. Per misurare il tempo trascorso tra un due segnali dell'encoder uso la funzione millis(). Il problema sorge quando alla PWM del pin 3, che nella motor shield preassemblata si occupa della gestione di uno dei motori, do un valore diverso da 0 o 255 (utilizzo arduino UNO rev3). Arduino mi restituisce ad ogni impulso una serie di 0 e 1 che vanno a incidere sulla misurazione. Credo ciò sia dato da un interferenza di qualche tipo. Il fenomeno può essere eliminato o aggirato? :~

non ho capito bene il problema però ricordati che un segnale PWM è un'onda quadra, ossia una sequenza di segnali alti e bassi alternati di differente lunghezza. Un segnale alto è letto 1, un segnale basso è letto 0. L'analogWrite dell'Arduino imbroglia, nel senso che con un'analogWrite(0) in realtà pone fisso il pin su Low, mentre con analogWrite(255) pone il pin su High. Tutti gli altri valori sono combinazioni di 0 e 1 dipendenti dal duty cycle impostato.

Se usi il pin 3 come entrata interrupt e il shield lo usa per il PWM del motore Tu ricevi gli interrupt con una frequenza di ca 490Hz indipendentemente dal encoder. Dovresti modificare la shield in modo che usi una uscita PWM diversa.

Ciao Uwe

conosco il funzionamento del duty cicle. Io uso come pin di interrupt il pin 2. Proprio per questo temo che la continua variazione del segnale su pin 3 possa portare a un malfunzionamento del pin2. Anche perchè con 0 e 255, ossia con segnale costante sul pin 3, l'intterupt funziona correttamente. :0

Come, usi solo un interrupt? Non Ti servono 2, uno per ciascun encoder / motore? Ciao Uwe

Come hai collegato l'encoder?

Sì può avere anche lo sketch?

volatile int t=0,t1,T,t2,t3,t4;
int i=150;
void setup(){
  Serial.begin(9600);
  pinMode(3,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(13,OUTPUT);
  pinMode(2,INPUT);
  pinMode(10,OUTPUT);
  attachInterrupt(0,funz,RISING);
  }
void loop(){
 digitalWrite(13,HIGH);
  digitalWrite(12,HIGH);
  analogWrite(11,i);
   analogWrite(3,i);
  }
  
 void funz(){
   time();
   }
   
 void time(){
   t4=t3;
   t3=t2;
   t2=t1;
   t1=t;
  t=millis();
  T=((t-t1)+(t1-t2)+(t2-t3)+(t3-t4))/4;
  T=t-t1;
  Serial.print(T);
   Serial.print("\n");
 }

utilizzo un unico encoder di uno dei due motori.

Come puoi usare un int per una funzione (millis() ) che da come risposta un valore unsigned long? Dopo 32 secondi hai il primo overflow.

saró vecchio e avere la testa dura ma non capisco il senso di questo codice:

void funz(){
   time();
   }

definisci una funzione come funzione che viene chiamato nel caso del interrupt che a sua volta non fa nient altro che chiamare un altra funzione. Questo non ha senso. Chiama subito dall'interrupt la funzione time.

 void time(){
   t4=t3;
   t3=t2;
   t2=t1;
   t1=t;
  t=millis();
  T=((t-t1)+(t1-t2)+(t2-t3)+(t3-t4))/4;
  T=t-t1;
  Serial.print(T);
   Serial.print("\n");
 }

prima fai tutti i Tuoi calcoli di T

t4=t3;
   t3=t2;
   t2=t1;
   t1=t;
  t=millis();
  T=((t-t1)+(t1-t2)+(t2-t3)+(t3-t4))/4;

e poi scrivi

T=t-t1;

che senso ha questo codice.

oltre questo é proibito usare il serial.print() dentro una funzione interrupt perché necessita di troppo tempo.

Ciao Uwe

T=t-t1;

mi sono dimenticato di eliminarlo. Avevo fatto delle prove per eliminare il problema senza riuscirci e non lo ho più modificato. Ho utilizzato un richiamo di funzione nell'interrupt sempre nei tentativi di eliminare il problema. Ho pensato infatti che se la funzione interna all'interrupt fosse stata troppo lunga avrebbe provocato problemi all'interrupt facendone richiamare una esterna, in caso di un altro interrupt la funzione sarebbe interrota.

BrMa: Ho pensato infatti che se la funzione interna all'interrupt fosse stata troppo lunga avrebbe provocato problemi all'interrupt facendone richiamare una esterna, in caso di un altro interrupt la funzione sarebbe interrota.

No. Le funzioni chiamate dagli interrupt sono compilate come non interrompibili da un altro interrupt per cui se hai un interrupt che richiede troppo tempo, tutto il micro ne risentirà subendo dei rallentamenti.

Ooook :sweat_smile:. Ho risolto il problema. :slight_smile: Grazie mille del supporto e delle dritte. Ciao :slight_smile: