I’d be happy to jump on a call with you to discuss this - back and forth here will just take way too long…
Yea, I agree. I’d like to just be testing myself. Probably should of just started with VM. Rainy days this weekend so no time like the present.
Thanks for the confirmation that it is not as easy as I thought. Trying to put some variables to the feels. There’s only so many inputs and outputs so I just took a swing. I really appreciate the call offer, but I should probably mess around first. I get the sense I’m not quite on a level to understand all knowledge you have to share so I’ll do some experimentation until I’m ready to ask the right questions. Sounds like you got some experiments of your own brewing so you might have it figured out by the time I catch up.
So, who’s down to try it out?
Surge behavior in Float Package - Firmware Customization and Testing - pev.dev
My surge code has been coming along well so I wanted to update ya’ll on what I have been working on. Ashton’s perspective was super helpful in identifying the behavior for me. Until I read this post, I did not realize what I have been missing from the onewheel. Here is how my code works.
Surge, by its nature, is a dynamic state. You will see the surge state itself is quite simple, but because it is so dynamic, the conditions that engage and disengage surge are very important. So what is the surge state? It is the motor being driven to maximum duty using the VESC IF function mc_set_duty(). The effect of this is quite predictable. The nose will go up fast and hard so how do we control this.
First, we set some time limits so we cannot surge uncontrolled. I have set up to surge for 250ms on a 750ms period so there will be a minimum of 500ms between each surge. I believe this period is close to what it feels like when you are inching up a steep hill.
Next, we have to know when to engage surge. We want surge to start at a very high torque (current). This will allow a smooth transition into surge because we are already applying a significant amount of force to the front footpad so it will not nose up too quickly.
Finally, we have to know when to end the surge or else the board will remain out of our control. First, we need to make sure we are still accelerating after the surge so we want the nose to be pitched down a minimum angle. If we are pitched up, surge ends with an abrupt brake, which can make you lose control. Second, the pitch cannot be traveling too fast back to center. This could make us overshoot our minimum angle. Lastly, we want some traction control so we don’t lose control during wheel slip.
I am at the point where the code works and I am massaging the start and stop conditions. There is also a vesc if function mc_set_duty_noramp that I have not tried yet. You are welcome to check out my code Izzygit · GitHub Surge9 branch, but be aware that only the main branch is released. No precompiled package yet. I don’t know how to write UI yet so my UI is kind of hacky. It uses the inputs from turntilt and I changed the AppUI.
Here are some examples. Debug data shows time since last surge, duty before surge, duty at end of surge, reason for surge end. If angle speed>0, that was the fault. If angle speed=0, it was a pitch fault. If pitch fault=100%, it was traction control.
Mid speed surge
Low speed surge
Bonk resulting in traction control fault (100% pitch fault)
I’m still workin away at my surge code. I’m very excited to release it but it is still not quite smooth enough transitioning from surge back to PID control in all situations. Particularly at higher speeds, 7000+ erpm, but I think I have a cure for that. I was able to take it for a trail ride last weekend and it performed great in lower speed, high torque situations.
There are now two triggers to surge. The primary trigger is nose angle speed, specifically in the downward direction. Once you hit this threshold the board will surge. This feels very much like the surge from dipping the onewheel nose.
The second trigger is high continuous current. This would be situation where you are going up a very steep hill and the board starts pulsing. This could also engage when the board starts to stall. My question is, probably specifically for @surfdado, how do I identify the maximum continuous current that we should start surging? The data I have gathered shows that the standard hypercore (120A motor/30A battery) setup is giving me anywhere from ~55-65 A of continuous current. So I am thinking I would like to surge if we maintain something like 55A for 500ms as a starting point. Is there anyway to identify this amperage value for different setups via VESC IF? I imagine this value can vary quite a bit from motor to motor. Thanks.
Pretty sure there’s no concept of continuous currents in the VESC code base. But the VESC_IF lets you call something like get_tot_current - but the float package already does that so you already have access to the actual motor current.
I just noticed your post from 10 days ago. As far as I’m concerned surge when at the speed limit is the only situation I’m interested in. How do you plan on making it (a) noticeable and (b) safe?
Also I’m questioning whether the nose angle speed trigger is something we really want - aren’t you simply preventing nosedrags? Don’t we already have other mechanisms to basically disable nosedrags? Like booster and torquetilt?
Not exactly sure how to answer. What I am doing right now is attempting to mimic the onewheel behavior. Whether or not everything about that is desirable or not, I will let the community decide. I have been switching back and forth between my onewheel and VESC and I am quite close to the same feel with some additional improvements. The advantages I see thus far are:
Crisper and higher curb nudges
Stronger reaction to nose diving
Fun feeling for acceleration if you commit your weight to your front foot after initiating surge. Essentially max acceleration.
Forward burnouts like the onewheel (surge forward and deweight while on dirt)
Pulsing while climbing at max torque to prevent nose dive (still working on this)
Surging at speed lets you feel how far from max duty you are by judging the reaction. The reaction feels softer at high duty.
When compared to booster, the surge reaction is stronger because it is the strongest continuous reaction the motor can have. I think for that reason alone it will have value. I think trick riders and dirt riders are going to see the most benefit.
I have not used torquetilt for nose dive prevention. I’m not a big fan of sharp setpoint changes because it makes the board feel a little tight. I will give it a try on my next trail ride. I am dubious about the efficacy because nose dives happen at 100+ deg/s and I don’t know if torquetilt will react fast enough without being too crazy in other situations.
Thanks for your response on the motor current.
Here is some nice data I collected. This is 3 surges in quick succession at relatively low speed. Full time scale is 5 seconds.
I guess I’m still confused about the purpose of this. How do you even nosedive with a VESC? What situations lead to a nosedive for you? My XR nosedives all the time on steep trails. My VESC never does, so I’m still confused about the exact situations where this would be of benefit.
Correction: my VESC does actually nosedive in one case: when I hit max duty, but at this point your “surge” would be of no benefit because it merely requests max duty - but we are already at max duty, so nothing happens…
I will explain the best I can. A nose dive is simply your body weight being too far in front of the wheel so that the board cannot react fast enough or it does not have any more power to give you. What you describe is the situation where the board not having any more power to give but that isn’t really the situation that concerns me or other experienced riders I think.
Nose dives can also occur because of sudden change in terrain or objects that rapidly decelerate the board. Naturally you want to move your weight back when this happens to avoid nose dip but when going hard on a trail it’s not unusual to misjudge or not see something. In that case your weight can go too far forward and the nose starts dipping fast. Surge counters this by driving your current and duty to the max continuous in an effort to get your nose up as quickly as the motor is capable of.
Here is an example from my last trail ride. I’m going down a decent slope and I see a rock I want to bonk. It’s maybe 4 inches tall and very rectangular, like no slope to it. I know it’s going to be a rough go but I decide not to slow down and just go for it at 12mph or so. I clear it and get some nice air but it decelerated my board quite a bit. I didn’t counter the deceleration enough with my body position so the wheel is a bit behind me. I land hard and the nose goes straight to the ground. The surge engages and it slides me another 1-2ft, but I’m can’t shift my weight back fast enough to get off the front pad. I run it out pretty easily. Had the surge not engaged, the nose would have planted and I would probably be on the ground so i considered that a minor success.
In short surge is max motor performance when you need it (i.e. nose dives) or ask for it (i.e. curb nudge).
Thanks for explaining, I still have a hard time wrapping my head around this though - it sounds like you are attributing the behavior you experienced to “surge” but are you sure this wouldn’t have also happened without it? Have you tried it?
Your use case with the downhill bonk and nosedive landing basically describes a situation where even without surge you should get max amps almost immediately, maybe your surge logic allows max amps to kick in a few milliseconds earlier, but overall the behavior should be very similar.
I started this endeavor by adjusting the booster. I would force the booster to maximum amps until back at the setpoint. I found this did not change the feel of the booster much. I found the same effect from just forcing high amps when a high amp trigger is met. It felt like a dead end. My conclusion was that the booster is in a good place as it is.
So your question is, what makes surge different from booster? You are right that the differential trigger allows for a slightly earlier reaction but while that helps, I don’t think that is the true effect I am feeling.
And this is where I might be talking out of my ass because it gets more technical than my qualifications, but this is the best I can figure. When you use the set duty function instead of the set current function the controller is now using the duty as it’s control value. This allows it to “lead” with higher duty and the amps become a result, instead of leading with high amps and the duty being the result. Duty is related to the apparent voltage received by the motor and seems somewhat restricted by erpm. By leading with higher duty we can deliver both the maximum possible, apparent motor voltage (at the current erpm) and maximum continuous amps immediately.
I am eager to get this code in a releasable state to get other people opinions. Sometimes I worry that I am losing the plot. Having done some many tests and so many surges you start to forget what feels different. But I jump on my onewheel and I do feel like it is so close to being the same.
I went on a 20 mi trail ride this weekend at a park notorious for really choppy trails from all the cows. I learned that my current code was total garbage. Worked on streets but trash on real challenging terrain. But from the ashes I figure a new surge end condition that I was able to get working on my first try that night. It is way smoother and there are significantly less variables. The code is in a good place right now if you want to check it out, branch Surge13. It uses turntilt for the entries and displays those entries on AppUI with appropriate debugs.
It feels like the onewheel actually overreacts more than the current code so that is what I am considering now. I expect at least one more trail ride before release but I am feeling pretty good about it today.
Hey Izzy I really like everything you posted and I think you are really understanding why the XR surge is so valuable. It is a repeatable analog power meter you can tap into at any speed under any condition at any time. Want to know how much more power you have on tap while going uphill? Press the nose down hard and feel how hard the board pushes back on your leg, that weight is the precise amount of weight the board will hold on the nose since you know surge is 100% power. So now you can put exactly that much weight on the front (a lil less for safety) and start going up the hill.
Has your code gotten somewhere where others can try it out? I’ve been super busy at the shop and basically forgot about this topic after I didn’t really like the duty cycle implementation cause thats basically just a speed warning and surge is more of a torque warning. Going uphill is actually one of the places I want it most! And someone mentioned FM surge being DC based but that couldn’t be since you can trigger it at 0 mph. My personal thoughts are that its start condition is purely % of max current based and being below setpoint. stop maybe just getting back to setpoint.
Now that I have many miles on my vesc and I have really started to push the limits of its straight line accelerations, Im finding a lack of TQ warning to be unsettling when at the very edge. I have no analog gauge/meter to know what is left on tap when I really hit the gas pedal. I really miss being able to calibrate to the board via the pressure on my front foot during surge.
One question I had was you mentioned you can only have one surge per 500ms, does that mean that you cant “ride the surge” like on the XR? or does your surge, once triggered, still wait for the stop condition.
Thanks!!