Hello!
I have some issues with an encoder on a motor from Pololu Motor, however I have been having some issues. First of all, this is a diagram of the motor circuit:
I'm going to ignore the circuit for the controller as this works fines (and this problems shows up even when the motor gets current directly from the voltage generator at 12V).
The pins A and B are connected to the arduino pins 2 and 3 respectively. While the encoder VCC and GND are connected to a voltage generator (3.3V). Where I see that the encoder draws 5mA of current*.
When I turn on my Arduino I see that I get some random data quite randomly: I see a lot of it when I'm handling the motor. I made sure that there's no touching between different wires and no wires get disconnected. Additionally, I looked online and saw that it's normal to get some noise, especially if the wires carrying current o the motor are next to the encoder wires, so I set the pins as "INPUT_PULLUP"** and this got rid of most of the noise. However, when the motor runs, I still RARELY see any position data.
I have tried different Arduinos as well, so the problem isn't in the Arduino or any of the components of my circuit.
#define readA bitRead(PIND,2)//faster than digitalRead()
#define readB bitRead(PIND,3)//faster than digitalRead()
#define ENCA 2
#define ENCB 3
long posi = 0;
long last_x_pos = -1;
void setup() {
// Wait for a second to ensure stable power and connections
delay(1000);
mcSerial.begin(assignBaudRate); // Start communication with motor controller
Serial.begin(assignBaudRate);
Serial.println("Starting setup");
// pinMode(ENCA, INPUT);
// pinMode(ENCB, INPUT);
pinMode(2, INPUT_PULLUP); // Enable internal pull-up resistor on pin 2
pinMode(3, INPUT_PULLUP); // Enable internal pull-up resistor on pin 3
attachInterrupt(digitalPinToInterrupt(ENCA),readEncoderA,CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCB),readEncoderB,CHANGE);
Serial.println("Setup complete");
}
void loop() {
if (posi != last_x_pos) {
Serial.println(posi);
last_x_pos = posi;
}
// delay(10);
}
// Interrupt service routine for reading the encoder
void readEncoderA(){
if(readB != readA) {
posi ++;
} else {
posi --;
}
}
void readEncoderB(){
if (readA == readB) {
posi ++;
} else {
posi --;
}
}
Any help would be appreciated.
Extras
While the code above gives me issues I also added the entirety of the code that's used to control the motor, just in case. In my opinion it can be ignored, and the code above is all that matters.
#include <Motoron.h>
#include <SoftwareSerial.h>
#define readA bitRead(PIND,2)//faster than digitalRead()
#define readB bitRead(PIND,3)//faster than digitalRead()
#define ENCA 2
#define ENCB 3
long posi = 0;
long last_x_pos = -1;
SoftwareSerial mySerial(10, 11); // RX, TX
#define mcSerial mySerial // Use SoftwareSerial for the Motoron controller
MotoronSerial mc;
const uint32_t assignBaudRate = 115200;
static_assert(assignBaudRate >= MOTORON_MIN_BAUD_RATE &&
assignBaudRate <= MOTORON_MAX_BAUD_RATE, "Invalid baud rate.");
bool initializeMotoren() {
mc.reinitialize();
mc.disableCrc();
mc.clearResetFlag();
// Verify initialization
uint16_t errors = mc.getErrorMask();
return (errors == 0);
}
void setup() {
// Wait for a second to ensure stable power and connections
delay(1000);
mcSerial.begin(assignBaudRate); // Start communication with motor controller
Serial.begin(assignBaudRate);
// pinMode(ENCA, INPUT);
// pinMode(ENCB, INPUT);
pinMode(2, INPUT_PULLUP); // Enable internal pull-up resistor on pin 2
pinMode(3, INPUT_PULLUP); // Enable internal pull-up resistor on pin 3
attachInterrupt(digitalPinToInterrupt(ENCA),readEncoderA,CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCB),readEncoderB,CHANGE);
Serial.println("Starting setup");
mcSerial.setTimeout(1); //Can be changed to get better values for pos (the lower the more precise)
mc.setPort(&mcSerial);
// Initialize the Motoron
initializeMotoren();
// Configure the motor (motor 1 only)
mc.setMaxAcceleration(1, 0);
mc.setMaxDeceleration(1, 0);
Serial.println("Setup complete");
}
void processCommandInt(int speed){
mc.setSpeed(1, speed);
}
void loop() {
while (Serial.available() > 0) {
String input = Serial.readStringUntil('\n');
input.trim(); // Remove any leading/trailing whitespace
// Check if the input is an integer or string
if (input.toInt() != 0 || input == "0") { // toInt() returns 0 if not a valid integer
int intInput = input.toInt();
processCommandInt(intInput);
Running = true;
input = "";
}
// delay(100);
}
if (posi != last_x_pos) {
Serial.println(posi);
last_x_pos = posi;
}
// delay(10);
}
// Interrupt service routine for reading the encoder
void readEncoderA(){
if(readB != readA) {
posi ++;
} else {
posi --;
}
}
void readEncoderB(){
if (readA == readB) {
posi ++;
} else {
posi --;
}
}
*The encoder supports voltages between 2.7V and 18V, when I switch between 3V and 5V I see no different in the current drawn, shouldn't it change if the voltage changes?
**I have noticed that the arduino reports some position data when the encoder is not plugged in and I'm handling the arduino, whether that's touching the 2 and 3 pins or any other pins. However setting the pins as INPUT_PULLUP removes this behaviour.