This is the working prototype code, for off-road use only 
Sensitivity = 40mV/A for the 50amp current transducer (hall), 20mV/A for 100amp is also available
ACS756 http://www.allegromicro.com/en/Products/Part_Numbers/0756/0756.pdf
Sensitivity = 40mV/A for the 50amp current transducer (hall), 20mV/A for 100amp is also available
ACS756 http://www.allegromicro.com/en/Products/Part_Numbers/0756/0756.pdf
Code:
// Alpha Motor Control program written by Steelmesh 2012
// Use any external motor controller with 0-5v throttle signal input
// ACS756 hall effect current sensor, two 0.1uf caps for VIN/VOUT, VIN = 5v
// ACS756 pins: (1)VCC- 5v Arduino, (2)GND- Ground Arduino, (3)VIOUT- Analog Input Arduino, (4) GND, (5) to Motor Controller - Battery Negative
// Common Ground: Arduino, Motor Controller, Batteries
//************REFERENCE IN/OUT******************
// pinMode(throttleCmd, OUTPUT);
// pinMode(brakeSwitch, INPUT);
// pinMode(throttleSignal, INPUT);
// pinMode(cruiseControl, INPUT);
// pinMode(buzzer, OUTPUT);
// pinMode(brakeLight, OUTPUT);
int throttleCmd = 3; //0-5v *PWM* output throttle signal to external motor controller
int hallIn = 2; //0-5v signal from Hall Sensor
int cruiseControl = 7; //Cruise control activate/deactivate
int throttleSignal = 4; //Throttle input; analog
int brakeSwitch = 12; //Safety, pulse and cruise kill
int brakeLight = 10; //out brake lamp transistor / relay
int brakeBlink = 0; //
int photoSensor = 8; //
boolean toggle = false; //toggle for cruise control
boolean toggleCruise = false; //toggling resume
boolean ampReducer = false; //toggle for ampDelta change reading
int limitRamp = 0; //Starting pulse adder is 0, if over limit, this value increase (pulse - this higher value = lowering pulse)
int ampSurge = 0; //Counter for amp surge sequence
int cruiseCount = 0; //
int resumePulse = 0; //resumePulse will be set after entering cruise and hitting resume
int toggleDebug = 0; //debugging
int ampDelta = 0; //change in amperage
int buzzer = 11; //startup buzzer
int buzzerCount = 0; //
//*******MANUAL INPUTS BEGIN*******
int ampLimit = 25; //manual input actual amp max set point, see also limitRamp above
int sensorCal = 531; //531 manual input raw input at zero amps for Hall Sensor, ~2.6v with 5v input to the ACS756
int sensorSpec = 40; //Hall Sensor spec = 40 mV per 1 Amp
int cruiseLimit = 20; //manual input for max amps during cruise economy
int cruiseDebouncePre = 10; //Actual ms to re-read button
int cruiseDebouncePost = 300; //Actual ms to wait for operator to release button
int cruiseCycles = 300000; //number of processing loops before it toggles resume ability off
//"Turbo button"
int ampSurgeMax = 5; //A loop-counter value to allow the amp surge mode, it will bypass limitRamp for "ampSurgeMax loop cycles"
int ampSurgeThreshold = 240; //pulse value for minimum throttle pulse to kick in ampSurge, see ampSurge above
int ampSmoothing = 2; //Actual amps to kick in ampDelta smoothing
int ampReducerCount = 0;
int duskDawnSet = 300; //photoSensor actual value dusk/dawn
//*******MANUAL INPUTS END*******
// Some unused ints are being declared above
void setup()
{
Serial.begin(9600);
pinMode(throttleCmd, OUTPUT);
pinMode(brakeSwitch, INPUT);
pinMode(throttleSignal, INPUT);
pinMode(cruiseControl, INPUT);
pinMode(buzzer, OUTPUT);
pinMode(brakeLight, OUTPUT);
}
void loop()
{
if(buzzerCount < 1) //initialized buzzer, only happens once
{
digitalWrite(buzzer, HIGH);
delay(130);
digitalWrite(buzzer, LOW);
buzzerCount = 1;
}
int throttleIn = analogRead(throttleSignal); //Main read throttle, declare pulse
int pulse = constrain(throttleIn, 0, 1023);
pulse = map(pulse, 0, 1022, 0, 254);
int cruisePulse = pulse; //to maintain same throttle level when entering cruise
if (pulse < 55) //to reset Reset rampLimit to zero at zero throttle, 55 chosen based on throttle output characteristics
{
limitRamp = 0;
}
if (pulse < ampSurgeThreshold) //Reset ampSurge counter if throttle falls below threshold
{
ampSurge = 0;
}
int ampRead = analogRead(hallIn); //Read raw hall sensor output signal hallIn
ampRead = constrain(ampRead, sensorCal, 1023); //constrain to sensor output range, sensorCal is zero amps
int actualAmp = ampRead - sensorCal; //Declare new int for conversion, actualAmp is Delta signal change above sensorCal
actualAmp = (actualAmp * 4.9) / sensorSpec; //Convert actualAmp to mV integer, divide by 40 "ACS756 = 40mV/1A" to get actual Amp integer
int hallMv = analogRead(hallIn) * 4.9; //debugging to view mV, Serial.print(hallMv) is below
// ***************CRUISE CONTROL BEGIN*****************
//toggle Cruise
if (digitalRead(cruiseControl) == HIGH && toggle == false) //Read cruise button input
{
delay(cruiseDebouncePre);
if (digitalRead(cruiseControl) == HIGH && toggle == false) //debounce
{
toggle = !toggle;
if (toggleCruise == false && pulse > 80)
{
throttleIn = analogRead(throttleSignal); //Grab throttle pulse value immediately
pulse = constrain(throttleIn, 0, 1023);
pulse = map(pulse, 0, 1022, 0, 254);
limitRamp = 0;
}
if (toggleCruise == true && pulse > 80)
{
throttleIn = analogRead(throttleSignal); //Grab throttle pulse value immediately
pulse = constrain(throttleIn, 0, 1023);
pulse = map(pulse, 0, 1022, 0, 254);
limitRamp = 0;
}
//Cruise resume at saved pulse
if (toggleCruise == true && pulse < 80) //No throttle threshold condition
{
pulse = resumePulse; //If shut down was via braking, this saves cruise...resumePulse can only initially be set by entering cruise loop first with toggleCruise false
pulse = constrain(pulse, 0, 254);
Serial.println("Resume Saved"); //Bingo
}
delay(cruiseDebouncePost);
Serial.println("Cruise On");
}
}
//toggle Cruise end
//Cruise while loop begin
while (toggle == true)
{
Serial.print("Cruise Running at "); //only prints when entering cruise
Serial.print(pulse);
Serial.print(" pulse");
Serial.print(" ");
Serial.print("Amps: ");
Serial.print(actualAmp);
Serial.println("");
ampRead = analogRead(hallIn); // Monitor amps see above for comments
ampRead = constrain(ampRead, sensorCal, 1023);
actualAmp = ampRead - sensorCal;
actualAmp = (actualAmp * 4.9) / sensorSpec;
int cruiseOnSmoothing = cruiseLimit; //smooth out amp surge when cruise resuming
cruiseOnSmoothing = cruiseOnSmoothing * 1.5;
if (actualAmp > cruiseOnSmoothing)
{
limitRamp = limitRamp + 30;
limitRamp = constrain(limitRamp, 0, 254);
}
//current limiter function under cruise
if (actualAmp > cruiseLimit)
{
limitRamp = limitRamp + 2;
limitRamp = constrain(limitRamp, 0, 254);
}
if (actualAmp < cruiseLimit)
{
limitRamp = limitRamp - 2;
limitRamp = constrain(limitRamp, 0, 254);
}
cruisePulse = pulse - limitRamp;
cruisePulse = constrain(cruisePulse, 0, 254);
analogWrite(throttleCmd, cruisePulse); //Here is where it hits the pavement
int brakeRead = digitalRead(brakeSwitch); //BRAKE SWITCH
if (brakeRead == LOW)
{
toggle = !toggle;
toggleCruise = false; //reset resume pulse number by toggling it off for next command
analogWrite(throttleCmd, 0);
pulse = 0;
Serial.println("Cruise OFF brake");
delay(cruiseDebouncePost);
}
int cruiseRead = digitalRead(cruiseControl); //CRUISE BUTTON
if (cruiseRead == HIGH && toggle == true)
{
delay(cruiseDebouncePre);
if (cruiseRead == HIGH && toggle == true)
{
toggle = !toggle;
resumePulse = pulse; //if user uses the cruise button to cut off cruise, it will save this value as resumePulse for cruiseCycles cycles
toggleCruise = true; //toggle on cruise resume pulse
cruiseCount = 0; //reset timer (timer to deactivate resume)
analogWrite(throttleCmd, 0);
Serial.println("Cruise OFF button");
Serial.println("Cruise Pulse Saved");
Serial.println(resumePulse);
delay(cruiseDebouncePost);
}
}
}
//***CRUISE CONTROL END****
//^^^^^^^^^^^^^^^^^^^^^^^^^DO NOT ERASE^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^BRAKE SAFETY CUTOFF^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
while (digitalRead(brakeSwitch) == LOW)
{
analogWrite(throttleCmd, 0);
digitalWrite(brakeLight, HIGH);
delay(1000);
Serial.println("Brake Shut Down");
}
//^^^^^^^^^^^^^^^^^^^^^^^^^DO NOT ERASE^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^BRAKE SAFETY CUTOFF^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Serial.print("Pulse: ");
Serial.print(pulse);
Serial.print(" ");
Serial.print("Amps: ");
Serial.print(actualAmp);
Serial.print(" ");
Serial.print("Hall mv: ");
Serial.print(hallMv);
Serial.print(" ");
// Serial.print("ActualV: ");
// Serial.print(actualVolt);
// Serial.print(" ");
Serial.print("Surge Count: ");
Serial.print(ampSurge);
Serial.print(" ");
Serial.print("BrakeSw: ");
Serial.print(digitalRead(brakeSwitch));
Serial.print(" ");
Serial.print("Resume: ");
Serial.print(resumePulse);
if (toggleCruise == false)
{
toggleDebug = 0;
}
else
{
toggleDebug = 1;
}
Serial.print(" ");
Serial.print("Cruise: ");
Serial.print(toggleDebug);
Serial.println("");
//limitRamp is a modifier for the throttle output to the external controller, higher amps = continuously lowering throttle signal to external controller
if (actualAmp > ampLimit) //Main current limiter function
{
limitRamp = limitRamp + 2; //[actual throttle output signal] = [your intended throttle signal integer] - [limitRamp integer]
limitRamp = constrain(limitRamp, 0, 254);
Serial.println("AMP OVERLIMIT");
}
else
{
limitRamp = limitRamp - 2;
limitRamp = constrain(limitRamp, 0, 254);
}
//REDUNDANT CODE
//^^^^^^^^^^^^^^^^^^^^^^^^^DO NOT ERASE^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^BRAKE SAFETY CUTOFF^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
while (digitalRead(brakeSwitch) == LOW)
{
analogWrite(throttleCmd, 0);
digitalWrite(brakeLight, HIGH);
delay(1000);
Serial.println("2 Brake Shut Down 2");
}
//^^^^^^^^^^^^^^^^^^^^^^^^^DO NOT ERASE^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
//^^^^^^^^^^^^^^^^^^^^^^BRAKE SAFETY CUTOFF^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
if (ampSurge < ampSurgeMax && pulse > ampSurgeThreshold) //AMP SURGE MODE, Full Throttle, gives "ampSurgeMax cycles" of full pulse commands bypassing limitRamp, "TURBO BUTTON"
{
analogWrite(throttleCmd, pulse);
ampSurge = ampSurge + 1;
limitRamp = 0; //Prevent adding to limitRamp while in ampSurge mode, so when exiting ampSurge, limitRamp starts compensating
Serial.println("SURGE MODE");
}
else
{
pulse = pulse - limitRamp; //The main outsignal to external controller, if not in ampSurge mode
pulse = constrain(pulse, 0, 254);
analogWrite(throttleCmd, pulse); //Main Throttle Command Line
}
int lastPulse = pulse; //grabs what the last pulse was for pulse smoothing
//delay(50); //Serial.print sake
}
//The End