Aren't the DUE inputs 3.3V? If TTL outputs (PUSH - PULL), you don't need pullups. You are getting interrupts on both edges (rising and falling) of both channels, so 8000 interrupts per rev, not 2000.
Yes, it is. However, I figured 5V could do no harm to the inputs. The inputs are 120mA Max, while the encoder's line driver is stated to have 100mA source/sink outputs.
Yes, they are (source/sink).
The encoder is a 500 line/rev one, so I defined the encoderCountsPerRevolution as 2000.
If you apply 5V to a 3.3V input you will be forcing current through the pin's protection diode into the 3.3V bus.
Do you think a series resistor could help?
Do you think it may be causing the issue I was initially describing?
I would use a 2 channel 5V to 3.3V level converter, one of the other members could advise, I've never had the need to use one. 2 voltage dividers would be an alternative.

Just thinking, 5V for level shifter reference voltage may not be available from encoder so dividers may be best.
Will do a voltage divider.
Do you think the excessive voltage could be the reason and was messing up my input signals causing missed pulses? Still can't see a relation.
Hard to say, but let's get the correct voltage on the input pins (hopefully they aren't damaged) and see if it helps.
OK, will do this later and report back.
Don't believe the input pins are damaged. I would have expected them to not function in case of being damaged.
I have added the voltage dividers for the inputs. Sure enough it didn't fix my issue. With this mod things even got worse: if with the 5V straight to the Arduino inputs it was only missing pulses in one direction and was pretty much consistent (3 pulses for roughly each 2.8 revolutions of the encoder repeatedly), then with the voltage divider it misses pulses in both directions and in an erratic manner (sometimes 1 pulse and other times 10 and more pulses for the same amount of revolutions).
By the way, measured the voltages and found that the 5V Due output that I was using to power the encoder was 4.8V, while the signals (no load) coming from the encoder were 5.9V. Very odd in itself - how the encoder's circuit manages to amplify the signal above the rail voltage?! Anyway, with the signals connected to the Due they measure around 3.4V.
I truly believe the voltage incompatibility is not what causes my issue. Furthermore, since the inputs are still functioning, I believe they were not damaged either.
Any suggestions why is my code missing pulses?
We need a complete diagram showing how every component is connected to every other component, including voltages and resistor / capacitor values.
This is pretty straightforward.
This is the diagram without voltage dividers, where the signals feed directly from the encoder to the Due:

This is the diagram with the voltage dividers (which proved to perform worse than the first one, as I have described in a previous message above):

You said the DUE's voltage on the 5V pin was 4.8, does it change if the encoder is disconnected?
Just try this simple test sketch, see if you get stable counts.
unsigned long start;
const byte
encoderPinA = 3,
encoderPinB = 4;
const uint16_t end = 300;
int speed;
volatile long pulse;
long PulseCopy
void setup()
{
Serial.begin(9600);
attachInterrupt(digitalPinToInterrupt(encoderPinA), readEncoder, RISING);
pinMode(encoderPinA,INPUT);
pinMode(encoderPinB,INPUT);
}
void loop()
{
if(millis() - start > end)
{
noInterrupts();
pulseCopy = pulse;
interrupts();
Serial.println(pulseCopy);
start += end;
}
}
void readEncoder()
{
digitalRead(4) ? --pulse : ++pulse;
}
This doesn't work. Keeps printing "-1" regardless of encoder position.
P.S. I did add the missing semicolon on line 9 and fixed the variable name to pulseCopy to be consistent with the variable call.
OK, TNX, It does work with a geared motor with 12 pulse hall effect encoder. I'm out of ideas, good luck.
Thanks! I need the luck here. Hopefully somebody else will chime in with an idea. I am out of ideas either.
Should not 'end' also be unsigned long - since millis() times are involved?
unsigned long start;
const byte
encoderPinA = 3,
encoderPinB = 4;
const uint16_t end = 300;
Yes, I assume it would be a better practice to declare "end" as unsigned long, especially since this is how "start" is declared and in the code they are being compared. Anyway, this doesn't help me.
Anyone, any thoughts?
Why does the following code miss encoder pulses (as far as I can see, they are being missed only in one direction and fairly consistently):
/*
This program is reading an encoder with an Arduino DUE, calculates the corresponding distance
its cirumference travels and prints to serial interface. The code has a debounce which is added
to deal with possible imperfections of the input signal. Only if the signal stays there longer
than the set debounceDelay it is counted by the program.
*/
// Define the pins for the encoder
const int encoderPinA = 3;
const int encoderPinB = 4;
//Read the pines
#define readA digitalRead(encoderPinA)//faster than digitalRead()
#define readB digitalRead(encoderPinB)//faster than digitalRead()
// Variables for encoder state and distance
volatile bool lastStateA = LOW;
volatile bool lastStateB = LOW;
volatile long encoderCount = 0;
volatile long myCount = 0;
const int countsPerRevolution = 2000; // Counts per revolution of the encoder
const float encoderDiameter = 11.021;//11.07; // Diameter of the encoder in millimeters
float lastDistanceTraveled = 0; // Last distance traveled by the encoder's circumference
float totalDistanceTraveled = 0; // Total distance traveled by the encoder's circumference
const unsigned long debounceDelay = 10; // Adjust as needed (microseconds)
// Variables for printing to serial port conditions
unsigned long lastEncoderChangeTime = 0; // Time of the last encoder count change
unsigned long lastPrintTime = 200; // Time of the last print to serial monitor
// Setup function
void setup() {
// Initialize serial communication
Serial.begin(9600);
// Set encoder pins as inputs
pinMode(encoderPinA, INPUT);
pinMode(encoderPinB, INPUT);
// Set output HIGH pins for using with external pull-up resistors
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
digitalWrite(8, HIGH);
digitalWrite(9, HIGH);
// Attach interrupts to the encoder pins
attachInterrupt(digitalPinToInterrupt(encoderPinA), readEncoder1, CHANGE);
attachInterrupt(digitalPinToInterrupt(encoderPinB), readEncoder2, CHANGE);
}
// Function to read the encoder
void readEncoder1() {
// Update the encoder count based on the direction of rotation
if (readB != readA) {
encoderCount++;
} else {
encoderCount--;
}
// Update the time of the last encoder count change
lastEncoderChangeTime = millis();
}
void readEncoder2() {
// Update the encoder count based on the direction of rotation
if (readA == readB) {
encoderCount++;
} else {
encoderCount--;
}
// Update the time of the last encoder count change
lastEncoderChangeTime = millis();
}
// Main loop
void loop() {
//Reset the distance upon any input from the serial port
if (Serial.available()){
Serial.read();
encoderCount = 0;
}
// Calculate distance traveled based on encoder counts and diameter
float circumference = PI * encoderDiameter; // Calculate circumference
float distance = ((encoderCount) * circumference) / (countsPerRevolution); // Calculate distance
// Update total distance traveled
totalDistanceTraveled = distance;
// Check conditions for printing to serial port
unsigned long currentTime = millis();
if ((currentTime - lastEncoderChangeTime >= 500) && (totalDistanceTraveled != lastDistanceTraveled) && (currentTime - lastPrintTime >= 100)) {
// Print distance traveled to serial monitor
Serial.print(totalDistanceTraveled);
Serial.print(", EncoderCount: ");
Serial.println(encoderCount);
// Update last printed distance and time values
lastDistanceTraveled = totalDistanceTraveled;
lastPrintTime = currentTime;
}
}