Firmware for an Android accessory electric bicycle. See http://www.danielcasner.org/tag/ebike/ for some more information on my build.
Dependencies: AndroidAccessory mbed
Revision 2:e2c3c7340fb3, committed 2012-08-20
- Comitter:
- DanielC
- Date:
- Mon Aug 20 05:18:03 2012 +0000
- Parent:
- 1:be88f22fc412
- Child:
- 3:dc564aaf8a81
- Commit message:
- Something that might actually work as a throttle pass through at least
Changed in this revision
--- a/main.cpp Sat Aug 11 21:20:13 2012 +0000 +++ b/main.cpp Mon Aug 20 05:18:03 2012 +0000 @@ -1,10 +1,14 @@ #include "mbed.h" #include "AndroidAccessory.h" +#include "throttle.h" -DigitalOut led1(LED1); -DigitalOut led2(LED2); -DigitalOut led3(LED3); -DigitalOut led4(LED4); +DigitalOut l_running(LED1); +DigitalOut l_cruise(LED2); +DigitalOut l_error(LED3); +DigitalOut l_debug(LED4); + +AnalogIn break_l(p19); +AnalogIn break_r(p20); static const size_t OUTL=61; static const size_t INBL=61; @@ -20,19 +24,27 @@ private: void onTick(); + void throttleTick(); char buffer[OUTL]; int bcount; + unsigned int blink_counter; Ticker tick; Timeout n; + Throttle* thr; + float I, v_f, v_r, cadence; }; DroidCycleMbed::DroidCycleMbed() : AndroidAccessory(INBL, OUTL, - "DC Labs", - "DroidCycle", - "Android E-Bike controller interface", - "0.1", - "http://www.danielcasner.org", - "0000000123456789") { + "DC Labs", + "DroidCycle", + "Android E-Bike controller interface", + "0.1", + "http://www.danielcasner.org", + "0000000123456789"), + bcount(0), + blink_counter(0), + thr(NULL) { + thr = Throttle::getThrottle(&I, &v_f, &v_r, &cadence, &break_l, &break_r); tick.attach(this, &DroidCycleMbed::onTick, 0.010); } @@ -57,14 +69,17 @@ void DroidCycleMbed::onTick() { - + blink_counter++; + if (blink_counter < 10) l_running = 1; + else if (blink_counter < 100) l_running = 0; + else blink_counter = 0; } int main() { - while(1) { - led1 = 1; - wait(0.2); - led1 = 0; - wait(0.2); + DroidCycleMbed instance; + + USBInit(); + while (1) { + USBLoop(); } }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/throttle.cpp Mon Aug 20 05:18:03 2012 +0000 @@ -0,0 +1,60 @@ +#include "throttle.h" + +AnalogIn gripThrottle(p17); +AnalogOut throttleOut(p18); + +Throttle* Throttle::instance = NULL; + +Throttle *Throttle::getThrottle(float *I, float *v_f, float *v_r, float *cadence, AnalogIn* break_l, AnalogIn *break_r) { + if (instance == NULL) { + instance = new Throttle(I, v_f, v_r, cadence, break_l, break_r); + } + return instance; +} + +Throttle::Throttle(float *I, float *v_f, float *v_r, float *cadence, AnalogIn* break_l, AnalogIn *break_r) : + mode(off), state(waiting), + I(I), v_f(v_f), v_r(v_r), cadence(cadence), + brkl(break_l), brkr(break_r), + target(0.0f), iLimit(0.0f), speedLimit(0.0f), + enforceSpeedLimit(false) + { + throttleOut = 0.0f; + tick.attach(this, &Throttle::onTick, 0.001); +} + +Throttle::~Throttle() { + tick.detach(); + throttleOut = 0.0f; +} + +void Throttle::onTick() { + if (brkl->read() < break_inhibit_threshold && brkr->read() < break_inhibit_threshold) { + switch(mode) { + case off: + throttleOut = 0.0f; + break; + case raw: + throttleOut = gripThrottle; + break; + case cruise_raw: + throttleOut = target; + break; + default: + throttleOut = 0.0f; + } + } + else { + state = inhibited; + } +} + +void Throttle::setMode(ThrottleMode m) { mode = m; } + +void Throttle::setILimit(float I) { iLimit = I; } + +void Throttle::setSpeedLimit(float v, bool enforce) { + speedLimit = v; + enforceSpeedLimit = enforce; +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/throttle.h Mon Aug 20 05:18:03 2012 +0000 @@ -0,0 +1,84 @@ +#ifndef _throttle_h_ +#define _throttle_h_ + +#include "mbed.h" + +/** Enumeration of different throttle operation modes. + * Determines how the throttle output is calculated from + * all possible inputs. + */ +typedef enum ThrottleMode { + off = 0, /// Throttle output is 0 + raw = 1, /// Throttle output is throttle input (possibly with calibrated curve) + torque = 2, /// Throttle output runs a PID loop on thorque output + cruise_raw, /// Throttle output is held to grip throttle at time cruise was set + cruise_speed, /// Throttle output runs cruise control PID on speed. + cruise_torque, /// Throttle output runs cruise control PID on torque. + droid, /// Throttle output is controlled by attached Android. + calibrate_speed = 0x55, /// Throttle to speed calibration mode + calibrate_torque = 0x56, /// Throttle to torque calibration mode + calibrate_input = 0x57, /// Grip throttle calibration mode +} ThrottleMode; + +/** State machine for running cruise control functions + */ +typedef enum CruiseState { + waiting, /// Waiting for a valid precondition to be met to start running cruise control + transition, /// A transition or ramp between cruise off and cruise on is in progress + running, /// Full cruise control operating + inhibited, /// Something (breaks) cause the cruise control to be inhibited +} CruiseState; + +/** A singleton class representing all aspects of throttle control (input and output) + * as well as regenerative breaking function and break inhibits. + */ +class Throttle { +public: + /** Get the singleton instance + * All variables will be used asynchronously so they must be available throughout the program + * @param I Motor current in Amps + * @param v_f Front wheel speed in RPM + * @param v_r Rear wheel speed in RPM + * @param cadence cadence in RPM + * @param break_l Left break input + * @param break_r Right break input + * @return A pointer to the singleton Throttle object + */ + static Throttle *getThrottle(float *I, float *v_f, float *v_r, float *cadence, AnalogIn* break_l, AnalogIn* break_r); + /// Set the throttle control mode + void setMode(ThrottleMode m); + /// Set a limit on motor current for closed loop regulation + void setILimit(float I); + /** Set a speed limit + * @param v Speed in RPM + * @param enforce if true, regenerative breaking will be used to slow the + * bike if it's going over the speed limit with the motor off. + */ + void setSpeedLimit(float v, bool enforce=false); + /// Set the external input (from Droid) + void input(float target); + +private: + /// Private constructor + Throttle(float *I, float *v_f, float *v_r, float *cadence, AnalogIn* break_l, AnalogIn* break_r); + /// and destructor + ~Throttle(); + /// Control loop tick + void onTick(); + + // The singleton instance + static Throttle* instance; + + Ticker tick; + ThrottleMode mode; + CruiseState state; + float *I, *v_f, *v_r, *cadence; + AnalogIn *brkl, *brkr; + float target, iLimit, speedLimit; + bool enforceSpeedLimit; + + static const float break_inhibit_threshold = 0.1; /// The thrshold at which the breaks cut off the throttle +}; + + +#endif