Hello,
So I have a problem I'm trying to read an encoder for a science project where I need to read the speed of my DC motor to calculate its torque constant.
I have tried several programs but it always sends incoherent values, here is the program:
int pinA = 2;
int pinB = 4;
volatile int pos = 0;
volatile unsigned long t = 0;
it just goes 1 then 2 and so on but really slowly, it changes number every 2 seconds .
I'm really new at arduino so i would really like some help thanks!
service-interrupt-routines should run through as fast as possible.
printing to the serial output slows down too much. especially at a slow baudrate of 9600 baud. But even if you would change the baudrate to 2.000.000 baud you should not do serial output in the interrupt-service-routine.
Some time ago I googled for a good example on how to use interrupts. I found 90% really bad example-codes because they did serial output inside of the interrupt-routine.
I know it's the basics but i don't know if in "loop" i need to reenable the interrupt after disabling the interrupt and copying the value of "pos" or is the setup part read after every loop?
the basic concept just is increment a variable inside the isr
then disabling the interrupts
copying the value of the isr-incremented variable to another variable
and then use this seond variable to print outside the isr
disabling the interrupt is nescessary because copying more than one byte needs multiple processor-cycles and inbetween copying the two bytes of an integer-value the next interrupt could occur who would change your isr-variable in the middle of the copying-process and then the copied value would be wrong.
You can find a lot of material with googling "arduino" + your keywords of interest
So in my encoder there's supposed to be 16 counts per revolution and the "pos" variable refers to those counts, it always sends out a minimum of a 100 for the pos even when i don't make the motor rotate, but the value when spinning the shaft looks good.
The speed value is also incoherent, when the motor is stopped it sends me a really high value (around 268000) and when it rotates sometimes it sends me 0 or 1 or around 268000.
So if you have the time could you look at my code and look if i have made any errors?
Thank you in advance!
there is another thing to improve:
he command delay() is blocking. Nothing else can be executed while a delay() is executed.
There is another non-blocking way to do timing and timed action which are based on the function millis().
There is a more or less "standard"-tutorial about millis() but it has a flaw.
this "standard"-tutorial has no everyday-example that would show the principle in detail.
here is the everyday example
as an everyday example with easy to follow numbers
delay() is blocking. As long as the delay is "delaying" nothing else of the code can be executed.
Now there is a technique of non-blocking timing.
The basic principle of non-blocking timing is fundamental different from using delay()
You have to understand the difference first and then look into the code.
otherwise you might try to "see" a "delay-analog-thing" in the millis()-code which it really isn't
Trying to see a "delay-analog-thing" in millis() makes it hard to understand millis()
Having understood the basic principle of non-blocking timing based on millis() makes it easy to understand.
imagine baking a frosted pizza
the cover says for preparation heat up oven to 200°C
then put pizza in.
Baking time 10 minutes
You are estimating heating up needs 3 minutes
You take a look onto your watch it is 13:02 (snapshot of time)
You start reading the newspaper and from time to time looking onto your watch
watch shows 13:02. 13:02 - 13:02 = 0 minutes passed by not yet time
watch shows 13:03. 13:03 - 13:02 = 1 minute passed by not yet time
watch shows 13:04. 13:04 - 13:02 = 2 minutes passed by not yet time
watch shows 13:05 when did I start 13:02? OK 13:05 - 13:02 = 3 minutes time to put pizza into the oven
New basetime 13:05 (the snapshot of time)
watch 13:06 not yet time
watch 13:07 not yet time
watch 13:08 not yet time (13:08 - 13:05 = 3 minutes is less than 10 minutes
watch 13:09 not yet time
watch 13:10 not yet time
watch 13:11 not yet time
watch 13:12 not yet time
watch 13:13 not yet time
watch 13:14 not yet time (13:14 - 13:05 = 9 minutes is less than 10 minutes
watch 13:15 when did I start 13:05 OK 13:15 - 13:05 = 10 minutes time to eat pizza (yum yum)
You did a repeated comparing how much time has passed by
This is what non-blocking timing does
In the code looking at "How much time has passed by" is done
currentTime - startTime >= bakingTime
bakingTime is 10 minutes
13:06 - 13:05 = 1 minute >= bakingTime is false
13:07 - 13:05 = 2 minutes >= bakingTime is false
...
13:14 - 13:05 = 9 minutes >= bakingTime is false
13:15 - 13:05 = 10 minutes >= bakingTime is TRUE time for timed action!!
So your loop() is doing
void loop()
// doing all kinds of stuff like reading the newspaper
if (currentTime - previousTime >= period) {
previousTime = currentTime; // first thing to do is updating the snapshot of time
// time for timed action
}
it has to be coded exactly this way because in this way it manages the rollover from Max back to zero
of the function millis() automatically
baldengineer.com has a very good tutorial about timing with function millis() too .
There is one paragraph that nails down the difference between function delay() and millis() down to the point:
The millis() function is one of the most powerful functions of the Arduino library. This function returns the number of milliseconds the current sketch has been running since the last reset. At first, you might be thinking, well that’s not every useful! But consider how you tell time during the day. Effectively, you look at how many minutes have elapsed since midnight. That’s the idea behind millis()!
Instead of “waiting a certain amount of time” like you do with delay(), you can use millis() to ask “how much time has passed”?