Reading Speed (MPH) and Incline from MC-2100 powered treadmill

Thread Starter

EricTurner

Joined Feb 3, 2020
7
I recently got a NordicTrack T5.7 treadmill which is powered by a MC2100LS-30. It is an older treadmill that works great, however one of the features of the new treadmills out today allow you to visualize your treadmill run like so:
1580768001210.png

This is amazing to me, but my treadmill is not smart like this nor does it have a screen so I want to try and replicate this with an arduino.

Currently, I have intercepted the connection between the controller and the console into a breadboard like so:
1580768317478.png


I want to know how to read the MPH (and then also the current incline) from these connectors. I currently have the blue wire hooked up to pin 9 and the green wire hooked up to pin 3. Description of what those wires do is below:
GREEN- This wire brings the speed sensor signal to the console. This is a pulsing 0, 5 VDC signal as the treadmill is
running. When the treadmill is at rest, this voltage may measure either 0 VDC or 5 VDC.

BLUE- This wire carries the square wave speed control signal from the console to the power board. The duty cycle of
this 5 VDC signal is used to set the speed of the treadmill. At the maximum duty cycle of 85% (meaning the 5 VDC is being sent 85% of the time and not being sent 15% of the time), approximately 4 VDC can be measured. At lower speeds, a lower voltage will be measured. NOTE: Many digital multimeters have difficulty measuring this square wave signal. They may only show a maximum of 1.5 VDC when the treadmill is set to its maximum speed. What is important to see in this instance is that the voltage goes up as the treadmill speed is increased.
I have tried several arduino scripts but my lack of expertise in arduino and electrical engineering have me stumped on how to convert all these numbers I am receiving from these wires into a human-readable MPH.

This is the closest I have gotten code wise, but after 2.0mph, the numbers dont matchup. I basically just slapped together code from all sorts of different places because I don't quite understand what is going on so if someone could guide me on how to properly read the data from these wires and convert it to MPH I would be grateful. Thanks!

Code:

Code:
const int sensorPin = 3; //Blue PWM
unsigned long pulseCount=0;
const unsigned long updateInterval=50000; //50ms
int RPM=0;
long startTime;

const float TireDiameter = 13.5;  // Tire diameter in inches (actually 1.9in)
const float TireCircumference = TireDiameter * PI;
const int FeetPerMile = 5280;
const int InchesPerFoot = 12;
const long InchesPerMile = (long)FeetPerMile * (long)InchesPerFoot;
const int MinutesPerHour = 60;

void setup()
{
  Serial.begin(9600);
  attachInterrupt(1, N1, RISING);
}

void N1() {
 pulseCount++;
}


void loop() {
 if (startTime == 0) {
  startTime=micros();
 }

 if (millis() - startTime > updateInterval) {
  RPM=((pulseCount/2)/((millis() - startTime)/600000000));
  startTime=0;
  pulseCount=0;
 }
 //display or otherwise use RPM value
 //Serial.print("RPM: ");
 //Serial.println(RPM);

  float InchesPerMinute = RPM * TireCircumference;
  float InchesPerHour = InchesPerMinute * MinutesPerHour;
  float MPH = InchesPerHour / InchesPerMile;
  Serial.print("MPH: ");
  Serial.println(MPH);
}
 

OBW0549

Joined Mar 2, 2015
3,566
It's not necessary to do that; by having two cross-linked threads on the same subject, you'll just cause confusion and annoyance.
 

dl324

Joined Mar 30, 2015
16,845
I basically just slapped together code from all sorts of different places because I don't quite understand what is going on so if someone could guide me on how to properly read the data from these wires and convert it to MPH I would be grateful.
Since you're not certain what the code is doing, why don't you explain what the signals on the blue and green wires represent?

What do the pulses on the speed sensor represent?

What is the frequency of the signal on the blue wire? Knowing that the on time can vary between 15-85% isn't very meaningful if we don't know the frequency.
 

Reloadron

Joined Jan 15, 2015
7,501
OK, let's look at green and blue which you wish to measure and convert to engineering units.
GREEN- This wire brings the speed sensor signal to the console. This is a pulsing 0, 5 VDC signal as the treadmill is
running. When the treadmill is at rest, this voltage may measure either 0 VDC or 5 VDC.

BLUE- This wire carries the square wave speed control signal from the console to the power board. The duty cycle of
this 5 VDC signal is used to set the speed of the treadmill. At the maximum duty cycle of 85% (meaning the 5 VDC is being sent 85% of the time and not being sent 15% of the time), approximately 4 VDC can be measured. At lower speeds, a lower voltage will be measured. NOTE: Many digital multimeters have difficulty measuring this square wave signal. They may only show a maximum of 1.5 VDC when the treadmill is set to its maximum speed. What is important to see in this instance is that the voltage goes up as the treadmill speed is increased.

Unfortunately green really doesn't give us much other than speed sensor signal to console is 5 volt pulses but no way to correlate pulse frequency to speed (MPH). you could maybe get a few frequency measurements and note the frequency verse speed on your console.

The blue tell us a lot more. " The duty cycle of this 5 VDC signal is used to set the speed of the treadmill". It looks like they use or send a PWM (Pulse Width Modulation" signal to the motor controller board to control motor speed and subsequent MPH of the treadmill. Since you know an 85% PWM equals max speed you can likely work with that. I am not sure why the voltage level reduces?

Just for starters you may want to give this a read. An Arduino like an Arduino Uno can easily generate PWM Out but with some effort there are a few ways to measure PWM in. Once you get that if the max speed is known an 85% PWM can be mapped to that number. I would start there.

Ron
 

dl324

Joined Mar 30, 2015
16,845
It just occurred to me that you can get the PWM frequency by measuring it with your Arduino. That and knowing the speed associated with 15% and 85% should allow you calculate MPH.
 

MaxHeadRoom

Joined Jul 18, 2013
28,619
The frequency of the control PWM is 20Hz. They do not go to full pulse width for max motor/belt speed.
Also the track is usually fitted with a hall sensor/detector for belt speed rate.
Max.
 
Last edited:

Thread Starter

EricTurner

Joined Feb 3, 2020
7
@Reloadron Thanks for the read! It does seem to be helpful
@dl324 Yes, I think I may be able to piece it together, I am just unsure if I am doing it properly.

So there is a setting on the treadmill that I can go into 'debug mode' and it will show each percentage PWM that corresponds with a speed. So 15% is the lowest and that is 0.3mph, 17% is 0.5 ... 85% is 10.0mph. I plugged these numbers into Excel and performed a linear regression with y being speed and x being the raw PWM value. I am going to try that to see if it will work.

@MaxHeadRoom I have seen the hall sensor / detector on the motor. It connects back to the contoller over the TACH wire. However, I found this information as well:
The MC-2100 has its own processor and software, which allows it to communicate with the console. This is done by a small digital signal carried by the GREEN tach wire. By entering calibration mode on the console, two alternate screens can be accessed which give information on the controller, including the status of the troubleshooting LED, motor voltage, and motor amperage. This greatly increases the amount of troubleshooting that can be done without removing the treadmill’s motor hood.
...
TACH- This connection is for the reed switch wire. This allows the tach signal to be received by the controller and passed to the console wire harness, where it is sent up the GREEN wire. Voltage is a pulsing 5 VDC when the treadmill is running. When the treadmill is at rest, this voltage may be 0 VDC or 5 VDC, depending on the whether the magnet is closing the reed switch or not.
So yes, the green wire has data coming from the TACH, but it also is mixed with another digital signal meant to be used for calibration or troubleshooting and I have no idea how I would filter that out. I definitely did think about just going down to the board itself and tapping into the pure TACH connection to get that raw value.

Also, I have seen that 20Hz before, but I apologize I do not know what that would be used for. I found this article that mentions some equations in the beginning so 20Hz would be:
the frequency = 20
T = T(on)+T(off) = 1/20 = 0.05ms
duty cycle = .85*0.05ms = 0.0425ms on time
0.0075ms off time
I now do not understand what to do with these numbers and how they would help. I would assume setting up a Timer of some sort and reading based off of those times but I am unsure if that is correct or how I would go about doing that.
 

Reloadron

Joined Jan 15, 2015
7,501
Just for the heck of it I tried a few schemes on my Arduino Uno from the link. The one method was giving me problems with the library link I used. I will mess around with it more see what develops and post it later..

The frequency of the control PWM is 20Hz. They do not go to full pulse width for max motor/belt speed.
Also the track is usually fitted with a hall sensor/detector for belt speed rate.
Max.
Live and learn, thanks Max I had no idea.

Ron
 

MaxHeadRoom

Joined Jul 18, 2013
28,619
@MaxHeadRoom I have seen the hall sensor / detector on the motor. It connects back to the contoller over the TACH wire. However, I found this information as well:
So yes, the green wire has data coming from the TACH, but it also is mixed with another digital signal meant to be used for calibration or troubleshooting and I have no idea how I would filter that out. I definitely did think about just going down to the board itself and tapping into the pure TACH connection to get that raw value.
Also, I have seen that 20Hz before, but I apologize I do not know what that would be used for. I found this article that mentions some equations in the beginning so 20Hz would be:
I now do not understand what to do with these numbers and how they would help. I would assume setting up a Timer of some sort and reading based off of those times but I am unsure if that is correct or how I would go about doing that.
I gather your aim is to enhance the present system on the T.M. as a unit.
As I believe you discovered, many of the signals are sent up to the console, rate of belt or motor etc. the board/belt speed is then controlled accordingly,
Some units with these boards monitor actual motor RPM, some the belt speed via a pulley sensor.
The 20hz PWM is used to control the motor RPM via a opto input IC and a microprocessor on the MC2100 , as soon as the board recieves a motor command the LED changes from steady to slow flash rate.
I made up some boards using a small pic to control the board where it is used for second purposes, mil/drills etc.
Max.
 

djsfantasi

Joined Apr 11, 2010
9,156
OK, with very minor effort or easily. The link I gave I think demonstrates three methods including pulsein() function. :)

Ron
Yes, you did! I missed the link; my bad.

As a suggestion, you can define a change pin in hardware, which changes and triggers an interrupt whenever multiple pins change. I have a multichannel RF control that always changes an interrupt output when any channel is modified. But I realize this may not apply here.
 

Reloadron

Joined Jan 15, 2015
7,501
I dug out an Arduino Uno and also a little Sunfounder 20 X 4 LCD. Months ago I used the Arduino to measure frequency. I started with an example and expanded on that. Looking back at my stash I think this was my basic starting point.

Code:
int pin = 7;
unsigned long duration;
unsigned long duration1;
unsigned long duration2;
unsigned long Freq;

void setup()
{
  Serial.begin(9600);
  pinMode(pin, INPUT);
}

void loop()
{
  duration = pulseIn(pin, HIGH);
  duration1 = pulseIn(pin, LOW);
  duration2 = (duration + duration1);
  Freq = (duration2 / 10000);
  Serial.println(duration);
  Serial.println(duration1);
  Serial.println(duration2);
  Serial.println(Freq);
  delay(1000);
}
This was using the pulse in method. Now I would have to check this out but if I recall correctly it did pretty well with a nice symmetrical square wave but had problems when I began changing the duty cycle. I was monitoring my signal input with both a scope and counter which agreed. Now for some reason looks like my LCD died as it won't respond to any code I have where I included the LCD. Maybe I'll drag out more stuff like scope and counter and try this again. The above code needs a little work but gets the idea of pulse in across. I am just annoyed my LCD won't work and it's known good code. Time for Amazon. :)

Ron
 

djsfantasi

Joined Apr 11, 2010
9,156
I am curious about your calculation of frequency. Your variable “duration2” is the period of the waveform. It’s units is in microseconds, or 10^-6 seconds. Your variable “frequency” is neither a frequency nor a frequency. The correct calculation of frequency, F, based on the length of the period in microseconds is as follows:
F = (10^6) / duration2​
 

Thread Starter

EricTurner

Joined Feb 3, 2020
7
So this is what I tried after doing the reading you linked, @Reloadron :
Code:
// https://www.benripley.com/diy/arduino/three-ways-to-read-a-pwm-signal-with-arduino/

volatile int pwm_value = 0;
volatile int prev_time = 0;
int total_pwm = 1023;
int max_pwm = total_pwm * .85; // PWM of the MC-2100 is a maxixum duty cycle of 85%
int min_pwm = total_pwm * .15; // Not being sent 15% of the time
float max_mph = 10.0; // our treadmill can reach a max speed of 10.0 mph
float min_mph = 0.3; // our treadmill can start as low as 0.3 mph


float cur_speed;
 
void setup() {
  //begin monitoring on a baud rate of 56800
  Serial.begin(56800);
  // attachInterrupt(digitalPinToInterrupt(pin), ISR, mode) 
  // https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
  // 1st param is the pin we are using, digital pin 2
  // 2nd param is the function we call once an interrupt occurs
  // 3rd param is the mode of when we should call the interrupt: LOW, CHANGE, RISING, FALLING
  attachInterrupt(digitalPinToInterrupt(2), rising, RISING);
}
 
void loop() { }
 
void rising() {
  //We know by calling this the PWM is rising, this stores in memory to call once it drops
  attachInterrupt(digitalPinToInterrupt(2), falling, FALLING);
  // In the mean time, grab the time that this function is called
  prev_time = micros();
}
 
void falling() {
  //Once the interrupt triggers, store in memory to keep a look out for the PWM to rise again
  attachInterrupt(digitalPinToInterrupt(2), rising, RISING);
  // do some math to calculate the PWM value by subtracting the time it takes between rising and falling
  pwm_value = micros()-prev_time;
  // this prints out the length of time the signal remains high for each cycle
  Serial.println(pwm_value);
    
  // I put the PWM values and MPH values on a scatter plot and came up with this regression:
  // s = 0.0141p - 1.972  
  // where s is speed (in MPH) and p is PWM (raw units, NOT percentage)
  cur_speed = (0.0141*pwm_value) - 1.972;
  //Serial.print("MPH: ");
  //Serial.println(cur_speed);

  
}
The PWM value it is returning doesn't seem to change when I change speed and always errs on the 16-52 range which is way too low for higher RPMs, so maybe I am approaching this wrong? I feel like I need to specify the 20Hz somewhere, but I am unsure where or how.
 

djsfantasi

Joined Apr 11, 2010
9,156
I am curious about your calculation of frequency. Your variable “duration2” is the period of the waveform. It’s units is in microseconds, or 10^-6 seconds. Your variable “frequency” is neither a frequency nor a frequency. The correct calculation of frequency, F, based on the length of the period in microseconds is as follows:
F = (10^6) / duration2
 

Thread Starter

EricTurner

Joined Feb 3, 2020
7
I am curious about your calculation of frequency. Your variable “duration2” is the period of the waveform. It’s units is in microseconds, or 10^-6 seconds. Your variable “frequency” is neither a frequency nor a frequency. The correct calculation of frequency, F, based on the length of the period in microseconds is as follows:
F = (10^6) / duration2
I did not calculate frequency in my code, I tried to calculate the length of the PWM then using a linear regression that related PWM to MPH display the MPH, but the PWM values I was reading don’t appear accurate
 

Reloadron

Joined Jan 15, 2015
7,501
I am curious about your calculation of frequency. Your variable “duration2” is the period of the waveform. It’s units is in microseconds, or 10^-6 seconds. Your variable “frequency” is neither a frequency nor a frequency. The correct calculation of frequency, F, based on the length of the period in microseconds is as follows:
F = (10^6) / duration2​
That's why I mentioned I never checked it but yes, I should have caught that. . That was out of Arduino Examples, not quite a good example. :)

Ron
 

Reloadron

Joined Jan 15, 2015
7,501
I did not calculate frequency in my code, I tried to calculate the length of the PWM then using a linear regression that related PWM to MPH display the MPH, but the PWM values I was reading don’t appear accurate
I will toss it around a little more later and keep in mind that example left a lot to be desired.

Ron
 
Top