cruise control on motorcycle, need to read timing between wheel RPMs on reed swi

How about this? i got some help to remove the loop()s

#include <Servo.h> 
Servo myservo; // create servo object to control a servo 
 
int potpin = 0;
int val; 
 
// set pin numbers:
const int buttonPin = 10; // the number of the pushbutton pin
const int buttonPin2 = 8;
const int buttonPin3 = 4;
const int buttonPin4 = 2;
 
void setup()
{
      myservo.attach(12); // attaches the servo on pin 12 to the servo object 
 
     // initialize the pushbutton pin as an input:
     pinMode(buttonPin, INPUT); 
     pinMode(buttonPin2, INPUT); 
     pinMode(buttonPin3, INPUT); 
     pinMode(buttonPin4, INPUT);
 
}
 
void loop()
{ 
     val = analogRead(potpin); //takes reading from pot current position 
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo outputmyservo.write(val); //writes current position to servo to move it
     myservo.write(val);      //writes current position to servo to move it
     if (digitalRead(buttonPin) == HIGH) 
     serloop1(); //sends command to SerLoop1
     if (digitalRead(buttonPin2) == HIGH) 
     serloop1(); //sends command to SerLoop1
 
}
 
void serloop1()
{
 
     int val1 = myservo.read(); //reads current servo location
 
     if (digitalRead(buttonPin) == HIGH)
     {
          myservo.write(val1 + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          delay(100); //allows time for switch ro reset
     }
 
     if (digitalRead(buttonPin2) == HIGH) 
     {
          myservo.write(val1 - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          delay(100); //allows time for switch ro reset
     }
 
     if (digitalRead(buttonPin3) == HIGH) 
     {
          //Nothing, just exit
     }
 
     if (digitalRead(buttonPin4) == HIGH) 
     {
          //Nothing, just exit
     }
 
     else
     {
          serloop1(); //returns to SerLoop1 to run again
     }
}

In serloop1() you seem to be modifying the servo position but you've already written the unmodified value to the servo. I suggest you work out what position you want the servo in, and only then move the servo to that position.

This code in serloop1() is completely wrong:

serloop1(); //returns to SerLoop1 to run again

You have misunderstood how the control passes between functions in 'C' and C++. If you want to stay in serloop1() then you need to either not return from it, or arrange that the code you're returning to will call it again. Since the calls to serloop1() are controlled by the switch input, it seems that it would do what you need anyway. But regardless of whether that does what you want, you need to get rid of that recursive call to serloop1().

Just to be clear about the kill switch method, it does definitely electrically and immediately isolate any part of your control circuit from the existing bike throttle control?

I mean, when I'm zooming speedily on those nice twisty corners around where I live, I will want to be 100% sure that even if not activated in cruise mode, that it can not suddenly just jump into cruise mode. I want my mind to be focused on riding, not 'ooops, I hope line 10 of my code is ok'.

Or, if I were using such a control system as you are attempting to build, that if I were zooming down a nice straight road with a good view of the road ahead, giving me assurance that all is clear, that again, suddenly, a rockwallaby jumps out from the side of the road and to avoid such a beautiful creature I need to make quick steering adjustment and maybe some throttle adjustment as well. Be 100% certain you understand the dynamics of any situation before hitting the road, or should I say laying tracks with this gadget of yours!

I really do need to agree with PaulS and others that it appears you are starting out with understanding the fundamentals of programing and that is not a good mix with motorbikes. It seems you are determined to persist. If we don't hear from you in the coming weeks, I guess we may fear what happened.

Also, quiet possibly regardless if the cruise control was even activated or turned on, be aware that such modifications may and most probably will void any and all insurance in case of a crash, needing you to pay all medical and other costs incurred as well as possibly having a fine, depending on your local road traffic regulations.

Keep the rubber side down.

Paul

If you are going to persist in this endeavor, might I suggest some changes.

const int buttonPin = 10; // the number of the pushbutton pin
const int buttonPin2 = 8;
const int buttonPin3 = 4;
const int buttonPin4 = 2;

Rubbish. Meaningless names. How about some meaningful names, like killSwitch, brakeSwitch, onOffSwitch, setSwitch, etc., so we have some clue what you are talking about.

int potpin = 0;

throttlePin?

Servo myservo; // create servo object to control a servo

cruiseServo?

int val;

throttlePos?

     val = map(val, 0, 1083, 0, 180);

Create a new variable, controlPos, rather than overwriting the poorly named val.

This is in addition to the other comments that have been posted.

Get rid of the recursive calls to any/all functions. Nothing in a cruise control setup requires recursion.

Also, quiet possibly regardless if the cruise control was even activated or turned on, be aware that such modifications may and most probably will void any and all insurance in case of a crash, needing you to pay all medical and other costs incurred as well as possibly having a fine, depending on your local road traffic regulations.

Good point!

I have been working with arduino for 2 years. I wouldnt even imagine of putting an arduino in my gsxr 750.
Remember the amount of crashes Carlos Checa had when Ducati was tunning the traction control? Imagine the brains working into this, imagine the money and technology!

I have an Arduino in my car but it does not mess around any throttle or brakes. There are many projects you can do with an arduino and a vehicle, but throttle and brakes in a bike are most surely the worst idea for a novice like you.

Be smart and start another interesting project.

While I appreciate all of your concerns, this is 99% bench project right now. It is only for my potential use. It will only go into actual use with extensive bench testing. I have limited knowledge on Arduino programming but extensive knowledge in design and build applications. I fully understand the difference between safe and unsafe. I have built from scratch, my own single side swing arm, handle bars and most of the rest of the bike. People often praise and criticize for those endeavors also because they lack the knowledge and understanding of technical design.

I would appreciate the continued support on programming help on this project and would again emphasize that at this stage it is a bench project.

For all the comments on here, it is interesting that everyone is quick to understand that I am lacking in programming skill and is more interested in telling me what is wrong with my code in ways that are over my head and never offers code snippets as examples to allow me to move forward.


Here is my latest code.

I am trying to incorporate debounce. I have probably done this in the worst way but with everything I have added, the program still works. I will condense it down later but for now I just would like to know how to add the final part that actually initializes the button push for my application.

Reference http://arduino.cc/en/Tutorial/Debounce

  // set the LED using the state of the button:
   digitalWrite(ledPin, buttonState);
#include <Servo.h> 
Servo throttleServo; // create servo object to control a servo 

// set pin numbers:
const int throttleSetPlusThrottleUp = 10; // the number of the pushbutton pin
const int throttleSetPlusThrottleDn = 8;
const int ReturnToPot = 4;
const int ReturnToPot2 = 2;

 // constants won't change. They're used here to 
// set pin numbers:
int throttlePositionPot = 0;
int val; 

// Variables will change:
int debounceThrottleSetPlusThrottleUp;             // the current reading from the input pin
int debounceThrottleSetPlusThrottleDn;             // the current reading from the input pin
int debounceReturnToPot;             // the current reading from the input pin
int debounceReturnToPot2;             // the current reading from the input pin
int lastdebounceThrottleSetPlusThrottleUp = LOW;   // the previous reading from the input pin
int lastdebounceThrottleSetPlusThrottleDn = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot2 = LOW;   // the previous reading from the input pin


// the following variables are long's because the time, measured in miliseconds,
 // will quickly become a bigger number than can be stored in an int.
 long lastDebounceTime = 0;  // the last time the output pin was toggled
  long lastDebounceTime2 = 0;  // the last time the output pin was toggled
   long lastDebounceTime3 = 0;  // the last time the output pin was toggled
    long lastDebounceTime4 = 0;  // the last time the output pin was toggled
 long debounceDelay = 50;    // the debounce time; increase if the output flickers
  long debounceDelay2 = 50;    // the debounce time; increase if the output flickers
   long debounceDelay3 = 50;    // the debounce time; increase if the output flickers
    long debounceDelay4 = 50;    // the debounce time; increase if the output flickers
 
int servoPosition = 0; //Old val1, used to store servo position. Allows use by whole program
 

 
void setup()
{
      throttleServo.attach(12); // attaches the servo on pin 12 to the servo object 
 
     // initialize the pushbutton pin as an input:
     pinMode(throttleSetPlusThrottleUp, INPUT); 
     pinMode(throttleSetPlusThrottleDn, INPUT); 
     pinMode(ReturnToPot, INPUT); 
     pinMode(ReturnToPot2, INPUT);
}
 
void loop()
{ 
     val = analogRead(throttlePositionPot); //takes reading from pot current position 
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
 
     if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
 
     if (digitalRead(throttleSetPlusThrottleDn) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
}
 
 
/**
 * If button control is enabled, loop and handle control buttons
 * If exit buttons (To return to pot control) are pressed, exit loop and return
 * to pot control
 */
void serloop1()
{
     servoPosition = throttleServo.read(); //reads current servo location
     
       // read the state of the switch into a local variable:
     int reading = digitalRead(throttleSetPlusThrottleUp);
     int reading2 = digitalRead(throttleSetPlusThrottleDn);
     int reading3 = digitalRead(ReturnToPot);
     int reading4 = digitalRead(ReturnToPot2);
     
       // If the switch changed, due to noise or pressing:
     if (reading != lastdebounceThrottleSetPlusThrottleUp) 
     // reset the debouncing timer
     lastdebounceThrottleSetPlusThrottleUp = millis();
          
       // If the switch changed, due to noise or pressing:
     if (reading2 != lastdebounceThrottleSetPlusThrottleDn) 
     // reset the debouncing timer
     lastDebounceTime2 = millis();
          
       // If the switch changed, due to noise or pressing:
     if (reading3 != lastdebounceReturnToPot) 
     // reset the debouncing timer
     lastDebounceTime3 = millis();
               
       // If the switch changed, due to noise or pressing:
     if (reading4 != lastdebounceReturnToPot2) 
     // reset the debouncing timer
     lastDebounceTime4 = millis();
     
       if ((millis() - lastDebounceTime) > debounceDelay) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleUp = reading;
   }
     if ((millis() - lastDebounceTime2) > debounceDelay2) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleDn = reading2;
   }
     if ((millis() - lastDebounceTime3) > debounceDelay3) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot = reading3;
   }
     if ((millis() - lastDebounceTime4) > debounceDelay4) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot2 = reading4;
   }
   
   
 
     int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0
 
     while(btnControlEnabled == 1)
     {
       if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
       {
          throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       //If first button not pressed, check the next...
       else if (digitalRead(throttleSetPlusThrottleDn) == HIGH) 
       {
          throttleServo.write(servoPosition - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       else if (digitalRead(ReturnToPot) == HIGH) 
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       else if (digitalRead(ReturnToPot2) == HIGH) 
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       //If nothing pressed...
       else
       {
         //...do nothing at all, go back to start of loop
       }
     }
     
}

Sorr for the multiple posts here. I changed the debounce instructions to the loop() instead of the serloop1() and added the

  // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastButtonState = reading;

into the code. Just need to figure out how to translate and use

  // set the LED using the state of the button:
   digitalWrite(ledPin, buttonState);

for my buttons use.

#include <Servo.h> 
Servo throttleServo; // create servo object to control a servo 

// set pin numbers:
const int throttleSetPlusThrottleUp = 10; // the number of the pushbutton pin
const int throttleSetPlusThrottleDn = 8;
const int ReturnToPot = 4;
const int ReturnToPot2 = 2;

 // constants won't change. They're used here to 
// set pin numbers:
int throttlePositionPot = 0;
int val; 

// Variables will change:
int debounceThrottleSetPlusThrottleUp;             // the current reading from the input pin
int debounceThrottleSetPlusThrottleDn;             // the current reading from the input pin
int debounceReturnToPot;             // the current reading from the input pin
int debounceReturnToPot2;             // the current reading from the input pin
int lastdebounceThrottleSetPlusThrottleUp = LOW;   // the previous reading from the input pin
int lastdebounceThrottleSetPlusThrottleDn = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot = LOW;   // the previous reading from the input pin
int lastdebounceReturnToPot2 = LOW;   // the previous reading from the input pin


// the following variables are long's because the time, measured in miliseconds,
 // will quickly become a bigger number than can be stored in an int.
 long lastDebounceTime = 0;  // the last time the output pin was toggled
  long lastDebounceTime2 = 0;  // the last time the output pin was toggled
   long lastDebounceTime3 = 0;  // the last time the output pin was toggled
    long lastDebounceTime4 = 0;  // the last time the output pin was toggled
 long debounceDelay = 50;    // the debounce time; increase if the output flickers
  long debounceDelay2 = 50;    // the debounce time; increase if the output flickers
   long debounceDelay3 = 50;    // the debounce time; increase if the output flickers
    long debounceDelay4 = 50;    // the debounce time; increase if the output flickers
 
int servoPosition = 0; //Old val1, used to store servo position. Allows use by whole program
 

 
void setup()
{
      throttleServo.attach(12); // attaches the servo on pin 12 to the servo object 
 
     // initialize the pushbutton pin as an input:
     pinMode(throttleSetPlusThrottleUp, INPUT); 
     pinMode(throttleSetPlusThrottleDn, INPUT); 
     pinMode(ReturnToPot, INPUT); 
     pinMode(ReturnToPot2, INPUT);
}
 
void loop()
{ 
  
         // read the state of the switch into a local variable:
     int reading = digitalRead(throttleSetPlusThrottleUp);
     int reading2 = digitalRead(throttleSetPlusThrottleDn);
     int reading3 = digitalRead(ReturnToPot);
     int reading4 = digitalRead(ReturnToPot2);
     
       // If the switch changed, due to noise or pressing:
     if (reading != lastdebounceThrottleSetPlusThrottleUp) 
     // reset the debouncing timer
     lastdebounceThrottleSetPlusThrottleUp = millis();
          
       // If the switch changed, due to noise or pressing:
     if (reading2 != lastdebounceThrottleSetPlusThrottleDn) 
     // reset the debouncing timer
     lastDebounceTime2 = millis();
          
       // If the switch changed, due to noise or pressing:
     if (reading3 != lastdebounceReturnToPot) 
     // reset the debouncing timer
     lastDebounceTime3 = millis();
               
       // If the switch changed, due to noise or pressing:
     if (reading4 != lastdebounceReturnToPot2) 
     // reset the debouncing timer
     lastDebounceTime4 = millis();
     
       if ((millis() - lastDebounceTime) > debounceDelay) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleUp = reading;
   }
     if ((millis() - lastDebounceTime2) > debounceDelay2) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceThrottleSetPlusThrottleDn = reading2;
   }
     if ((millis() - lastDebounceTime3) > debounceDelay3) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot = reading3;
   }
     if ((millis() - lastDebounceTime4) > debounceDelay4) {
     // whatever the reading is at, it's been there for longer
     // than the debounce delay, so take it as the actual current state:
     debounceReturnToPot2 = reading4;
   }
   
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceThrottleSetPlusThrottleUp = reading;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceThrottleSetPlusThrottleDn = reading2;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceReturnToPot = reading3;
     // save the reading.  Next time through the loop,
   // it'll be the lastButtonState:
   lastdebounceReturnToPot2 = reading4;
   
   
     val = analogRead(throttlePositionPot); //takes reading from pot current position 
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
 
     if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
 
     if (digitalRead(throttleSetPlusThrottleDn) == HIGH)
     {
          serloop1(); //Enters button control loop
     }
}
 
 
/**
 * If button control is enabled, loop and handle control buttons
 * If exit buttons (To return to pot control) are pressed, exit loop and return
 * to pot control
 */
void serloop1()
{
     servoPosition = throttleServo.read(); //reads current servo location   
 
     int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0
 
     while(btnControlEnabled == 1)
     {
       if (digitalRead(throttleSetPlusThrottleUp) == HIGH)
       {
          throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       //If first button not pressed, check the next...
       else if (digitalRead(throttleSetPlusThrottleDn) == HIGH) 
       {
          throttleServo.write(servoPosition - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
       }
       else if (digitalRead(ReturnToPot) == HIGH) 
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       else if (digitalRead(ReturnToPot2) == HIGH) 
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       //If nothing pressed...
       else
       {
         //...do nothing at all, go back to start of loop
       }
     }
     
}
         // read the state of the switch into a local variable:
     int reading = digitalRead(throttleSetPlusThrottleUp);
     int reading2 = digitalRead(throttleSetPlusThrottleDn);
     int reading3 = digitalRead(ReturnToPot);
     int reading4 = digitalRead(ReturnToPot2);

You now have some good names for some of the pins. It's a shame that the same can not be said for the states of those pins.

What do ReturnToPot and ReturnToPot2 mean?

Personally, I think that if find yourself in a position where some of the variables need numbers, all the related ones need numbers (ReturnToPot1 and reading1).

     if (reading != lastdebounceThrottleSetPlusThrottleUp)

I also think that variables being compared like this should have names that indicate that they go together. I can see that currDebounceThrottleSetPlusThrottleUp and lastDebounceThrottleSetPlusThrottleUp go together. I can't see that reading and lastdebounceThrottleSetPlusThrottleUp go together.

Using camel case notation requires capital letters on ALL words, except the first one, not capital letters on some of the words.

Debounce and state change detection are two separate things. It looks, from the names, that you are trying to mix them.

Time works seamlessly with unsigned longs, no problem with roll over.
Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.

Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.

Not too many people can ride for 24 plus days at a time, without gas or other stops, so this isn't likely to be a real problem.

Edit: fixed typo.

PaulS:

Time is a fudge-up with longs but you got almost 25 days find that bug, and if you kludge your way around it then it will never get you except that you won't get why unsigned's are right for handling time.

No too many people can ride for 24 plus days at a time, without gas or other stops, so this isn't likely to be a real problem.

May be someone very excited about the cruise controller may ride and sleep both..just like a crazy little boy with his new toy :grin: :grin:

msumrell ...

Since timing your wheel rotation seems to be a major problem, why not start with that problem and make a simple fully-operational speedometer program with your reed switch and your board. That way you can SAFELY create a sketch that will help with the overall program (the wisdom of which is not mine to judge). Once you get that working and comprehensively tested with ZERO glitches or anomalies, you can think about integrating it into other functions. This effort will help you to understand the complexities of interrupt driven timing and debouncing contact closures/opens. For example, you may not have thought about it, but a bumpy road can do VERY weird things to contact state detection. Hey, then there's mechanical resonance if you're using a reed switch!

Opinions are like noses ... everybody's got one. Break the task into primitive pieces. Fully understand the mechanics and process for each piece that you work on.

Blessings in abundance, all the best, & ENJOY! ... and STAY SAFE
Art in Carlisle, PA USA

I have completed an initial program that works well as far as throttle control from the pot and setting speed with two buttons that bump up or down the servo by 2* and two others that release the first two buttons back to the throttle pot, clutch and front break levers.

I have now also written code in to read the speed hall sensor and bump the servo by 2 degrees based on the loop comparison. I got the code from youTube for an LCD RPM read out of a hall sensor reading rpm of a drill motor. I removed all the LCD refference and incorporated. I have not made any attempt to tie it into the bikes hall sensor as of yet.

I would like to know if the code looks like it makes any sense as I really do not fully understand the hall read/calculation part of the program.

#include <Bounce.h>
#include <Servo.h> 

   Servo throttleServo; // create servo object to control a servo 
 
   int throttleServoPotpin = 0;
   int servoPosition = 0; //Old val1, used to store servo position. Allows use by whole program
   int val; 
 

 
   // set pin numbers:
   const int throttlePosSet_Up = 10; // the number of the pushbutton pin
   const int throttlePosSet_Dn = 8;
   const int returnThrottleToPot1 = 4;
   const int returnThrottleToPot2 = 2;
   // read the hall effect sensor on pin 6 
   const int rpmHallSensor=6;
 
 
   long debounceDelay = 50;    // the debounce time; increase if the output flickers
 
   //Debounce objects
   // Instantiate a Bounce object with a 5 millisecond debounce time
   Bounce bouncer1 = Bounce(throttlePosSet_Up, debounceDelay);
   Bounce bouncer2 = Bounce(throttlePosSet_Dn, debounceDelay);
   Bounce bouncer3 = Bounce(returnThrottleToPot1, debounceDelay);
   Bounce bouncer4 = Bounce(returnThrottleToPot2, debounceDelay);

   const unsigned long sampleTime=100;
   const int maxRPM = 10200;
   int currentRPM = 0;
   int kount2rpm = 0; 
      

void setup() 
{
     throttleServo.attach(12); // attaches the servo on pin 12 to the servo object 
     // initialize the pushbutton pin as an input:
     pinMode(throttlePosSet_Up, INPUT); 
     pinMode(throttlePosSet_Dn, INPUT); 
     pinMode(returnThrottleToPot1, INPUT); 
     pinMode(returnThrottleToPot2, INPUT);
     // initialize input for pick up of motorcycle speed hall sensor
     pinMode(rpmHallSensor,INPUT);
 }
 
void loop()
{ 
     val = analogRead(throttleServoPotpin); //takes reading from pot current position 
     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it
 
     //Update debounce tool
     bouncer1.update();
     bouncer2.update();
 
     //Do not need to update these here are they are not used
     //bouncer3.update();
     //bouncer4.update();
 
 
     if (bouncer1.read() == HIGH)
     {
          serloop1(); //Enters button control loop
     }
 
     if (bouncer2.read() == HIGH)
     {
          serloop1(); //Enters button control loop
     }
} 
/**
 * If button control is enabled, loop and handle control buttons
 * If exit buttons (To return to pot control) are pressed, exit loop and return
 * to pot control
 */ 
void serloop1()
{
     servoPosition = throttleServo.read(); //reads current servo location 
     int btnControlEnabled = 1; //If button control is enabled this equals 1, else it equals 0 
     while(btnControlEnabled == 1)
     {
       //Update all debounce tools
       bouncer1.update();
       bouncer2.update();
       bouncer3.update();
       bouncer4.update();
 
       if (bouncer1.read() == HIGH)
       {
          throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
          
          digitalRead(rpmHallSensor);          
               
          currentRPM = digitalRead(rpmHallSensor);
          if (kount2rpm != currentRPM);
         
           serloop2();
         

             
       }
              

       //If first button not pressed, check the next...
       else if (bouncer2.read() == HIGH)
       {
          throttleServo.write(servoPosition - 2); //ADDS 2 degrees to servo position for decreased motor rpm
          servoPosition = throttleServo.read(); //Read new servo position
          delay(100); //allows time for switch ro reset
          
          digitalRead(rpmHallSensor);          
               
          currentRPM = digitalRead(rpmHallSensor);
          if (kount2rpm != currentRPM); 
         
           serloop3();
         
          }          

       
       
       else if (bouncer3.read() == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       else if (bouncer4.read() == HIGH)
       {
          btnControlEnabled = 0; //Set loop exit condition
       }
       //If nothing pressed...
       else
       {
         //...do nothing at all, go back to start of loop
       }
     }

      int rpm=getRPM(); 
      }      
      int getRPM()
      { 
      // sample for sampleTime in millisecs 
      int kount=0;
 
      boolean kflag=LOW;
 
      unsigned long currentTime=0;
 
      unsigned long startTime=millis();
 
      while (currentTime<=sampleTime) 
      { 
      if (digitalRead(rpmHallSensor)==HIGH) 
      { 
       kflag=HIGH; 
      } 
      if (digitalRead(rpmHallSensor)==LOW && kflag==HIGH) 
      { 
      kount++; 
      kflag=LOW; 
      } 
      currentTime=millis()-startTime; 
      } 
      int kount2rpm = int(60000./float(sampleTime))*kount; 
      return kount2rpm;
      serloop1();
}     
void serloop2()
{
      if (kount2rpm < currentRPM);      
      serloop4();
}    
void serloop3()
{      
      if (kount2rpm > currentRPM);
      serloop5();
}
void serloop4()
{
      servoPosition = throttleServo.read(); //reads current servo location
      throttleServo.write(servoPosition + 2); //SUBTRACT 2 degrees to servo position for increased motor rpm       
}
void serloop5()
{
      servoPosition = throttleServo.read(); //reads current servo location
      throttleServo.write(servoPosition - 2); //SUBTRACT 2 degrees to servo position for increased motor rpm       
}
     val = analogRead(throttleServoPotpin); //takes reading from pot current position

Why is Servo in this name? It's not the Servo pot that you are reading. Pin should be capitalized.

     val = map(val, 0, 1083, 0, 180); //maps pot inputs to servo output
     throttleServo.write(val); //writes current position to servo to move it

The analogRead() range is 0 to 1023, not 0 to 1083.

There does not to be any test for whether the servo should be controlling the speed.

Function names should reflect what they do. serloop1(), serloop2(), serloop3(), etc. do not even come close.

      return kount2rpm;
      serloop1();
}

If it weren't for the return statement stopping serloop1() from calling serloop1() again, this would be another instance of recursion. You REALLY need to get out of the habit of doing that.

I gave up reading at that point. The horrid indenting makes it too hard to see the structure of the code. Before posting code here, please use Tools + Auto Format to correct the indenting. You'll find that it makes your coding easier, too.

This code is not doing anything useful:

if (kount2rpm != currentRPM);

As a general comment, your function names 'serloop1' etc are utterly useless and the structure of the code does not seem remotely sensible.

I would expect to find a state machine at the high level dealing with the logic to engage and disengage cruise control. In the 'engaged' mode I'd expect to find code managing the target speed in response to user commands to increment/decrement it, code to determine the actual speed and take action to make the actual speed move towards the target speed. The function name 'getRPM' at least indicates what it does, although it's a blocking function working on a very short timescale and that doesn't seem like a very good approach - I think it would work better to use an asynchronous approach to count revolutions in a period and then calculate the 'current speed' at the end of each period. Blink without delay shows you how to carry out processing at regular intervals, and I'd use that to trigger the calculation at the end of each period. This has the disadvantage that the RPM Hall sensor would only be polled once per loop() rather than being polled intenseively in getROM(). Can you actually afford to poll the RPM Hall sensor in the background? If not, I'd consider counting pulses using an interrupt. Given that the result will be used to drive a mechanical actuator I assume you want to avoid jitter, so I'd suggest applying some smoothing to the calculated speed - an exponential average would probably work well (e.g. smoothed speed equals 90% of previous smoothed speed plus 10% of measured speed).

I would like to reference the following in my attempt to get this code figured out.
"Jaycar Water Flow Gauge | Freetronics"

I do not know how to determine calibration number for my application and if this looks feasible for calculating rpm from the bike hall sensor (not motor rpm but just rather a constant), I still have to figure out how to incorporate it back into my main program.

I took their code,

#include <LiquidCrystal.h>
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Specify the pins for the two counter reset buttons and indicator LED
byte resetButtonA = 11;
byte resetButtonB = 12;
byte statusLed    = 13;

byte sensorInterrupt = 0;  // 0 = pin 2; 1 = pin 3
byte sensorPin       = 2;

// The hall-effect flow sensor outputs approximately 4.5 pulses per second per
// litre/minute of flow.
float calibrationFactor = 4.5;

volatile byte pulseCount;  

float flowRate;
unsigned int flowMilliLitres;
unsigned long totalMilliLitresA;
unsigned long totalMilliLitresB;

unsigned long oldTime;

void setup()
{
  lcd.begin(16, 2);
  lcd.setCursor(0, 0);
  lcd.print("                ");
  lcd.setCursor(0, 1);
  lcd.print("                ");
  
  // Initialize a serial connection for reporting values to the host
  Serial.begin(38400);
   
  // Set up the status LED line as an output
  pinMode(statusLed, OUTPUT);
  digitalWrite(statusLed, HIGH);  // We have an active-low LED attached
  
  // Set up the pair of counter reset buttons and activate internal pull-up resistors
  pinMode(resetButtonA, INPUT);
  digitalWrite(resetButtonA, HIGH);
  pinMode(resetButtonB, INPUT);
  digitalWrite(resetButtonB, HIGH);
  
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  flowRate          = 0.0;
  flowMilliLitres   = 0;
  totalMilliLitresA = 0;
  totalMilliLitresB = 0;
  oldTime           = 0;

  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
}

/**
 * Main program loop
 */
void loop()
{
  if(digitalRead(resetButtonA) == LOW)
  {
    totalMilliLitresA = 0;
    lcd.setCursor(0, 1);
    lcd.print("0L      ");
  }
  if(digitalRead(resetButtonB) == LOW)
  {
    totalMilliLitresB = 0;
    lcd.setCursor(8, 1);
    lcd.print("0L      ");
  }
  
  if( (digitalRead(resetButtonA) == LOW) || (digitalRead(resetButtonB) == LOW) )
  {
    digitalWrite(statusLed, LOW);
  } else {
    digitalWrite(statusLed, HIGH);
  }
  
  if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);
    //lcd.setCursor(15, 0);
    //lcd.print("*");
    
    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    flowRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;
    
    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();
    
    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    flowMilliLitres = (flowRate / 60) * 1000;
    
    // Add the millilitres passed in this second to the cumulative total
    totalMilliLitresA += flowMilliLitres;
    totalMilliLitresB += flowMilliLitres;
  
    // During testing it can be useful to output the literal pulse count value so you
    // can compare that and the calculated flow rate against the data sheets for the
    // flow sensor. Uncomment the following two lines to display the count value.
    //Serial.print(pulseCount, DEC);
    //Serial.print("  ");
    
    // Write the calculated value to the serial port. Because we want to output a
    // floating point value and print() can't handle floats we have to do some trickery
    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;
    
    // Print the flow rate for this second in litres / minute
    Serial.print(int(flowRate));  // Print the integer part of the variable
    Serial.print(".");             // Print the decimal point
    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (flowRate - int(flowRate)) * 10;
    Serial.print(frac, DEC) ;      // Print the fractional part of the variable

    // Print the number of litres flowed in this second
    Serial.print(" ");             // Output separator
    Serial.print(flowMilliLitres);

    // Print the cumulative total of litres flowed since starting
    Serial.print(" ");             // Output separator
    Serial.print(totalMilliLitresA);
    Serial.print(" ");             // Output separator
    Serial.println(totalMilliLitresB);
    
    lcd.setCursor(0, 0);
    lcd.print("                ");
    lcd.setCursor(0, 0);
    lcd.print("Flow: ");
    if(int(flowRate) < 10)
    {
      lcd.print(" ");
    }
    lcd.print((int)flowRate);   // Print the integer part of the variable
    lcd.print('.');             // Print the decimal point
    lcd.print(frac, DEC) ;      // Print the fractional part of the variable
    lcd.print(" L");
    lcd.print("/min");
    
    lcd.setCursor(0, 1);
    lcd.print(int(totalMilliLitresA / 1000));
    lcd.print("L");
    lcd.setCursor(8, 1);
    lcd.print(int(totalMilliLitresB / 1000));
    lcd.print("L");

    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;
    
    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}

/**
 * Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
 * handlers should be kept as small as possible so they return quickly.
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

and turned it into this.

// HOW WOULD I DETERMINE MY CALIBRATION FACTOR?
float calibrationFactor = 4.5;

volatile byte pulseCount;
float rpmRate;

unsigned int rpm;

byte sensorInterrupt = 0;  // 0 = pin 2; 1 = pin 3
byte sensorPin       = 2;

unsigned long oldTime;


void setup()
{
  Serial.begin(9600);
  pinMode(sensorPin, INPUT);
  digitalWrite(sensorPin, HIGH);

  pulseCount        = 0;
  rpmRate          = 0.0;
  rpm   = 0;
  oldTime           = 0;


  // The Hall-effect sensor is connected to pin 2 which uses interrupt 0.
  // Configured to trigger on a FALLING state change (transition from HIGH
  // state to LOW state)
  attachInterrupt(sensorInterrupt, pulseCounter, FALLING);

}


void loop()
{
  

  if((millis() - oldTime) > 1000)    // Only process counters once per second
  { 
    // Disable the interrupt while calculating flow rate and sending the value to
    // the host
    detachInterrupt(sensorInterrupt);


    // Because this loop may not complete in exactly 1 second intervals we calculate
    // the number of milliseconds that have passed since the last execution and use
    // that to scale the output. We also apply the calibrationFactor to scale the output
    // based on the number of pulses per second per units of measure (litres/minute in
    // this case) coming from the sensor.
    rpmRate = ((1000.0 / (millis() - oldTime)) * pulseCount) / calibrationFactor;

    // Note the time this processing pass was executed. Note that because we've
    // disabled interrupts the millis() function won't actually be incrementing right
    // at this point, but it will still return the value it was set to just before
    // interrupts went away.
    oldTime = millis();

    // Divide the flow rate in litres/minute by 60 to determine how many litres have
    // passed through the sensor in this 1 second interval, then multiply by 1000 to
    // convert to millilitres.
    rpm = (rpmRate / 60);

    // to output the whole number part, then a decimal point, then the fractional part.
    unsigned int frac;


    // Determine the fractional part. The 10 multiplier gives us 1 decimal place.
    frac = (rpmRate - int(rpmRate)) * 10;


    // Reset the pulse counter so we can start incrementing again
    pulseCount = 0;

    // Enable the interrupt again now that we've finished sending output
    attachInterrupt(sensorInterrupt, pulseCounter, FALLING);
  }
}


/**
 * Invoked by interrupt0 once per rotation of the hall-effect sensor. Interrupt
 * handlers should be kept as small as possible so they return quickly.
 */
void pulseCounter()
{
  // Increment the pulse counter
  pulseCount++;
}

Giving that a quick once over it appears that they count pulses for a period of time then do the calculations. I don't see that approach working for cruise control. I think you want to generate a signal with the hall sensor and track it's frequency. Basically the times between pulses. It's this frequency that you'll ultimately have to control via the servo and throttle setup. It will have to try to match the frequency it was reading when you set it.

How will you read the brake to disconnect things? You mention the front lever. I'd use the brake light circuit and a relay. Tap the wire and put it through the coil to ground. When you hit the brakes, front or rear, the light goes on, the relay closes, a pin goes low and an interrupt can disconnect the servo. This has to be almost instant. Your code above disables interrupts. I don't see that as feasible.

Just some ideas. Please just do this as an intellectual exercise. I don't agree with cruise on bikes period.

Jimmy60:
I don't see that approach working for cruise control.

I don't see why not. If anything, a controller that took a second or so to respond would be less likely to keep twitching the throttle around in response to timing jitter, and would probably give you a smoother and more consistent control.

With the time/distance (appx 7 ft) between data points, he's going to need code just to keep it from constantly over-adjusting throttle. His response will always lag worse at lower speed.