System Management code

Dependencies:   mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP

Fork of SystemManagement by Martin Deng

Files at this revision

API Documentation at this revision

Comitter:
pspatel321
Date:
Thu Jan 22 07:58:51 2015 +0000
Parent:
35:9337ac9f4e1b
Child:
37:2207b58b9a7f
Commit message:
Tested in car with other systems. Most features are good to go. Except xbees need work. The DC-DC protection features were giving problems due to spurious current measurements. They have been edited to reduce glitchy errors.

Changed in this revision

Constants.h Show annotated file Show diff for this revision Revisions of this file
IOobjects/CAN_RxIDs.h Show annotated file Show diff for this revision Revisions of this file
IOobjects/CAN_TxIDs.h Show annotated file Show diff for this revision Revisions of this file
IOobjects/IOobjects.cpp Show annotated file Show diff for this revision Revisions of this file
IOobjects/IOobjects.h Show annotated file Show diff for this revision Revisions of this file
Libs/CANBuffer.lib Show annotated file Show diff for this revision Revisions of this file
Libs/CoulombCounter/CoulombCounter.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/CoulombCounter/CoulombCounter.h Show annotated file Show diff for this revision Revisions of this file
Libs/DC_DC/DC_DC.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/DC_DC/DC_DC.h Show annotated file Show diff for this revision Revisions of this file
Libs/DC_DC/FanPump/FanPump.cpp Show diff for this revision Revisions of this file
Libs/DC_DC/FanPump/FanPump.h Show diff for this revision Revisions of this file
Libs/IMD/IMD.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/IMD/IMD.h Show annotated file Show diff for this revision Revisions of this file
Libs/LPCDigitalIn.lib Show diff for this revision Revisions of this file
Libs/LatchMonitor/LatchMonitor.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/LatchMonitor/LatchMonitor.h Show annotated file Show diff for this revision Revisions of this file
Libs/PollSwitch/PollSwitch.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/PollSwitch/PollSwitch.h Show annotated file Show diff for this revision Revisions of this file
Libs/Watchdog.lib Show annotated file Show diff for this revision Revisions of this file
inCommands/inCommands.cpp Show annotated file Show diff for this revision Revisions of this file
inCommands/inCommands.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
outDiagnostics/outDiagnostics.cpp Show annotated file Show diff for this revision Revisions of this file
runTime/runTime.cpp Show annotated file Show diff for this revision Revisions of this file
runTime/runTime.h Show annotated file Show diff for this revision Revisions of this file
--- a/Constants.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Constants.h	Thu Jan 22 07:58:51 2015 +0000
@@ -1,10 +1,10 @@
 #ifndef CONSTANTS_H
 #define CONSTATNS_H
 
-#define BAUD            460800  // Serial port baud rate
-#define CHAR_TIME       0.00002 // Time to send 1 char @ above baud
+#define BAUD            230400  // Serial port baud rate
+#define CHAR_TIME       0.00005 // Time to send 1 char @ above baud
 #define TX_SIZE         1000    // Serial buffer TX size
-#define RX_SIZE         100     // Serial buffer RX size
+#define RX_SIZE         60      // Serial buffer RX size
 
 #define XBEE_BAUD       250000  // 250k baud serial for xbees
 #define XBEE_TX_SIZE    1000    // Serial buffer TX size for xbees
@@ -13,7 +13,7 @@
 #define START_DELAY     10      // Startup delay for latch monitor circuits
 #define FAST_LOOP       0.01    // Period (seconds) for fast loop (sampling, filters)
 #define GATHER_LOOP     0.1     // Period (seconds) for main data processing loop
-#define WDT_TIME        0.1     // Normal, running mode WDT timeout
+#define WDT_TIME        0.5     // Normal, running mode WDT timeout
 #define CAN_LOOP        0.1     // Output period for CAN transmissions
 
 #endif
\ No newline at end of file
--- a/IOobjects/CAN_RxIDs.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/IOobjects/CAN_RxIDs.h	Thu Jan 22 07:58:51 2015 +0000
@@ -4,15 +4,15 @@
 #define BASE_ID             0x500              // Start at 0x500 for this device
 
 // Receive IDs
-#define FAN_CONTROL_ID      BASE_ID + 80
-#define PUMP_CONTROL_ID     BASE_ID + 81
-#define DCDC_CONTROL_ID     BASE_ID + 82
+#define FAN_CONTROL_ID      BASE_ID + 0x80
+#define PUMP_CONTROL_ID     BASE_ID + 0x81
+#define DCDC_CONTROL_ID     BASE_ID + 0x82
 
-#define GLVBAT_CLEARSOC_ID  BASE_ID + 90
-#define GLVBAT_CLEARAH_ID   BASE_ID + 91
-#define GLVBAT_SETCAPAC_ID  BASE_ID + 92
+#define GLVBAT_SETSOC_ID    BASE_ID + 0x90
+#define GLVBAT_SETAH_ID     BASE_ID + 0x91
+#define GLVBAT_SETCAPAC_ID  BASE_ID + 0x92
 
-#define AMS_RELAYS_ID       0x303
+#define AMS_MODE_ID         0x301
 #define STEERING_RESET_ID   0x602
 
 #endif
\ No newline at end of file
--- a/IOobjects/CAN_TxIDs.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/IOobjects/CAN_TxIDs.h	Thu Jan 22 07:58:51 2015 +0000
@@ -5,34 +5,34 @@
 
 // Transmit IDs - System Mgmt Specific
 // Operating diagnostics
-#define SYS_ERROR_ID            BASE_ID + 00       // Error frame - critical errors that require shutdown
-#define SYS_XBEE1_ID            BASE_ID + 01       // Message in/out counter for xbee1
-#define SYS_XBEE2_ID            BASE_ID + 02       // Message in/out counter for xbee2
-#define SYS_TEMP_ID             BASE_ID + 03       // Internal temperature of the glv battery chargerFET
+#define SYS_ERROR_ID            BASE_ID + 0x00       // Error frame - critical errors that require shutdown
+#define SYS_XBEE1_ID            BASE_ID + 0x01       // Message in/out counter for xbee1
+#define SYS_XBEE2_ID            BASE_ID + 0x02       // Message in/out counter for xbee2
+#define SYS_TEMP_ID             BASE_ID + 0x03       // Internal temperature of the glv battery chargerFET
 
 // GLV Battery
-#define SYS_GLV_CURRENT_ID      BASE_ID + 10       // GLV battery current
-#define SYS_GLV_CAPACITY_ID     BASE_ID + 11       // GLV battery capacity setting
-#define SYS_GLV_AH_ID           BASE_ID + 12       // GLV battery amphours
-#define SYS_GLV_SOC_ID          BASE_ID + 13       // GLV battery SOC
+#define SYS_GLV_CURRENT_ID      BASE_ID + 0x10       // GLV battery current
+#define SYS_GLV_CAPACITY_ID     BASE_ID + 0x11       // GLV battery capacity setting
+#define SYS_GLV_AH_ID           BASE_ID + 0x12       // GLV battery amphours
+#define SYS_GLV_SOC_ID          BASE_ID + 0x13       // GLV battery SOC
 
 // DC-DC Converter
-#define SYS_DCDC_CURRENT_ID     BASE_ID + 20       // DC-DC current 
-#define SYS_DCDC_STATUS_ID      BASE_ID + 21       // DC-DC status byte
+#define SYS_DCDC_CURRENT_ID     BASE_ID + 0x20       // DC-DC current 
+#define SYS_DCDC_STATUS_ID      BASE_ID + 0x21       // DC-DC status byte
 
 // PWM Channels
-#define SYS_PWM_FAN_ID          BASE_ID + 30       // FAN1 actual pwm
-#define SYS_PWM_PUMP_ID         BASE_ID + 31       // PUMP1 actual pwm
+#define SYS_PWM_FAN_ID          BASE_ID + 0x30       // FAN1 actual pwm
+#define SYS_PWM_PUMP_ID         BASE_ID + 0x31       // PUMP1 actual pwm
 
 // IMD
-#define SYS_IMD_STATUS_ID       BASE_ID + 40       // IMD status byte
-#define SYS_IMD_RESIST_ID       BASE_ID + 41       // IMD resistance measurement
+#define SYS_IMD_STATUS_ID       BASE_ID + 0x40       // IMD status byte
+#define SYS_IMD_RESIST_ID       BASE_ID + 0x41       // IMD resistance measurement
 
 // Latch Supervisor states
-#define SYS_IMD_LATCH_ID        BASE_ID + 50       // IMD Latch circuit error byte
-#define SYS_AMS_LATCH_ID        BASE_ID + 51       // AMS Latch circuit error byte
+#define SYS_IMD_LATCH_ID        BASE_ID + 0x50       // IMD Latch circuit error byte
+#define SYS_AMS_LATCH_ID        BASE_ID + 0x51       // AMS Latch circuit error byte
 
 // Shutdown Switches
-#define SYS_SWITCHES_ID         BASE_ID + 60       // Shutdown Switch State
+#define SYS_SWITCHES_ID         BASE_ID + 0x60       // Shutdown Switch State
 
 #endif
\ No newline at end of file
--- a/IOobjects/IOobjects.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/IOobjects/IOobjects.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,29 +1,29 @@
 #include "IOobjects.h"
 
-Watchdog wdt(1);                                  // Watchdog timer (TIMEOUT (sec))
-LPCDigitalIn sw[]={                 // Shutdown switch sense lines
-    LPCDigitalIn(p1_0, PullUp),     // Sense0 - fuse power
-    LPCDigitalIn(p1_1, PullUp),     // Sense1 - AMS latch
-    LPCDigitalIn(p1_4, PullUp),     // Sense2 - IMD latch
-    LPCDigitalIn(p1_8, PullUp),     // Sense3 - PCM relay
-    LPCDigitalIn(p1_9, PullUp),     // Sense4 - Brake plausibility relay
-    LPCDigitalIn(p1_10, PullUp),    // Sense5 - Left e-stop
-    LPCDigitalIn(p1_14, PullUp),    // Sense6 - Brake over-travel
-    LPCDigitalIn(p1_15, PullUp),    // Sense7 - Inertia switch
-    LPCDigitalIn(p1_16, PullUp),    // Sense8 - Cockpit e-stop
-    LPCDigitalIn(p1_17, PullUp),    // Sense9 - Right e-stop
-    LPCDigitalIn(p1_27, PullUp),    // Sense10 - HVD/Charger
-    LPCDigitalIn(p1_28, PullUp),    // Sense11 - TSMS/tractive enable
+Watchdog wdt;                      // Watchdog timer (TIMEOUT (sec))
+DigitalIn sw[]={                   // Shutdown switch sense lines
+    DigitalIn(P1_0, PullDown),     // Sense0 - fuse power
+    DigitalIn(P1_1, PullDown),     // Sense1 - AMS latch
+    DigitalIn(P1_4, PullDown),     // Sense2 - IMD latch
+    DigitalIn(P1_8, PullDown),     // Sense3 - PCM relay
+    DigitalIn(P1_9, PullDown),     // Sense4 - Brake plausibility relay
+    DigitalIn(P1_10, PullDown),    // Sense5 - Left e-stop
+    DigitalIn(P1_14, PullDown),    // Sense6 - Brake over-travel
+    DigitalIn(P1_15, PullDown),    // Sense7 - Inertia switch
+    DigitalIn(P1_16, PullDown),    // Sense8 - Cockpit e-stop
+    DigitalIn(P1_17, PullDown),    // Sense9 - Right e-stop
+    DigitalIn(P1_27, PullDown),    // Sense10 - HVD/Charger
+    DigitalIn(P1_28, PullDown),    // Sense11 - TSMS/tractive enable
 };
-CANBuffer can(CAN2, MEDIUM, p4_28);                  // Buffered CAN interface (PORT, SPEED, SILENT PIN)
+PollSwitch switches(sw, sizeof(sw)/sizeof(sw[0]));   // Shutdown switch sense pins (SWITCH PIN ARRAY, NUM PINS)
+CANBuffer can(CAN2, MEDIUM, P4_28);                  // Buffered CAN interface (PORT, SPEED, SILENT PIN)
 CoulombCounter glvBat(p19, FAST_LOOP*1000);          // Coulomb counter battery monitor for GLV Battery (CURRENT SENSE PIN, INTEGRATION TIME)
-DC_DC dcdc(p18, p20, p26, p25, p24, p23, 0.01, 1);   // DC-DC converter & high-current load control (CONTROL PIN< CURRENT SENSE PIN, FAN1 PIN, FAN2 PIN, PUMP1 PIN, PUMP2 PIN, PWM PERIOD (sec), FULL-SCALE SLEW (sec))
-IMD imd(p1_26);                                      // IMD PWM sense channel to read status and resistance (IMD PWM PIN)
-LatchMonitor AMSlatch(p0_18, p0_22, START_DELAY*1000);  // Supervisor for AMS hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms))
-LatchMonitor IMDlatch(p0_17, p0_21, START_DELAY*1000);  // Supervisor for IMD hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms))
+IMD imd(P1_26);                                      // IMD PWM sense channel to read status and resistance (IMD PWM PIN)
+LatchMonitor AMSlatch(P0_18, P0_22, START_DELAY*1000);  // Supervisor for AMS hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms))
+LatchMonitor IMDlatch(P0_17, P0_21, START_DELAY*1000);  // Supervisor for IMD hardware latch/reset circuit (OK PIN, FAULT PIN, STARTUP DELAY (ms))
 MODSERIAL pc(USBTX, USBRX, TX_SIZE, RX_SIZE);        // Serial to computer for diagnostics, 3kB output buffer, 256 byte input buffer
+DC_DC dcdc(p18, p20, p26, p25, p24, p23, 0.01, 1);   // DC-DC converter & high-current load control (CONTROL PIN, CURRENT SENSE PIN, FAN1 PIN, FAN2 PIN, PUMP1 PIN, PUMP2 PIN, PWM PERIOD (sec), FULL-SCALE SLEW (sec))
 Temperature internalTmp(&NXFT15XH103_TABLE, p15);    // Temperature conversion look-up table for internal temperature on the GLV bat charger FET (TABLE PTR, PIN)
-PollSwitch switches(sw, sizeof(sw)/sizeof(sw[0]));   // Shutdown switch sense pins (SWITCH PIN ARRAY, NUM PINS)
 
 XbeeManager xbeeRelay(p9, p10, p13, p14, XBEE_BAUD, XBEE_TX_SIZE, XBEE_RX_SIZE);
 //XbeeRelay xbee;
--- a/IOobjects/IOobjects.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/IOobjects/IOobjects.h	Thu Jan 22 07:58:51 2015 +0000
@@ -2,6 +2,7 @@
 #define _IO_OBJECTS_H
 
 #include "mbed.h"
+#include "rtos.h"
 #include "Constants.h"
 #include "CAN_RxIDs.h"
 #include "CAN_TxIDs.h"
@@ -17,9 +18,6 @@
 #include "XbeeManager.h"
 //#include "XbeeRelay.h"
 
-#define OS_TIMERPRIO    6
-#include "rtos.h"
-
 extern CANBuffer can;
 extern CoulombCounter glvBat;
 extern DC_DC dcdc;
@@ -81,6 +79,7 @@
 public:
     char inputStr[RX_SIZE+1];
     char parseGoodChar;
+    void* wdtThreadId;
 };
 
 extern CANinputs CANdata;
--- a/Libs/CANBuffer.lib	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/CANBuffer.lib	Thu Jan 22 07:58:51 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/Penn-Electric-Racing/code/CANBuffer/#533722a1a6cf
+http://developer.mbed.org/teams/Penn-Electric-Racing/code/CANBuffer/#b2b886bdb080
--- a/Libs/CoulombCounter/CoulombCounter.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/CoulombCounter/CoulombCounter.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,8 +1,8 @@
 #include "CoulombCounter.h"
 
 const float MSEC_HRS = 2.77778e-7;                          // Multiplier to convert milliseconds to hours
-const float BAT_ISENSE_MULTIPLIER = 6.2299;                 // Multiplier to convert float to amps
-const float BAT_ISENSE_OFFSET = -0.5*BAT_ISENSE_MULTIPLIER; // Offset to convert float to amps
+const float BAT_ISENSE_MULTIPLIER = /*6.2299*/6.640114;     // Multiplier to convert float to amps, calibrated using 3 points with Fluke 87V meter and code on 1/9/15
+const float BAT_ISENSE_OFFSET = /*-0.5*BAT_ISENSE_MULTIPLIER*/-3.344968; // Offset to convert float to amps, calibrated using 3 points with Fluke 87V meter and code on 1/9/15
 const float BAT_ISENSE_LIMS = 3.0;                          // Over-current limit = +/- 3A
 
 CoulombCounter::CoulombCounter(PinName _pin, int _mSec) : BatISense(_pin) {
@@ -22,18 +22,15 @@
     
     // Take the initial readings, fill the buffer
     for (int i = 0; i < CC_FILTER_TAPS; i++) {
-        buffArr[i] = BatISense.read() * BAT_ISENSE_MULTIPLIER + BAT_ISENSE_OFFSET;
+        buffArr[i] = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
     }
-    current();      // Get avg and fill out overCurrent flag
+    updateAvg();      // Get avg and fill out overCurrent flag
     tracker=0;
-    
-    // Start counting
-    // sampler.attach_us(this, &CoulombCounter::sample, mSec*1000);
 }
 
 void CoulombCounter::sample() {
     // Take the reading
-    currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
+    float currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
         
     // Integrate
     float f = ampHours()-currentSample*mSec*MSEC_HRS;
@@ -50,16 +47,17 @@
     buffArr[tracker] = currentSample;
     tracker++;
     if (tracker >= CC_FILTER_TAPS) tracker = 0;
+    updateAvg();
 }
 
-float CoulombCounter::current() { 
+void CoulombCounter::updateAvg() {
     float avg = 0;
     for (int i = 0; i < CC_FILTER_TAPS; i++) {
         avg += buffArr[i];   
     }
     avg /= CC_FILTER_TAPS;
     if (abs(avg) > BAT_ISENSE_LIMS) overCurrent = true;
-    return avg;
+    currentFiltered = avg;
 }
 
 bool CoulombCounter::overCurrentDetected() {
--- a/Libs/CoulombCounter/CoulombCounter.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/CoulombCounter/CoulombCounter.h	Thu Jan 22 07:58:51 2015 +0000
@@ -7,20 +7,21 @@
 
 const float defaultAh = 1.5;        // Default amphours of battery, in case store read is bad/empty
 const float defaultSOC = 0.5;
-const int CC_FILTER_TAPS = 10;
+const int CC_FILTER_TAPS = 50;                              // Nominal current draw with only Sys.Mgmt plugeed in should be 0.182A for calibration
 const int rtcGPREG_counter = 0;                             // rtc GPREG offset for the coulomb counter
 const int rtcGPREG_capacity = 1;                            // rtc GPREG offset for the capacity spec
-const float MIN_CAPACITY_SETTING = 0.5;                       // Lowest allowable capacity setting
-const float MAX_CAPACITY_SETTING = 10;                        // Largest allowable capacity setting
+const float MIN_CAPACITY_SETTING = 0.5;                     // Lowest allowable capacity setting
+const float MAX_CAPACITY_SETTING = 10;                      // Largest allowable capacity setting
 
 class CoulombCounter {
+    
 public:
 
     // Configures for a certain pin, millisecond sample period, and which GPREG in store to use to store the ampHours
     CoulombCounter(PinName _pin, int _mSec);
     
     bool overCurrentDetected();                                 // Sensor above range
-    float current();                                            // Last current reading in Amps
+    float current() { return currentFiltered; }                 // Last current reading in Amps
     void sample();
     
     float capacity() { return store.read(rtcGPREG_capacity); }
@@ -47,8 +48,9 @@
     //Ticker sampler;         // Used to capture next sample and coulomb count
     RTCStore store;
     volatile bool overCurrent;
+    void updateAvg();         // Used to get average current and update flags
     int mSec;
-    volatile float currentSample;
+    volatile float currentFiltered;
     AnalogIn BatISense;     // Analog input pin
     
     volatile float buffArr[CC_FILTER_TAPS];
--- a/Libs/DC_DC/DC_DC.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/DC_DC/DC_DC.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,22 +1,23 @@
 #include "DC_DC.h"
 #include <math.h>
 
-#define OFF 1
-#define ON 0
+#define TURN_OFF dcdcControl = 1; isControlPinOn = false;
+#define TURN_ON  dcdcControl = 0; isControlPinOn = true;
 
 const float CURRENT_MULTIPLIER_DEFAULT = 41.35338345864663;      // Full scale amps
 const float CURRENT_OFFSET_DEFAULT = 0.0909090909090909;         // Float adc reading for 0 amps
 
-const float DC_DC_ON_THRESHOLD = 0.5;                    // Current draw required in order to declare it as ON
-const int STARTUP_DELAY_MS = 500;                        // DC-DC converter startup time in milliseconds
-const float OVER_CURRENT_THRESHOLD = 25;                 // Overcurrent threshold
-const float CURRENT_SENSOR_LLIM = -0.5;                  // Lowest allowable reading before declaring sensor broken
-const int ZEROING_SAMPLES = 50;                          // Number of samples to average for zeroing
-const int STOP_DELAY_MS = 500;                           // Amount of time given to turn-off before flagging error
+const float DC_DC_ON_THRESHOLD     = 0.5;                    // Current draw required in order to declare it as on
+const int   STARTUP_DELAY_MS       = 1000;                   // DC-DC converter startup time in milliseconds
+const float OVER_CURRENT_THRESHOLD = 25;                     // Overcurrent threshold
+const float CURRENT_SENSOR_LLIM    = -1.0;                   // Lowest allowable reading before declaring sensor broken
+const float CURRENT_SENSOR_ULIM    = 33;                     // Sensor is at 5V rail, broken
+const int   STOP_DELAY_MS          = 1000;                   // Amount of time given to turn-off before flagging error
 
-DC_DC::DC_DC(PinName _dcdcPin, PinName _dcdcCurrent, PinName _fan1, PinName _fan2, PinName _pump1, PinName _pump2, float period, float slew) : 
-    dcdcControl(_dcdcPin, OFF), dcdcCurrent(_dcdcCurrent), fan1(_fan1, period, slew), fan2(_fan2, period, slew), pump1(_pump1, period, slew), pump2(_pump2, period, slew) {
-
+DC_DC::DC_DC(PinName _dcdcPin, PinName _dcdcCurrent, PinName _fan1, PinName _fan2, PinName _pump1, PinName _pump2, float period, float slew) :
+    dcdcControl(_dcdcPin, 1), dcdcCurrent(_dcdcCurrent), fan1(_fan1, period, slew), fan2(_fan2, period, slew), pump1(_pump1, period, slew), pump2(_pump2, period, slew)
+{
+    TURN_OFF
     currentOffset = CURRENT_OFFSET_DEFAULT;
     starting = false;
     stopping = false;
@@ -29,23 +30,23 @@
     // Fill up the buffer
     for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
         filterBuff[i] = (dcdcCurrent - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;
+        wait_ms(10);
     }
-    updateCurrent();
-    sample();
-    if (!critError) zeroCurrent();
+    updateCurrent();                // Compute avg
+    sample();                       // Use sample() function to check for errors
+    
+    if (!critError) {               // If no errors, zero the sensor
+        currentOffset = (current / CURRENT_MULTIPLIER_DEFAULT) + CURRENT_OFFSET_DEFAULT;
+    }
+    
+    // Correct the buffer for the new zero
+    for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
+       filterBuff[i] = ((CURRENT_OFFSET_DEFAULT - currentOffset) * CURRENT_MULTIPLIER_DEFAULT) + filterBuff[i];
+    }
 }
 
-void DC_DC::zeroCurrent() {
-    float avg=0;
-    for (int i = 0; i < ZEROING_SAMPLES; i++) {
-        avg+=dcdcCurrent;
-        wait_ms(1);   
-    }
-    avg /= ZEROING_SAMPLES;
-    currentOffset = avg;
-}
-
-void DC_DC::updateCurrent() {
+void DC_DC::updateCurrent()
+{
     float avg=0;
     for (int i = 0; i < DC_DC_FILTER_TAPS; i++) {
         avg += filterBuff[i];
@@ -54,28 +55,32 @@
     current = avg;
 }
 
-void DC_DC::set(bool on) {
+void DC_DC::set(bool on)
+{
     // Do nothing if already on
-    if (on && dcdcControl == ON) return;
+    if (on && isControlPinOn) return;
     
+    // Do nothing if already off
+    if (!on && !isControlPinOn) return;
+
     // If start requested and no error
     if (on && !critError) {
-        dcdcControl = ON;
         starting = true;
+        TURN_ON
         startTimer.reset();
         startTimer.start();
         stopTimer.stop();
         stopTimer.reset();
         stopping = false;
-        
-    // If stop requested
+
+        // If stop requested
     } else {
-        stopping=true;
+        stopping = true;
         fan1.directOff();
         fan2.directOff();
         pump1.directOff();
         pump2.directOff();
-        dcdcControl = OFF;
+        TURN_OFF
         stopTimer.reset();
         stopTimer.start();
         startTimer.stop();
@@ -84,26 +89,25 @@
     }
 }
 
-void DC_DC::sample() {
-    
+void DC_DC::sample()
+{
     // Get next current sample
-    float curr = (dcdcCurrent - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;
-    if (curr < CURRENT_SENSOR_LLIM) curr = -INFINITY;               // Check if sensor out of range
-    else if (curr < 0) curr = 0;                                    // Floor to zero             
-    filterBuff[buffTracker] = curr;                                 // Add to buffer filter
+    float curr = (dcdcCurrent.read() - currentOffset) * CURRENT_MULTIPLIER_DEFAULT;    
+
+    filterBuff[buffTracker] = curr;                             // Add to buffer filter
     buffTracker++;
     if (buffTracker >= DC_DC_FILTER_TAPS) buffTracker = 0;
-    updateCurrent();                                                // Compute average
+    updateCurrent();                                            // Compute average
     
     // Update status
-    register char stat = status & 0xF0;                        // The the upper 4 bits (locking errors)
-    if (current >= DC_DC_ON_THRESHOLD) stat |= ConvOn;         // The converter is actually on (positive current)
-    if (dcdcControl == ON) stat |= SetOn;                      // The converter is set on
-    
+    register char stat = status & 0xF0;                         // The upper 4 bits (locking errors)
+    if (current >= DC_DC_ON_THRESHOLD) stat |= ConvOn;          // The converter is actually on (positive current)
+    if (isControlPinOn) stat |= SetOn;                          // The converter is set on
+
     // During Timed Startup Phase
     if (starting) {
         stat |= PowerUp;                                        // Indicate state in status byte
-        if (startTimer.read_us() >= STARTUP_DELAY_MS*1000) {    // Start time elapsed
+        if (startTimer.read_ms() >= STARTUP_DELAY_MS) {         // Start time elapsed
             if (stat & ConvOn) {                                // Positive current detected
                 startTimer.stop();      // Stop timer
                 startTimer.reset();     // Reset to zero
@@ -114,35 +118,37 @@
                 stat |= FailStart;      // Failed to start
             }
         }
-    }
-   
+    } else stat &= ~PowerUp;
+
     // During Timed Stopping Phase
     if (stopping) {
-        stat |= PowerDown;                                    // Indicate state in status byte      
-        if (stopTimer.read_us() >= STOP_DELAY_MS*1000) {      // Stop time elapsed
-            if (stat & ConvOn) {                              // Converter still on
+        stat |= PowerDown;                                      // Indicate state in status byte
+        if (stopTimer.read_ms() >= STOP_DELAY_MS) {             // Stop time elapsed
+            if (stat & ConvOn) {                                // Converter still on
                 stopTimer.stop();
                 stopTimer.reset();
                 stat |= FailStop;         // It didn't turn off even after timer expired!
             } else {                      // Its actually off
                 stopping = false;
                 stopTimer.stop();
-                stopTimer.reset();   
+                stopTimer.reset();
             }
         }
+    } else stat &= ~PowerDown;
+
+    // While in steady state
+    if (!stopping && !starting) {
+        if ((stat & SetOn) && !(stat & ConvOn)) stat |= FailStart;    // Should be running but its not
+        else                                    stat &= ~FailStart;
+        if (!(stat & SetOn) && (stat & ConvOn)) stat |= FailStop;     // Should be stopped but its not
+        else                                    stat &= ~FailStop;
     }
     
-    if (current > OVER_CURRENT_THRESHOLD) stat |= OverCurrent;  // Over current
-    if (current == -INFINITY) stat |= SensorFault;              // Sensor out of range
-   
-    // While in steady state
-    if (!stopping && !starting) {
-        if ((stat & SetOn) && !(stat & 1)) stat |= FailStart;    // Should be running but its not
-        if (!(stat & SetOn) && (stat & 1)) stat |= FailStop;     // Should be stopped but its not
-    }
-    
+    if (current < CURRENT_SENSOR_LLIM || current > CURRENT_SENSOR_ULIM) stat |= SensorFault;    // Sensor out of range
+    else if (current > OVER_CURRENT_THRESHOLD) stat |= OverCurrent;                             // Over current
+
     // Process critical error conditions
-    if (stat & 0xF0) critError = true;
+    if (stat & (SensorFault | OverCurrent)) critError = true;
     else critError =  false;
     status = stat;
 
@@ -152,25 +158,27 @@
         fan2.directOff();
         pump1.directOff();
         pump2.directOff();
-        dcdcControl = OFF;
+        TURN_OFF
         startTimer.stop();
         startTimer.reset();
         starting = false;
     }
 }
 
-void DC_DC::setPwm(enum Channel_T chan, float duty) {
+void DC_DC::setPwm(enum Channel_T chan, float duty)
+{
     // Do nothing if error present, starting in startup, or DC-DC not actually on, or not set on
-    if (critError || starting || stopping || !(status & 1) || dcdcControl == OFF) return;
-    
+    if (critError || starting || stopping || !(status & ConvOn) || !isControlPinOn) return;
+
     else {
         if (chan == FAN1)  fan1.write(duty);
         if (chan == FAN2)  fan2.write(duty);
         if (chan == PUMP1) pump1.write(duty);
-        if (chan == PUMP2) pump2.write(duty);   
+        if (chan == PUMP2) pump2.write(duty);
     }
 }
-float DC_DC::readPwm(enum Channel_T chan) {
+float DC_DC::readPwm(enum Channel_T chan)
+{
     if (chan == FAN1) return fan1.readRaw();
     if (chan == FAN2) return fan2.readRaw();
     if (chan == PUMP1) return pump1.readRaw();
--- a/Libs/DC_DC/DC_DC.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/DC_DC/DC_DC.h	Thu Jan 22 07:58:51 2015 +0000
@@ -20,13 +20,12 @@
     FailStart=64,
     FailStop=128,
 };
-const int DC_DC_FILTER_TAPS = 10;
+const int DC_DC_FILTER_TAPS = 50;
 
 class DC_DC{
 public:
     DC_DC(PinName _dcdcPin, PinName _dcdcCurrent, PinName _fan1, PinName _fan2, PinName _pump1, PinName _pump2, float period, float slew);
     float getCurrent() { return current; }
-    void zeroCurrent();
     void set(bool on); 
     void setPwm(enum Channel_T chan, float duty);
     float readPwm(enum Channel_T chan);
@@ -50,7 +49,7 @@
     Timer stopTimer;
     volatile bool starting;
     volatile bool stopping;
-
+    volatile bool isControlPinOn;
     DigitalOut dcdcControl;
     AnalogIn dcdcCurrent;
     volatile float currentOffset;
--- a/Libs/DC_DC/FanPump/FanPump.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,87 +0,0 @@
-#include "FanPump.h"
-
-static FanPump* instance[6] = { NULL };      // Access pwm object by channel#
-const int PCLK = 24e6;                       // 24Mhz clock
-
-// Interrupt handler, must be called from static context, calls all the slew functions
-void pwmIRQ() {
-    int sum = 0;
-    int items = 0;
-    if (LPC_PWM1->IR & 1) {
-        for (int i = 0; i < 6; i++) {
-            if (instance[i] != NULL) {
-                items++;
-                sum += instance[i]->slew();
-            }
-        }
-    }
-    LPC_PWM1->IR = 0x73F;                 // Clear interrupts
-    if (items == sum) {
-        LPC_PWM1->MCR = 0;  // Detach all the interrupts, every pin is already where it needs to be
-    }
-}
-
-// Called on each timer expire for each pwm object
-int FanPump::slew() {
-    uint32_t currPulseT = *MR_base;                               // Get the current pulsewidth ticks
-    uint32_t setPointT = setPoint_us * (PCLK/1e6);                // Convert us into ticks
-    if (currPulseT == setPointT) return 1;                        // Nothing to slew here, already at its setpoint
-    
-    uint32_t currPulse_us = currPulseT / (PCLK/1e6);              // Convert to us
-    if (currPulseT < setPointT) {
-        if (setPoint_us - currPulse_us <= maxChange_us) pwm.pulsewidth_us(setPoint_us);  // Close to the setpoint, write it directly
-        else pwm.pulsewidth_us(currPulse_us + maxChange_us);       
-    } else {
-        if (currPulse_us - setPoint_us <= maxChange_us) pwm.pulsewidth_us(setPoint_us);  // Close to the setpoint, write it directly
-        else pwm.pulsewidth_us(currPulse_us - maxChange_us);
-    }
-    return 0;
-}
-
-FanPump::FanPump(PinName pin, float period, float slew) : pwm(pin) {
-    
-    // Match the pin# to the PWM object for the interrupt
-    int channel = 0;
-    if (pin == p26 || pin == LED1) channel = 1;
-    if (pin == p25 || pin == LED2) channel = 2;
-    if (pin == p24 || pin == LED3) channel = 3;
-    if (pin == p23 || pin == LED4) channel = 4;
-    if (pin == p22)                channel = 5;
-    if (pin == p21)                channel = 6;
-    if (channel == 0) return;     // Invalid pin
-    instance[channel-1] = this;   // Attach this object to an instance pointer to access from interrupt
-    
-    // Set the match register address, gap between MR3 and MR4
-    if (channel <= 3) MR_base = (uint32_t*)(&LPC_PWM1->MR0)+channel;
-    else MR_base = (uint32_t*)(&LPC_PWM1->MR4)+(channel-4);
-    
-    setPoint_us = 0;
-    period_us = period * 1.0e6;
-    pwm.period_us(period_us);
-    maxChange_us = (period / slew) * period_us;
-
-    LPC_PWM1->IR = 0x73F;    // Clear interrupts
-    NVIC_SetVector(PWM1_IRQn, (uint32_t)&pwmIRQ);
-    NVIC_SetPriority(PWM1_IRQn, 0);
-    NVIC_EnableIRQ(PWM1_IRQn);
-    LPC_PWM1->MCR = 1;       // Enable interrupt on MR0 (when the pwm period expires)
-}
-void FanPump::write(float duty) {
-    if (duty < 0) duty = 0;
-    if (duty > 1) duty = 1;
-    setPoint_us = duty * period_us;
-    LPC_PWM1->MCR = 1;       // Enable interrupt on MR0 (when the pwm period expires)
-}
-void FanPump::directOff() {
-    __disable_irq();
-    pwm.pulsewidth_us(0);
-    setPoint_us = 0;
-    __enable_irq();
-}
-float FanPump::read() {
-    return (float)(setPoint_us)/(float)(period_us);
-}
-float FanPump::readRaw() {
-    uint32_t currPulseT = *MR_base;    // Get the current pulsewidth ticks
-    return ((float)(currPulseT) / (float)(PCLK/1e6)) / (float)(period_us);
-}
\ No newline at end of file
--- a/Libs/DC_DC/FanPump/FanPump.h	Wed Jan 07 03:36:43 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,25 +0,0 @@
-#ifndef _FILE_FANPUMP_H
-#define _FILE_FANPUMP_H
-
-#include "mbed.h"
-
-class FanPump{
-public:
-    // Takes Pwmout pin, period (seconds), duty cycle slew rate in second^-1 (1 means duty 0 to 1 occurs over 1 second, 0 means no slew)
-    // Use slew rate to implement soft start
-    FanPump(PinName pin, float period, float slew);
-    void write(float duty);
-    float read();       // Read the last setpoint
-    float readRaw();    // Read the raw current duty (may be mid-transition)
-    void directOff();   // Turn off the channel immediately (no slew)
-    
-    int slew();         // Slew rate callback function
-private:
-    PwmOut pwm;         // mbed PWM out
-    uint32_t* MR_base;                  // pwm channel# match register pointer
-    volatile uint32_t period_us;        // pwm period in us, shared by all channels
-    volatile uint32_t setPoint_us;
-    volatile uint32_t maxChange_us;     // Max pulsewidth change allowed to achieve the slew rate
-};
-
-#endif
\ No newline at end of file
--- a/Libs/IMD/IMD.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/IMD/IMD.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,5 +1,6 @@
 #include "IMD.h"
 #include <math.h>
+#include "pinmap.h"
 
 static IMD* instance[4] = { 0 };    // Access member from static frame, one IMD permitted per timer module (4 total IMD objects)
 
@@ -29,42 +30,37 @@
     LPC_TIM3->IR=0x3F;        // Clear interrupt flags
 }
 
-bool cmpPin(LPC_pin p1, LPC_pin p2) {
-    if (p1.gpio_addr == p2.gpio_addr && p1.gpio_num == p2.gpio_num) return true;
-    else return false;
-}
-
-IMD::IMD(LPC_pin _pin) {
+IMD::IMD(PinName _pin) {
     // Setup the timer/pin access variables
-    if (cmpPin(_pin, p1_26)) {          // CAP0.0
+    if (_pin == P1_26) {          // CAP0.0
         timer=0;
         pin=0;
         timerBase=LPC_TIM0;
-    } else if (cmpPin(_pin, p1_27)) {   // CAP0.1
+    } else if (_pin == P1_27) {   // CAP0.1
         timer=0;
         pin=1;
         timerBase=LPC_TIM0;
-    } else if (cmpPin(_pin, p1_18)) {   // CAP1.0
+    } else if (_pin == P1_18) {   // CAP1.0
         timer=1;
         pin=0;
         timerBase=LPC_TIM1;
-    } else if (cmpPin(_pin, p1_19)) {   // CAP1.1
+    } else if (_pin == P1_19) {   // CAP1.1
         timer=1;
         pin=1;
         timerBase=LPC_TIM1;
-    } else if (cmpPin(_pin, p0_4)) {    // CAP2.0
+    } else if (_pin == P0_4) {    // CAP2.0
         timer=2;
         pin=0;
         timerBase=LPC_TIM2;
-    } else if (cmpPin(_pin, p0_5)) {    // CAP2.1
+    } else if (_pin == P0_5) {    // CAP2.1
         timer=2;
         pin=1;
         timerBase=LPC_TIM2;
-    } else if (cmpPin(_pin, p0_23)) {   // CAP3.0
+    } else if (_pin == P0_23) {   // CAP3.0
         timer=3;
         pin=0;
         timerBase=LPC_TIM3;
-    } else if (cmpPin(_pin, p0_24)) {   // CAP3.1
+    } else if (_pin == P0_24) {   // CAP3.1
         timer=3;
         pin=1;
         timerBase=LPC_TIM3;
@@ -97,9 +93,9 @@
         LPC_SC->PCLKSEL1 &= ~(3<<14);
     }
     
-    *(_pin.pinsel_addr)  |= 3 << _pin.selmode_num;     // Set pin as capture pin
-    *(_pin.pinmode_addr) |= 3 << _pin.selmode_num;     // Pull down
-    
+    pin_function(_pin, 3);      // Capture input
+    pin_mode(_pin, PullDown);   // Pull-down
+
     timerBase->TCR=2;       // Stop counter and hold at 0, for configuration
     timerBase->IR=0x3F;     // Clear any interrupt flags
     timerBase->CTCR=0;      // Use pclk, not external pin
@@ -125,7 +121,7 @@
     uint32_t capTime = pin?timerBase->CR1:timerBase->CR0;   // Get the time of the capture event
     timerBase->MR0 = capTime + TIMEOUT_TICKS;               // Move the zero timeout ahead
     
-    // Special case - on first pulse after a timeout or on startup, period cannot be calculated
+    // Special case - on first pulse after a timeout or on startup == Period cannot be calculated
     //    so set startTime such that periodTicks remains unchanged from its zero state (periodTicks=1)
     if (first) {
         first = false;
--- a/Libs/IMD/IMD.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/IMD/IMD.h	Thu Jan 22 07:58:51 2015 +0000
@@ -4,7 +4,6 @@
 #define _FILE_IMD_H  
 
 #include "mbed.h"
-#include "LPCDigitalIn.h"
 
 const float ZERO_HZ_TIMEOUT = 0.15;     // Time (sec) that must pass without an edge to call it 0 Hz, set to greater than the longest expected pulse width
 
@@ -20,7 +19,7 @@
 
 class IMD{
 public:
-    IMD(LPC_pin _pin);
+    IMD(PinName _pin);
     
     char status();
     // Gets the insulation resistance reading
--- a/Libs/LPCDigitalIn.lib	Wed Jan 07 03:36:43 2015 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1 +0,0 @@
-https://mbed.org/teams/Penn-Electric-Racing/code/LPCDigitalIn/#963ce3b85931
--- a/Libs/LatchMonitor/LatchMonitor.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/LatchMonitor/LatchMonitor.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,6 +1,6 @@
 #include "LatchMonitor.h"
 
-LatchMonitor::LatchMonitor(LPC_pin _ok, LPC_pin _fault, unsigned int startupDelay_ms):okPin(_ok, PullDown), faultPin(_fault, PullDown) {
+LatchMonitor::LatchMonitor(PinName _ok, PinName _fault, unsigned int startupDelay_ms):okPin(_ok, PullDown), faultPin(_fault, PullDown) {
     
     // Power-on reset detected
     if (LPC_SC->RSID & 1) {
--- a/Libs/LatchMonitor/LatchMonitor.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/LatchMonitor/LatchMonitor.h	Thu Jan 22 07:58:51 2015 +0000
@@ -2,7 +2,6 @@
 #define __LATCH_MONITOR_H
 
 #include "mbed.h"
-#include "LPCDigitalIn.h"
 
 enum LatchMon_Status_Bits {
     okPinF=1,
@@ -15,7 +14,7 @@
 
 public:
     // Make this startup delay longer than the actual hardware circuit delay so that it can catch errors in the circuit
-    LatchMonitor(LPC_pin _ok, LPC_pin _fault, unsigned int startupDelay_ms);
+    LatchMonitor(PinName _ok, PinName _fault, unsigned int startupDelay_ms);
     /*
         char update() returns status encoded in a char
         bit0 = okPinFault - equals 1 when the OK pin from the monitored device is LOW indicating device fault
@@ -28,8 +27,8 @@
     Timeout startup;
     void startupDelay();
     bool started;
-    LPCDigitalIn okPin;
-    LPCDigitalIn faultPin;
+    DigitalIn okPin;
+    DigitalIn faultPin;
 };
 
 #endif
\ No newline at end of file
--- a/Libs/PollSwitch/PollSwitch.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/PollSwitch/PollSwitch.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,6 +1,6 @@
 #include "PollSwitch.h"
 
-PollSwitch::PollSwitch(LPCDigitalIn *swArr, int numSw){
+PollSwitch::PollSwitch(DigitalIn *swArr, int numSw){
     numSwitches = numSw;
     sw = swArr;
 }
@@ -8,10 +8,11 @@
 char PollSwitch::poll(){
     char i = 0;
     
-    // if a low signal is detected, previous switch is broken
+    // If a low signal is detected, previous switch is broken
     for (i = 0; i < numSwitches; i++) {
-        if (!sw[i].read()) break;
+        if (sw[i].read() == 0) break;
     }
     if (i >= numSwitches) i = 0;
-    return i+1;
+    else i++;
+    return i;
 }
\ No newline at end of file
--- a/Libs/PollSwitch/PollSwitch.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/PollSwitch/PollSwitch.h	Thu Jan 22 07:58:51 2015 +0000
@@ -1,17 +1,17 @@
 #ifndef _FILE_POLLSWITCH_H
 #define _FILE_POLLSWITCH_H
 
-#include "LPCDigitalIn.h"
+#include "mbed.h"
 
 class PollSwitch{
     public:
-        PollSwitch(LPCDigitalIn *sw, int numSwitches);
+        PollSwitch(DigitalIn *sw, int numSwitches);
         
         // Returns new state, 0 means all Closed, 1=first sense line (fuse), 12=last (TSMS)
         char poll();
     
     private:
-        LPCDigitalIn *sw;
+        DigitalIn *sw;
         int numSwitches;
 };
 #endif
\ No newline at end of file
--- a/Libs/Watchdog.lib	Wed Jan 07 03:36:43 2015 +0000
+++ b/Libs/Watchdog.lib	Thu Jan 22 07:58:51 2015 +0000
@@ -1,1 +1,1 @@
-http://developer.mbed.org/teams/Penn-Electric-Racing/code/Watchdog/#cb296650f43e
+http://developer.mbed.org/teams/Penn-Electric-Racing/code/Watchdog/#339e2407baaa
--- a/inCommands/inCommands.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/inCommands/inCommands.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -32,9 +32,9 @@
             else dcdc.set(0);
             break;
 
-        case AMS_RELAYS_ID:
+        case AMS_MODE_ID:
             if (msg.len != sizeof(char)) break;
-            if ((msg.data[0] & (1<<3|1<<4|1<<5)) == (1<<3|1<<4|1<<5)) {     // AIRs closed? 1<<3=posAIR, 1<<4=negAIR, 1<<5=tractiveEnable signal
+            if (msg.data[0] & 1<<2) {     // AIRs closed?
                 CANdata.airsClosed = true;
                 dcdc.set(1);
             } else {
@@ -43,12 +43,12 @@
             }
             break;
 
-        case GLVBAT_CLEARSOC_ID:
+        case GLVBAT_SETSOC_ID:
             if (msg.len != sizeof(float)) break;
             glvBat.resetToSOC(*((float*)(&msg.data[0])));
             break;
 
-        case GLVBAT_CLEARAH_ID:
+        case GLVBAT_SETAH_ID:
             if (msg.len != sizeof(float)) break;
             glvBat.resetToAh(*((float*)(&msg.data[0])));
             break;
@@ -80,14 +80,16 @@
 
 // Compare string to a word in the serial input, shorter to type
 #define CMP(w, string)                                              if (!strcasecmp(word[w-1], string))
-static char word[3][RX_SIZE+1];
+
 // Serial input
 int inCommands::serviceSerial()
 {
+ static int end = 0;                                 // End of string position
 
-    static int end = 0;                              // End of string position
-    int c = pc.getcNb();                             // Get char from RX buffer (returns an int)
+    int c=0;
+    if (pc.readable()) c = pc.getc();
     if (c == -1) return -2;                          // Invalid char, no char available
+    
     char b = c;                                      // Casted to char type
     bool process = false;                            // Is string complete (ready to parse)?
 
@@ -101,22 +103,20 @@
         tempData.inputStr[end] = 0;                  // Erase char
 
     } else if (b > 31 && b < 127) {                  // New valid displayable char
-        tempData.inputStr[end] = b;                  // Add to buffer
-        end++;                                       // Increment end
+        tempData.inputStr[end++] = b;                // Add to buffer
         tempData.inputStr[end] = 0;                  // Add null terminator
         if (end >= RX_SIZE) {
             end = 0;                                 // Reset end location
             process = true;                          // Flag for processing
         }
     }
-
     // Continue to parsing section only if flagged as complete and string not empty
-    if (!process || strlen(tempData.inputStr) == 0) return 0;
-
+    if (!process || strlen((char*)tempData.inputStr) == 0) return 0;
+    
+    static char word[3][RX_SIZE+1];                  // Hold 3 words
     int pieces = sscanf(tempData.inputStr, "%s %s %s", word[0], word[1], word[2]);      // Populate words
     tempData.inputStr[0] = 0;                        // Empty the string displayed on screen
-
-    char *next;                                      // Used by strtod and strtoul
+    char *next;                                      // Used by strtof and strtoul
 
     // One word commands
     if (pieces == 1) {
@@ -125,8 +125,8 @@
             NVIC_SystemReset();
             return 1;
         }
-        // Two word commands
     }
+    // Two word commands
     if (pieces == 2) {
         // Manual DC-DC on/off control
         CMP(1, "dcdc") {
@@ -170,9 +170,10 @@
             if (*next == 0) {
                 if (glvBat.changeCapacity(cap)) return 1;
             }
-            return -1;   
+            return -1;
         }
     }
+    // Three word commands
     if (pieces == 3) {
         // Fan Duty
         CMP(1, "Fan") {
@@ -203,4 +204,17 @@
         }
     }
     return -1;
+}
+
+void inCommands::thread_getInputs(void const* args)
+{
+    while(1) {
+        inCommands::serviceCAN();
+        inCommands::receiveMsgXbee();
+
+        int ret = inCommands::serviceSerial();
+        if (ret == -1) tempData.parseGoodChar = 'x';
+        if (ret == 1)  tempData.parseGoodChar = 251;
+        osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<2);      // Signal watchdog thread
+    }
 }
\ No newline at end of file
--- a/inCommands/inCommands.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/inCommands/inCommands.h	Thu Jan 22 07:58:51 2015 +0000
@@ -9,6 +9,7 @@
     bool serviceCAN(CANMessage* fromXbee=0);
     bool receiveMsgXbee();
     int serviceSerial();
+    void thread_getInputs(void const* args);
 }
 
 #endif
\ No newline at end of file
--- a/main.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/main.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -3,18 +3,33 @@
 #include "outDiagnostics.h"
 #include "inCommands.h"
 
+//#define DEBUG_MODE
+
+void thread_watchDog(void const* args) {
+    tempData.wdtThreadId = Thread::gettid();
+#ifdef DEBUG_MODE
+    wdt.kick();
+#else
+    wdt.kick(WDT_TIME);
+#endif
+    while(1) {
+        Thread::signal_wait(0x1F);
+        wdt.kick();
+    }   
+}
+
 int main() {
-    wdt.kick();                         // Kick the watchdog timer
     pc.baud(BAUD);
-    pc.format(8, SerialBase::None, 2);  // 2 Stop bits, reduce bad serial packets
+    pc.format(8, SerialBase::None, 2);      // 2 Stop bits, reduce bad serial packets
+    pc.printf("\033[2J\033[2J\r\n");        // Clear screen
     
     can.mode(FIFO);
+    NVIC_SetPriority(TIMER0_IRQn, 0);
+    NVIC_SetPriority(PWM1_IRQn, 1);
+    NVIC_SetPriority(CAN_IRQn, 2);
+    NVIC_SetPriority(UART0_IRQn, 3);
     NVIC_SetPriority(TIMER3_IRQn, 4);
-    NVIC_SetPriority(UART0_IRQn, 0);
-    NVIC_SetPriority(CAN_IRQn, 3);
-    NVIC_SetPriority(TIMER0_IRQn, 1);
-    NVIC_SetPriority(PWM1_IRQn, 2);
-    
+
     bool normalReset = true;
     // Did a watchdog reset occur since last power cycle?
     if (wdt.checkFlag()) {
@@ -31,28 +46,25 @@
     }
     // Print normal reset string
     if (normalReset) pc.printf("Sys Mgmt Reset\r\n");
-    
-    // Start the 10Hz data thread
-    Thread gather(runTime::thread_gather, 0, osPriorityHigh, 512);
-    
-    // Start the 100Hz data timer (more time critical than thread)
+        
+    // Start the watchdog check-in thread
+    Thread watchdogCheck(thread_watchDog, 0, osPriorityRealtime, 128);
+        
+    // Start the 100Hz data timer (priotity high)
     RtosTimer sample(runTime::thread_sample, osTimerPeriodic);
     sample.start(FAST_LOOP*1000);
     
     // Start the serial, CAN threads
-    Thread serial_out(outDiagnostics::thread_serialOut, 0, osPriorityAboveNormal, 2000);     // Allocate 6kB RAM stack
-    Thread can_out(outDiagnostics::thread_canOut, 0, osPriorityAboveNormal, 512);            // Allocate 256B RAM stack
+    Thread serial_out(outDiagnostics::thread_serialOut, 0, osPriorityBelowNormal);
+    Thread can_out(outDiagnostics::thread_canOut, 0, osPriorityBelowNormal, 512);
     
-    wdt.kick(1);     // Startup complete, normal timeout
-    // Background task
+    // Start the input polling thread
+    Thread getInputs(inCommands::thread_getInputs, 0, osPriorityLow);
+        
+    // Main task
     while(1) {
-        // Service CAN and Xbee logic
-        inCommands::serviceCAN();
-        inCommands::receiveMsgXbee();
-        
-        int ret = inCommands::serviceSerial();
-        if (ret == -1) tempData.parseGoodChar = 'x';
-        if (ret == 1)  tempData.parseGoodChar = 251;
-        wdt.kick();
+        runTime::gather(0);
+        osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<0);      // Signal watchdog thread
+        Thread::wait(GATHER_LOOP*1000);
     }
 }
\ No newline at end of file
--- a/outDiagnostics/outDiagnostics.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/outDiagnostics/outDiagnostics.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -1,59 +1,42 @@
 #include "outDiagnostics.h"
 
-osThreadId Serialthread_id = 0;                         // RTOS thread ID of thread_serialOut
+osThreadId serialID = 0;                         // RTOS thread ID of thread_serialOut
 const int max_charsPerLine = 80;                        // Max chars per line of printed information
-const int max_lines = TX_SIZE / (max_charsPerLine+2);   // Lines per printing chunk (write chunk to MODSERIAL Buffer every x lines)
 
-// Interrupt function called when the MODSERIAL TX buffer is empty
-// The functions signals RTOS to unblock to serial thread and allow it
-// to produce the chunk of serial output data
-void empty(MODSERIAL_IRQ_INFO *q)
-{
-    osSignalSet(Serialthread_id, 1);                    // Set signal 1 for serial thread
+// Use the txEmpty interrupt from MODSERIAL to pace the thread so it always runs as fast as possible
+void empty(MODSERIAL_IRQ_INFO *q) {
+    osSignalSet(serialID, 1);
 }
 
-// Add a line of text to the printing queue.
-// Actually gets added to another local buffer, which gets copied into the MODSERIAL TX buffer when it
-// empties.  Provides double-buffered output stream so inflow and outflow rates can be different.
-// Char *str NEEDS to be NULL terminated string! bool newline determines whether newline characters \r\n are appended to the line
-void AddToChunk (char *str, bool newline=true)
+// Output a string to the MODSERIAL tx buffer, wait when buffer full
+void AddtoBuffer(char *str, bool newline=true)
 {
-    static char chunk[(max_charsPerLine+5)*max_lines];          // The chunk buffer, holds one chunk= max_charsPerLine*max_lines characters
-    static int pos = 0;                                         // The position to load next character
-    static int lines = 0;                                       // Number of lines currently stored in the chunk
-    static int wait = pc.txBufferGetSize(0) * (CHAR_TIME*1000); // Max wait time to empty the tx buffer = max time to send out all chars
-
-    pos += sprintf(chunk+pos, "%s%s", str, newline?"\r\n":"");  // Append to working array
-    lines++;                                                    // New line added to array
-
-    if (lines >= max_lines) {                                   // Time to print the block
-        // Is buffer free enough to accept the block?
-        if (pc.txBufferGetCount() - pc.txBufferGetSize(0) > pos+5) {
-            for (int i = 0; i < pos; i++) pc.putc(chunk[i]);    // Add the string to the buffer
-        } else {
-            // No, it is not free enough to hold the string
-            osSignalClear(Serialthread_id, 1);                  // Clear signal if it was set
-            Thread::signal_wait(1, wait);                       // RTOS wait for empty signal, max wait if it never occurs
-            for (int i = 0; i < pos; i++) pc.putc(chunk[i]);    // Add into the output buffer
+    const int waitT = TX_SIZE * CHAR_TIME*1000;             // Max wait time to empty the tx buffer = max time to send out all chars
+    int len = strlen(str);
+    int times = newline ? (len + 2) : (len);                // If newline requested, add 2 chars for "\r\n"
+    for (int i = 0; i < times; i++) {
+        if (!pc.writeable()) {                              // Keep writing till it fills
+            osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<3);  // Check-in with watchdog thread
+            Thread::signal_wait(1, waitT);                  // Wait for empty signal from MODSERIAL tx empty interrupt, timeout in waitT ms
         }
-        lines = 0;                                              // Chunk added, reset line counter
-        pos = 0;                                                // Chunk added, reset position
+        if (i < len) pc.putc(str[i]);                       // Print the string
+        else if (i == len) pc.putc('\r');                   // Add carriage return
+        else if (i > len) pc.putc('\n');                    // Add newline
     }
 }
 
 // Print to internal string buffer, pad to maxLen chars and center it with char pad, str must be null terminated!
 void padCenter(int LineLen, char *str, char pad)
 {
-    static char line[max_charsPerLine+5];                    // String buffer to work with one line at a time
+    static char line[max_charsPerLine+5];                   // String buffer to work with one line at a time
+    int len = strlen(str);                                  // Length of input string
+    int padL = (LineLen-len)/2;                             // How many pad chars needed on left side?
+    for (int i=0; i<padL; i++) line[i] = pad;               // Fill in the left padding chars
+    strcpy(line+padL, str);                                 // Copy to line string
+    for (int i = padL+len; i<LineLen; i++) line[i] = pad;   // Fill remaining with padding chars
+    line[LineLen-1] = '\0';                                 // Add null terminator
 
-    int len = strlen(str);                                   // Length of input string
-    int padL = (LineLen-len)/2;                              // How many pad chars needed on left side?
-    for (int i=0; i<padL; i++) line[i] = pad;                // Fill in the left padding chars
-    strcpy(line+padL, str);                                  // Copy to line string
-    for (int i = padL+len; i<LineLen; i++) line[i] = pad;    // Fill remaining with padding chars
-    line[LineLen-1] = '\0';                                  // Add null terminator
-
-    AddToChunk(line);
+    AddtoBuffer(line);
 }
 
 
@@ -67,11 +50,10 @@
 // Generates the serial dashboard, uses MODSERIAL, self-paced (thread yields when buffer is full, resumes when empty)
 void outDiagnostics::thread_serialOut(void const *args)
 {
-    Serialthread_id = Thread::gettid();              // Record thread ID so empty() can signal this thread
+    serialID = Thread::gettid();                     // Record thread ID so empty() can signal this thread
     char temp[max_charsPerLine+5];                   // String buffer to sprintf into, max 1 line
 
     pc.attach(&empty, MODSERIAL::TxEmpty);           // Attach the tx empty interrupt which paces this thread
-    pc.printf("\033[2J");                            // Clear the screen to get rid of reset message
 
     tempData.parseGoodChar = ' ';
     tempData.inputStr[0] = 0;
@@ -89,7 +71,7 @@
         serialLoop.reset();
 
         sprintf(temp, "\033[0;0H\033[0;0H");
-        AddToChunk(temp, false);                     // Move to 0,0, do not append newline
+        AddtoBuffer(temp, false);                     // Move to 0,0, do not append newline
         
         DIVIDER_LINE
         TITLE(" Penn Electric Racing - REV0 System Management Controller Dashboard ")
@@ -97,10 +79,10 @@
         
         int tempLength=0;
         tempLength += sprintf(temp, "Command Input:%c %s%c", tempData.parseGoodChar, tempData.inputStr, 176);  // Command input: print header, reply, input string, and cursor marker
-        for (int i = 0; i < max_charsPerLine - strlen(temp)- 1; i++) {      // Fill in the rest of the line with blanks
+        for (int i = 0; i < max_charsPerLine - tempLength - 1; i++) {      // Fill in the rest of the line with blanks
             tempLength += sprintf(temp+tempLength, " ");                    // Append spaces
         }
-        AddToChunk(temp);        // Add this to the chunk
+        AddtoBuffer(temp);        // Add this to the chunk
         
         TITLE(" GLV Battery ")
         BLANK_LINE
@@ -121,7 +103,7 @@
         else if (!(DCDC & SetOn))  dcdcMode = 4;
         sprintf(temp, "Active: %3s     Mode: %10s     AIRS: %6s     StatusByte: 0x%02x", (DCDC & ConvOn)?"YES":"NO", dcdcModesStr[dcdcMode], CANdata.airsClosed?"CLOSED":"OPEN", DCDC);
         ADD_SPRINTF_LINE
-        sprintf(temp, "Current: %5.3fA     Overcurrent: %3s     SensorFault: %3s", data.dcdcCurrent, BOOL(DCDC & OverCurrent), BOOL(DCDC & SensorFault));
+        sprintf(temp, "Current: %5.2fA     Overcurrent: %3s     SensorFault: %3s", data.dcdcCurrent, BOOL(DCDC & OverCurrent), BOOL(DCDC & SensorFault));
         ADD_SPRINTF_LINE
         sprintf(temp, "StartFault: %3s     StopFault:   %3s     CritErrors:  %3s", BOOL(DCDC & FailStart), BOOL(DCDC & FailStop), BOOL(data.dcdcError));
         ADD_SPRINTF_LINE
@@ -146,9 +128,9 @@
         BLANK_LINE
         char AMSerr = data.AMSlatchError;
         char IMDerr = data.IMDlatchError;
-        sprintf(temp, "AMS: OK: %4s Latch: %3s SoftFault: %3s HardFault: %3s", (AMSerr & 1)?"LOW":"HIGH", BOOL(AMSerr & 2), BOOL(AMSerr & 4), BOOL(AMSerr & 8));
+        sprintf(temp, "AMS -    OK: %4s Latch: %3s   SoftFault: %3s   HardFault: %3s", (AMSerr & 1)?"LOW":"HIGH", BOOL(AMSerr & 2), BOOL(AMSerr & 4), BOOL(AMSerr & 8));
         ADD_SPRINTF_LINE
-        sprintf(temp, "IMD: OK: %4s Latch: %3s SoftFault: %3s HardFault: %3s", (IMDerr & 1)?"LOW":"HIGH", BOOL(IMDerr & 2), BOOL(IMDerr & 4), BOOL(IMDerr & 8));
+        sprintf(temp, "IMD -    OK: %4s Latch: %3s   SoftFault: %3s   HardFault: %3s", (IMDerr & 1)?"LOW":"HIGH", BOOL(IMDerr & 2), BOOL(IMDerr & 4), BOOL(IMDerr & 8));
         ADD_SPRINTF_LINE
 
         BLANK_LINE
@@ -163,15 +145,15 @@
         BLANK_LINE
         TITLE(" Telemetry ")
         BLANK_LINE
-        sprintf(temp, "Channel 1: MessagesIn: %5d MessagesOut: %5d", xbeeRelay.counterX1in, xbeeRelay.counterX1out);
+        sprintf(temp, "Channel 1 -    MessagesIn: %5d   MessagesOut: %5d", xbeeRelay.counterX1in, xbeeRelay.counterX1out);
         ADD_SPRINTF_LINE
-        sprintf(temp, "Channel 2: MessagesIn: %5d MessagesOut: %5d", xbeeRelay.counterX2in, xbeeRelay.counterX2out);
+        sprintf(temp, "Channel 2 -    MessagesIn: %5d   MessagesOut: %5d", xbeeRelay.counterX2in, xbeeRelay.counterX2out);
         ADD_SPRINTF_LINE
 
         BLANK_LINE
         TITLE(" Miscellaneous ")
         BLANK_LINE
-        sprintf(temp, "Temp: %5.1fC %3s canFault: %3s Watchdog: %3s ErrorCode: 0x%02x SerailTime: %3dms", data.internalTemp, BOOL(data.internalOverTemp), BOOL(data.canFault), BOOL(data.watchdogReset), data.errorFrame, serialTime_ms);
+        sprintf(temp, "Temp: %5.1fC %3s canFault: %3s Watchdog: %3s ErrorCode: 0x%02x SerialTime: %3dms", data.internalTemp, BOOL(data.internalOverTemp), BOOL(data.canFault), BOOL(data.watchdogReset), data.errorFrame, serialTime_ms);
         ADD_SPRINTF_LINE
 
         // Erase screen every 5sec to remove glitches
@@ -232,7 +214,8 @@
 
         // Shutdown Switches
         CHAR(data.switchState, SYS_SWITCHES_ID)
-
+        
+        osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<4);      // Signal watchdog thread
         Thread::wait(CAN_LOOP*1000);
     }
 }
\ No newline at end of file
--- a/runTime/runTime.cpp	Wed Jan 07 03:36:43 2015 +0000
+++ b/runTime/runTime.cpp	Thu Jan 22 07:58:51 2015 +0000
@@ -2,48 +2,48 @@
 
 const float INTERNAL_OVER_TEMP_THRES = 60;  // Overtemp at 60C
 
-void runTime::thread_gather(void const* args) {
-    while(1) {
-        
-        // GLV battery coulomb counter
-        data.glvCurrent = glvBat.current();
-        data.glvSOC = glvBat.SOC();
-        data.glvAmphours = glvBat.ampHours();
-        data.glvCapacity = glvBat.capacity();
-        data.glvOverCurrent = glvBat.overCurrentDetected();
-        
-        // DC-DC converter & PWM channels
-        data.dcdcStatus = dcdc.getStatus();
-        data.dcdcError = dcdc.hasCritError();
-        data.dcdcCurrent = dcdc.getCurrent();
-        data.dcdcFan1Duty = dcdc.readPwm(FAN1);
-        data.dcdcFan2Duty = dcdc.readPwm(FAN2);
-        data.dcdcPump1Duty = dcdc.readPwm(PUMP1);
-        data.dcdcPump2Duty = dcdc.readPwm(PUMP2);
-        
-        // IMD PWM
-        data.imdStatus = imd.status();
-        data.imdResistance = imd.resistance();
-        data.imdError = ((data.imdStatus != NORMAL) && (data.imdStatus != SPEEDSTART)) || (isnan(data.imdResistance));
-        
-        // Reset latches
-        data.AMSlatchError = AMSlatch.update();
-        data.IMDlatchError = IMDlatch.update();
+void runTime::gather(void const* args)
+{
+    // GLV battery coulomb counter
+    data.glvCurrent = glvBat.current();
+    data.glvSOC = glvBat.SOC();
+    data.glvAmphours = glvBat.ampHours();
+    data.glvCapacity = glvBat.capacity();
+    data.glvOverCurrent = glvBat.overCurrentDetected();
+
+    // DC-DC converter & PWM channels
+    data.dcdcStatus = dcdc.getStatus();
+    data.dcdcError = dcdc.hasCritError();
+    data.dcdcCurrent = dcdc.getCurrent();
+    data.dcdcFan1Duty = dcdc.readPwm(FAN1);
+    data.dcdcFan2Duty = dcdc.readPwm(FAN2);
+    data.dcdcPump1Duty = dcdc.readPwm(PUMP1);
+    data.dcdcPump2Duty = dcdc.readPwm(PUMP2);
 
-        // Switches
-        data.switchState = switches.poll();
-        
-        // Temperaure
-        data.internalTemp = internalTmp.read();
-        if (data.internalTemp > INTERNAL_OVER_TEMP_THRES) data.internalOverTemp = true;
-        else data.internalOverTemp = false;
-        
-        // Error frame
-        data.errorFrame = data.canFault<<0 | data.watchdogReset<<1 | data.internalOverTemp<<2 | (data.IMDlatchError!=0)<<3 | (data.AMSlatchError!=0)<<4 | data.imdError<<5 | data.dcdcError<<6 | data.glvOverCurrent<<7;
-        Thread::wait(GATHER_LOOP*1000);   
-    }
+    // IMD PWM
+    data.imdStatus = imd.status();
+    data.imdResistance = imd.resistance();
+    data.imdError = ((data.imdStatus != NORMAL) && (data.imdStatus != SPEEDSTART)) || (isnan(data.imdResistance));
+
+    // Reset latches
+    data.AMSlatchError = AMSlatch.update();
+    data.IMDlatchError = IMDlatch.update();
+
+    // Switches
+    data.switchState = switches.poll();
+
+    // Temperaure
+    data.internalTemp = internalTmp.read();
+    if (data.internalTemp > INTERNAL_OVER_TEMP_THRES) data.internalOverTemp = true;
+    else data.internalOverTemp = false;
+
+    // Error frame
+    data.errorFrame = data.canFault<<0 | data.watchdogReset<<1 | data.internalOverTemp<<2 | (data.IMDlatchError!=0)<<3 | (data.AMSlatchError!=0)<<4 | data.imdError<<5 | data.dcdcError<<6 | data.glvOverCurrent<<7;
 }
-void runTime::thread_sample(void const* args) {
+
+void runTime::thread_sample(void const* args)
+{
+    osSignalSet((osThreadId)(tempData.wdtThreadId), 1<<1);      // Signal watchdog thread
     glvBat.sample();    // Integrate next sample in GLV Battery coulomb counter
     dcdc.sample();      // Handle dc-dc filter and errors
 }
\ No newline at end of file
--- a/runTime/runTime.h	Wed Jan 07 03:36:43 2015 +0000
+++ b/runTime/runTime.h	Thu Jan 22 07:58:51 2015 +0000
@@ -5,7 +5,7 @@
 
 
 namespace runTime {
-    void thread_gather(void const* args);
+    void gather(void const* args);
     void thread_sample(void const* args);
 }