Motor control using single channel encoder

I’m working on a simple control application, with a single channel wheel encoder as feedback and a dc motor with a wheel as output. I am also new to Arduino. What I’m trying to do to know when it’s moving forward or backward is take the derivative and change whether the pulse counter variable is adding or subtracting based on when the derivative hits near zero. My problem is I can’t get my program to calculate this derivative.

So in my code I have pulseCount adding every time the interrupt gets a change. Now in the middle of the loop I want to find the change in pulse per change in time. So I use this bit:

dpdt = (pulseCount - oldpulse) / (millis()-oldTime);
oldTime = millis();
oldpulse=pulseCount;

The problem is dpdt is output as 0 when it serial prints it. I’m not sure if it’s a problem with the type of variable they are or if my code is all wrong or what.

Thanks for any help.

System_ID_DC.ino (1.23 KB)

You cannot tell if it is running forward or backward with a single slot wheel encoder. There is no difference to the signal that can be used to sense direction.

Weedpharma

I know that. So I'm trying to take the derivative of the feedback and have it switch when it hits zero or near zero.

And how will you know the difference between moving forward, slowing, stopping, then re-starting forward, and moving forward, slowing, stopping, then re-starting in reverse?? From a single-channel encoder, you CANNOT tell the difference.

Regards,
Ray L.

I agree with weedpharma and with RayLivingston. May I add that this code:

``````dpdt = (pulseCount - oldpulse) / (millis()-oldTime);
``````

will be calculated as int (or long). Thus, if (pulseCount - oldpulse) is less than (millis()-oldTime), the result of the division will be zero. I also don't understand why you keep calling millis() when you already called it and stored the result in t (which should be unsigned long, not long, but that is another story).

Perhaps you intended to declare t as unsigned long, intended to declare dpdt as float (or double), and intended to write:

``````dpdt = ((float)(pulseCount - oldpulse)) / ((float)(t-oldTime));
``````

...or something similar.

Good Luck!

You might try changing the count direction only when the wheel is at standstill and according to the direction command.

if(standstill && dirCmnd == forward) count_up;
else if(dirCmnd == reverse) count_dn;

The only way you can say which way it is turning by keeping track in the program.

Start motor fwd, set flag, stop motor, start in reverse, clear flag. The encoder can give the speed but not direction so you need to do it manually.

The question then becomes what is driving the motor? If it is your program, you already know which way it rotates as you are controlling it.

Weedpharma

Yeah it knows which way it's going by the command being given. It just takes a second for it to stop in the direction it's going and start in the opposite and I don't want it to start counting the pulses backwards the instant it gives the command.

jcallen, that's exactly what I'm trying to accomplish. I just am having trouble with my variables, and I think vaj4088 has the solution. I'm still getting a grasp on how the variable types get handled.