Hi everyone, hope you're doing well. I'm new to Arduino and got the homework to read an optical incremental encoder. I already saw many videos and did a sample code in 1X mode (just checking the rising edges of Channel A).
The encoder is a TAISS E38S6-600-24G, which has 600 PulsesPerRevolution.
The problem here is I'm afraid Arduino will miss some data because the process will be very slow. Many of the data types I used were int's or double's. Although I did this to understand the logic behind position and velocity estimation, I'm looking for a way to optimize the code.
#include <digitalWriteFast.h>
#define pinA 2
#define pinB 3
// Position and Direction
int16_t firstCounter = 0; // First counter
volatile int16_t secondCounter = 0; // Second counter
int16_t previousSecondCount = 0; // Previous count of the secondCounter (previous loop)
int8_t currentDirection = 0;
int8_t previousDirection = 0;
const int pulsesPerRev = 600; // Pulses per Revolution [PPR](Check YOUR encoder)
// Velocity
uint32_t lastPulseTime = 0; // Time of the last pulse (in microseconds)
uint32_t periodTime = 0; // Period between two pulses
double RPM = 0; // Estimated velocity in RPM
volatile bool pulseDetected = false;
double convert_Pulses2Degs (int x) {
float degs = x * 360 / pulsesPerRev;
return degs;
}
void setup() {
Serial.begin(614400);
// Config pins as inputs
pinModeFast(pinA, INPUT_PULLUP);
pinModeFast(pinB, INPUT_PULLUP);
// FLAG to trigger
enableInterrupt(pinA, checkDirection, RISING);
}
void loop() {
// Counts Periods when flag/interrupt is activated
if (pulseDetected){
pulseDetected = false;
uint32_t currentPulseTime = micros();
if (lastPulseTime != 0) {
periodTime = currentPulseTime - lastPulseTime;
}
lastPulseTime = currentPulseTime;
}
// Position and Direction
//
// Pulses 2 Degs
degsA = convert_Pulses2Degs(secondCounter);
Serial.println((String)"Pulses: " + secondCounter + ", Degrees: " + degsA);
// Update direction (with the change in the Count of Pulses)
if (secondCounter > previousSecondCount) {
currentDirection = 1;
Serial.println("Direction: CCW");
} else if (secondCounter < previousSecondCount) {
currentDirection = -1;
Serial.println("Direction: CW");
} else {
currentDirection = 0;
Serial.println("Direction: Stopped");
}
// FIRST COUNTER:
// Counts until direction changes and reset the counter
if (currentDirection != previousDirection) {
Serial.println((String)"CHANGE!!! Pulses: " + firstCounter + ", Degrees: " + convert_Pulses2Degs(firstCounter));
firstCounter = 0;
}
// Counts only if there's movement
if (currentDirection != 0) {
firstCounter++;
}
// Update the previous count and direction
previousSecondCount = secondCounter;
previousDirection = currentDirection;
// Velocity
//
// Estimates RPM from counting periods
if (periodTime > 0) {
RPM = (1.0 / periodTime) * 1000000.0 * 60.0 * currentDirection / pulsesPerRev;
Serial.println((String)"Estimated Velocity: " + RPM);
}
/*
Serial.print(firstCounter);
Serial.print("\t");
Serial.print(secondCounter);
Serial.print("\t");
*/
}
void checkDirection() {
pulseDetected = true;
if (digitalReadFast(pinB) == HIGH) {
secondCounter++;
} else {
secondCounter--;
}
}
