Go Down

Topic: Errore LiquidCrystal I2C  (Read 369 times) previous topic - next topic

Maurotec

Quote
Il fatto è che non riesco a capire se è un problema hardware o software...

Qualcuno mi può aiutare?
Si, però senza vedere il codice, lo schema è difficile aiutarti. Si può ipotizzare, ad esempio se usi un delay nel codice ti perdi uno o più passi dell'encoder, oppure la velocità di aggiornamento del display è inferiore ai tempi di reazione del encoder per cui da 0 passa a 4 saltando 123.

PS: La mia sfera di cristallo è a bassa risoluzione appena ingrandisco sgrana :D

orzowilde

#16
Jul 14, 2019, 07:30 pm Last Edit: Jul 14, 2019, 08:05 pm by orzowilde
 :)  :)  :)  hai ragione!!!

In allegato invio sia lo schema che il codice...
Grazie

Maurotec

Code: [Select]

void doEncoderB()
{
    if  (boolean)digitalRead(encoder0PinA)  {
   
         parameterValue[index]++;

    } else {

         parameterValue[index]--;

    }
}


Quello sopra è un esempio alternativo a quello che fai tu nel codice, purtroppo non risolve il tuo problema che credo
sia altrove. parameterValue è un array di ad es byte e index varrà 0 per le ore, 1 per i minuti e 2 per i secondi.

Comunque solitamente con l'encoder si vuole modificare il valore di un parametro e non sappiamo prima se questo è di tipo byte o word con o senza segno, inoltre non sappiamo i limiti oltre il quale il valore di un parametro non deve potere andare.
La soluzione è un po più complessa e richiede del codice che abbina ad un parametro il nome, il limite superiore, quello inferiore, il puntatore alla variabile valore e un byte codifica a bit per stabilire come sarà visualizzato (es byte, intero, float ecc). 

Andiamo al problema specifico, secondo me devi isolare le varie parti del codice in modo da lasciare solo quella parte che
modifica i valori tramite encoder. Per non incasinare il codice attuale potresti creare un altro sketch che implementa encoder e le variabili evitando il più possibile delay.

Ciao.

orzowilde

 :o  :o  :o  ho capito tutto il senso di quello che hai detto... quello che devo cercare di capire come mettere in atto quello che mi hai spiegato....

Provo e vediamo se ce la faccio...

 :smiley-confuse:

Maurotec

Quote
Provo e vediamo se ce la faccio...
Per adesso limitati ad isolare il codice del'encoder come ho scritto nella parte finale, poi vado a cercare codice mio che implementa qualcosa di simile.

Scrivo qua solo per ricordarmi (sono smemorato), in sostanza si crea una struttura (o in C++ classe) e all'interno ci sono le due varibili limiteMax e limiteMin, ci sarò un metodo incrementa e uno decrementa ecc. Eventualmente si può anche esagerare con i metodi save, load, displayValue, displayName ecc. Ripeto questo lo vediamo dopo, prima cerca di fare funzionare l'encoder.

Ciao.

Maurotec

Dall'immagine allegata non si capisce il tipo di encoder se ottico o meccanico, sembrerebbe meccanico ed allora in questo caso i contatti meccanici soffrono del fenomeno di rimbalzo e questo fa si che uno step dell'encoder venga contato più volte tante quanto sono i rimbalzi. Una possibile soluzione hardware consiste nel collegare un circuito antirimbalzo, uno per ogni uscita dell'encoder, diciamo A e B.



Maggiore è il valore delle capacità (uF) più lentamente risponderà l'encoder. Valori possibili sono 22nF, 47nF, 100nF o 10nF (0.01 uF) come scritto nel disegno.

Per soluzioni software vedi: https://www.best-microcontroller-projects.com/rotary-encoder.html sezione Digital Debounce Filter.

Ciao.

orzowilde

Non riesco a capire come fare il debounce tramite software.... non lo capiscoooo...  :(

orzowilde

Salve a tutti, ho costruito come mi aveva suggerito @Maurotec il circuito antirimbalzo, usando gli stessi componenti da lui suggeriti e collegati ad ogni uscita dell'encoder. La situazione è un po migliorata visto che riesco a settare le ore i minuti ed i secondi, ma ancora non è scorrevole e salta ancora diversi numeri.... come posso fare?

Grazie

Maurotec

Non ho un encoder meccanico e non l'ho mai provato. Io ho un encoder ottico la cui rotazione non al tatto non si avverte scatto ,questo tipo è più indicato per rilevare la velocità di motori e non soffre di debounce.

Con il tipo ottico è facile il codice ma servono due pin interrupt, INT0 e INT1, oppure due pin qualsiasi attivando gli interrupt PINCHANGE anche se meno reattivo.

Con encoder meccanico che soffre di debounce si potrebbe tentare di introdurre del codice per l'anti rimbalzo nella funzione do EncoderB ma questo codice richiede almeno 20ms per ogni step dell'encoder.

Proviamo ad isolare il codice e concentrarci sull'anti rimbalzo.

Code: [Select]

#include <EEPROM.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 16, 2); // set the LCD address to 0x27 for a 16 chars and 2 line display


#define encoder0PinA  2
#define encoder0PinB  3

volatile long encoderValue = 0;

byte pushButton = 4;


void setup() {

  lcd.begin();
  Serial.begin(9600);
  Serial.begin(9600);
  pinMode(pushButton, INPUT_PULLUP); // configura il pin "pushButton" come input con pullup:

  pinMode(encoder0PinA, INPUT);  // pin A encoder come input senza pullup (dipende dallo schema)
  pinMode(encoder0PinB, INPUT);  // pin B encoder come input senza pullup (dipende dallo schema)
 
  attachInterrupt(1, doEncoderB, FALLING); // collega funzione utente doEncoderB ad interrupt falling di pin 1

  lcd.clear();
  lcd.setCursor(0, 0);
  lcd.print("Hello Word");
  lcd.setCursor(0, 1);
  lcd.print("Counter = ");

}


void loop() {
  lcd.setCursor(9, 1);
  lcd.print("          ");  // pulisce il campo (10 spazi)
  lcd.setCursor(9, 1); 
  lcd.print(encoderValue);  // visualizza encoderValue


}


// PARAMETRI LEGATI ALLE LETTURE ENCODE TRAMITE INTERRUPT


void doEncoderB()
{
  delay(1) // se c'è un rimbalzo encoder0PinB sarà alto e quindi usciamo senza fare nulla
  if (digitalRead(encoder0PinB)
     return;
  else {  // altrimenti aspetta un millesimo di secondo
     delay(1);
     if (digitalRead(encoder0PinA))  // se PinA è alto
       encoderValue--;   
     else
       encoderValue++;                     // se PinA è basso
  }
}



Prova questo codice con lo schema che ti ho linkato (schema di cui non sono molto contento), e dimmi se scorre più gradevole e salta qualche conteggio. Prova ad muovere di uno scatto l'encoder lentamente tra uno scatto e l'altro se va bene, incrementa la velocità di rotazione e fammi sapere come va.

Go Up