Go Down

Topic: Ergometer / rowing computer help for a novice (Read 3225 times) previous topic - next topic

-Nathan

Hi

I'm pretty new to all of this, please bear with me as I fumble my way though.  I am attempting to create a computer to give me a visual feed back via LCD screen on a rowing machine I have recently constructed.  The machine uses an old bike wheel acting as a fan for resistance.  So far I've had success creating a timer, recording speed output and counting revolutions of the wheel which gives me distance.  I've based my code on several examples of bike computers as the process is pretty much the same.  To do this I've implemented an Uno board using a Hall effect sensor. While this is all well and good I've gotten stuck trying to use the wheel acceleration to keep track of strokes per minute to help with pace.   I know that a stroke starts every time the revolution wheel is faster than the past few revolutions of the weel, but I'm stuck getting this to read out.  As my code stands below all I can get out is the revolutions/ minute...  not the strokes/min.  Any help would be greatly appreciated.
Code: [Select]
#include <Average.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(12, 11, 5, 4, 3, 1);
volatile byte revs;
unsigned int rps;
unsigned int turns = 0;
unsigned int stroke = 0;
unsigned long strokeold;
float spm =0.0;
unsigned long timeold;
float circ = .743;  // update this value so aproximate max speed is 7meters per second decrease to slow down speed
//float velocity =0.0;
float spd = 0.0;
unsigned int avg[4]; //array for averaging speed
float distance;
unsigned long elapsed;
int h;
int m;
float s = 0.0;


void setup()
{
  digitalWrite(2, HIGH);
  attachInterrupt(0, rpm_fun, FALLING);
  lcd.begin(20, 4);  // set up the LCD's number of columns and rows: 
  delay(500);
  lcd.blink();
  lcd.print("READY TO ROW?");
  delay(2000);
  lcd.clear();

  revs = 0;
  rps = 0;
  timeold = 0;
}

void loop()
{
  if (revs >= 2) //Update rps every 2 counts, increase this for better RPM resolution, decrease for faster update
  {     
    rps = 1000/(millis() - timeold)*revs;      // this gives us the revolutions per second
    timeold = millis();
    revs = 0;
    timer();
    calc();   
    stroketimer();
    lcdupdate();
   
  }
}

void calc()
{
distance = turns * circ;
//velocity = rps * circ;  // speed is expressed in meters per second as averaged by the # pass interval specified in the loop
avg[0] = avg[1]; //shift storage array
avg[1] = avg[2]; // "
avg[2] = avg[3]; // "
avg[3] = int(rps); //insert current calculated revolutions per second
spd = ((avg[0] + avg[1] + avg[2] + avg[3]) / 4) * circ; //average the speed over the last four readings (mean)
}

void stroketimer()
{
if (rps > maximum(avg, 4))// if the latest turn of the wheel is faster than the time of the last four turns, assumes acceleration or new stroke
stroker();
spm = 60000/(millis() - strokeold);      // this gives us the strokes per minute 
strokeold = millis();
stroke = 0;
}

void timer()
{
  unsigned long over;
  elapsed=millis();
  h=int(elapsed/3600000);
  over=elapsed%3600000;
  m=int(over/60000);
  over=over%60000;
  s=int(over/1000);
}

void lcdupdate()
{
  lcd.setCursor(0,0);
  lcd.print("Time = ");
  lcd.print(h);
  lcd.print( ":");
  lcd.print(m);
  lcd.print( ":");
  lcd.print(s);
  lcd.setCursor(0,1);
  lcd.print(" Speed:");
  lcd.print(spd);
  lcd.print(" m/s");
  lcd.setCursor(0,2);
  lcd.print("Distance");
  lcd.print(distance);
  lcd.setCursor(0,3);
  lcd.print("SPM= ");
  lcd.print(spm);
 
}
void rpm_fun()
{
  revs++;
  turns++;
  //Each rotation, this interrupt function is run once
}

void stroker()
{
stroke ++;
}



Thank you in advance,

-Nathan


JimboZA

Would it not be easier to sense a pull on the line to signal the start of a stroke, rather than look for an acceleration of the wheel?

(Or get a concept2.....  8) )
Johannesburg hams call me: ZS6JMB on Highveld rep 145.7875 (-600 & 88.5 tone)
Dr Perry Cox: "Help me to help you, help me to help you...."
Your answer may already be here: https://forum.arduino.cc/index.php?topic=384198.0

ChilliTronix

You have a global variable "stroke" incremented in a function "stroker" which just after you call "stroker" you set to a value of 0.

I may be wrong, but that is always going to result in a stroke count of 0.

apollinaire

I suppose your construction works more or less like the concept2, so the handbar is at the end of a bike chain which runs over the bike wheel's sprocket?

So when the stroke is finished, the chain is somehow retracted and the sprocket is freewheeling backwards.

If you manage to couple a rotation encoder to the sprocket you can easily detect the turn points of the movement.
Or you can place a marker on the chain which passes two sensors, one at the start of the stroke, (setting strokestart=true, strokeend=false) and one near the end (strokestart=false, strokeend=true).

These events don't have to occur at the exact moment of the stroke's progress, since you are only interested in the time between them to calculate the stroke rate.

This way you do not have to deal with the first end second derivative in the speed of the wheel.

-Nathan

Yes my construction functions most like a concept two.  The freewheel does spin backwards on the return of the stroke.

From what everybody is saying here, the way to capture stroke count/timing is to use another hall effect sensor and interrupt.  Either on the chain, the freewheel or my original plan was to place it in relation to the sliding seat.  It seems to be a more robust solution to have only one piece of hardware recording "motion."

Because I am new to arduino, I just was not sure if there was a way to compare rotational speeds of the flywheel to capture if the last rotation was faster than the previous 3 or 4. which would signify a stroke.

Thanks for the help.

-Nathan

stevescot

I'm trying to pull together some code to perform row-computer functions in an arduino ,

if anyone wants to help - please feel free to contribute - git will allow you to modify the code and post it up:

https://github.com/stevescot/OpenRowingCode

Steve

Go Up