DailyDevice – Speedometer – IR_Rotary_Sensor

My daily device is a Speedometer that measures the number of times a wheel turns over time.

I wanted to figure out the relationship between the rotations per minute (rpm) of a DC motor with the amount of PWM voltage (controlled via transistor) and this method worked out.

To figure out the motor and transistor I used Marcello’s Daily Device (DC motor and potentiometer)

Parts for this Setup

– Potentiometer (to control wheel speed)

– Transistor + DC motor + SpokesWheel on axle (to measure amount of rotation)

– IR Rotary Sensor

IR Rotary Sensors

I bought an IR Sensor rotary kit from Creatron to do this. See the below link to see the sensors. It is basically an IR emitter and sensor put adjacent to each other. When the sensor is looping, it returns zeros when the sensor detects a signal from the emitter, and returns ones when the sensor is interrupted.

http://www.tinyosshop.com/index.php?route=product/product&product_id=541

The IR sensor can therefore detect whether it is being interrupted by the spokes of a turning wheel. By sampling the 0s and 1s over a set period of time, and determining the geometry of the spokes and wheels (e.g., 20 spokes per one rotation of wheel) one can calculate the amount that the wheel has turned over a set period of time. This value can then be converted into rotations per minute, which can be then converted into speed (speed = distance / time) by calculating the circumference of wheel.

Visuals of Setup and Demo

Overview

IR Sensor + DC motor with black spokes wheel connected to transistor + Potentiometer

IR Sensor – 3 Pins: 5Vs, Ground, and Digital output

IMG_0160

Clearer image of spokes wheel

IMG_0162

Video Demo

Serial.print values shows Potentiometer, DC voltage, digital IR value, # of rotations per sample interval (1 second), rotations per minute (RPM)

Code

// Function to use IR sensor to measure speed of turning spokes-wheel

// Motor and Potentiometer Values
int potPin = A4; int potValue = 0;
int motorPin = 3; int motorValue = 0;

// Rotary Wheel-Spin Sensor Values
int sensorRotaryPin = A0;
int sensorVal = 0; // 0 or 1 depending on whether the IR sensor detects the spokes or passes through them
int previousSensorVal = 0; // previous 0/1 value to use during loop calculations
int count = 0; // used for counting times digital signal shifts btw 0 and 1
float revolutions = 0; // number of times the wheel has turned 360 degrees
float rpm = 0; // rotations per minute
float speedVal = 0; // distance/time val calculated using revolutions and constants
int samplingInterval = 1000; // sample period of wheel turns over milliseconds to determine speed
long previousMillis = 0;

// Setup and Loop
void setup() {
Serial.begin(250000);
pinMode(8, INPUT);
}

void loop() {
potValue = analogRead(potPin); constrain(potValue, 0, 1023); // if(potValue>1023) {potValue=1023;}
motorValue = map(potValue, 0, 1023, 0, 255); analogWrite(motorPin, motorValue);
sensorVal = digitalRead(sensorRotaryPin);
spokesCounter();
GetSpeed();

// Serial Value Printing
Serial.print(potValue); Serial.print(” “);
Serial.print(motorValue); Serial.print(” “);
Serial.print(sensorVal); Serial.print(” “);
Serial.print(count); Serial.print(” “);
Serial.print(revolutions); Serial.print(” “);
Serial.println(rpm);
}

// Functions
int spokesCounter() { // Counts the number of times that analogRead changes values. A count of 20 spokes is 360 degrees.
if (sensorVal != previousSensorVal) {
count++;
}
previousSensorVal = sensorVal; // sets previous sensor val for next iteration through loop to compare
}

float GetSpeed() {
if(millis() – previousMillis >= samplingInterval) { // uses timer to turn count() value into rotation values and speed data
revolutions = (count/2.0)/20.; // # of revolutions. 20 spokes. count value divided by 2 so each change between 0/1 counts as 1 spoke. If 20 changes then the wheel has gone around 360 degree and revolutions = 1
rpm = revolutions * (60000.0/samplingInterval); // revolutions per minute (60,000 ms)
speedVal = (rpm * 20.0); // 20 cm is the wheel’s circumference. speed = cm/minute
previousMillis = millis(); // reset timer to resample
count = 0; // reset counter for next sample
}
}