Sull'encoder ho calettato un motorino per fare dei test sulla velocita di acquisizione.
Per ogni unità di tempo l'Arduino invia il numero di impulsi, positivi o negativi, ricevuti dall'ultima lettura.
L'RTC serve per loggare l'impulso con il time.
// Comment // *********************************** // Test Lettura Encoder con logger video // Reteservizi di Paolo Fiaschi // 2016 // *********************************** #include#include #include "RTClib.h" RTC_DS1307 rtc; elapsedMillis timeElapsed; DateTime now; const int BUFFSIZE = 20; // dimensioni buffer char buffer[BUFFSIZE]; // buffer per la ricezione dalla seriale String Buff = ""; boolean codeValid = false; boolean debug = false; unsigned long previousMillis = 0; unsigned int interval = 2000; // timeout della ricezione dati seriale unsigned long currentMillis; unsigned long Contatore=0; int encoderPin1 = 2; int encoderPin2 = 3; int ledLeftPin = 5; int ledRightPin = 6; int ledStopPin = 7; int ledAlarmPin = 8; int Direzione=0; volatile int lastEncoded = 0; volatile long encoderValue = 0; volatile long localEncoderValue = 0; long lastEncoderValue = 0; long checkEncoderValue= 0; int lastMSB = 0; int lastLSB = 0; // ******************************************** void setup() { Serial.begin (115200); // *** init RTC Wire.begin(); rtc.begin(); // ************** // settaggio RTC // ************** if (! rtc.isrunning()) { Serial.println("RTC is NOT running!"); // following line sets the RTC to the date & time this sketch was compiled rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // This line sets the RTC with an explicit date & time, for example to set // January 21, 2014 at 3am you would call: // rtc.adjust(DateTime(2014, 1, 21, 3, 0, 0)); } // *** pinMode(encoderPin1, INPUT); pinMode(encoderPin2, INPUT); pinMode(ledLeftPin, OUTPUT); pinMode(ledRightPin,OUTPUT); pinMode(ledStopPin, OUTPUT); pinMode(ledAlarmPin, OUTPUT); digitalWrite(encoderPin1, HIGH); //turn pullup resistor on digitalWrite(encoderPin2, HIGH); //turn pullup resistor on // interrupt agganciati sul cambio di stato delle porte attachInterrupt(0, updateEncoder, CHANGE); attachInterrupt(1, updateEncoder, CHANGE); } // ********************************************** void loop(){ // la lettura dell'encoder viene fatta dagli interrupt. if (timeElapsed > interval) { // errore timeout //if(debug) Serial.println("Errore Timeout Comunicazione"); digitalWrite(ledAlarmPin,HIGH); } if (Serial.available() > 0) { timeElapsed = 0; digitalWrite(ledAlarmPin,LOW); int index=0; //delay(10); // aspetta si riempia il buffer (non serve per 1 solo carattere) int numChar = Serial.available(); if (numChar > BUFFSIZE) numChar = BUFFSIZE; while (numChar--) { buffer[index++] = Serial.read(); } splitString(buffer); // Elabora la stringa ricevuta } // gestione indicatori di direzione if(lastEncoderValue==localEncoderValue) Direzione=0; if(Direzione==0) { digitalWrite(ledLeftPin,LOW); digitalWrite(ledRightPin,LOW); digitalWrite(ledStopPin,HIGH); } if(Direzione==1) { digitalWrite(ledLeftPin,HIGH); digitalWrite(ledRightPin,LOW); digitalWrite(ledStopPin,LOW); } if(Direzione==2) { digitalWrite(ledLeftPin,LOW); digitalWrite(ledRightPin,HIGH); digitalWrite(ledStopPin,LOW); } lastEncoderValue=localEncoderValue; delay(5); // serve solo per dare tempo ai led di accendersi. } // ***************************************** void updateEncoder(){ int MSB = digitalRead(encoderPin1); //MSB = bit + significativo int LSB = digitalRead(encoderPin2); //LSB = bit - significativo 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 ++; Direzione=1; if(encoderValue>200000) { // per evitare l'overflow encoderValue=1; lastEncoderValue=0; } } if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000) { encoderValue --; Direzione=2; if(encoderValue<-200000 and="" ata="" break="" buff.concat="" buffer="" buffers="" c="Check" caratteri="" case="" char="" check="" clear="" codevalid="true;" command="" commands="" converte="" data="ConvData(now);" de-tokenize="" debug="" do="" e="Encoder" each="" encodervalue="" entered:="" erial.println="" evitare="" for="" from="" i="" if="" in="" int="" l="" lastencoded="encoded;" lastencodervalue="0;" list="" localencodervalue="encoderValue;" next="" now="" null="" ontatore="" onvdata="" overflow="" parameter="strtok" parse="" parsecmd="" pass="" per="" processed="" received="" remove="" result="" ricevuti="" sequentially="" serial.flush="" serial.print="" serial.println="" serial="" splitstring="" store="" stringa="" switch="" text="" the="" this="" time="" to="" tring="" value="" void="" while="" x="">2000000000) Contatore=0; // resetta il long Serial.print(++Contatore); Serial.print("-"); Serial.println(encoderValue); encoderValue=0; // una volta inviato il valore lo azzera per ripartire codeValid = true; break; case ('T'): //check T=Timer switch(data[1]) { case('T'): // Time (TT) now = rtc.now(); Serial.println(ConvData(now)); codeValid = true; break; case('S'): // Time setting xxddmmyyyyhhmmss (TS) String str(data); if(str.length()==18) { // ci sono anche i CRLF String anno=str.substring(6,10); String mese=str.substring(4,6); String giorno=str.substring(2,4); String ora=str.substring(10,12); String minuti=str.substring(12,14); String secondi=str.substring(14,16); rtc.adjust(DateTime(anno.toInt(), mese.toInt(), giorno.toInt(), ora.toInt(), minuti.toInt(), secondi.toInt())); now = rtc.now(); //Serial.print("Nuova Data:"); Serial.println(ConvData(now)); codeValid = true; } break; } default: if(debug) { Serial.println(data); } } //if(codeValid) Serial.println(buffer); //echo back what is received codeValid = false; Buff = ""; //Reset passing string } // ********************************* String ConvData(DateTime Data) { /* String result=""; char buffer[30]; PString str(buffer, sizeof(buffer)); str = Data.day(); // assignment str += "/"; str += Data.month(); // concatenation str += "/"; str += Data.year(); // concatenation str += " "; str += Data.hour(); // concatenation str += ":"; str += Data.minute(); // concatenation str += ":"; str += Data.second(); // concatenation */ char buf[30]; sprintf(buf, "%02d/%02d/%04d %02d:%02d:%02d",Data.day(), Data.month(), Data.year(), Data.hour(), Data.minute(), Data.second()); return buf; }
Buongiorno Paolo: Mi permetto di disturbarti per chiederti un consiglio sulla lettura degli encoder. Premetto che sono a zero con la conoscenza di Arduino. Ti spiego la mia situazione. Devo misurare i gradi in Azimut e Elevazione di una antenna, usando 2 encoder incrementali. Ho studiato un pò gli sketch che ho trovato in giro e usando Arduino Mega che ha 3 ingressi Interrupt sono riuscito a leggere e scrivere su un I2C LCD la lettura di uno dei due encoder: quello che è identificato in queste righe "void updateEncoder(){
RispondiEliminaint MSB = digitalRead(encoderPinA); //MSB = most significant bit
int LSB = digitalRead(encoderPinB); //LSB = least significant bit. E qui mi sono bloccato perchè non so come dire al microproc. di leggere e scrivere i dati anche dell altro encoder (encoderPinC) e (encoderPinD). In pratica non so come e dove mettere l'istruzione per far si che mi venga letto anche l'altro valore e naturalmente venga inviato al display. Ho bisogno insomma di chiamare i 2 dispositivi Encoder 1 e Encoder 2 o A e B. Se vuoi e ti interessa la sfida ti posso inviare il codice da me buttato giu. Se non hai voglia e tempo nessun problema. Grazie comunque per avermi letto. Carlo Carini
Scusa ma ti leggo solo ora, spero che tu abbia già risolto il tuo problema. Comunque, se ho capito la tua domanda, se tu leggi già gli interrupt per l'encoder 'A' ti basta 'duplicare' quello che hai già fatto, agganciando i pin dell' encoder B ai pin di interrupt rimasti liberi, che sul mega mi pare siano 6 disponibili e tutto dovrebbe funzionare allo stesso modo.
EliminaPer esempio potresti fare:
int encoder2Pin1 = 18;
int encoder2Pin2 = 19;
digitalWrite(encoder2Pin1, HIGH); //turn pullup resistor on
digitalWrite(encoder2Pin2, HIGH); //turn pullup resistor on
attachInterrupt(digitalPinToInterrupt(encoder2Pin1), updateEncoder2, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoder2Pin2), updateEncoder2, CHANGE);
e duplichi la updateEncoder in updateEncoder2 o meglio ancora riconosci nella updateEncoder quale dei due encoder ha generato la chiamata.
Buon lavoro.
Paolo