You are here

Solved: Cruise Control: Push to Activate; Cancel on BRK or Throttle Touched

11 posts / 0 new
Last post
vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431
Solved: Cruise Control: Push to Activate; Cancel on BRK or Throttle Touched

Update 10/25/2023:

3+ years after posting this, I still see people asking about it without a solution in sight, so I bit the bullet and spent a a few hours getting this to work, so I am sure it will be useful for many people that inquired over the years as well.

The problem: Described below in the original post but, in essence, you have to keep the cruise button pressed to keep the cruise mode activated. Keeping the cruise button pressed on a skateboard or even a stand up scooter is ok, and likely safer (it gets released quickly in an emergency), but it get tiring quickly on a larger vehicle. You don't hold the cruise button in your car or a motorcycle to enjoy cruising. A toggle switch would accomplish hands free cruising without the code change but would be a huge downgrade in safety as it requires an action from the driver to disengage.  

How we want it to work:

 Push button is how most cruise control systems work. Push and release to enable and meet some condition to disable, such as touching the brake, pushing the cruise again.

The code below now makes the button attached to PPM/Servo input behave the same way: Get up to speed with throttle and push the button momentarily: cruise is enabled. Push again or touch the brake lever/throttle connected to ADC2 and cruise is disabled. The accelerator can be used to modify RPMs while in cruise mode. The cruise mode will not enable when the motor is not spinning at least with 10% of duty cycle (for safety). Additionally, there is a logic for "longPress" (2 sec) that I wanted to use for reverse. It's not working yet but will be imlemented soon. The same button can be used for legal limiting or anything else. 

Disclaimer: The code was tested on a stand and is expected to work correctly in various situations but use it at your own risk on a vehicle. 

Code:

        // When only one button input is available, use it differently depending on the control mode
            if (config.ctrl_type == ADC_CTRL_TYPE_CURRENT_REV_BUTTON ||
                    config.ctrl_type == ADC_CTRL_TYPE_CURRENT_REV_BUTTON_BRAKE_CENTER ||
                    config.ctrl_type == ADC_CTRL_TYPE_CURRENT_NOREV_BRAKE_BUTTON ||
                    config.ctrl_type == ADC_CTRL_TYPE_DUTY_REV_BUTTON ||
                    config.ctrl_type == ADC_CTRL_TYPE_PID_REV_BUTTON) {
                rev_button = !palReadPad(HW_ICU_GPIO, HW_ICU_PIN);
                if (config.rev_button_inverted) {
                    rev_button = !rev_button;
                }
            } else {

                if ((fabsf(brake_at_cruise - brake)) > 0.1 && cc_button) { // reset cruise if it's active and brake input changed by 0.1v
                    cc_button = false; 
                }

                cc_button_now = !palReadPad(HW_ICU_GPIO, HW_ICU_PIN); // keep the button pin in check
                if (cc_button_now != lastButtonState) { // detect button press

  if (chVTGetSystemTime() - lastTimeButtonStateChanged > longPress) { 
    if (mc_interface_get_duty_cycle_now() < 0.05) { // if not spinning, enable reverse
        lastTimeButtonStateChanged = chVTGetSystemTime();
                  lastButtonState = cc_button_now; // this will set lastButtonstate to the opposite
                          if (cc_button_now == false) {
                              if (rev_button) { //from Cruise On to Off
                                  rev_button = false;
                              }
                  else {
                    cc_button = false; //turning off cruise just in case before enabling reverse
                    rev_button = true;
                  }
  }
    } //end if not spinning (duty cycle is less than 5%
    else {} // if spinning, process something else with a long press, like speed limit setting etc.
  } // end process longPress

    if ((chVTGetSystemTime() - lastTimeButtonStateChanged) > shortPress) { 
        if (mc_interface_get_duty_cycle_now() >= 0.1) { // trigger only if spinning
            lastTimeButtonStateChanged = chVTGetSystemTime(); // need to convert to milliseconds?
                  lastButtonState = cc_button_now; // this will set lastButtonstate to the opposite
                          if (cc_button_now == false) {
                              if (cc_button || rev_button) { //from Cruise On to Off
                                  cc_button = false;
                    rev_button = false; //also disable reverse on short press
                              }
                  else {
                    rev_button = false; //making sure revers is off before enabling cruise
                    cc_button = true;
                    brake_at_cruise = brake; // remember the last set brake input, and check if it changed to disable cruise if it was touched
                  }
  }

    } //end process if spinning

        else {} // do something else on short press and not spinning

  } // end process long press

lastTimeButtonStateChanged = chVTGetSystemTime(); // keep the counter reset if neither short, nor long press is satisfied

} // end detect button press
                
                if (config.cc_button_inverted) {
                    cc_button = !cc_button;
                }

            } //end else

 

********

Original/old post:

I've searched a few topics here about the cruise control but could not find an answer for this specific issue with the CC behavior. I realize VESC has been originally geared towards skateboards and this would make sense for skateboards, but it's a no go on anything with a twist throttle or accelerator pedal.

I tested the servo pin (PB6) to ground and it works, kind of, just not the way cruise control would normally work on a car for example.

It seems like I have to press and hold the cruise button to maintain the speed and it would cancel as soon as I release it. I can make it a switch but it's not safe.

This is how I would set the CC control on my bike with a non-VESC controller: get up to the designed speed, push cruise and release the throttle. The bike maintains the speed regardless of the incline or change in the load, basically keeping the desired RPMs. Touching the throttle, brake input or the cruise button again would immediately cancel cruise. This behavior is very intuitive and safe on a bike. I've used this kind of cruise control on my bikes for years and it has worked very well. Now, any suggestions how we can make it work on ou awesome VESCs?

 

 

pf26
Offline
Last seen: 3 days 10 hours ago
VESC FreeVESC Silver
Joined: 2018-12-04 08:44
Posts: 53

You can do a little custom application : In this app thread, you could have a state machine with 4 states:

1. running normally  2. transitioning to cruise control  3. cruise control  4. transition to normal

Hitting the button in state 1 (ie reading a digital input edge)  forces state 2: now store the current RPM, and start a delay to leave some time to release the throttle then state 3 : periodically call "mcpwm_foc_set_pid_speed(float stored_rpm)" and check digital input edge or throttle change (with threshold against noise) -> state 4 if change.

It needs some time to setup this kind of thing, but once you get used to these apps, it really give unlimitted features to the VESC.

 

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

That's a really good suggestion. Thank you so much!

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

A quick follow up question on this. I always run in current control mode for my application. Looking at the mcpwm_foc_set_pid_speed function, it seems like it assumes running speed control mode as seen below. For cruise control, it does make sense to hold specific RPMs which means that current can fluctuate based on the load. I think this should work but wanted to confirm there should be no problem running in current control mode then switching to speed control for the cruise and then back to the current control once the cruise control is canceled? Thank you.

 

void mcpwm_foc_set_pid_speed(float rpm) {
  m_control_mode = CONTROL_MODE_SPEED;
  m_speed_pid_set_rpm = rpm;
   
  if (m_state != MC_STATE_RUNNING) {
  m_state = MC_STATE_RUNNING;
  }
  }

 

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)

pf26
Offline
Last seen: 3 days 10 hours ago
VESC FreeVESC Silver
Joined: 2018-12-04 08:44
Posts: 53

I think this should work (ie changing control mode can be done on the fly, motor already running). Obviously, you should first test your app with a low power motor / low max current / low RPM...  From my experience, it is sometimes difficult to adjust the speed control PID - lower the settings at first - and be aware it may reach max motor current (large torque) in case of an accident (a fast stop).  It might be wise to add some safety features to release cruise control upon funny events.. 

CruiseControl can be dangerous. Making your own app too. On a bike, please add some extra safety (I always have at least an easily accessible and removable fuse at the main battery).

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

Yes, good suggestions. I've run cruise control on sinusoidal controllers like Infienon/Xi Chang types and it worked surprisingly well. I would reach the desired speed, push the CC button and release the throttle. It would apply the right amount of current to maintain this speed. touching any control such as throttle, brakes, or CC again would immediately reset cruise and goes to free rolling. I've used it for a few years and there has never been concern with the way it works or situations where it caused crash or made it worse. With that, I can see how it can be made safer. I have embedded 9DOF that can be used to detect crashes. For example, bike changes position from vertical to horizontal and/or abrupt stop is detected. I was thinking what would be a good use for IMU on a bike and this is a good one I think.

The other one would be controlled wheelies but that takes a way lot more variables to get it work consistently.

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)

frank
Offline
Last seen: 3 weeks 4 days ago
VESC BronzeVESC FreeVESC GoldVESC OriginalVESC PlatinumVESC Silver
Joined: 2016-12-27 20:19
Posts: 847

That's  how the VESC Wand handles the CC. 

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

I would think that's how pretty much any CC should work. At least on a bike or a car. Maybe a boat even an airplane. 

For cruise control, you want to maintain a certain speed (altitude?) and it should reset to normal operation mode if any controls are touched.  

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

This is now implemented - see the code example and explanation in the first post of this thread.

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)

Ryobi master
Offline
Last seen: 2 months 3 weeks ago
Joined: 2024-02-05 20:32
Posts: 2

Has this code been implemented in any of the new hardware. I have the new flipsky 75100 pro v2 controller and vesc firmware 6.02 . 

vadicus
Offline
Last seen: 1 month 3 weeks ago
VESC Free
Joined: 2018-08-17 07:26
Posts: 431

It's implemented in my controller. Per link below.

 

 

NextGen FOC High voltage 144v/34s, 30kw (https://vesc-project.com/node/1477)