// ebike controller
// wheel reedswitch/hall on D2
// gearbox reedswitch/hall on D3
// brake switch on A2
// throttle on A1
// battery current on A0
// battery volts on A3
// D9 is PWM control to ESC
// D8 connected to D9 - use D9 pwm to time program flow
// D10 is PWM to control speedometer needle on an RC servo
#include <PWM.h>
#define throttleMin 165 //ADC when throttle wound on full
#define throttleMax 740 //ADC when throttle off
#define servomin 65 //PWM control for servo left PWM 125=1ms 65 is min servo
#define servomax 295 //PWM control for servo right PWM 250=2ms 295 is max servo
#define ESCmin 65 //PWM control for ESC slow PWM 125=1ms
#define ESCmax 295 //PWM control for ESC fast PWM 250=2ms
#define LVC 789 //battery volts conversion low limit
#define speedfactor 22374 //this is 22374 x circumfrence(m) to give 1/10mph scaling
#define ampsscale 93 //= Rshunt * 1024 / 1.1
#define voltsscale 0.05156 //= 48 * 1.1 / 1024
#define ampsfilter 0.001 // filter delay = 20ms/ampsfilter
int throtl; // Throttle position ADC
int dashno; // dash readout control ADC
int ESCno;
int test2; //
int test3; //
int dashselect; // Adc input 0 = brake switch, else dash select
float volts; // battery volts
volatile int gearspeedcount; // 20ms cycles since last gear turn
volatile unsigned int Tgear; // gear turn duration in milliseconds
int lastTg; // enable Tgear calculation
volatile int speedcount; // 20ms cycles since last wheel turn
volatile unsigned int Twheel; // wheel turn duration in milliseconds
int lastTw; // enable Twheel calculation
unsigned int roadspeed; // speed in 1/10ths mph
unsigned int rpm; // rpm in err.... rpm
float amps; // battery amps
float filteredamps; // battery amps filtered 20s
// Interrupt Service Routine (ISR) for gear sensor
void ISR_gear ()
{ unsigned int temp;
gearspeedcount = 0;
temp = millis();
Tgear = (temp - lastTg);
lastTg = temp;
} // end of ISR_gear
// Interrupt Service Routine (ISR) for wheel sensor
void ISR_wheel ()
{ unsigned int temp;
speedcount = 0;
temp = millis();
Twheel = (temp - lastTw);
lastTw = temp;
} // end of ISR_wheel
void setup() {
// put your setup code here, to run once:
Serial.begin(9600); // serial debug via the usb uart
Serial.setTimeout(10000); // 10s serial timeout
Serial.println("throttle ADC conversion");
pinMode(2, INPUT); // wheel reedswitch falling interrupt
pinMode(3, INPUT); // gearbox reedswitch falling interrupt
pinMode(4, INPUT); // brake switch pulls low
pinMode(8, INPUT); // ESC output (9) fed back in here
attachInterrupt(digitalPinToInterrupt(3), ISR_gear, RISING); //pin 3 gearspeed
attachInterrupt(digitalPinToInterrupt(2), ISR_wheel, RISING);//pin 2 wheelspeed
InitTimersSafe();
// SetPinFrequencySafe(11, 30); // D11 is another RCservo interface.
SetPinFrequencySafe(9, 50); // D9 is ESC control output at 50Hz. Also sets D10
pinMode(13, OUTPUT); // LVC lights LED on arduino
analogWrite(9, servomin); // motor off
analogWrite(10, servomax); // try 2nd pwm pin
pwmWrite(11, 128);
//analogWrite(11, 1); // try 3rd pwm pin
analogReference(INTERNAL); // use bandgap 1.1V ref
delay(10);
throtl = analogRead(A1); // and do a dummy ADC read
dashno = 150;
test2 = 150;
test3 = 30;
filteredamps = 0.0;
ESCno = ESCmin;
}
void loop() {
// put your main code here, to run repeatedly:
while (digitalRead(8) == 0) { // delay - wait for 50Hz clock
}
noInterrupts();
gearspeedcount += 1;
speedcount += 1;
interrupts();
if (gearspeedcount > 50) { //1second
rpm = 0;
}
else {
rpm = 60000 / Tgear;
}
if (speedcount > 100) { //2seconds
roadspeed = 0;
}
else {
roadspeed = speedfactor / Twheel; //in 0.1mph steps
}
amps = float(analogRead(A0)) * ampsscale; // ampsscale;
throtl = analogRead(A1); // read throttle
if (throtl < 0) {throtl = 0;}
dashselect = analogRead(A2); // what to display?
volts = float(analogRead(A2)) * voltsscale; //
filteredamps = (1.0 - ampsfilter) * filteredamps + ampsfilter * amps;
if ((dashselect < 135) || (throtl < (throttleMin - 20)) || (throtl > (throttleMax + 20)))
{ // brake switch or throttle too high or low....... stop motor
ESCno = ESCmin - 20;
}
else if (dashselect < 419) { // display battery amps
dashno = int(amps * float(servomax-servomin) / 20.0);
} // 20amp range
else if (dashselect < 719) { // display speed
// dashno = roadspeed * (servomax-servomin) / 350;
dashno = (throtl - throttleMin)/3;
} // 35mph range
else { // display battery volts
dashno = volts * (servomax-servomin) / 300;
} // 30V range
analogWrite(9, ESCno);
analogWrite(10, (dashno+servomin));
analogWrite(11, test2);
Serial.print(amps);
Serial.print(" ");
Serial.print(throtl);
Serial.print(" ");
Serial.print(dashselect);
Serial.print(" ");
Serial.println(volts);
}