Arduino PID current limiter values

I have now dropped using the PID control as I could not get it dialed 100% for my needs and started over with my control code. I looked at Hornet Dave's code found here http://endless-sphere.com/forums/viewtopic.php?f=30&t=33947 thought I would swap out may control code for daves , I had to make some adjustments that allowed it to fit straight as I use a 200A hall current sensor and not a shunt ( this makes things so much easier ) also I use a regular e-bike output ( not PWM ) in to the rest of my code but the results are better than using the PID and so much easier to tune the response, I also made a few additions that allowed a current/phase based throttle rather than just a hard current/phase limit. The results are very good and I would just like to give Hornet dave a shout out, and if anyone else want to try and go down this route using a arduino then daves code is the best way to go.. ( well for the time being anyway its the best solution I have tried and found so far :p )

Daves original code:

Hornet dave said:
Moderate success! I've got the interface seemingly working as desired, but I won't have a chance to give it a real-world test until spring. I'll scribble up a circuit diagram in the next day or two, but the code i'll post here right now. First I need to explain my application a little. I'm using this for a brushless powered (63-74-200kv) RC glider winch. Here's a sample I found on youtube:

http://www.youtube.com/watch?v=UGimKxzWe2I&feature=related

This being a glider winch, my user control interface is not a proportional throttle but rather an on-off switch that is foot activated. So if you use this code for a bike application, you'll have to re-write the throttle input section so that it takes your throttle range and scales it appropriately. Next, depending on your ESC, you may have to treat the throttle endpoints from the arduino to the ESC in a different manner than what i've done. With a Castle ESC, absolutely do NOT use the auto-calibrating endpoints as you have to calibrate the endpoints on every power-up. Use fixed endpoints instead, it's a lot easier to deal with. Lastly, this is pretty hacked together and i'm not looking for the most elegant code on the planet, i'm just looking for something that works! So, that being said, go ahead and use this for any purpose you may desire, I make no guarantees about anything, just realize that this is a work in progress, it may be full of bugs, dangerous, it may blow stuff up, etc.

As far as the circuit goes, it's bone simple:
1) My on-off switch goes into a digital input with a (pull-down?) resistor. You'll probably want to route your throttles to an analog pin instead. If you want to use a hybrid control scheme that uses half throttle position and half current control, it would be easy to implement. So would a current only control scheme.
2) The high-side current monitor output connects to an analog pin. The monitor connects to a shunt in the + wire of the battery (this particular chip will work on 60v batteries if I recall correctly. The monitor measures the delta-V across the shunt and multiplies this by X100 and the X100 voltage is then read by the analog input on the arduino. A capacitor and resistor smooths out the voltage from the shunt. Size your shunt to get .02 - .04V drop at the battery currents which you want to control.
3) The arduino outputs an RC signal to the ESC.

One last thing, this code will result in battery current overshoots and phase current overshoots, so leave yourself an ample margin and take some measurements to check your work. I have no idea what a "safe" phase current limit would be for a given controller, so you're on your own when it comes to finding performance limits. Also... the phase current computation is very simplified and does not account for any expo-curves that may be used by the ESC. If you want to look at duty cycles vs ESC throttle inputs and develop a curve or correction of some sort, that would be nice for the rest of us without an o-scope!

// winch_a by Dave Wolfe
// this is a work in progress R/C ESC interface that is intended to control
// phase current and battery current.
// This example code is in the public domain.


#include <Servo.h>

Servo myservo; // create servo object to control a servo
// a maximum of eight servo objects can be created

int throttleOut = 1000; // variable to store the servo position
int throttleReq = 1150; // the throttle setting requested by user via pedal
int throttleCurrent = 0; // throttle setting to achieve current limit
int throttlePhase = 0; // throttle setting to achieve phase current limit
long phaseCurrent = 0; // phase current variable; 10X actual
int buttonState = 0; // variable for reading the pushbutton status
long current = 0; // variable for current from shuntInputPin

const int throttleZero = 1150; // initialization/zero endpoint for controller
const int throttleMin = 1245; // min setting for current or phase-current limited
// throttle output, microseconds
const int throttleMax = 1900; // max throttle output, microseconds

const int currentMax = 400; // maximum current *10 (set to 400 for 40 amps)
const int currentGain = 25; // proportional gain setting for current limiting

const int phaseMax = 300; // maximum phase current *10 (set to 900 for 90 amps)
const int phaseGain = 6; // proportional gain for phase current limiting

const long currentScaling = 110; // adjust this so current is 10X actual current
const long currentOffset = 28; // corrects for min shunt voltage not being zero
const int buttonPin = 10; // the number of the pin for the input on/off switch
const int shuntInputPin = A0; // analog input pin from current monitor (shunt)

void setup()
{
myservo.attach(4); // attaches the servo on pin 4 to the servo object
Serial.begin(9600);
// initialize the pushbutton (pedal) pin as an input:
pinMode(buttonPin, INPUT);
}


void loop()
{
// read the amplified shunt voltage from the current monitor, scale it, offset it
// (i should probably offset the raw input and then scale it rather than what i've done..)
current = (analogRead(shuntInputPin) * currentScaling / 100) - currentOffset;
current = max(0,current); // do not allow negative currents, it causes errors later!


// this converts the pedal taps to a throttle signal.
// for an ebike, replace this with a routine to read your throttle
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH)
{
throttleReq += 10; // 10
throttleReq = min(throttleReq,throttleMax);
// throttleReq = min(throttleReq,1300);
}
else
{
throttleReq -= 14; //14
throttleReq = max(throttleReq,throttleZero);
}
// end of the throttle input routine


// this routine computes the throttle output required for current control
throttleCurrent = throttleOut - currentGain*(current - currentMax)/100;
throttleCurrent = max(throttleCurrent,throttleMin);

// compute the phase current phase current = shunt current/throttle
phaseCurrent = current * (throttleMax - throttleMin)/max((throttleOut - throttleMin),20); //set last term to be appx 2.5% of throttle max - throttle min
throttlePhase = throttleOut - phaseGain*(phaseCurrent - phaseMax)/100;
throttlePhase = max(throttlePhase,throttleMin);


throttleCurrent = min(throttleCurrent,throttlePhase); //choose lower of phase or current throttle
throttleOut = min(throttleReq,throttleCurrent); // use the lower of current-limited or user requested throttle value
myservo.writeMicroseconds(throttleOut); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
// (not very elegant, I should synch this with the RC throttle signal frequency somehow)


// DEBUG! Pick whatever variables you want to see, use the Arduino serial monitor
// to view your values in real time. Tools -> Serial Monitor

// Serial.print("position:");
Serial.print(throttleOut);
Serial.print(" ");
// Serial.print(", pc:");
Serial.println(phaseCurrent);
// Serial.println(current);

}


(edit - fixed a couple lines of code)
 
gwhy! said:
I use a 200A hall current sensor and not a shunt ( this makes things so much easier ) also I use a regular e-bike output ( not PWM ) in to the rest of my code but the results are better than using the PID and so much easier to tune the response, I also made a few additions that allowed a current/phase based throttle rather than just a hard current/phase limit. The results are very good and

Can you share your code?
 
h0tr0d said:
gwhy! said:
I use a 200A hall current sensor and not a shunt ( this makes things so much easier ) also I use a regular e-bike output ( not PWM ) in to the rest of my code but the results are better than using the PID and so much easier to tune the response, I also made a few additions that allowed a current/phase based throttle rather than just a hard current/phase limit. The results are very good and

Can you share your code?

new topic:

http://endless-sphere.com/forums/viewtopic.php?f=2&t=61004
 
Truly awesome, thank you!
 
How on earth did you find that old program of mine? Must have been Google!!?!
Glad to see things are working well.
 
I tried making an analog PID for an RC controller but I never got it dialed in properly either. It always had a tendency to oscillate. I think the big problem was the latency (delay time) between a controller input and motor output change.
 
fechter said:
I tried making an analog PID for an RC controller but I never got it dialed in properly either. It always had a tendency to oscillate. I think the big problem was the latency (delay time) between a controller input and motor output change.

I made your original analog circuit and I did manage to get it working well, I had to change out the opamp and mess around with the RC values but I got it to a point that it was very useable. I would have stuck with it but wanted more functions and something that was easier to change parameters so took the plunge into digital.

Hornet dave said:
How on earth did you find that old program of mine? Must have been Google!!?!
Glad to see things are working well.

The digital PID I was using worked but it needed different parameters for which motor/controller/bike I was using, so needed a lot of messing around with to get it right. Your code more or less worked out of the box and was consistent no matter what motor/controller/bike I was using, should have tried ages ago, I could have saved myself a lot of frustration and time. Thanks.
 
Back
Top