System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
Revision 36:0afc0fc8f86b, committed 2015-01-22
- 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
--- 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);
}
