Hi!
I'm trying to make a 12v engine work along with it's controller and an incremental encoder, but the encoder seems to be responding wrongly to real interactions, so to isolate this component I created a specific diagram using Fritzing (first time using it, sorry if it's kind of messy), and an ChatGPT-generated arduino code.
SPECIFICATIONS:
- Schmitt Trigger Cd40106 Dip Cd40106b Cd40106be
- Arduino Uno
- 2x 1kohm resistors
- ROTARY ENCODER LPD3806-600BM-G5-24C
Code:
#define ENCODER_A 2
#define ENCODER_B 3
const int PULSES_PER_REVOLUTION = 600; // Adjust this according to your encoder
volatile int pulseCounter = 0;
void setup() {
// Configure the encoder pins as inputs (without internal pull-ups)
pinMode(ENCODER_A, INPUT);
pinMode(ENCODER_B, INPUT);
// Start serial communication
Serial.begin(9600);
Serial.println("System started");
// Configure the interrupts for the encoder pins
attachInterrupt(digitalPinToInterrupt(ENCODER_A), onChangeA, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_B), onChangeB, CHANGE);
}
void loop() {
// Calculate the current angular position in degrees
float angle = (pulseCounter % PULSES_PER_REVOLUTION) * 360.0 / PULSES_PER_REVOLUTION;
// Ensure the angle is within the range [0, 360)
if (angle < 0) {
angle += 360;
}
// Print the current angular position on the Serial Monitor
Serial.print("Angular position: ");
Serial.print(angle, 2); // Print with two decimal places
Serial.println(" degrees");
delay(100); // Wait 100 ms for faster readings
}
void onChangeA() {
noInterrupts(); // Disable interrupts while executing this function
int stateA = digitalRead(ENCODER_A);
int stateB = digitalRead(ENCODER_B);
// Increment or decrement the pulse counter depending on the rotation direction
if (stateA == HIGH) {
if (stateB == LOW) {
pulseCounter++;
} else {
pulseCounter--;
}
} else {
if (stateB == LOW) {
pulseCounter--;
} else {
pulseCounter++;
}
}
interrupts(); // Re-enable interrupts
}
void onChangeB() {
noInterrupts(); // Disable interrupts while executing this function
int stateA = digitalRead(ENCODER_A);
int stateB = digitalRead(ENCODER_B);
// Increment or decrement the pulse counter depending on the rotation direction
if (stateA == HIGH) {
if (stateB == LOW) {
pulseCounter++;
} else {
pulseCounter--;
}
} else {
if (stateB == LOW) {
pulseCounter--;
} else {
pulseCounter++;
}
}
interrupts(); // Re-enable interrupts
}
The results I'm getting when I manually rotate the axis of the encoder 360º are these (far from reality):
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 0.00 degrees
Angular position: 359.40 degrees
Angular position: 359.40 degrees
It never prints more than 20º in total, totally weird. And this is the reason why I'm using a Schmitt trigger for noise cancel (just in case. I read it may be helpful).
Any ideas? Did you ever use an incremental encoder for arduino?
Thank you very much!!!