wrong encoder counts

Hello guys,

I am working on a project in which I am controlling large size BLDC motors (very cheap infact manufacturer has no datasheet and model name) controlled by a motor controller. For feedback to PID I am using optical encoders (increment type) giving the number of ticks as input and provided a set point and calculating PID for every 10ms by updating the variable. But the Output observed was very much weird, So when I have observed in the serial monitor the number of ticks the encoder gives I found that many numbers in between are missing because of this input given for every 10 ms some times the input goes as (For ex: 3,5,9 even 14 sometimes observed in the serial plotter).

This input is calculated as current_ticks - previous ticks; PID is done using arduino PID library.

Details:

The screenshots for left and right encoder reading have been attached. The attachment with less ticks missing is right and the left shows very much weird count( like has to produce 225 ticks it shows 600 because of wrong counts displayed).

My optical encoder schematic is also attached below.

Regarding the code and board, I am using arduino Mega 2560, and what the code does is just prints the tick count and uses an interrupt on pin2. The repeated value in the serial monitor is just because the loop prints only the tick counts. (sorry for bad english)

Any response is highly appreciated.
BN.

mail upload.PNG

attachment has left encoder ticks. encoder output is directly connected to arduino. No external hardware between encoder and arduino.

upload_left.PNG

Images from Original Post and Reply #1 so we don't have to download them. See this Image Guide

c248a18e25f1f424842e36b4af32d09fe6152e77.png

46d6a1d93e4529251e5dc9f9e5b41a4cf2bd243a.png

...R

Have you written a test program just to detect the encoder pulses? If so, please post it.

Post a link to the datasheet for the encoder you are using.
A photo of the encoder in situ would probably also be useful.

I have a project in which I am using a QRE1113 optical detector to detect the speed and count the revs of a small DC motor. It seems similar electrically to your diagram. It seems to me that the QRE1113 works reliably with an Atmega 328 or an Attiny 1634 on a breadboard but not when connected to my Uno. I have not tried in on my Mega. I wonder (from the depths of ignorance) if there might be extra capacitance or inductance on the Uno board which affects the small signal from the encoder.

...R

Thanks Robin,

yes my test code was,

const byte intr_pin = 2;
unsigned long state_motor_L = 0;
void setup()
{
pinMode(intr_pin, INPUT);
attachInterrupts(0, enc_loop, RISING);
Serial.begin(57600);
}

void loop()
{
Serial.println(state_motor_L);
}

void enc_loop()
{
state_motor_L++;
}

I have also tried at very low speeds just by manually turning the wheel and check,even then the results are weird.

upload1.jpg

Your code won't compile. I suspect you typed it and added an 's' to attachInterrupt(). You should copy and paste code.

Try this version. It compiles but I have not tried it. Note the changes which are pretty much essential when using an ISR.

I have also introduced a newISR variable so the serial output is not overwhelmed

const byte intr_pin = 2;
volatile unsigned long state_motor_L = 0;
volatile bool newISR = false;
unsigned long workingMotorCount;
void setup()
{
    pinMode(intr_pin, INPUT);
    attachInterrupt(0, enc_loop, RISING);
    Serial.begin(57600);
}

void loop()
{
    if (newISR == true) {
        newISR = false;
        noInterrupts();
            workingMotorCount = state_motor_L;
        interrupts();
        Serial.println(workingMotorCount);
    }
}

void enc_loop()
{
    state_motor_L++;
    newISR = true;
}

...R

I cannot see any code for a defined time interval. The counter increments, i.e. the pulses arrive.

DrDiettrich:
I cannot see any code for a defined time interval. The counter increments, i.e. the pulses arrive.

I had assumed the timing would be added later

...R

Thanks robin for your kind reply( even I didn't provide sufficient information).

I have solved my problem. I expect there was some debounce in the encoder as i don't have access to a scope i couldn't observe the misbehaviour. But however i have suspected that, and I put a schmidt trigger from the encoder output, for the schmidt trigger i added a de-coupling capacitor and added a pull-up resistor of 330k on the encoder output pin. Form the schmidt trigger output I connected it to arduino mega and read that in the serial monitor the output was impressive. No value was missing.

If any of the members feels that there was something wrong or i got the right answer by chance, please let me know I don't to face this error again once i proceed to some other part.

Cheers,
BN

A 330k pullup is way too high, 1k-10k were a more practical resistance with open collector outputs.

Signal recovery at the receiver side indicates a poor overall design. The signal should be formed properly at the sensor side. The contrast between bright and dark segments must be high enough to form a rectangle on the output. Then this information has to be transferred by reliable means, which are sufficiently insensitive to interference. This includes the choice of the right cables and line drivers, where twisted pair cables and sufficiently low pullup resistors should be sufficient for short distances, or differential line drivers and receivers with long lines.

Similarly power lines have to be routed in a way that minimizes crosstalk to sensor lines. A breadboard with Schmitt triggers on it introduces chances for additional interference, such trouble makers should be eliminated in the first place.

I know very very little about electronics and the sort of things that @DrDiettrich mentions in Reply #9.

My QRE1113 device is wired the same as the SparkFun analog breakout board (I don't have space for a breakout board) and the interrupt pin on my Atmega 328 and Attiny1634 uses pinMode(INPUT_PULLUP). However I have not checked whether the attachInterrupt() function might negate the PULLUP.

Anyway, it seems to work very reliably recording the value of micros() for every revolution. But, as I said before it did not work reliably on my Uno.

...R