Firmware for an Android accessory electric bicycle. See http://www.danielcasner.org/tag/ebike/ for some more information on my build.

Dependencies:   AndroidAccessory mbed

Files at this revision

API Documentation at this revision

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

main.cpp Show annotated file Show diff for this revision Revisions of this file
throttle.cpp Show annotated file Show diff for this revision Revisions of this file
throttle.h Show annotated file Show diff for this revision Revisions of this file
--- 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