Bicyclist Computer Program Help

Hello Everyone,

so I'm pretty much a newb at arduino programming and this is my first real bit of software. I'm typically a PLC programmer so this is quite a bit different. So i was wondering if you could look at my code see what i could do to make it function better and maybe look at some of the problems I'm having. This is on an Arduino UNO. Attached to an Adafruit ILI9431. It should record data from 2 hall effect sensors one on the wheel and one on the pedal. Then the user can input 2 values in the setup screen rider weight and tire diameter. From there i do my calculations for Ride Time, Speed, Distance, Cadence, Calories Burned, and Pace. However these are not functioning like i though they would. If you could take a look and give me feedback that would be great. Each problem location is marked with a // PROBLEM (then some info)

Thanks for any help given

#define sclk 13  // Don't change
#define mosi 11  // Don't change
#define cs   10
#define dc   9
#define YP   A2
#define XM   A3
#define XP   9
#define YM   8

#define TS_MINX 150
#define TS_MINY 120
#define TS_MAXX 920
#define TS_MAXY 940

#define MINPRESSURE 10
#define MAXPRESSURE 1000

unsigned long TotalWheelCount;
unsigned long TotalPedalCount;
unsigned long NewTime;
unsigned long Time;
unsigned long previoustime = 0;
byte sec;
byte minute;
byte hour;
volatile byte WheelRpmCount;
unsigned int WheelRpm;
volatile byte PedalRpmCount;
unsigned int PedalRpm;
int WheelDiameter = 15;
int RiderWeight;
int Calories;
int TotalCalories;
float Speed;
float Distance;
float Pace;

#include <Adafruit_GFX_AS.h>    // Core graphics library
#include <Adafruit_ILI9341_AS.h> // Hardware-specific library
#include <SPI.h>
#include "TouchScreen.h"

Adafruit_ILI9341_AS tft = Adafruit_ILI9341_AS(cs, dc);       // Invoke custom library
TouchScreen ts = TouchScreen(XP, YP, XM, YM, 300);

void setup(void){

 tft.init();
 tft.setRotation(1);  

/* **** uncomment this block and the two blocks of code below to test touch calibration in Serial Monitor
   Serial.begin(9600);
   Serial.println(F("Touch to mark point"));
*/
   Serial.begin(9600);
   Serial.println(testLines(ILI9341_CYAN)); // print opening graphic
   delay(500);
       
   Serial.println(Startup()); // print title screen
   delay(1500);
   
   attachInterrupt(0, WheelRpm_fun, RISING); // interrupt for wheel sensor
   WheelRpmCount = 0;
   WheelRpm = 0;
 
   
   attachInterrupt(1, PedalRpm_fun, RISING); // interrupt for pedal sensor
   PedalRpmCount = 0;
   PedalRpm = 0;
   
   Time = 0;
   
   tft.fillScreen(ILI9341_BLACK);

}



void loop (){
 
   

   tft.setTextColor(ILI9341_CYAN);
   Serial.println(calcTime());
   Serial.println(calcSpeed());
   Serial.println(calcDistance());
   Serial.println(calcCadence());
   Serial.println(calcCalories());
   Serial.println(calcPace());
   

   TSPoint p = ts.getPoint(); //acquire touch data
   
/*     Testing purpose only prints touch data to serial monitor
   Serial.print("X = "); Serial.print(p.x);
   Serial.print("\tY = "); Serial.print(p.y);
   Serial.print("\tPressure = "); Serial.println(p.z);  
*/   

   if (p.z < MINPRESSURE || p.z > MAXPRESSURE) { // sets a touch pressure range
     return;
   }
   p.x = map(p.x, TS_MINX, TS_MAXX, 0, tft.width()); // maps the x touch location
   p.y = map(p.y, TS_MINY, TS_MAXY, 0, tft.height()); // maps the y touch location

/*      Testing purpose only prints touch data to serial monitor
   Serial.print("("); Serial.print(p.x);
   Serial.print(", "); Serial.print(p.y);
   Serial.println(")");
*/    

  if ((p.x > 180) && (p.x < 250) && (p.y > 100) && (p.y < 200)) { 
    // sends user to setup screen
    // PROBLEM once touched the touch functionality goes away so how do i receive data and return to loop
     Serial.println (SetupScreen());
   }
}



unsigned long Startup() {
  
   tft.fillScreen(ILI9341_BLACK);
   tft.setTextColor(ILI9341_CYAN);
   tft.drawString("Team D:",0,10,2);
   tft.drawString("CYCLING TRACKER",50,110,4);
   delay(2000);
}

unsigned long testLines(uint16_t color) {
 unsigned long start, t;
 int           x1, y1, x2, y2,
               w = tft.width(),
               h = tft.height();

 tft.fillScreen(ILI9341_BLACK);

 x1 = y1 = 0;
 y2    = h - 1;
 start = micros();
 for(x2=0; x2<w; x2+=6) tft.drawLine(x1, y1, x2, y2, color);
 x2    = w - 1;
 for(y2=0; y2<h; y2+=6) tft.drawLine(x1, y1, x2, y2, color);
 t     = micros() - start; // fillScreen doesn't count against timing

}

unsigned long SetupScreen (){
 
}

unsigned long calcTime () {   //prints time since program started

 // PROBLEM seems to work but actual time is off
 
 if (millis () >= (previoustime)  ) {
   previoustime = previoustime + 1000;  
   sec = sec +1;
      if (sec == 60){
        sec = 0;
        minute = minute +1;
      }
      if (minute == 60){
        minute = 0;
        hour = hour +1;
      }
      if (hour == 13){
        hour = 1;
      }
 }
 
 tft.fillRect(200,10,120,25,ILI9341_BLACK);
 tft.setTextColor(ILI9341_CYAN);
 tft.drawString("Ride Time:",0,10,4);
 tft.setTextColor(ILI9341_GREEN);  
 tft.drawNumber(hour, 200,10,4);
 tft.drawString(":", 230,10,4);
 tft.drawNumber(minute, 240,10,4);
 tft.drawString(":", 270,10,4);  
 tft.drawNumber(sec, 280,10,4);
 // wait a second so as not to send massive amounts of data
 delay (560);  
}


unsigned long calcSpeed (){ 
 
 // calculate speed using single hall effect sensor attachted to pin 2 using interrupt 0 
 // PROBLEM  speed never seems to update correctly and i may be getting 0 for wheel RPM even though its counting
 
   delay(1000); 
   detachInterrupt(0); 

   WheelRpm = (60*1000/65768)* WheelRpmCount;

   TotalWheelCount = TotalWheelCount + WheelRpmCount;
   WheelRpmCount = 0;
   Speed = ((WheelDiameter * 3.14159 * WheelRpm) / 63360);
   Speed = Speed * 60.00;
   tft.fillRect(200,40,120,25,ILI9341_BLACK);
   tft.setTextColor(ILI9341_CYAN);
   tft.drawString("Speed:",0,40,4); 
   tft.setTextColor(ILI9341_GREEN);
   tft.drawNumber(Speed, 200,40,4);
   tft.drawString("MPH", 260,40,4);

   attachInterrupt(0, WheelRpm_fun, RISING);
  
  
}

unsigned long calcCadence () {
 
 // calculate Cadance or pedal RPM using single hall effect sensor and interrupt 1
 // PROBLEM cadence RPM does not update

   delay(1000); 
   detachInterrupt(1); 

   PedalRpm = (60*1000/65768)* PedalRpmCount;
   
   tft.fillRect(200,70,120,25,ILI9341_BLACK);
   tft.setTextColor(ILI9341_CYAN);
   tft.drawString("Cadence:",0,70,4); 
   tft.setTextColor(ILI9341_GREEN);
   tft.drawNumber(Speed, 200,70,4);
   tft.drawString("RPM", 260,70,4);
   
   attachInterrupt(1, PedalRpm_fun, RISING);
   
}

unsigned long calcDistance () {
 
 // calculate total distance traveled using the hall effect on the tire to count revolutions
 // PROBLEM distance does not update and does not display decimals .00

  Distance = TotalWheelCount * (WheelDiameter * PI / 12);
  Distance = Distance / 5280.00;
  tft.fillRect(200,100,120,25,ILI9341_BLACK);
  tft.setTextColor(ILI9341_CYAN);
  tft.drawString("Distance:",0,100,4); 
  tft.setTextColor(ILI9341_GREEN);
  tft.drawNumber(Distance, 200,100,4);
  tft.drawString("Mi", 280,100,4);
    
}

unsigned long calcCalories() {
 
 // calculate calories burned based on speed and rider weight multiplied by time
 // not tested need other code to function first
 
   Time = millis()-Time;
   
   if (Speed < 5.5 && Speed > 1){
     Calories = 3.5 * RiderWeight * Time;
   }
   else if (Speed >5.5 && Speed < 9.4){
     Calories = 5.8 * RiderWeight * Time;      
   }
   else if (Speed > 9.4 && Speed < 11.9){
     Calories = 6.8 * RiderWeight * Time;      
   }
   else if (Speed > 11.9 && Speed < 13.9){
     Calories = 8.0 * RiderWeight * Time;      
   }
   else if (Speed >13.9 && Speed < 15.9){
     Calories = 10.0 * RiderWeight * Time;      
   }
   else if (Speed >15.9 && Speed < 20){
     Calories = 12.0 * RiderWeight * Time;
   }
   else if (Speed >20){
     Calories = 15.8 * RiderWeight * Time;      
   }
   else {
     Calories = 0;
   }
   
  Time = millis();
 
  TotalCalories = TotalCalories + Calories;

   tft.fillRect(200,130,120,25,ILI9341_BLACK);
   tft.setTextColor(ILI9341_CYAN);
   tft.drawString("Calories:",0,130,4); 
   tft.setTextColor(ILI9341_GREEN);
   tft.drawNumber(TotalCalories, 200,130,4);
   tft.drawString("Cal", 260,130,4);
   
}

unsigned long calcPace () {
 
 // calculates minutes per mile or the pace of the cyclist
 // not tested need other code to function first
 
   Pace = 3600/Speed;
   
   Pace = Pace / 60;
 
 
   tft.fillRect(200,160,120,25,ILI9341_BLACK);
   tft.setTextColor(ILI9341_CYAN);
   tft.drawString("Pace:",0,160,4); 
   tft.setTextColor(ILI9341_GREEN);
   tft.drawNumber(Speed, 200,160,4);
   tft.drawString("m/Mi", 260,160,4);
}


void WheelRpm_fun ()
{   // function to count the hall effect
 WheelRpmCount++;
}

void PedalRpm_fun()
{   // function to count the hall effect
 PedalRpmCount++;
}

Start here

I did start there. What did I do incorrectly?

acezeesawtooth:
I did start there. What did I do incorrectly?

Until 13:47:18, the whole of reply #1.

Thank you.

Hi,
What is it not doing, and what are you seeing on the monitor as you trip the hall effect sensors?

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Tom.... :slight_smile:

acezeesawtooth:
However these are not functioning like i though they would.

You need to tell us what they are doing and also what they should be doing.

It would be much too time consuming to try to figure that out by studying your program.

If this was my project I would start by simply reading the pedal and wheel pulses and displaying the values on the serial monitor - keeping the code to the absolute minimum.

When that worked I would add other pieces one step at a time ensuring that each change works before going on to the next one.

...R

ok I will try and get a schematic drawn up. As far as problems I'm seeing the Timer is running slower than actual time for the ride time. The Wheel Counter is tripping off the hall effect but it is not making it through the calculations because it comes up 0. Same for the Cadence. and the others I need these to work before i can judge if they function. I will Try just getting the pulses to display and go from there. Thanks

EDIT

Im not sure a schematic will help. The only things i have wired are for the touch screen which functions fine and the 2 Hall effect sensors which are wired to pin 2 for the wheel sensor and pin 3 for the pedal sensor. Those are the 2 pins that are attached to the interrupts 0 and 1 respectively

WheelRpm = (60*1000/65768)* WheelRpmCount;

Multiply anything by zero, and you get zero.

I would agree with that AWOL except for when i print WheelRpmCount it displays the number of clicks of the sensor since the last interrupt so it should be getting something. I have also tried doing this instead of the numbers

WheelRpm = 60*1000/ (millis() - TimeOld) * WheelRpmCount

This does give me a value for the WheelRpm but it is an astronomical value like for 1 revolution in the second my rpm is at 63130.

Welcome to the world of 16 bit signed integer arithmetic.

Hi,
What AWOL is being cryptic about is the mix of int, float etc type of variables and constantsin an equation and the results they give.

Google int floats equations arduino

Also have a read of;

Tom...... :slight_smile: