I have an encoder wheel that is attached to a DC geared motor and is told to advance a certain distance via the command
M602 E45A0519-A1A7-499C-BF30-720107FE5FFB 6
M602 = Forward
E45A0519-A1A7-499C-BF30-720107FE5FFB = Address of slave (I have many encoder wheels)
6 = 6mm distance. This is converted in the slave code to encoder counts. There's a setting Xmm = Y counts.
There are two reflective sensors under the wheel that count the holes in the wheel. There is also an op-amp that filters the pulses and I checked with oscilloscope, and from what I can see, the square waves appear very clear, although the ON pulses are wider than the OFF pulses, not sure if this has any effect. See attached picture.
There are several other features on the PCB and code such as a forward and a reverse button to manually rotate the encoder. And there's also an optical slot sensor called "pulse_sense" that isn't related to this, it's to detect something else.
I had someone else with more experience write this code for me but the issue I'm experiencing is that the encoder doesn't move the correct, or same distance every time I send that command. Sometimes it moves a bit less, sometimes a bit more. I'm wondering if anyone can check my code to see if they can spot anything wrong with it or is there a better way to write it? It would be much appreciated. The code is above my knowledge.
You have polling and calls to delay. Getting rid of delays is probably your first concern. How fast are these motors and more importantly, how long are the encoder pulses?
wildbill:
You have polling and calls to delay. Getting rid of delays is probably your first concern. How fast are these motors and more importantly, how long are the encoder pulses?
Hi wildbill,
Thank you for your reply. I'm using an N20 geared DC motor that is rated for 300 RPM. Running the entire board at 5V. I'm not sure how to measure "how long are the encoder pulses". Do you have any suggestion how to do that? I'm assuming it's from the oscilloscope that it can be told?
void blink() {
if (start == 1) { //If motor is start read the encoder low pulse
counter = counter + 1; //Increment the counter
Serial.println(counter);
check = 0;
c = false;
}
}
Don't do serial printing inside the ISR.
counter should be declared with the volatile keyword added and should have noInterrupts() before and interrupts() following where it ( counter ) is read.
The only action ever taken on check is to set it to zero. What might be its purpose?
JCA34F:
Doesn't look like a good quadrature signal to me, the blue pulse should switch near the center of the yellow, not near the edge.
Wouldn't it be when one signal goes off the next goes up? (which is close to what it's like, but agreed there's a gap, not sure why) The sensors are placed exactly so that one is off and one is on and the holes are divided 50/50 around the circumference.
Yes, the 'scope will tell you. It looks like about 2.2Hz, which is slow enough that a few little delays aren't quite so important.
However, since the two channels change around the same time, those delays and some of your serial prints may actually cause you to miss a transition. People often use interrupts to ensure that no edge is missed. It looks like you were doing this at some point.
I'd try writing something mush more simple using interrupts to prove to yourself that you are getting good counts from the encoder.
Wouldn't that assume that both sensors can be on at the same time? Because that isn't how this was designed in mind and is why my square wave isn't showing up like that intentionally.
The reason there are 2 sensors is to get a higher resolution reading of angle of rotation. I could only fit so many holes on the encoder so I used 2 sensors that are offset from one another so that while 1 sensor is on, the other is off and then they switch. This allows me to get a finer rotation reading by using 2 sensors instead of doubling the hole count in the encoder.
Quadrature is usually used to be able to tell direction of rotation. I'm not trying to do that here, just encoder count.
cattledog:
Did you ever run the program with the one encoder and the interrupt? What were the results?
I've had this work before where it was precise at one point with two sensors, but somewhere along the development, it stopped working precisely and my only conclusion that I can come up with is that it's the code since the oscilloscope shows a good signal, but I have no clue what it is because I didn't write the code.