Hi,
I have a coded-wheel that I am testing to set up relative quadrature encoders for my mobile robot. At the moment it is simply a test with one wheel.
I attached interrupt to pin 2, and this pin is connected to my digital encoder which is faced to the coded wheel. I have tested it and it works fine, i.e. when faced to the black area it outputs 0, and if white area, 1.
Interrupt mode is CHANGE.
I still don't turn the motor on, but rotate the wheel by hand for a test. When I just turn the system on, encoder has 1 or 0 and as it is not changing, mycounter stays on 0. Just as I rotate the wheel so that a change happens, the counter jumps from 0 to a strange value, say 28200. This is not a stable one and if turn off/on, may be a different value! The encoder behaves logically, turning from 1 to 0 and back, but the counter jumps to strange values. Anyway the change in the counter happens at the right time, i.e. the interrupt is working fine.
It seems as if the counter is showing some values in the ram, but not the value I set up for it!
Am I wrong in defining this variable? What could be the cause?
I also used "RISING" and "FALLING" modes. The problem stays the same: counter takes strange values!
My coded-wheel is printed with a laser printer. One guess is that at the moment when the light passes from edges, there is some oscillation before the signal fixes on either 1 or 0, and so the ISR is triggered for multiple time. Another reason for the inconsistent signal may be the encoder board itself: it may need a time delay to come to a stable signal, and the ISR is being called faster than that!
Any idea how to prove this by a test, or how to get rid of it?!
the counter jumps from 0 to a strange value, say 28200.
would require 282000 cycles all being caught by interrupt. This is too big to be caught like this.
What sort of code wheel is it, mechanical or optical? An optical one is unlikely to give you problems.
I would remove the :-
if((iRead ^ intEncMem)==1)
bit and just use the rising or falling edge to simply count like the example does. Posting the full code or at least the bit of the code that initialises the code and attaches the interrupt.
The encoder is optical. Exactly, it is the vishay TCRT5000L infrared reflector that I installed faced to the coded wheel.
//int 0 is on pin 2
//int 1 is on pin 3
//motor running must be donw using timer2
#include <SoftwareServo.h>
#define STEPS 15
SoftwareServo LMotor;
int LMotorPin = 4;
int LMotorPulse = 80;
volatile int intCounter = 0;
volatile int intRotated = 0;
volatile int intEncMem;
int encPin = 2;
void setup()
{
Serial.begin(115200);
pinMode(LMotorPin, OUTPUT);
pinMode(encPin, INPUT);
attachInterrupt(0, isrEncL, CHANGE);
LMotor.attach(LMotorPin);
intEncMem = digitalRead(encPin);
intCounter=0;
}
void loop()
{
LMotor.write(LMotorPulse);
delay(15);
SoftwareServo::refresh();
if(intRotated % 10 == 0)
Serial.println(intRotated, DEC);
}
void isrEncL()
{
if(digitalRead(encPin) ^ HIGH == 0)
{
intCounter++;
if(intCounter % STEPS == 0)
{
intRotated++;
intCounter = 0;
}
}
}
I played more with it and I'm quite sure that the error is coming from signal instability, but I don't know how to solve it.
For instance, if I pulse my continuous servo motor HSR-1425CR with 80, and then force the ISR to execute with a 40ms delay (using an if statement and tracking time with millis()) then the counter won't jump that many times. Near the edge, there are lots of jumps to 0 and 1 before a stable 0 or 1 being achieved.
Anyway I implement it, there is one complete rotation error in each 10 rotation! So, it can't be called encoder. I also googled a lot for using optical mouse for odometry purpose with Arduino (to put two of them at the either end of the robot).
Do I have real option to solve this BIG error somehow, or it is a known issue not worth to work on?
Is it real to get good odometry using optical mouse under the robt? May be you suggest a better solution I don't know?
Then if there is jitter on the edge you could pass the signals through something with a Schmitt trigger input like a 74LS14 buffer. This has some hysteresis and so more likely to give you clean edges.
Only if all that fails then try putting some small capacitors on the input of the Schmitt trigger buffers.