encoder rotativo

ciao a tutti, la mia intenzione è collegare un encoder rotativo ad un “vitone” che sposta un carrello su una guida, e sapendo che ogni 360° si sposta di 5mm, poi andrò a visualizzare la quota su un display.
la velocità di rotazione (generata da un motoriduttore) è di 2 giri al secondo.

ora sto facendo delle prove a banco con un encoder della rotellina del mouse e dei codici che ho scopiazzato da varie guide.
quello che ho trovato più affidabile è il seguente, e ad ogni giro completo mi segna un valore di 48.
ora non riesco a capire come posso convertire quel valore in millimetri da poi mandare al display

grazie a chiunque possa aiutarmi!

int encoderPin1 = 2;
int encoderPin2 = 3;
 
volatile int lastEncoded = 0;
volatile long encoderValue = 0;
 
long lastencoderValue = 0;
 
int lastMSB = 0;
int lastLSB = 0;
 
void setup() {
  Serial.begin (9600);
 
  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);
 
  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);
 
}
 
void loop(){
  Serial.println(encoderValue); 
}
 
void updateEncoder(){
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit
 
  int encoded = (MSB << 1) |LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;
 
  lastEncoded = encoded; //store this value for next time
}/code]

Quindi un giro completo di 360 è diviso in 48 passi, cioè 360/48 = 7.5° per passo.
Ogni giro completo hai uno spostamento totale di 5mm, quindi 5/48=0,104166667mm per passo.

Conoscendo il passo in millimetri (come pure quello in gradi) puoi calcolare lo spostamento moltiplicando encoderValue per il passo, cioè

#define MM_PER_STEP 0.104166667
float spostamentoInMillimetri = encoderValue * MM_PER_STEP;

Supponiamo l'encoder abbia fatto la metà del giro 360/2 = 180 in gradi, encoderValue sarà uguale 48/2 = 24 in steps, per cui
24 x 0.104166667 = 2.5mm.

Ciao.

grazie @maurotec , mi stavo perdendo in mille pensieri quando in realtà era banalissimo! provato e funziona.

ora vorrei usare la eeprom per salvare il valore dell'encoder in modo da mantenerlo in mancanza di alimentazione.
da quello che ho capito ogni bit può avere un valore compreso tra 0 e 255, mentre il mio encoder lavorerà circa da -1000 a +3500.
sto cercando una soluzione per dividere quel numero e salvarlo a pezzi ma non mi combino, soprattutto con la parte negativa.

nel codice che ho scritto succede questo:
numero 4356 scompone in 4 3 5 6
numero 82 scompone in 0 0 8 2
numero -471 scompone in 0 -4 -7 -1

il problema starebbe poi nel ricomporlo... cè qualche altro metodo più serio?

int num = 0;

void setup() {
  // put your setup code here, to run once:

  Serial.begin (9600);
}

void loop() {
  num=4356;
  Serial.println ((num / 1000) % 10);
  Serial.println ((num / 100) % 10);
  Serial.println ((num / 10) % 10);
  Serial.println (num % 10);
  delay (4000);

  num=82;
  Serial.println ((num / 1000) % 10);
  Serial.println ((num / 100) % 10);
  Serial.println ((num / 10) % 10);
  Serial.println (num % 10);
  delay (4000);

  num=-471;
  Serial.println ((num / 1000) % 10);
  Serial.println ((num / 100) % 10);
  Serial.println ((num / 10) % 10);
  Serial.println (num % 10);
  delay (4000);
}

mi sono evoluto e sono arrivato ad una conclusione utilizzando 5 slot della eeprom:
al primo vado ad assegnargli il valore di 1 o 2 in base al numero se è negativo o positivo, e gli atri 4 per le migliaia/centinaia/decine/unità.
tutto sembra funzionare, solo che ora non riesco a trovare nessuno spunto per riunire il numero andando a leggerlo da eeprom.

questo è quello che riesco ad estrapolare (che poi ogni println andrà a scrivere su un differente bit della eeprom:

int num = 0;
int encoderPin1 = 2;
int encoderPin2 = 3;
int salvataggio = 0;

volatile int lastEncoded = 0;
volatile long encoderValue = 0;
volatile long Misura = 0;

long lastencoderValue = 0;

int lastMSB = 0;
int lastLSB = 0;

void setup() {
  // put your setup code here, to run once:

  Serial.begin (9600);
  pinMode(encoderPin1, INPUT_PULLUP);
  pinMode(encoderPin2, INPUT_PULLUP);

  attachInterrupt(0, updateEncoder, CHANGE);
  attachInterrupt(1, updateEncoder, CHANGE);

}

void loop() {

  if (encoderValue < 0)
  {
    salvataggio = encoderValue;
    Serial.println (salvataggio);
    salvataggio = abs(salvataggio);

    Serial.println (1); //bit 0 per sapere se il numero è negativo
    Serial.println ((salvataggio / 1000) % 10); //migliaia
    Serial.println ((salvataggio / 100) % 10); //centinaia
    Serial.println ((salvataggio / 10) % 10); //decine
    Serial.println (salvataggio % 10);  //unità
    Serial.println (" ");
    Serial.println (" ");

  }
  else  {
    salvataggio = encoderValue;
    Serial.println (salvataggio);

    Serial.println (2); //bit 0 per sapere se il numero è positivo
    Serial.println ((salvataggio / 1000) % 10); //migliaia
    Serial.println ((salvataggio / 100) % 10); //centinaia
    Serial.println ((salvataggio / 10) % 10); //decine
    Serial.println (salvataggio % 10);  //unità
    Serial.println (" ");
    Serial.println (" ");
  }

  delay (2000);
}

void updateEncoder() {
  int MSB = digitalRead(encoderPin1); //MSB = most significant bit
  int LSB = digitalRead(encoderPin2); //LSB = least significant bit

  int encoded = (MSB << 1) | LSB; //converting the 2 pin value to single number
  int sum  = (lastEncoded << 2) | encoded; //adding it to the previous encoded value

  if (sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011) encoderValue ++;
  if (sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) encoderValue --;

  lastEncoded = encoded; //store this value for next time
  Misura = ((encoderValue / 12) * 1.25);
}

poi in “setup” andrei a ricomporre il numero in funzione se è salvato negativo o positivo in questo modo, ma poi non so se cè qualche funzione per unire le cifre insieme:

segno = EEPROM.read(0);
  if (segno == 2) //segno positivo
  {

  }

  if (segno == 1)  //segno negativo
  {

  }

Scusa ma adesso non so risponderti nel dettaglio, non ricordo come si usa la libreria EEprom vero che l'ho usata poco, in sua sostituzione ho sempre usato la le funzioni C della avr-libc incluse con arduino.

Per cui non ho codice al momento da mostrarti, ma la soluzione al tuo problema è comune e si risolve creando una struttura dati con struct .

Questa struttura conterrà dei campi membro di vario tipo, ma tutta la struttura è sempre scomponibile in byte ed è questo che ci permette di scrivere l'intera struttura in EEprom così come si presenta in memoria RAM. Sostanzialmente si tratta di una copia e incolla da RAM a EEprom e viceversa quando devi aggiornare i dati in RAM (cioè nella struttura).

Nel frattempo che recupero qualcosa sempre che riesca in tempi brevi, prova a documentarti su queste funzioni:
avr-libc eeprom

Se noti 3 di queste funzioni nel nome c'è block che sta ad indicare che muovono blocchi di memoria, l'ultima in particolare scrive in eeprom solo se i dati presente attualmente in eeprom sono differenti da quelli che si vuole salvare.

Ciao.

acuplush:
da quello che ho capito ogni bit può avere un valore compreso tra 0 e 255

Ogni byte (gruppo di 8 bit) può contenere da 0 a 255, ogni cella della EEPROM è un byte.

il mio encoder lavorerà circa da -1000 a +3500.
sto cercando una soluzione per dividere quel numero e salvarlo a pezzi ma non mi combino, soprattutto con la parte negativa.

il problema starebbe poi nel ricomporlo… cè qualche altro metodo più serio?

Si, facendo come si fa da 80 anni con i numeri binari. Una variabile int (16 bit con segno) contiene un numero binario con valore compreso tra -32768 e +32767 ed è composta da due byte, basta suddividerli (vengono chiamati byte alto e basso):

int valore = -4567;

byte alto = valore >> 8;
byte basso = valore & 0xFF;

o usando le funzioni già pronte che fanno la stessa cosa:

byte alto = highByte(valore);
byte basso = lowByte(valore);

e poi ricomporli:

int valorericomposto = ((int)alto << 8) | basso;

Claudio_FF:
Ogni byte (gruppo di 8 bit) può contenere da 0 a 255, ogni cella della EEPROM è un byte.
Si, facendo come si fa da 80 anni con i numeri binari. Una variabile int (16 bit con segno) contiene un numero binario con valore compreso tra -32768 e +32767 ed è composta da due byte, basta suddividerli (vengono chiamati byte alto e basso):

int valore = -4567;

byte alto = valore >> 8;
byte basso = valore & 0xFF;



o usando le funzioni già pronte che fanno la stessa cosa:



byte alto = highByte(valore);
byte basso = lowByte(valore);




e poi ricomporli:



int valorericomposto = ((int)alto << 8) | basso;

perfetto grazie, l’ho integrata al mio codice e funziona molto bene!!
ero riuscito anche a ricomporre il numero con il mio sistema, ma questo sistema è molto più pulito e mi occupa solo 2 byte a differenza del mio sistema che ne occupa 5!
grazie!!