Angular Speed with arduino

Hello world!
My goal is to calculate angular speed of a rotating object. I'm using arduino and a potentiometer aligned with the rotation axis. With a rotary potentiometer I'm able to detect the angular position but is it possible to detect also the velocity of the performance? Have you got any ideas? is it possible to have a derivative function on arduino? Thank you so much

The time derivative of two readings is calculated as (reading at time1 - reading at time0)/(time1 - time0).

You can use millis() for time measurements, and always use unsigned long variables for all time calculations.

A pot is useful for a limited angle only (<270°), for a full or more turns you need a rotary encoder.

As analogRead() takes less than a millisecond, it’s better to use micros() for the time difference instead, or to use millis() to determine the time when the next value shall be taken.

I would like to measure the angular velocity of a bar that performs a circular movement at 80 Hz frequency via arduino. To do this, I have implemented a loop while () that reads the measurement and I have used the delay function (12.5) (where 12.5 ms is 1/80) at the beginning of each cycle to simulate sampling times. Is it correct my way of work? Thank you

I cannot answer that question, it depends on the signal that you measure finally. E.g. you cannot wait for the next sample, when a rotary encoder outputs pulses every now and then.

I'm using a rotary potentiometer that is aligned with the rotatioanl axis of the bar. My goal is to measure the angular speed with a frequency of 80 Hz. From the zero position I want to detect every 12,5 milliseconds the value of the angular speed during the movement. I hope that in this case I have been clearer on my explanation :slight_smile:

Read reply #1 again. Your task is simplified if time period is constant.

To do this, I have implemented a loop while () that reads the measurement and I have used the delay function (12.5) (where 12.5 ms is 1/80) at the beginning of each cycle to simulate sampling times. Is it correct my way of work?

Please post your code.

You don't want to be using delay() for timing. The 12.5 ms readings can be triggered from either a software or hardware timer.

int pinLed = 13;
int buttonPin = 9;
String stringa;
char c;
unsigned long time1 = 0;
unsigned long time2 = 0;
unsigned long time3 = 0;
unsigned long time4 = 0;
int potentiometer = 0;
int potentiometer1 = 0;
int potentiometer2 = 0;
int val;
const int voltage = 5;
float angrad;
float angRad;
float velang

void setup() {
 potentiometer = analogRead (A0);

void loop() {
       if(c != "\n")
   }while(c != "\n");

  if((stringa == "start")){
       time1 = millis();
   while ((digitalRead(buttonPin)==LOW)) {

       tempo2 = millis();
       potentiometer1 = analogRead (A0);
       potentiometer2 = potentiometer1 - potentiometer;
       valore = map(potentiometer2,0,1023,0,5);
       angrad = (320*val)/voltage;
       angRad = map(angrad,0,320,0,6.283);
       time3 = time2 - time1;
       velang = angRad/time3;

Sorry for the misunderstanding :slight_smile:

The code is very simple. In the setup() method I detect the "zero" position of the potentiometer. After the word "start" written by the user the acquisition starts. Before real acquisition the Arduino detects the initial time that must be subtracted to the actual one to find the angular speed by the divisione space/time

Please read #7 of this "How to use the Forum" post in order to post your code using the code tags.,148850.0.html

You can modify the posting you just made.

Learning to use code tags is a "skills filter". If you can't figure out how get your posted code within code tags, there is no hope that you can solve your problem.

Please edit your posting and include the code in code tags </>.

I still don’t know how your pot works. When it jumps back to zero after some time, I don’t see how you handle that case. Your code also contains a lot of variables, which are used but don’t change during the computation.

Can you tell which angle corresponds to the analogRead() range of 0-1024?

IMO you should read the pot as fast as possible, correct an eventual wraparound, and sum up the total traversed angle. Then use millis() to implement a sample frequency, e.g. 1Hz, and divide the traversed angle by that time to get the velocity. Reset the traversed angle for the next sample and continue summing up the traversed angle.

Thanks for getting your code into code tags.

You are doing all your calculations from a starting time and starting position, rather than taking the changes between readings. In essence you get an average velocity from the beginning rather than an instantaneous snap shot of the last 12.5 ms.

Is that what you want?

Other comments:

You are better off to keep all the math using the analogRead() values 0-1023 rather than convert into voltage.

The map function does not return a float.

Cattledog you got my point. I want to see how the velocity changes from an initial position an initial time. Every 12,5 milliseconds I want to see the value of the angular velocity. To be more clear I give you an example:

At 12,5 milliseconds -> 25 rad/s

At 62,5 milliseconds -> 65 rad/s

My final goal is to have a graph in which on x-axis I have got time value while on y-axis angular velocities. To do it I use a software from Parallax but my problem now is to deal with the angular velocity with a frequency of 80 Hz


This is bad syntax. delay() takes an unsigned long.

If you want to take measurements every 12.5 ms, replace the delay() and use a timer with micros() like the one used in the "blink without delay" example in the ide. See also Robin2's tutorial on millis() timers. You will use micros() instead of millis() for better precision.

if (micros() -timeOfLastReading >= 12500)
timeOfLastReading +=12500;

//take a reading and calculate

If you know the Hz, that is full cycles per second, 2pi radians/sec per Hz. At steady 80Hz you get steady 160pi rad/s.

If you could put a pot on the end of the bar, could you put a short bar magnet aligned across the spin axis center?
A linear Hall sensor positioned over the center of that, when the sense axis is aligned with the magnet axis will read max (might need tuning) while off-alignment reads give cosine of angle factored values.

Thank you so much cattledog. Your advice has been very helpfull!

DrDiettrich: My potentiometer is very simple. It detects the angular position in a range between 0 - 1023.
I tranform the value found in the corresponds value in voltage. My pot is linked to the ground and
to the 5 V pins on the board so that the value found between 0 and 1023 corresponds to a value
between 0 and 5V. The angular position is equal to: alpha = (360*voltage_value_founded)/5V.
This alpha must be converted in rad. Once done this the value must be divided by the time to
capture the angular speed.

GoForSmoke: I have thought to use an Hall sensor but my project works with very low speeds values but thank
for the advise!

Linear Hall sensor is not the Hall Switch. Linear Halls are used in high-end joysticks to get precise angular measurements.
The Hall Effect gets used in different devices that all get Hall in the name regardless of application.

I have got one more question...My project has got also a differential amplifier to read values coming from a wheatstone bridge. My goal is to calculate the power generates by the bar so that I need the angular speed and the torque. My question is simple...How does works the synchronization of analog/digital inputs in Arduino? Is it enough to declare in the right way them? Thank you

So the output of your pot is a sawtooth?

Have you got an oscilloscope to check your signals?

Tom... :slight_smile:

80Hz= 80 rotations per second
80Hz = 80 *60 = 4800 rpm, thats not slow.

Are you trying to analyse the torque/work cycle of a heat engine?

Tom... :slight_smile: