Cos'è ElectroYou | Login Iscriviti

ElectroYou - la comunità dei professionisti del mondo elettrico

Debounce software interrupt esterno

Progetti, interfacciamento, discussioni varie su questa piattaforma.

Moderatori: Foto UtenteMassimoB, Foto Utentexyz, Foto UtenteWALTERmwp

0
voti

[21] Re: Debounce software interrupt esterno

Messaggioda Foto Utentelucaking » 28 ago 2022, 17:51

luxinterior ha scritto:Mi puoi spiegare una cosa
le orme d'onda non sono quelle di un segnale encoder Se fosse ecoder incrementale sarebbero due onde quadre sfasate di 90°
Anche sulllo stampato le label dei pin sono CLK_PIN e DRCT_PIN a me fa pensare più a una seriale con segnale di clock e dato.
AVresti mica un datashhet o della documentaizone della tua schedina che descrive l'interfaccia
Ho notato anch' io questa cosa, e la cosa che meno capisco è perché ruotandolo un po piu velocemente (immagine 3), il segnale sembri "corretto", mentre ruotando lentamente no....
Purtroppo non ho nessun datasheet, sono dei modulini (quasi sicuramente cinesi) che avevo in casa acquistati anni fa.
L' unica cosa che posso confermarti che sono esattamente come quello in foto.


djnz ha scritto:
lucaking ha scritto:ho modificato anche il codice come segue

:?: :?: :?:
E hai ragione anche tu .... :oops:
Eccolo:
Codice: Seleziona tutto
#define SW_PIN 2
#define CLK_PIN 3
#define DRCT_PIN 4

volatile int encoder_count = 0;
volatile boolean encoder_trig = 0;
volatile boolean button_trig = 0;

void button_handler ()
{
   static unsigned long button_time;
   static unsigned long last_button_time = 0;
   button_time = millis();
   if ((button_time - last_button_time) > 300) {
      last_button_time = button_time;
      button_trig = 1;
   }
}

void encoder_handler ()
{
   static unsigned long encoder_time;
   static unsigned long last_encoder_time = 0;
   encoder_time = millis();
   if ((encoder_time - last_encoder_time) > 10) {
      last_encoder_time = encoder_time;
      delay(5);
      boolean clk_pin_state = digitalRead (CLK_PIN);
      boolean drct_pin_state = digitalRead (DRCT_PIN);
      if (clk_pin_state == !drct_pin_state) {
         encoder_count ++;
      }
      if (clk_pin_state == drct_pin_state) {
         encoder_count --;
      }
      encoder_trig = 1;
   }
}

void setup() {
   pinMode (SW_PIN, INPUT);
  pinMode (CLK_PIN, INPUT);
  pinMode (DRCT_PIN, INPUT);
  attachInterrupt (0, button_handler, FALLING); // encoder SW_PIN.
  attachInterrupt (1, encoder_handler, FALLING); // encoder CLK_PIN.
   Serial.begin (9600);
}

void loop() {
   if (encoder_trig) {
       Serial.print(encoder_count);
       Serial.print(" ");
       encoder_trig = 0;
    }
    if (button_trig) {
       Serial.print("\n\rConfermato ");
       Serial.println(encoder_count);
       Serial.println();
       button_trig = 0;
    }
}



Foto Utentedjnz, come avrai capito il mio livello tecnico è piuttosto scarso, ti ringrazio per il tuo codice ma con solo una rapida occhiata, fatico un po' a capirlo.
Devo riguardarmi alcuni concetti base, tipo il bitshifting, operatori logici e array bidimensionali, giusto due dettagli insomma.... :oops:
Nei giorni a venire vorrei dedicare un po di tempo sia al tuo che ha quello della libreria che ho linkato, mi sembra di capire che il metodo alla base sia simile.
Avatar utente
Foto Utentelucaking
1.398 3 5 8
Expert
Expert
 
Messaggi: 1243
Iscritto il: 29 mag 2015, 14:28

1
voti

[22] Re: Debounce software interrupt esterno

Messaggioda Foto UtenteGioArca67 » 28 ago 2022, 18:06

delay() in una ISR non funziona! Toglilo.
Aumenta la velocità della seriale.
Quando l'encoder gira veloce potresti perdere qualcosa perché la seriale è lenta e non fai in tempo a scrivere.
Nell'handler prova a scrivere
Codice: Seleziona tutto
encoder_trig++

fallo poi scrivere quando nel loop mandi i valori alla seriale: se lo trovi >1 il micro ha acchiappato più di un INT ma tu ne hai scritto solo uno.
Avatar utente
Foto UtenteGioArca67
2.075 2 4 9
Master
Master
 
Messaggi: 1830
Iscritto il: 12 mar 2021, 9:36

1
voti

[23] Re: Debounce software interrupt esterno

Messaggioda Foto Utentedjnz » 28 ago 2022, 18:59

lucaking ha scritto:perché ruotandolo un po piu velocemente (immagine 3), il segnale sembri "corretto", mentre ruotando lentamente no

Trigger oscilloscopio impostato su alternate? (se sui moderni dso esiste ancora una cosa del genere...)

Osservando lentamente le uscite dell'encoder tramite due LED si dovrebbe notare meglio la sfasatura di 90 gradi.
Avatar utente
Foto Utentedjnz
590 2 5
Expert
Expert
 
Messaggi: 281
Iscritto il: 26 lug 2020, 14:52

0
voti

[24] Re: Debounce software interrupt esterno

Messaggioda Foto Utentelucaking » 30 ago 2022, 10:42

GioArca67 ha scritto:delay() in una ISR non funziona! Toglilo.
Eh si, sapevo anch' io che non fosse una bella cosa, bloccare una ISR, ma sta di fatto che se lo tolgo le cose funzionano peggio.
Quello che ho visto facendo qualche prova è che posso abbassarlo a 1ms.

Qui sotto gli output di un giro intero di encoder (a velocità abbastaza lenta) con e senza il delay in questione.
Codice: Seleziona tutto
void encoder_handler ()
{
   static unsigned long encoder_time;
   static unsigned long last_encoder_time = 0;
   encoder_time = millis();
   if ((encoder_time - last_encoder_time) > 10) {
      last_encoder_time = encoder_time;
      delay(1);
      boolean clk_pin_state = digitalRead (CLK_PIN);
      boolean drct_pin_state = digitalRead (DRCT_PIN);
      if (clk_pin_state == !drct_pin_state) {
         encoder_count ++;
      }
      if (clk_pin_state == drct_pin_state) {
         encoder_count --;
      }
      encoder_trig = 1;
   }
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
28 29 30 31 32 33 34 35 36


Codice: Seleziona tutto
void encoder_handler ()
{
   static unsigned long encoder_time;
   static unsigned long last_encoder_time = 0;
   encoder_time = millis();
   if ((encoder_time - last_encoder_time) > 15) {
      last_encoder_time = encoder_time;
//      delay(1);
      boolean clk_pin_state = digitalRead (CLK_PIN);
      boolean drct_pin_state = digitalRead (DRCT_PIN);
      if (clk_pin_state == !drct_pin_state) {
         encoder_count ++;
      }
      if (clk_pin_state == drct_pin_state) {
         encoder_count --;
      }
      encoder_trig = 1;
   }
}
1 2 3 4 5 4 5 4 5 4 5 6 7 8 9 10 11 12 13 12 13 12 13 14 15 16 17 18 19
20 21 22 23 24 25 24


GioArca67 ha scritto:Aumenta la velocità della seriale.
Quando l'encoder gira veloce potresti perdere qualcosa perché la seriale è lenta e non fai in tempo a scrivere.
Grazie del suggerimento, capisco la ratio, ma ho provato 57600 b/s e non cambia nulla.
Daltronde, a 9600 b/s, per stampare un numero a tre cifre e uno spazio con codifica 8N1 servono 40 bits, che si traducono in poco più di 4 ms.
Considerato che alle massime velocità a cui riesco a ruotare a mano, non sono mai riuscito a vedere due fronti di discesa a meno di 15 ms, direi che tutto torna.
Avatar utente
Foto Utentelucaking
1.398 3 5 8
Expert
Expert
 
Messaggi: 1243
Iscritto il: 29 mag 2015, 14:28

0
voti

[25] Re: Debounce software interrupt esterno

Messaggioda Foto Utenteluxinterior » 30 ago 2022, 15:21

A me le forme d'ona non tornano a prescindere dalla velocità dovrebbero essere due onde quadre sfasate di 90°
Se la velocità varia vedi i fronti dello stesso segnale avvicinarsi o allontanarsi ma la relazione di fase con altro segnale non cambia. In altre parole il segnale B commuta sempre a metà tra due fronti del segnale A.
Cercherò un datasheet.

Se ho capito bene il tuo problema e l'encoder ha 256 impulsi/giro tu per ogni giro considera meno impulsi ad esempio fino a 64 o anche meno In questo modo le inevitabili oscillazioni di un passo le filtri.
Avatar utente
Foto Utenteluxinterior
3.265 2 4 8
Master
Master
 
Messaggi: 1968
Iscritto il: 6 gen 2016, 17:48

0
voti

[26] Re: Debounce software interrupt esterno

Messaggioda Foto UtenteEtemenanki » 30 ago 2022, 16:18

luxinterior ha scritto:... l'encoder ha 256 impulsi/giro ...


Sicuro ? ... in media quegli encoder per manopole hanno 12 o 16 impulsi (o scatti) per giro.
"Sopravvivere" e' attualmente l'unico lusso che la maggior parte dei Cittadini italiani,
sia pure a costo di enormi sacrifici, riesce ancora a permettersi.
Avatar utente
Foto UtenteEtemenanki
2.867 2 4 8
Master
Master
 
Messaggi: 1887
Iscritto il: 2 apr 2021, 23:42
Località: Dalle parti di un grande lago ... :)

0
voti

[27] Re: Debounce software interrupt esterno

Messaggioda Foto Utentelucaking » 31 ago 2022, 9:44

Gli encoder di cui dispongo hanno 20 scatti.

Ho guardato un po' meglio il codice della libreria che ho linkato in precedenza e quello proposto da Foto Utentedjnz (che ad onor del vero non ho compreso a pieno) ed ho provato a procedere in maniera simile.
Sono arrivato a scrivere questo:
Codice: Seleziona tutto
#define SW_PIN 2
#define CLK_PIN 3
#define DT_PIN 4

volatile boolean button_trig = 0;
volatile boolean encoder_trig = 0;
volatile int encoder_count = 0;

void button_handler ()
{
   static unsigned long button_time;
   static unsigned long last_button_time = 0;
   button_time = millis();
   if ((button_time - last_button_time) > 300) {
      last_button_time = button_time;
      button_trig = 1;
   }
}

void encoder_handler ()
{
   static unsigned int encoder_val = 0;
   static unsigned int encoder_last_val = 0;
   delay(2);
   encoder_val = digitalRead(CLK_PIN) << 1 | digitalRead(DT_PIN);
   if (encoder_val != encoder_last_val) {
      switch (encoder_val) {
      case 0: /* case 3: */
         encoder_count--;
         encoder_trig = 1;
         break;
      case 1:  /* case 2: */
         encoder_count++;
         encoder_trig = 1;
         break;
         }
      }
   encoder_last_val = encoder_val;
}

void setup() {
  pinMode (SW_PIN, INPUT);
  pinMode (CLK_PIN, INPUT);
  pinMode (DT_PIN, INPUT);
  attachInterrupt (0, button_handler, FALLING); // encoder SW_PIN.
  attachInterrupt (1, encoder_handler, CHANGE); // encoder CLK_PIN.
   Serial.begin (9600);
}

void loop() {
    if (encoder_trig) {
       Serial.print(encoder_count);
       Serial.print(" ");
       encoder_trig = 0;
    }
    if (button_trig) {
       Serial.print("\n\rConfermato ");
       Serial.println(encoder_count);
       Serial.println();
       button_trig = 0;
    }
}

che con mia grade sorpresa e gioia, sembra funzionare benissimo, conteggiando 20, oppure 40 decommentando case: 3 e case: 2, impulsi a salire o a scendere a qualunque velocità io ruoti l' encoder.
Ora, i punti che mi lasciano piu perplesso alla luce di quanto emerso sono:
- l' averlo trattato come un encoder in quadratura
- aver usato quel delay() nell' ISR
- aver spostato all' interno dell' ISR anche la parte "decisionale" (switch case).
L' ho fatto per comodità, nell' ottica di una funzione loop() futura che dovrà gestire un po piu cose.
Perplessità a parte, devo dire che nella pratica sembra fuzionare, oserei dire perfettamente.
Detto cio sono pronto ad essere insultato da coloro che sanno programmare per davvero. :mrgreen:
Avatar utente
Foto Utentelucaking
1.398 3 5 8
Expert
Expert
 
Messaggi: 1243
Iscritto il: 29 mag 2015, 14:28

1
voti

[28] Re: Debounce software interrupt esterno

Messaggioda Foto Utentelucaking » 31 ago 2022, 9:56

Le parti che non capisco del codice proposto da Foto Utentedjnz sono l' uso dell' array bidimensionale tabT e della variabile fase.
Codice: Seleziona tutto
const uint8_t tabT[7][4] = {
    { 0, 4, 1, 0 },
    { 2, 1, 1, 0 },
    { 2, 3, 1, 2 },
    { 2, 3, 3, 0 },
    { 5, 4, 4, 0 },
    { 5, 4, 6, 5 },
    { 5, 6, 6, 0 }
};

void readEncoder()
{
    static uint8_t  fase = 0;
    uint8_t enc = (digitalRead(ENCODER_B) << 1) | digitalRead(ENCODER_A);
    onUp = (3 == fase  &&  3 == enc);
    onDn = (6 == fase  &&  3 == enc);
    fase = tabT[fase][enc];
}

Scusate, ma tanto il mio livello ormai lo avrete capito.... :oops:
Comunque se qualcuno volesse darmi qualche dritta a riguardo, gliene sarei grato.
Avatar utente
Foto Utentelucaking
1.398 3 5 8
Expert
Expert
 
Messaggi: 1243
Iscritto il: 29 mag 2015, 14:28

0
voti

[29] Re: Debounce software interrupt esterno

Messaggioda Foto Utentestefanopc » 31 ago 2022, 13:00

Siccome sono autodidatta anche io seguo con piacere la eventuale spiegazione.
Riguardo al fatto che lo sfasamento tra i due segnali non sia simmetrico potrebbe essere causato dallaforza della molla a sfera che blocca la rotazione creando gli step.
La velocità angolare non dovrebbe essere costante ma qualcosa di simile ad un moto accelerato.

Ciao
600 Elettra
Avatar utente
Foto Utentestefanopc
7.641 4 8 12
Master EY
Master EY
 
Messaggi: 2492
Iscritto il: 4 ago 2020, 9:11

2
voti

[30] Re: Debounce software interrupt esterno

Messaggioda Foto UtenteGioArca67 » 31 ago 2022, 13:23

lucaking ha scritto:Le parti che non capisco del codice proposto da Foto Utentedjnz sono l' uso dell' array bidimensionale tabT e della variabile fase.
Codice: Seleziona tutto
const uint8_t tabT[7][4] = {
    { 0, 4, 1, 0 },
    { 2, 1, 1, 0 },
    { 2, 3, 1, 2 },
    { 2, 3, 3, 0 },
    { 5, 4, 4, 0 },
    { 5, 4, 6, 5 },
    { 5, 6, 6, 0 }
};

void readEncoder()
{
    static uint8_t  fase = 0;
    uint8_t enc = (digitalRead(ENCODER_B) << 1) | digitalRead(ENCODER_A);
    onUp = (3 == fase  &&  3 == enc);
    onDn = (6 == fase  &&  3 == enc);
    fase = tabT[fase][enc];
}

Scusate, ma tanto il mio livello ormai lo avrete capito.... :oops:
Comunque se qualcuno volesse darmi qualche dritta a riguardo, gliene sarei grato.


L'array tabT raccoglie lo stato (fase) futuro per ogni possibile stato presente, riga, ed ogni possibile ingresso, colonna.
Legge lo stato delle due uscite dell'encoder (A e B) ad un certo istante e costruisce enc (l'ingresso alla macchina a stati), enc ha 2 bit: 4 possibili valori.
Codice: Seleziona tutto
uint8_t enc = (digitalRead(ENCODER_B) << 1) | digitalRead(ENCODER_A);


Calcola l'uscita della macchina a stati sulla base dello stato interno corrente (fase) e l'ingresso (enc):
Codice: Seleziona tutto
onUp = (3 == fase  &&  3 == enc);
onDn = (6 == fase  &&  3 == enc);

se lo stato attuale è 3 e ho l'ingresso a 3 (b11, entrambi A e B a 1) giro in un senso
se lo stato attuale è 6 e ho l'ingresso a 3 (b11, entrambi A e B a 1) giro nell'altro senso.

Calcola il nuovo stato a partire dal corrente e dall'ingresso
Codice: Seleziona tutto
fase = tabT[fase][enc];
Avatar utente
Foto UtenteGioArca67
2.075 2 4 9
Master
Master
 
Messaggi: 1830
Iscritto il: 12 mar 2021, 9:36

PrecedenteProssimo

Torna a Arduino

Chi c’è in linea

Visitano il forum: Nessuno e 1 ospite