Throttle Current/phase power control

gwhy!1

100 kW
Joined
Jun 8, 2011
Messages
1,652
Location
Bristol, Uk
Arduino code for throttle interface that allows current and phase limiting to be pre set. Original code was by Hornet Dave for use with RC controllers : original thread is here http://endless-sphere.com/forums/viewtopic.php?f=30&t=33947

EDIT: A link to my watt/volt meter that can also use this code http://endless-sphere.com/forums/viewtopic.php?f=2&t=61407

this was his original code:

Code:
// 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); 

}

I took Daves code and modified it slightly for use with a ebike controller, instead of a current shunt I use a hall current sensor for current monitoring:

un-rem (rc esc) sections and rem (e-bike) sections for rc esc controller.

Code:
// original code by Dave Wolfe on ES.
// modiffied by Gwhy! on ES for use with a e-bike throttle into a e-bike controller 
// also added a pot to set max phase current and battery current.
// uses a hall Current sensor instead of shunt.
// This example code is in the public domain.

// set servo for 1.1ms min - 1.8ms max ( or auto range )
/********************************************************
 * A7 (throttle input)
 * A6 (current pot input)
 * A5 (Isensor input)
 * D3 (control) (throttle output) , RC filter is required on output for e-bike controller,, no rc filter for rc esc 
 *******************************************************/

// #include <Servo.h>   //  (rc esc)

const int Throttle_Input_pin = 7;  // Throttle input A7
const int Pot_Input_pin = 6;   //Pot input A6
const int Isensor_Input_pin = 5;  //Isensor input A5
const int Throttle_Output_pin = 3;  //Throttle output D3.. RC filter need is e-bike controller .. no RC filter for rcesc 

//const int Set_Min_Servo = 1000;  // esc start with this as min throttle  // (rc esc)
//const int Set_Max_Servo = 1800;  // esc end with this as max throttle  // (rc esc)
//int Servo_time = 1000;   // (rc esc)                                                 


long phaseCurrent = 0; // phase current variable; 
const int currentGain = 25; // (25 default) proportional gain setting for current limiting // this value sets how fast the system reacts to throttle input, to high a value causes oscillation around the setpoint , so need to be mess around with to optimize , same with phasegain value.
const int phaseGain = 6; // (6 default)proportional gain for phase current limiting
//const float Current_pot = 512; // un-rem to use a hard codded current limit ( 0-1023 = 0A upto the value of current sensor) 
int Sensor_Cal = 512; // grab real value of this is set in setup section
int throttleCurrent = 0; // throttle setting to achieve current limit
int throttlePhase = 0; // throttle setting to achieve phase current limit
int phaseMax = 0; 
int max_throttleOut = 1023;
int Throttle_Value=0;
int Throttle_Pulse=0;
int Set_Throt_Min = 55; // this needs to be the min value to remove dead band from throttle output , around 55
int Set_Throt_Max = 180; // this needs to be the max value to achive full throttle without cutting out , around 180
int Cal_Throt_Min = 176; // this needs to be set to the real value of the throttle when fully closed;
int Cal_Throt_Max = 842; // this needs to be set to the real value of the throttle when fully open;
float SensorRT=1023; // variable to store value of current sensor. 
float Current_pot=0;  // variable to store value that sets max current/phase limit. //rem out.. if using hard coded current limits

void setup()
{ //--- initialize serial communication at 9600 bits per second:
   Serial.begin(9600); 
// initialize the variables we're linked to
   pinMode(Throttle_Output_pin, OUTPUT);   // sets the D3 pin as output // (e-bike)
   analogWrite(Throttle_Output_pin,0);  // (e-bike)
   
   // Servo_Pulse.attach(6);      // Attach Servo_Pulse to pin 3  //  (rc esc)
   // Servo_Pulse.writeMicroseconds(Servo_time);  //  (rc esc)
   
   delay(1000);
   Sensor_Cal = analogRead(Isensor_Input_pin); // grabs offset of current sensor that must be connected at power up or the code will not funtion corectly.

}

void loop()
{
// throttle, pot, raw current reading/offsetting
Throttle_Value = analogRead(Throttle_Input_pin);
Throttle_Pulse = constrain(map(Throttle_Value,Cal_Throt_Min,Cal_Throt_Max,0,1023),0,1023); // set range on throttle and zero's throttle value
Current_pot = constrain(analogRead(Pot_Input_pin),0,1023); // rem out.. if this value is hard coded to speed things up a bit and to free up a adc input
SensorRT = map(analogRead(Isensor_Input_pin)- Sensor_Cal ,0,1023-Sensor_Cal,0,1023); 
SensorRT = max(0,SensorRT);

Current_pot = (Throttle_Pulse*Current_pot)/1023; // use current pot to set overall max power%
phaseMax = Current_pot*2;  
Throttle_Pulse=max(Throttle_Pulse,120); // Throttle pulse uses highest value 
if (Current_pot < 2)  max_throttleOut=0;  // stop jitter and reset throttle value



// this routine computes the throttle output required for current control
throttleCurrent = max_throttleOut - currentGain*(SensorRT - Current_pot)/100;
throttleCurrent = max(throttleCurrent,0);

// compute the phase current phase current = shunt current/throttle
phaseCurrent = SensorRT * 1023 /max(max_throttleOut,25); //set last term to be appx 2.5% of throttle max - throttle min
throttlePhase = max_throttleOut - phaseGain*(phaseCurrent - phaseMax)/100;
throttlePhase = max(throttlePhase,0);

throttleCurrent = min(throttleCurrent,throttlePhase); //choose lower of phase or current throttle
max_throttleOut = min(Throttle_Pulse,throttleCurrent); // use the lower of current-limited or user requested throttle value

Throttle_Pulse = map(max_throttleOut,0,1023, Set_Throt_Min, Set_Throt_Max);// scale throttle output limits  
analogWrite(Throttle_Output_pin,Throttle_Pulse);  // write throttle to controller //  (e-bike)

//Servo_time = map(max_throttleOut,0,1023,Set_Min_Servo,Set_Max_Servo); // scale output   //  (rc esc)
//Servo_Pulse.writeMicroseconds(Servo_time); //output servo signal to controller  //  (rc esc)   


// 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(throttlePhase);
//Serial.print("  ");
//Serial.print(Throttle_Pulse);
//Serial.print("  ");
//Serial.print(SensorRT);
//Serial.print("  ");
//Serial.print(Current_pot);
//Serial.print("  ");
//Serial.println(max_throttleOut);
}

Edit :

The code now includes throttle battery/phase control , I am still testing the addition code at the moment (throttle current/phase controller) , initial results are good.

The above code is stripped out of my full code from my throttle interface, and I have not tested this code above as a stand alone controller but as far as I can see all the relevant parts are there and it should work the same as my full code in my interface.
 
Just thought I would also post up a couple of basic input output interface circuits ( building blocks ) useable for the arduino . some may find useful.

arduino building blocks.jpg

Edit:
If using powering the arduino (+5v) from a external source the do not connect the throttle output +5v to the controller.
 
Thank you for open sourcing this, really nice! 8)

Can you provide a BOM and a PCB file...? Some photos?
Just to make this post a "sticky" or Endless Wiki entry.
 
The arduino that I am using is the nano v3 http://www.ebay.co.uk/itm/New-Mini-Arduino-Nano-V3-0-ATmega328-Microcontroller-Board-USB-Cable-/251370458513?pt=UK_BOI_Electrical_Components_Supplies_ET&hash=item3a86d8cd91

as it has the usb programming port built onto it so makes it a complete package.

nano.jpg

the current sensors I use I get from Farnell ( ACS758 family of sensor IC ) ( at the moment I use a bi-directional 200A sensor ) But a uni-directional sensor will be better as it will give you more resolution http://uk.farnell.com/allegro-microsystems/acs758ecb-200u-pff-t/current-sensor-200a-uni/dp/2057428 most people will not need a 200A range so select a value that covers you controller max amp output, a good one to go for would be the 100A as this will cover most stuff (the smaller the current value of sensor the higher resolution you will get).

sensor.jpg

you will need the throttle input circuit, throttle output circuit and current sensor input circuit, You use another throttle input circuit but with a 5k pot input instead of a throttle to set the max current, And thats basically it. the whole thing is very easy to put together on a small piece of strip board. The only complication is powering it as it needs a voltage input of 5-18v max .

Edit:
On the throttle out circuit don't connect the +5v ( just use the gnd and signal connections unless powering the arduino from the throttle +5v) as this can cause problems when plugged in to the controller .
 
Any idea how your solution can compare with this?? Complete noob here... :oops:

scan0002.jpg
 
I would say it the arduino version will be much easer to make, less components. Easier to tweek ( tune ) or add more functions if needed, the arduino version also limits the phase current , that circuit do not.
 
Easier to tweak for sure. Any idea on price?

Actually, it was a true phase current controller via throttle (the current sensor was in one of the motor wires), not battery amps / PWM.
http://endless-sphere.com/forums/viewtopic.php?f=28&t=34652&p=503834#p504564

It had a real problem: when accelerating from a dead stop (or locked rotor), if the 2 "other" phases were used (since the current sensor is only in 1 wire), no current limitation... Kaboom! :mrgreen:
 
around £15.00 ($25) total in parts.

Edit:
I assumed the current sensor was in the battery lead :oops:

The circuit circuit you posted only allows a preset max current, its not a current/phase current based throttle control.
 
For ref:
Picture of one of my current monitors / shunt (hall sensor ) this one is 200A, uni-polar, output 0-5v.

200A current monitor.jpg
 
My code above, now includes throttle based ( battery/phase current) control ... still testing, but initial results are very good.
 
I have just been taking some current readings of the basic arduino circuit and for anyone that don't want anything to fancy i.e screen or BT connected to there arduino then powering the arduino can be done via the throttle connection of the controller. Which opens the use of the arduino up and a lot easier to power without having to worry about a dc to dc converter to run it.

Arduino nano information and programer/software download (free) is here: http://arduino.cc/en/Main/ArduinoBoardNano
 
I thought I would buy another arduino nano and sick it on a piece of vero board, to test the above code as standalone code , my original nano setup and code is completely different from the code above..

Any way

I thought I would post up a few pics as I am going as it may help peeps with layout and give some idea of what is required.

This is the basic input circuits for throttle,pot and current sensor. I will post a picture of the finished board when i have finished it :)

vero layout1.jpg
vero layout1_bottom.jpg
vero layout1_nano.jpg

Note: changed input pins in above code to match this layout.
 
finished layout ready for playing with.
vero layout2a.jpg
vero layout2_rc_filter.jpg
vero layout2_bottom.jpg

I have upload a program into this nano just to test out the layout and make sure it works, blue wire is current sensor input , green wire next to blue is throttle input , geen on rc filter is throttle output to controller.

made a small addition to the above code to get the current sensor offset at power on.
 
izeman said:
i don't know where this will go, and am not sure if this is usable already as is, but i already ordered a arduino and different amp sensors to play with when back from vacation ;). really looking forward to it.


The code above is not very tidy but it is functional . I hope to post some amendments soon that will tidy it up and improve the operation. I hope more people will have a go at this and post up any improvements or additions. I may add a display once the power throttle has been tested and all is good.

Edit:
Code above programmed into my vero layout and tested with a infineon controller ( on a bike ) upto a 50A limit.. does what its supposed to do :mrgreen:
 
I think the fact that most of the arduino range has a onboard usb programming interface and that the programming software is free makes it a very nice complete package to experiment with. Im no expert and just muddling why way through code, but its not that bad.
 
Alan B said:
Looks like a good start. The Teensy 2.0 is another good small Arduino board, I've done a few projects with various Arduino boards.

I like the look of the Teensy !.. no leds and no builtin 5v reg this means even less power to drive it which will be even better if powering it from the throttle line,but it dont appear to be as popular on ebay as the nano ( cant find the teeny cheaper than the nano ) .. have you got any links to buy?
 
for my other projects I have been using a small nokia LCD display.. very cheap!!

lcd.JPG
there are lots of place to get these displays not just this seller..
http://www.ebay.co.uk/itm/New-5pcs-84-48-LCD-Module-White-backlight-adapter-pcb-for-Nokia-5110-Hotsell-WST-/300955472722?pt=UK_Mobiles_Accessories_RL&hash=item4612581352

For the vero layout above it will be very easy to add this display to the arduino.. then you can add a lot more functions to the device. follow on Thread here http://endless-sphere.com/forums/viewtopic.php?f=2&t=61407.
 
izeman said:
i ordered one of those 128x160 spi tft displays. they are only some €/$/£ more expensive

yes the price of those displays are coming down all the time...

but 8 quid for 5 is pretty hard to beat for the nokia lcds .
 
$_12.JPG

I've used this hall sensor that you can get on ebay in 50 100 150 200 amp either bidirectional or unidirectional. They are from China and the slotted holes fit a deans connector. I dont know if they are noisy or instantaneous current depends on when you read it. It the same sensor Gwhy is using just mounted on a board although they could be of a lesser quality. Readings from it would have some high and low variations. I used some code to average the last ten readings. I'm using a PID loop to limit current by controlling throttle. I'm getting some overshoot with sudden rapid increase in throttle input. I'm going to try to incorporate some of the code here to limit overshoot and improve throttle response.

http://www.ebay.com/itm/50A-100A-150A-200A-Bi-Uni-AC-DC-Current-Sensor-Module-arduino-compatible-/111327343425?pt=LH_DefaultDomain_0&var=&hash=item19eba07341
 
Back
Top