Problema programmazione encoder rotativo

Buongiorno a tutti, sono nuovo del mondo di Arduino e della programmazione e avrei bisogno di un aiuto.
Sto programmando un encoder rotativo e ho trovato tale codice on line , già pronto e bello funzionante.

#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC
 
void setup()
{
  /* Setup encoder pins as inputs */
  pinMode(ENC_A, INPUT);
  digitalWrite(ENC_A, HIGH);
  pinMode(ENC_B, INPUT);
  digitalWrite(ENC_B, HIGH);
  Serial.begin (9600);
  Serial.println("Start");
}
 
void loop()
{
 static uint8_t counter = 0;      //this variable will be changed by encoder input
 int8_t tmpdata;
 /**/
  tmpdata = read_encoder();
  if( tmpdata ) {
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
    counter += tmpdata;
  }
}
 
/* returns change in encoder state (-1,0,1) */
int8_t read_encoder()
{
  static int8_t enc_states[] = {0,-1,1,0,1,0,0,-1,-1,0,0,1,0,1,-1,0};
  static uint8_t old_AB = 0;
  /**/
  old_AB <<= 2;                   //remember previous state
  old_AB |= ( ENC_PORT & 0x03 );  //add current state
  return ( enc_states[( old_AB & 0x0f )]);
}

Il codice va bene ma io avrei bisogno di qualcosa di leggermente diverso.
I dati vengono scritti a frequenze di ogni cambiamento di stato (il dato nuovo compare solo quando giro la manopola, se la manopola rimane ferma la scrittura si arresta all’ultimo dato rilevato), mentre io avrei bisogno che i dati vengano scritti di continuo, ad una frequenza da me scelta, rilevando ovviamente tutte le variazioni di stato anche…
Ho provato un pò ma non ne sono venuto fuori, qualcuno può aiutarmi?

Benvenuto!

Prima che sia avventino su di te i "falchi" del comportamento corretto in questo forum, ti suggerisco di modificare il tuo post inserendo la parte di codice con l'apposito tag "#".

Detto questo, lo sketch che stai usando non consente di fare altro, essendo il loop completamente dedicato all'acquisizione del segnale dell'encoder.

Bisogna usare l'external interrupt, in modo da rendere "automatica" l'acquisizione:

mixmaxmaxxx:
Buongiorno a tutti, sono nuovo del mondo di Arduino

Ti invitiamo a presentarti (dicci quali conoscenze hai di elettronica e di programmazione) qui: Presentazioni
e a leggere il regolamento: Regolamento

Ok, ora mi sono presentato e ho letto il regolamento!
Allora studio ancora un pò i dati linkati ed in caso mi faccio nuovamente vivo :grin:
Intanto grazie XD

cyberhs:
Detto questo, lo sketch che stai usando non consente di fare altro, essendo il loop completamente dedicato all'acquisizione del segnale dell'encoder.

Bisogna usare l'external interrupt, in modo da rendere "automatica" l'acquisizione:
http://arduino.cc/en/Reference/AttachInterrupt

E se volessi affiancare ad ogni dato acquisito riguardante la rotazione dell'encoder un riferimento temporale (in millisec) rispetto al momento in cui è iniziata l'acquisizione??? saebbe possibile lavorando su questo sketch?

Quello sketch usa gli ingressi A0(14) ed A1(15) come input digitali, essendo normalmente analogici.
Per acquisire velocemente lo stato di questi due ingressi, legge il registro della porta C (PORTC) che contiene lo stato di tutti gli altri ingressi (A0, A1, A2, A3, A4, A5) prelevando solo i primi due bit (ENC_PORT & 0x03).

Se non ho capito male quello che desideri, devi usare un qualcosa di simile:

#define ENC_A 14
#define ENC_B 15
#define ENC_PORT PINC

unsigned int counter = 0;      //this variable will be changed by encoder input 
unsigned int tmpdata = 0;
unsigned long Timer = 0;
unsigned long Delay = 1000;    // 1 second

void setup() {
  pinMode(ENC_A, INPUT_PULLUP);
  pinMode(ENC_B, INPUT_PULLUP);
  Serial.begin (9600);
  Serial.println("Start");
}
 
void loop() {
  tmpdata = read_encoder();
  counter += tmpdata;
  if (millis() - Timer > Delay) {  // ogni tot secondi
    Timer = millis();
    Serial.print("Counter value: ");
    Serial.println(counter, DEC);
  }
}

int read_encoder() {              // returns change in encoder state (-1, 0, 1)
  static int enc_states[] = {0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0};
  static unsigned int old_AB = 0;
  old_AB <<= 2;                   // remember previous state
  old_AB |= (ENC_PORT & 0x03);    // add current state
  return (enc_states[(old_AB & 0x0f)]);
}

cyberhs:
Quello sketch usa gli ingressi A0(14) ed A1(15) come input digitali, essendo normalmente analogici.
Per acquisire velocemente lo stato di questi due ingressi, legge il registro della porta C (PORTC) che contiene lo stato di tutti gli altri ingressi (A0, A1, A2, A3, A4, A5) prelevando solo i primi due bit (ENC_PORT & 0x03).

Se non ho capito male quello che desideri, devi usare un qualcosa di simile:

L'ho provato! E' esattamente quello che cercavooo XD XD XD
Grandissimo!!! Grazie mille veramente!!!
Adesso me lo studio per bene per capirlo...ancora grazie!

Buonasera, mi ricollego a questo topic dato che si tratta del medesimo prodotto.

Dopo aver preso un pò la mano con arduino, ho deciso di sperimentare acquistando a qualche euro un encoder rotativo, giusto per capire il suo funzionamento e per cimentarmi un pò sulla parte di codice e acquisizione dei dati…il mio intento sarebbe quello di riuscire a rilevare il massimo regime di rotazione di un meccasimo meccanico “come un asse di una ruota di bicicletta ad esempio” e di rilevare se possibile delle rotazioni anche minime di qualche grado “ad esempio, ottenere in gradi la rotazione di un asse…”

Sapete consigliarmi sui vari collegamentida effetuare?
Dispongo di un foglio dato dal costruttore ma almeno per me è incomprensibile “in cinese”, le uscite non sono allo stesso voltaggio, leggendo ho visto che è risovlibile inserendo una resistenza, ma non ho ben chiaro il da farsi…

Vi ringrazio in anticipo, a presto

20141018_210448.jpg

ciao
dovresti avere 5 fili + lo schermo a meno che lo schermo non sia il GND, il filo rosso dovrebbe essere +i restanti sono i segnali A B Z

probabilmente è un open collector, non sono un esperto, prova a partire da questo schema

encoder.pdf (4.69 KB)

Dovrebbe essere un encoder incrementale da 600 impulsi/giro funzionante tra 5 e 24V con uscite open collector

Rosso +V
Nero Ground
Verde A
Bianco B
Giallo Z

Le uscite A, B e Z sono collegate a transistor che chiudono verso massa, quindi le puoi collegare ad altrettanti ingressi digitali con modalità INPUT-PULLUP, così eviti i tre resistori di pull-up esterni .

Vi ringrazio per l'aiuto, si è un 5 pin, fili "nero, rosso, verde, bianco, stagnola", Il giallo non c'è però..

Quindi ricapitolando, riuscite a farmi uno schema di come dovrei collegarlo?

Non per altro, vorrei evitare di far danni alla scheda dato che è il primo encoder con cui ho a che fare, preferisco chiedere un vostro aiuto e parere prima di pentirmene..

A presto.

ciao
comincia con la alimentazione, il rosso dovrebbe essere il positivo e azzardo a dirti che la treccia potrebbe essere il negativo

Ho trovato questo esempio, però i colori delle uscite non corrispondono...

http://waihung.net/rotary-encoder-500ppr-resolution/

Per l'alimentazione, ok, ma una volta che l'alimento, per le uscite come mi regolo?
La resistenza da 1kohm è necessaria?

Grazie

Ho fatto varie prove, sono giunto alla conclusione che il rosso +5v, nero gnd 0v, verde uscita A, bianco uscita B, sono riuscito ad acquisire dei valori in rpm, ma non ho riscontrato valori reali.

Ho inserito due resistenze da 16kohm non avendo le 10kohm, una cad. una per ogni segnale in uscita collegata con l'alimentazione +5v, ho fatto bene?

Il valore della resistenza superiore è possibile mi sballi i valori ottenuti?

Ho notato che variando nel monitor seriale lo speed ottengo valori diversi.
Cosa mi consigliate?

Grazie mille

ciao
io uso questo per un solo canale per un encoder open collector come potrebbe essere il tuo

//valido per contare con interrupt

//#include <LiquidCrystal.h>
//LiquidCrystal lcd(9, 8, 7, 6, 5, 4);

#define encoder0PinA 2
volatile int count, countold;

void setup()
{
  count = 0;
  countold = 0; 
  //lcd.begin(16,4); // set up the LCD's number of columns and rows:

  // statosensore1=HIGH;  //stato iniziale del sensore
  pinMode(encoder0PinA, INPUT_PULLUP); 
  attachInterrupt(0, sensore1, FALLING); //sensore induttivo collegato al pin 2
  //   lcd.clear();
  Serial.begin(115200); // initialize serial communication:

}

void loop()
{
  if (countold != count)
  {

    //lcd.home();
    //lcd.print(count);
    //delay(500);

    Serial.println(count);
    //lcd.clear();
    //lcd.print(count);
    countold = count;
  }
}

void sensore1()
{
  count++;
}

encoder.pdf (4.69 KB)

Grazie Stefa, collegando un solo canale, ad esempio alla porta 2 come hai fatto tu, perdo precisione oppure perdo solo la capacità di determinare il senso della rotazione?
Sto diventando pazzo, sto cercando a destra e manca, ma questo encoder mi ha proprio mandato in cofnusione...

Scusa, ma se proprio ti vuoi incasinare la vita, perche' non usi un 2017 o qualche altro decoder hardware simile a quello ?

http://www.avagotech.com/docs/AV01-0041EN

Ciao
in quanto a precisione finora non mi ha dato problemi, però si perdi il senso di rotazione, a me non serviva.
Nel playground trovi altri esempi per usare l'encoder