Equipment:
-
Arduino ATmega2560
-
Rotary Encoder: https://www.amazon.ca/gp/product/B08RS6M32J/ref=ppx_yo_dt_b_asin_title_o06_s01?ie=UTF8&psc=1
-
Manual Curved Treadmill
Background:
I have a manual treadmill and I want to use my Arduino to capture distance and speed data. To do this, my approach was to use a rotary encoder, attach it to a skateboard wheel (older picture is attached, I'm using a bigger wheel now and there's no photo for that right now) such that when I run on the treadmill, the wheel spins proportionately.
In the code below, whenever I run it, the counter variable would accumulate to about 2000 (pulses) every time the wheel makes a full rotation. The wheel diameter = 6cm, therefore, it's circumference = 18.8495559215 cm.
This means for every centimeter I travel, there are about 106 pulses. (2000 pulses/18.8495559215 cm = ~106 pulses/cm).
Here's the code: (I got it from this website and only changed 2 lines of code because my sensor doesn't need to go in reverse; the treadmill only travels in one direction - How to connect optical rotary encoder with Arduino - Electric Diy Lab)
volatile long temp, counter = 0; //This variable will increase or decrease depending on the rotation of encoder
void setup() {
Serial.begin (9600);
pinMode(2, INPUT_PULLUP); // internal pullup input pin 2
pinMode(3, INPUT_PULLUP); // internalเป็น pullup input pin 3
//Setting up interrupt
//A rising pulse from encodenren activated ai0(). AttachInterrupt 0 is DigitalPin nr 2 on moust Arduino.
attachInterrupt(0, ai0, RISING);
//B rising pulse from encodenren activated ai1(). AttachInterrupt 1 is DigitalPin nr 3 on moust Arduino.
attachInterrupt(1, ai1, RISING);
}
void loop() {
// Send the value of counter
if( counter != temp && counter % 106 == 0 ){ // Only print something if the wheel travels in increments of 1 cm.
Serial.println (counter);
temp = counter;
}
}
void ai0() {
// ai0 is activated if DigitalPin nr 2 is going from LOW to HIGH
// Check pin 3 to determine the direction
if(digitalRead(3)==LOW) {
counter++;
}else{
counter++; // The original code said counter-- but my treadmill only goes one direction and the this variable starts to decrease when I reach a certain speed (around 5 kmk/h or (3.1 mph) or so). After I changed it to counter++, this issue was resolved however, the arduino serial monitor kept freezing at high speeds.
}
}
void ai1() {
// ai0 is activated if DigitalPin nr 3 is going from LOW to HIGH
// Check with pin 2 to determine the direction
if(digitalRead(2)==LOW) {
counter++; //// The original code said counter-- but my treadmill only goes one direction and the this variable starts to decrease when I reach a certain speed (around 5 kmk/h or (3.1 mph) or so). After I changed it to counter++, this issue was resolved however, the arduino serial monitor kept freezing at high speeds.
}else{
counter++;
}
}
The Problem
*To get the speed is easy, it's just not in this code right now. Accomplished by using t1 and t2 variables and the Millis() function.
When I walk on the treadmill, I typically walk at about 4 or 5 km/h (3.1 mph). This works fine. However, the issue is I want to be able to sprint over 30 km/h (18.6 mph) and have the code be able to support up to 50 km/h (31 mph). Right now, I'm unable to run at speeds over 5 km/h without the serial monitor freezing periodically, or there being inaccurate data.
At these speeds, I would need the sensor to support the wheel moving at over 4500 RPM -> 75 RPS or (75 RPS x 2000 P/R = 150,000 Pulses/Second)
I have absolutely no idea why this issue is happening and how I should approach this to achieve my desired speeds.
Possible reasons why this is happening:
-
I'm not an expert at Arduino at all and am just starting to understand things like interrupts. I have my pins in 2 and 3. Should I leave this alone or change it?
-
If you click the Amazon link, you'll see that there is a 3rd Orange "Z" wire which I have absolutely no idea what it does. The few tutorials I could find only involve the two "A" and "B" wires. Maybe incorporating the "Z" wire would point me in the right direction?
-
My Rotary encoder sensor is using the Arduino's 5V. If you click on the Amazon link, you'd see that it actually supports up to 26V. Should I find an external power source that allows up to 26V and pair it with a relay? Not sure if the extra voltage will help me.
-
I'm not sure why by default, the sensor counted a full rotation for the wheel to be 2000 pulses. On Amazon, you'll see that it supports the following Pulses/Revolution:
Resolution (pulse/rotation) : 100, 200, 300, 360, 400, 500, 600, 1000, 1024, 1200, 2000, 2500, 3600, 5000 (optional)
How can I change my 2000 P/R to 5000 P/R for example? Would this help?
Summary
I want to use my Arduino and rotary sensor to collect speed and distance data from my manual treadmill. At slow speeds (up to 5 km/h), the code works fine, but at high speeds, the data is highly inaccurate, and the serial monitor freezes every few seconds. I want the Arduino to support speeds up to 50 km/h which is about 4500 RPM. If my solution with the rotary sensor is not feasible, I am 100% open to other ideas as I just want the speed and distance data. I'll purchase any new equipment that's necessary but ideally, I'd like to work with what I have right now.
Thank you for your help!
