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

I have built a control box using a mini ATmega 328, servo, potentiometer and 4 button inputs. Currently it works for what i have done. Throttle turns the pot wich moves the servo to pull/push the throttle cables. Two buttons on the handle bars sets the current throttle position and then if pushed, pulls or pushes the servo in 2* incriments. If you pull the front brake or clutch levers it releases the servo control back to the pot. It all works well but now I want to add a reed switch to the front wheel to pick up revolution time of the wheel and feed the change in speed back to the Arduino to move the servo to adjust for change in wheel speed to create a true speed control. I am really condused on this part. i have read a lot on the timers and different posts but dont know how to do this part. What I am thinking is something like if button one is pushed (lockes out the pot and increases 2* servo position) take reading of reed, if rpm slows, increase servo position, if rpm speeds up decrease servo position and do this action every 1/2 second. here is my current code which works for the first part, simple throttle control, button one and two set position and decrease/increase throttle position and button 4 and 5 to release button 1 and 2 back to pot control.

(Button 3 is wired to pin 6 and available on the bike to wire in the reed switch.)

#include <Servo.h>
Servo myservo;  // create servo object to control a servo
int potpin = 0; //potentiometer pin location
int val;       //name given for pot input value
int button1 = 10;
int button2 = 8;
int button3 = 6;
int button4 = 4;
int button5 = 2;

void setup() { //assigns inputs and outputs
    pinMode(button1, INPUT); //button 1 input assignment
    pinMode(button2, INPUT); //button 2 input assignment
    pinMode(button3, INPUT); //button 3 input assignment
    pinMode(button4, INPUT); //button 3 input assignment
    pinMode(button5, INPUT); //button 3 input assignment
    myservo.attach(12);
}


void loop(){
  val = analogRead(potpin);  //takes reading from pot current position          
  val = map(val, 0, 1083, 0, 180);   //maps pot inputs to servo output, cut off 0-9 to eliminate gitter  
  myservo.write(val);      //writes current position to servo to move it
  delay(150); //allows time for switch ro reset  
   if (digitalRead(button1) == HIGH) 
   SerLoop1(); //sends command to SerLoop1 which is normal throttle control
   if (digitalRead(button2) == HIGH) 
   SerLoop1(); //sends command to SerLoop1 which is normal throttle control
   else loop(); //returns to loop to run again
}
void SerLoop1(){
    myservo.attach(12); //attaches servo to pin 10
    int val1 = myservo.read(); //reads current servo location
    if (digitalRead(button1) == HIGH)
    myservo.write(val1 + 2); //SUBTRACT 2 degrees to servo position for increased throttle
    delay(100); //allows time for switch ro reset
    if (digitalRead(button2) == HIGH) 
    myservo.write(val1 - 2); //ADDS 2 degrees to servo position for decreased throttle
    delay(100); //allows time for switch ro reset
    if (digitalRead(button5) == HIGH) 
    loop(); //returns to normal cruise position
        if (digitalRead(button4) == HIGH) 
    loop(); //returns to normal cruise position
    else SerLoop1(); //returns to SerLoop2 to run again

I am really condused on this part.

Then you should stop. You do not have the skills or expertise to be building a cruise control.

  delay(150); //allows time for switch ro reset

That is more than enough time to get yourself killed. During that time, you can not do anything about shutting off the cruise control if things go to shit.

Stop right now. This project is well beyond your capabilities.

   else loop(); //returns to loop to run again

Never call loop().

Really. Stop!

Do you have a scheme which enables the rider to shut the power off regardless of anything the Arduino does to increase power?

Perhaps we could avoid the sarcasm.

Yes there are safe guards in place, thank you. I have test rode it and it works without flaw. The only failure it can have is to lose power and throttle down. If anyone can help with adding the reed switch into the programming that would be appreciated.

Are you only getting 1 pulse per wheel turn? That can be a lot of lag between change in speed and data capture.

Could you try rolling a thin small roller that rolls on the bike wheel and watch -that- turn? Then you know of change within the circumference of the little wheel of when the change began.

If you can put a bar magnet across a wheel shaft end center and mount a Hall sensor right over that you can use analog read to know the angle of the wheel maybe 5 times a millisecond.

Do you know how many meters or feet 1 turn of your motorcycle wheel covers? Or how much the speed of that wheel can change in that distance?

There are problems you're going to have you don't even know yet. You really used delay(150)?
Take all your "good pictures" now so you can look back on those days later.

I have test rode it and it works without flaw.

Have you fixed those recursive calls to loop()? If not fundamentally flawed and works without flaw are not compatible.

Consider buying another arduino and building a motorcycle simulator for your project. That way you can test your code without having to put yourself at risk. An SD card to record telemetry data would be handy for debugging too.

But seriously, leave this and build up your expertise with some safer projects first.

msumrell:
The only failure it can have is to lose power and throttle down.

I don't think you understood the point of my question.

Assume that the Arduino does anything that the hardware is capable of doing - at the worst possible time. Assume that any wire could fall out, any electronic component could fail, any piece of code could do something that you never intended or expected. So, whatever actuator you're using could be commanded to do something completely wrong, in the worst way, at the worst time.

Given that situation, does the rider have a practical and easy means to override the cruise control and kill the power? (If your bike has a clutch, that might be your solution - but not all bikes do.)

Peter, as I already replied, yes there are safety overrides that kill the arduino which alows the return spring to pull the throttle closed.

I have several arduinos and am bench testing as I go, or should I say kitchen table testing.

As far as the recursive calls to loop()?, I think this was how I was able to get it to work but I will remove them and see. thanks,

Let me ask my question differently. How would I write the code to sense the reed switch close, count the millis before it closes again (one revolution)? If I need to sense it more than once I will address. I am just asking for help with the code.

i have this piece of code that maybe you could tinker with, what it does is if you press a switch that is connected to pin 2 on the arduino board, like so

pin2------|/|-----Ground

the code will measure how long the switch was press and will light up the on board led (pin 13) the same amount of time that the switch was press after the switch was release

uint8_t Switch = 2;
uint8_t Led =13;

boolean LedState =LOW;
int SwitchState =0;
int SwitchDebounce;
int LastSwitchState=HIGH;
int LastSwitchDebounce=LOW;

unsigned long LastDebounceTime = 0;
unsigned long DebounceDelay = 50;
unsigned long TimeRelease=0;
unsigned long TimePress=0;

void setup()
{
  pinMode(Switch,INPUT);
  digitalWrite(Switch,HIGH);
  pinMode(Led,OUTPUT);
  digitalWrite(Led,LOW);
}

void loop() 
{
  int CurrentSwitch = digitalRead(Switch);
  if (CurrentSwitch != LastSwitchDebounce)
  {
    LastDebounceTime = millis();
  } 
  if ((millis() - LastDebounceTime) > DebounceDelay) 
  {
    SwitchState = digitalRead(Switch);
    if (SwitchState != LastSwitchState) 
    {
      if(SwitchState)
      {
        TimeRelease=millis();
        digitalWrite(Led,HIGH);
      }
      if (!SwitchState)
      {
        TimePress=millis();
      }
      LastSwitchState=SwitchState;
    }
  }
  if ((millis()-TimeRelease)>=(TimeRelease-TimePress))
  {
    digitalWrite(Led,LOW);
  }
  LastSwitchDebounce = CurrentSwitch;
}

I am just asking for help with the code.

Have you addressed the recursive calls to loop(), yet?

Have you removed the delay()s yet?

If not, then adding more code is premature.

You do not want to have any calls to loop() in your code, ever, under any conceivable circumstances. Is that clear enough? :slight_smile:

msumrell:
Let me ask my question differently. How would I write the code to sense the reed switch close, count the millis before it closes again (one revolution)? If I need to sense it more than once I will address. I am just asking for help with the code.

Use an interrupt to set a flag. Next time loop() runs if that flag is set, check millis() and do the calcs and display/control.

BUT -- you are missing on what only reading 1 time per wheel turn does to your automatic actions. You want to know way more often. That's why I suggested having a small roller with
magnet in contact with the tire and measure the turns that makes. You can know change of speed in 1 roller circumference, far sooner than 1 wheel circumference, less control lag.

I am trying to remove the call to loop() but not having much luck.

I have tried to remove the loop() but the program does not work then.

I did remove one in void loop(), else loop(); and it works fine. this makes the void loop() clean of calls to loop() and delays.

I dont know how to fix the serloop(). If I remove the last else serloop1(); //returns to SerLoop2 to run again
then the buttons to move the servo two degrees up or down do not work. Also I need it to be able to go back to the original void loop thus the

    if (digitalRead(buttonPin3) == HIGH) 
    loop(); //returns to normal cruise position
    if (digitalRead(buttonPin4) == HIGH) 
    loop(); //returns to normal cruise position

Here is what I currently have that still works as I need it to.

#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 9 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 output, cut off 0-9 to eliminate gitter  
  myservo.write(val);      //writes current position to servo to move it

   if (digitalRead(buttonPin) == HIGH) 
   serloop1(); //sends command to SerLoop1 which is normal throttle control
   if (digitalRead(buttonPin2) == HIGH) 
   serloop1(); //sends command to SerLoop1 which is normal throttle control

 }
 
void serloop1(){
    myservo.attach(12); //attaches servo to pin 10
    int val1 = myservo.read(); //reads current servo location
    if (digitalRead(buttonPin) == HIGH)
    myservo.write(val1 + 2); //SUBTRACT 2 degrees to servo position for increased throttle
    delay(100); //allows time for switch ro reset
    if (digitalRead(buttonPin2) == HIGH) 
    myservo.write(val1 - 2); //ADDS 2 degrees to servo position for decreased throttle
    delay(100); //allows time for switch ro reset
    if (digitalRead(buttonPin3) == HIGH) 
    loop(); //returns to normal cruise position
    if (digitalRead(buttonPin4) == HIGH) 
    loop(); //returns to normal cruise position

    else serloop1(); //returns to SerLoop2 to run again
  1. When loop() finishes, loop() is run by design.

  2. The faster you can run loop() the more responsive your program can be.

  3. Instead of writing code to do one major task at a time, divide the work into small steps that fit in loop() with steps from other tasks.
    Example: -only- [watching serial to read and buffer text until that is done] code vs catching serial available to buffer 1 char at a time as they arrive +and+ allowing other tasks to run and then loop() to end, all quickly if possible. That's why to divide any task to small pieces, so they run quick. You can run the next part in a later execution of loop() when conditions ( if()'s ) are right when everything's ready.

  4. Every time through loop() is later than the last time, real time code, and loop() has to contain code for what to do every time.

PeterH:
You do not want to have any calls to loop() in your code, ever, under any conceivable circumstances. Is that clear enough? :slight_smile:

Apparently it wasn't clear enough. If your code calls loop(), it is wrong. How many ways do we need to say this?

PaulS:
Really. Stop!

Please dont kill innovative ideas....

Khalid:

PaulS:
Really. Stop!

Please dont kill innovative ideas....

Nothing innovative about a cruise control. Standard equipment on many motorcycles.

Unless you're referring to the OP's code, it isn't so much innovative as icky and broken. I wouldn't trust it with my life.

PeterH:

PeterH:
You do not want to have any calls to loop() in your code, ever, under any conceivable circumstances. Is that clear enough? :slight_smile:

Apparently it wasn't clear enough. If your code calls loop(), it is wrong. How many ways do we need to say this?

+1

It's a bad idea to re-enter code on memory-challenged hardware. The stack can grow real fast.

As used in the IDE, setup() and loop() provides a frame for real time code able to handle multiple tasks usually under-1-ms-responsive on simple, limited microcontrollers.
You trim your code and use the right tricks, you can read-and-do a subtask 20+ times per millisecond. And just what subtask(s) to perform each time through loop() can vary completely and independently or by pattern to suit your app.
A state machine in loop() can reduce a whole lot of control code structure to simple state value changes instead. It cuts complexities and dependencies that make debugging headaches. It can exist along with other state machines, timers, and events (RX and sensors) in the Arduino setup() and loop() system.

Not knowing what the bike is I can't be sure, but if something brown DID hit the fan, couldn't you just click off the kill switch and roll yourself to a gentle stop?