System Management code
Dependencies: mbed CANBuffer Watchdog MODSERIAL mbed-rtos xbeeRelay IAP
Fork of SystemManagement by
Revision 13:fbd9b3f5a07c, committed 2014-10-24
- Comitter:
- pspatel321
- Date:
- Fri Oct 24 22:09:04 2014 +0000
- Parent:
- 12:e0adb697fcdb
- Child:
- 14:8d4959210d4b
- Child:
- 25:900579201439
- Commit message:
- Fork showing Parth's changes to current monitor, IMD, and fanpump.
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CoulombCounter/CoulombCounter.cpp Fri Oct 24 22:09:04 2014 +0000
@@ -0,0 +1,33 @@
+#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_LIMS = 3.0; // Over-current limit = +/- 3A
+
+CoulombCounter::CoulombCounter(PinName _IsensePin, int mSec, int _rtcGPREG_counter, int _rtcGPREG_capacity) : BatISense(p19) {
+ mSec = _mSec;
+ rtcGPREG_counter = _rtcGPREG_counter;
+ rtcGPREG_capacity = _rtcGPREG_capacity;
+
+ // Take the initial reading
+ currentSample = BatISense*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
+ if (currentSample < -BAT_ISENSE_LIMS || currentSample > BAT_ISENSE_LIMS) overCurrent = true;
+ else overCurrent = false;
+
+ // Start counting
+ sampler.attach_us(this, &CoulombCounter::sample, mSec*1000);
+}
+
+void CouloumbCounter::sample() {
+ // Take the reading
+ currentSample = BatISense.read()*BAT_ISENSE_MULTIPLIER+BAT_ISENSE_OFFSET;
+
+ // Signal error on over current
+ if (currentSample < -BAT_ISENSE_LIMS || currentSample > BAT_ISENSE_LIMS) {
+ overCurrent = true;
+ } else overCurrent = false;
+
+ // Integrate
+ store.write(ampHours()+currentSample*mSec*MSEC_HRS, rtcGPREG_counter);
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CoulombCounter/CoulombCounter.h Fri Oct 24 22:09:04 2014 +0000
@@ -0,0 +1,41 @@
+#ifndef _FILE_CURRENTMONITOR_H
+#define _FILE_CURRENTMONITOR_H
+
+#include "mbed.h"
+#include "CANBuffer.h"
+#include "Store_RTC.h"
+
+RTCStore store;
+
+class CoulombCounter {
+public:
+
+ // Configures for a certain pin, millisecond sample period, and which GPREG in RTC to use to store the ampHours
+ CoulombCounter(int _mSec, int _rtcGPREG_counter, int _rtcGPREG_capacity);
+
+ // Allow zeroing the SOC when the battery is fully charged/dead, SOC in % from 0 to 1
+ void resetToSOC(float SOC) { store.write(SOC*capacity(), rtcGPREG_counter); }
+
+ // Allow zeroing the SOC (via zeroing the Ah) when the battery is fully charged/dead
+ void resetToAh(float Ah) { store.write(Ah, rtcGPREG_counter); }
+
+ // Allow change of capacity spec (changes SOC)
+ void changeCapacity(float capAh) {store.write(capAh, rtcGPREG_capacity); }
+
+ bool overCurrent; // Sensor above range
+ float current() { return currentSample; } // Last current reading in Amps
+ float ampHours() { return store.read(rtcGPREG_counter); }
+ float capacity() { return store.read(rtcGPREG_capacity); }
+ float SOC() { return ampHours()/capacity(); }
+
+private:
+ Ticker sampler; // Used to capture next sample and coulomb count
+ void sample();
+ int mSec;
+ float currentSample;
+
+ int rtcGPREG_counter;
+ int rtcGPREG_capacity;
+ AnalogIn BatISense; // Analog input pin
+};
+#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/CoulombCounter/RTCStore.h Fri Oct 24 22:09:04 2014 +0000
@@ -0,0 +1,38 @@
+/* Test Code
+ #include "Battery_Status.h"
+ #include"mbed.h"
+ BatteryStatus battery;
+
+ int main()
+ {
+ //battery.write(6.92,0);
+ printf("LPC_RTC->GPREG0:%f\n\r",battery.read(0));
+ //battery.write(7.92,1);
+ printf("LPC_RTC->GPREG1:%f\n\r",battery.read(1));
+ //battery.write(8.92,2);
+ printf("LPC_RTC->GPREG2:%f\n\r",battery.read(2));
+ //battery.write(9.92,3);
+ printf("LPC_RTC->GPREG3:%f\n\r",battery.read(3));
+ //battery.write(10.92,4);
+ printf("LPC_RTC->GPREG4:%f\n\r",battery.read(4));
+ }
+*/
+
+#ifndef _RTC_STORE_H
+#define _RTC_STORE_H
+#include "mbed.h"
+
+class RTCStore {
+public:
+ RTCStore() {
+ LPC_SC->PCONP |= (1<<9); // Enable RTC Peripheral
+ }
+ void write(float data, int block) {
+ *((float*)(&LPC_RTC->GPREG0)+sizeof(float)*block) = data;
+ }
+ float read(int block) {
+ return *((float*)((&LPC_RTC->GPREG0)+sizeof(float)*block));
+ }
+};
+#endif
+
\ No newline at end of file
--- a/CurrentMonitor/CurrentMonitor.cpp Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#include "mbed.h"
-#include "CurrentMonitor.h"
-#include "Store_RTC.h"
-
-#define MSEC_HRS 2.77778e-7
-#define DC_DC_ISENSE_OFFSET_V 0.5
-#define DC_DC_ISENSE_INCREMENT 0.133
-
-#define BAT_ISENSE_OFFSET_V 1.65
-#define BAT_ISENSE_INCREMENT 0.5297
-
-CANBuffer *tx_Current_Buffer;
-
-double BATmA_Hr;
-float DCA_msec,BATA_msec;
-float Bat_I_Ratio,DC_I_Ratio;
-
-AnalogIn BatISense(p19);
-AnalogIn DCSense(p20);
-
-RTCStore store;
-
-union converter{
- float data;
- char ch[4];
-} convert;
-
-CurrentMonitor::CurrentMonitor(CANBuffer *can){
- tx_Current_Buffer = can;
-}
-
-void update_current(const void *arg){
- char data[4] = {0};
- while(1){
- float bat_reading = store.read(1);
- convert.data = bat_reading;
-
- data[0] = convert.ch[0];
- data[1] = convert.ch[1];
- data[2] = convert.ch[2];
- data[3] = convert.ch[3];
-
- CANMessage txMessage(TX_CURRENT_ID, data, 4);
- tx_Current_Buffer->txWrite(txMessage);
-
- Thread::wait(100); //10 Hz update
- }
-}
-
-void monitor_current(const void *arg){
- while(1){
- Bat_I_Ratio=BatISense.read();
- BATA_msec=(((Bat_I_Ratio*3.3) - BAT_ISENSE_OFFSET_V)/BAT_ISENSE_INCREMENT);
- BATmA_Hr+=(BATA_msec*MSEC_HRS);
- store.write(BATmA_Hr,0);
-
- DC_I_Ratio=DCSense.read();
- DCA_msec=(((DC_I_Ratio*3.3) - DC_DC_ISENSE_OFFSET_V)/DC_DC_ISENSE_INCREMENT);
- store.write(DCA_msec,1);
-
- Thread::wait(1); //1 Khz coulomb counter
- }
-}
-
-void CurrentMonitor::start_update(){
- Thread monitor_thread(monitor_current);
- Thread update_thread(update_current);
-}
\ No newline at end of file
--- a/CurrentMonitor/CurrentMonitor.h Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,18 +0,0 @@
-#ifndef _FILE_CURRENTMONITOR_H
-#define _FILE_CURRENTMONITOR_H
-
-#include "mbed.h"
-#include "rtos.h"
-#include "CANBuffer.h"
-
-const int TX_CURRENT_ID = ((4 << 8) | 3);
-
-class CurrentMonitor{
-public:
- CurrentMonitor(CANBuffer *can);
- void start_update();
-
-private:
-
-};
-#endif
\ No newline at end of file
--- a/FanPump/FanPump.cpp Tue Oct 21 23:44:15 2014 +0000
+++ b/FanPump/FanPump.cpp Fri Oct 24 22:09:04 2014 +0000
@@ -1,110 +1,56 @@
-#include "mbed.h"
#include "FanPump.h"
-PwmOut pwmPins[PIN_NUM] = {
- PwmOut(P2_0), // pump 1
- PwmOut(P2_1), // pump 2
- PwmOut(P2_2), // fan 1
- PwmOut(P2_3), // fan 2
-};
-
-PinStatus pin_status[PIN_NUM];
-CANBuffer *tx_Fan_Buffer;
+static FanPump* instance[6] = { NULL };
-FanPump::FanPump(CANBuffer *can){
- for(int i = 0; i < PIN_NUM; i++){
- pin_status[i].cur_duty = 0.0;
- pin_status[i].new_duty = 0.0;
-
- pin_status[i].pin = &pwmPins[i];
- pin_status[i].pin->period_ms(10);
- pin_status[i].pin->write(0.0);
-
- pin_threads[i] = NULL;
- }
-
- tx_Fan_Buffer = can;
+// Interrupt handler, must be called from static context, calls all the slew functions
+void pwmIRQ() {
+ if (LPC_PWM1->IR & 1) {
+ for (int i = 0; i < 6; i++) {
+ if (instance[i] != NULL) instance[i]->slew();
+ }
+ }
+ LPC_PWM1->IR = 0x73F; // Clear interrupts
}
-// this is not a member function. For some reason, thread does weird things
-// with functions in classes. Apparently pointers get messed up when pointing to
-// a function in a class
-void ramp_pin(void const *arg)
-{
- PinStatus *pin_stat = (PinStatus *)arg;
- float *cur_duty = &(pin_stat->cur_duty);
- float *new_duty = &(pin_stat->new_duty);
-
- while(*cur_duty != *new_duty)
- {
- if(*new_duty > *cur_duty){
- *cur_duty += 1.0;
-
- if(*cur_duty > *new_duty)
- *cur_duty = *new_duty;
- } else if(*new_duty < *cur_duty){
- *cur_duty -= 1.0;
-
- if(*cur_duty < *new_duty)
- *cur_duty = *new_duty;
- }
-
- pin_stat->pin->write((*cur_duty));
-
- Thread::wait(5); //1% duty cycle per 0.005 s
+// Called on each timer expire for each pwm object
+void FanPump::slew() {
+ uint32_t currPulseT = *(&LPC_PWM1->MR0+pin);
+ uint32_t currPulse_us = currPulseT / 24;
+ uint32_t setPointT = setPoint_us * 24; // Convert us into ticks
+ if (currPulseT == setPointT) return; // Nothing to slew here, already at its setpoint
+
+ 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);
+ else pwm.pulsewidth_us(currPulse_us - maxChange_us);
}
}
-void FanPump::set_fan_pump(FanPumpSelect fan_pump, float duty){
- if((int)fan_pump >= PIN_NUM || duty > 100.0)
- return;
+FanPump::FanPump(PinName pin, float period, float slew) : pwm(pin) {
+ setPoint_us = 0;
+ period_us = period / 1.0e6;
+ pwm.period_us(period_us);
+ maxChange_us = (period / slew) * period_us;
- free_pin(fan_pump);
-
- pin_status[fan_pump].new_duty = duty;
- pin_threads[fan_pump] = new Thread(ramp_pin, &pin_status[fan_pump]);
-}
-
-void FanPump::shutdown(FanPumpSelect fan_pump){
- free_pin(fan_pump);
+ // Match the pin# to the PWM object for the interrupt
+ if (pin == p26 || pin == LED1) pin = 1;
+ if (pin == p25 || pin == LED2) pin = 2;
+ if (pin == p24 || pin == LED3) pin = 3;
+ if (pin == p23 || pin == LED4) pin = 4;
+ if (pin == p22) pin = 5;
+ if (pin == p21) pin = 6;
+ instance[pin-1] = this;
- pin_status[fan_pump].cur_duty = 0;
- pin_status[fan_pump].new_duty = 0;
- pin_status[fan_pump].pin->write(0);
-}
-
-void FanPump::shutdown_all(){
- for(int i = 0; i < PIN_NUM; i++)
- FanPump::shutdown((FanPumpSelect)i);
+ LPC_PWM1->IR = 0x73F; // Clear interrupts
+ NVIC_SetVector(PWM1_IRQn, (uint32_t)&pwmIRQ);
+ NVIC_SetPriority(PWM1_IRQn, 0);
+ NVIC_EnableIRQ(PWM1_IRQn);
+ LPC_PWM1->MR |= 1; // Enable interrupt on MR0 (when the pwm period expires)
}
-
-void FanPump::free_pin(FanPumpSelect fan_pump){
- if(pin_threads[fan_pump] != NULL){
- pin_threads[fan_pump]->terminate();
- free(pin_threads[fan_pump]);
- }
-}
-
-void update_fans_pumps(void const *arg){
- char data[8] = {0};
- while(1){
- memcpy(&pin_status[0].cur_duty, data, sizeof(float));
- memcpy(&pin_status[1].cur_duty, data+4, sizeof(float));
-
- CANMessage txPumpMessage(TX_PUMP_ID, data, 8);
- tx_Fan_Buffer->txWrite(txPumpMessage);
-
- memcpy(&pin_status[2].cur_duty, data, sizeof(float));
- memcpy(&pin_status[3].cur_duty, data+4, sizeof(float));
-
- CANMessage txFanMessage(TX_FAN_ID, data, 8);
- tx_Fan_Buffer->txWrite(txFanMessage);
-
- Thread::wait(100); // 10 Hz update
- }
-}
-
-void FanPump::start_update()
-{
- Thread update_thread(update_fans_pumps);
+void FanPump::write(float duty) {
+ if (duty < 0) duty = 0;
+ if (duty > 1) duty = 1;
+ setPoint_us = duty * period_us;
}
\ No newline at end of file
--- a/FanPump/FanPump.h Tue Oct 21 23:44:15 2014 +0000
+++ b/FanPump/FanPump.h Fri Oct 24 22:09:04 2014 +0000
@@ -2,38 +2,22 @@
#define _FILE_FANPUMP_H
#include "mbed.h"
-#include "rtos.h"
-#include "CANBuffer.h"
-
-typedef enum {
- Pump1 = 0,
- Pump2 = 1,
- Fan1 = 2,
- Fan2 = 3,
-} FanPumpSelect;
-
-typedef struct{
- float cur_duty;
- float new_duty;
- PwmOut *pin;
-} PinStatus;
-
-const int PIN_NUM = 4;
-const int TX_FAN_ID = ((0x4 << 8) | 0x11);
-const int RX_FAN_ID = ((0x4 << 8) | 0x81);
-const int TX_PUMP_ID = ((0x4 << 8) | 0x10);
-const int RX_PUMP_ID = ((0x4 << 8) | 0x80);
class FanPump{
public:
- FanPump(CANBuffer *can);
- void set_fan_pump(FanPumpSelect fan, float duty);
- void shutdown(FanPumpSelect fan);
- void shutdown_all();
- void start_update();
+ // 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 slew(); // Slew rate callback function
private:
- Thread *pin_threads[PIN_NUM];
- void free_pin(FanPumpSelect fan);
+ PwmOut pwm; // mbed PWM out
+ int pin; // pwm channel#
+ static uint32_t period_us; // Period in microseconds (shared by all channels)
+ uint32_t setPoint_us;
+ uint32_t maxChange_us; // Max pulsewidth change allowed to achieve the slew rate
};
#endif
\ No newline at end of file
--- a/Get_IMD/Get_IMD.h Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,133 +0,0 @@
-#include "mbed.h"
-#include "string.h"
-
-DigitalOut myled(LED1);
-
-//Serial pc(USBTX,USBRX);
-
-#ifndef GET_IMD_H
-#define GET_IMD_H
-
- typedef struct
- {
- float Frequency;
- float Duty_Cycle;
- char State[50];
- char Encoded_Status;
- }IMD_Measurement_Output;
-
- bool FirstFE=true;
- bool FirstRE=true;
- uint32_t ON_Period =0;
- uint32_t INT0_RE,INT0_FE;
- uint32_t CAP0RE=0, CAP0FE=1, CRO_I=4;
- IMD_Measurement_Output Result;
-
- extern "C" void TIMER0_IRQHandler(void)
- {
- INT0_RE=LPC_TIM0->CCR;
- INT0_FE=LPC_TIM0->CCR;
-
-
- if(((INT0_FE & (1 << CAP0FE)) >> CAP0FE))
- {
- if(!FirstFE)
- {
- //pc.printf("LPC_TIM1->TC in FE:%d\n\r",LPC_TIM1->TC);
- ON_Period = LPC_TIM1->TC;
- //pc.printf("On Period:%d\n\r",ON_Period);
- LPC_TIM0->CCR |= ((1<<0) | (1<<2)); //Copy TC to CRO on Rising Edge AND Generate Interrupt
- LPC_TIM0->CCR &= ~(1<<1); //Disable Falling Edge
- }
- else
- FirstFE=false;
- }
- else if((INT0_RE & (1 << CAP0RE))>> CAP0RE)
- {
- //pc.printf("On Period In RE:%d\n\r",ON_Period);
- if(!FirstRE)
- {
- //pc.printf("LPC_TIM1->TC in RE:%d\n\r",LPC_TIM1->TC);
- //pc.printf("On Period In RE:%d\n\r",ON_Period);
- Result.Frequency=((1/(float)LPC_TIM1->TC)*1000);
- Result.Duty_Cycle=((ON_Period/(float)LPC_TIM1->TC)*100);
- LPC_TIM0->CCR |= ((1<<1) | (1<<2)); //Copy TC to CRO on Falling Edge AND Generate Interrupt
- LPC_TIM0->CCR &= ~(1<<0); //Disable Rising Edge
- LPC_TIM1->TCR |= (1<<1); //Reset Timer1
- LPC_TIM1->TCR &= ~(1<<1); //Restart Timer1
- }
- else
- FirstRE=false;
- }
- LPC_TIM0->IR |= (1<<CRO_I); //Reset Counter0 Interrupt
- return;
- }
-
- void init()
- {
- Result.Frequency=0;
- Result.Duty_Cycle=0;
- strcpy(Result.State,"");
- //Set pin as capture mode
- //Initialize Counter2
- LPC_PINCON->PINSEL3 |= ((1<<21) | (1<<20)); //Set Pin1.26 as CAP0.0
- LPC_SC->PCONP |= (1<<1); //PowerOn Timer/Counter0.
- LPC_TIM0->CCR |= ((1<<1) | (1<<2)); //Copy TC to CRO on Falling Edge AND Generate Interrupt
- NVIC_SetPriority(TIMER0_IRQn,255);
- NVIC_EnableIRQ(TIMER0_IRQn); //Enable TIMER0 IRQ
-
- //Initiallize Timer1
- LPC_SC->PCONP |= (1<<2); //PoewerOn Timer/Counter1
- LPC_SC->PCLKSEL0 |= ((1<<4) | (1<<5)); //Prescale Timer1 CCLK/8
- LPC_TIM1->CTCR &= ~((1<<1) | (1<<0)); //Set Timer/Counter1 as as Timer mode
- LPC_TIM1->PR = 11985; //Timeout every 1msec(Timer Resolution)
- LPC_TIM1->TCR |= (1<<1); //Reset Timer1
- LPC_TIM1->TCR |= (1<<0); //Enable Timer1
- //LPC_TIM1->TCR &= ~(1<<1); //Restart Timer1
- FirstRE=false;
- FirstFE=false;
- }
-
- void Disable()
- {
- LPC_TIM1->TCR |= (1<<1); //Reset Timer1
- LPC_TIM0->IR |= (1<<4); //Reset Counter0 Interrupt
- NVIC_DisableIRQ(TIMER0_IRQn);
- }
-
- IMD_Measurement_Output Get_Measurement()
- {
- init();
- wait_ms(300);
- Disable();
- if(Result.Frequency >=5 && Result.Frequency <15){
- strcpy(Result.State, "Normal condition");
- Result.Encoded_Status='1';
- }
- else if(Result.Frequency >=15 && Result.Frequency <25){
- strcpy(Result.State, "underVoltage condition");
- Result.Encoded_Status='2';
- }
- else if(Result.Frequency >=25 && Result.Frequency <35)
- {
- if(Result.Duty_Cycle <=15){
- strcpy(Result.State, "Insulation measurement:good");
- Result.Encoded_Status='3';
- }
- else if(Result.Duty_Cycle > 85 && Result.Duty_Cycle < 100){
- strcpy(Result.State, "Insulation measurement:bad");
- Result.Encoded_Status='4';
- }
- }
- else if(Result.Frequency >=35 && Result.Frequency <45){
- strcpy(Result.State, "Device error");
- Result.Encoded_Status='5';
- }
- else if(Result.Frequency >=45 && Result.Frequency <55){
- strcpy(Result.State, "Connection fault earth");
- Result.Encoded_Status='6';
- }
- return Result;
- }
-
- #endif/* GET_IMD_H */
\ No newline at end of file
--- a/Get_IMD/IMD.cpp Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-#include "IMD.h"
-
-CANBuffer *tx_IMD_Buffer;
-
-IMD::IMD(CANBuffer *can): _p(P1_26) {
- _p.rise(this, &IMD::rise);
- _p.fall(this, &IMD::fall);
- _period = 0.0;
- _pulsewidth = 0.0;
-
- tx_IMD_Buffer = can;
-}
-
-void IMD::rise() {
- _period = _t.read();
- _t.reset();
-}
-
-void IMD::fall() {
- _pulsewidth = _t.read();
-}
-
-float IMD::frequency() { return 1/_period; }
-float IMD::pulse_width() { return _pulsewidth; }
-float IMD::duty() { return _pulsewidth / _period; }
-
-/*
- Status State
- 1 Normal
- 2 under voltage
- 3 Insulation measurement: good
- 4 Insulation measurement: bad
- 5 Device error
- 6 Connection fault earth
-*/
-void update_IMD(void const *arg){
- IMD *instance = (IMD *)arg;
- char data[1] = {0};
- while(1){
- float freq = instance->frequency();
- float duty = instance->duty();
-
- if(freq >= 5 && freq <15){
- data[0] = 1;
- }else if(freq >= 15 && freq < 25){
- data[0] = 2;
- }else if(freq >= 25 && freq < 35){
- if(duty <= 15){
- data[0] = 3;
- } else if(duty > 85 && duty < 100){
- data[0] = 4;
- }
- }else if(freq >= 35 && freq < 45){
- data[0] = 5;
- }else if(freq >= 45 && freq < 55){
- data[0] = 6;
- }
-
- CANMessage txMessage(TX_IMD_ID, data, 1);
- tx_IMD_Buffer->txWrite(txMessage);
-
- Thread::wait(100); //10 Hz update
- }
-}
-
-void IMD::start_update(){
- Thread update_thread(update_IMD, this);
-}
--- a/Get_IMD/IMD.h Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,28 +0,0 @@
-// copied idea from http://developer.mbed.org/forum/mbed/topic/466/?page=1#comment-2457
-
-#ifndef _FILE_IMD_H
-#define _FILE_IMD_H
-
-#include "mbed.h"
-#include "CANBuffer.h"
-#include "rtos.h"
-
-const int TX_IMD_ID = ((0x4 << 8) | 0x20);
-
-class IMD{
- public:
- IMD(CANBuffer *can);
- void start_update();
- float frequency();
- float pulse_width();
- float duty();
-
- private:
- InterruptIn _p;
- Timer _t;
- float _pulsewidth, _period;
- void rise();
- void fall();
-};
-
-#endif
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMD/IMD.cpp Fri Oct 24 22:09:04 2014 +0000
@@ -0,0 +1,127 @@
+#include "IMD.h"
+#include <math.h>
+
+static IMD* instance;
+
+const uint32_t PCLK = 24000000; // Timer counting clock = 24Mhz
+const uint32_t TIMEOUT_TICKS = PCLK*ZERO_HZ_TIMEOUT; // Zeroing timeout in clock ticks = seconds * PCLK
+const float EXTRA = 0.01; // Margin on the IMD PWM limits
+const float ULIM = 50000000; // Max value produced by IMD
+
+// Interrupt function, must be static context
+void TIM0_IRQ() {
+ // Capture event was found
+ if (LPC_TIM0->IR & 1<<4) instance->edgeIRQ();
+
+ // MR0 (zero Hz timeout) event was found
+ if (LPC_TIM0->IR & 1) instance->zeroIRQ();
+ LPC_TIM0->IR=0x3F; // Clear interrupt flags
+}
+
+IMD::IMD() {
+ instance = this;
+ first = true;
+ startTime = 0;
+ widthTicks = 0; // Zero low, so that duty = 0/1 = 0%
+ periodTicks = 1;
+
+ LPC_SC->PCONP |= (1<<2); // Power on timer1
+ LPC_SC->PCLKSEL0 &= ~(3<<4); // Clock at 24MHz
+
+ *(p1_26.pinsel_addr) |= 3 << p1_26.selmode_num; // Set pin as capture pin
+ *(p1_26.pinmode_addr) |= (3 << p1_26.selmode_num); // Pull down
+
+ LPC_TIM0->TCR=2; // Stop counter and hold at 0, for configuration, set to 1 to start operation
+ LPC_TIM0->IR=0x3F; // Clear any interrupt flags
+ LPC_TIM0->CTCR=0; // Use pclk, not external pin
+ LPC_TIM0->PR=0; // No prescale value, clock at full pclk=24Mhz
+ LPC_TIM0->EMR=0; // Do not use external match pins
+
+ NVIC_SetVector(TIMER1_IRQn, (uint32_t)&TIM0_IRQ); // Point to the edge interrupt handler
+ NVIC_SetPrioriry(TIMER1_IRQn, 0); // Highest Priority
+ NVIC_EnableIRQ(TIMER1_IRQn); // Enable IRQ
+ LPC_TIM0->CCR = RISING; // Generate interrupt on capture, capture on rising edge to start
+ LPC_TIM0->MCR = 1; // Interrupt on Match0 to establish the zero speed timeout
+ LPC_TIM0->MR0 = LPC_TIM0->TC+TIMEOUT_TICKS;
+ LPC_TIM0->TCR = 1; // Start counting, GO!
+}
+
+void IMD::edgeIRQ() {
+ enum EdgeT type = LPC_TIM0->CCR;
+ uint32_t capTime = LPC_TIM0->CR0;
+ LPC_TIM0->MR0 = capTime+TIMEOUT_TICKS; // Set the next zeroing timeout
+
+ // 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;
+ startTime = capTime - 1;
+ }
+ if (type == RISING) {
+ periodTicks = capTime - startTime; // Get the period on Rising edge
+ startTime = capTime; // Set the start of the next pulse
+ }
+ if (type == FALLING) {
+ widthTicks = capTime - startTime; // Get the pulse width on Falling edge
+ }
+
+ // Switch interrupt types to capture the next edge
+ if (type == RISING) LPC_TIM0->CCR = FALIING;
+ if (type == FALLING) LPC_TIM0->CCR = RISING;
+}
+
+void IMD::zeroIRQ() {
+ enum EdgeT type = LPC_TIM0->CCR;
+ periodTicks = 1;
+ first = true;
+
+ // Timeout occurred after FALLING edge, now looking for RISING edge
+ if (type == RISING) {
+ widthTicks = 0; // Signal is low = 0/1 = 0% duty
+ }
+ if (type == FALLING) {
+ widthTicks = 1; // Signal is high = 1/1 = 100% duty
+ }
+}
+float IMD::frequency() {
+ // Handle the case where we want to say 0Hz not infinity Hz
+ if (periodTicks == 1 || periodTicks == 0) return 0;
+ else return (float)(PCLK)/(float)(periodTicks);
+}
+float IMD::duty() {
+ return (float)(widthTicks)/(float)(periodTicks);
+}
+
+char IMD::status() {
+ float freq = frequency();
+ if (freq == 0) return 0; // IMD off
+ else if (05 < freq && freq <= 15) return 1; // 10Hz normal mode
+ else if (15 < freq && freq <= 25) return 2; // 20Hz undervoltage mode
+ else if (25 < freq && freq <= 35) return 3; // 30Hz speed start mode
+ else if (45 < freq && freq <= 55) return 4; // 40Hz IMD error
+ else if (55 < freq && freq <= 65) return 5; // 50Hz Ground error
+ else return -1; // Invalid
+}
+
+float IMD::resistance() {
+ char status = status();
+ float duty = duty();
+
+ // In normal or undervoltage mode, where Rf is available
+ if (status == 1 || status == 2) {
+ if (0.05-EXTRA <= duty && duty >= 0.95+EXTRA) {
+ float rf = (0.9*1200e3/(duty-0.05)) - 1200e3;
+ if (rf < 0) rf = 0;
+ if (rf > 50e6) rf = 50e6;
+ return rf;
+ }
+ else return -1;
+ }
+ // In speed start, where only good/bad estimate is available
+ if (status == 3) {
+ if (0.05-EXTRA <= duty && duty >= 0.10+EXTRA) return 50e6; // Good
+ else if (0.90-EXTRA <= duty && duty >= 0.95+EXTRA) return 0; // Bad
+ else return -1;
+ }
+ return NaN;
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/IMD/IMD.h Fri Oct 24 22:09:04 2014 +0000
@@ -0,0 +1,53 @@
+// copied idea from http://developer.mbed.org/forum/mbed/topic/466/?page=1#comment-2457
+
+#ifndef _FILE_IMD_H
+#define _FILE_IMD_H
+
+#include "mbed.h"
+#include "LPCDigitalIn.h"
+
+const float ZERO_HZ_TIMEOUT = 0.1; // Time (sec) that must pass without an edge to call it 0 Hz, set to greater than the longest expected pulse width
+
+enum EdgeT {
+ RISING=5,
+ FALLING=6,
+ BOTH=7,
+};
+class IMD{
+public:
+ IMD();
+
+ // Get the IMD status
+ /*
+ Status State
+ 0 IMD off
+ 1 Normal
+ 2 under voltage
+ 3 Speed Start
+ 4 IMD error
+ 5 Ground error
+ */
+ char status();
+
+ // Gets the insulation resistance reading
+ // Returns 0 to 50,000,000 in normal/UV modes
+ // Returns 0 or 50,000,000 in speed start (good/bad only)
+ // -1 for invalid measurement (out of permissible range)
+ // and NaN for not applicable mode
+ float resistance();
+
+ // Interrupt function for the edge type detected
+ void edgeIRQ();
+ // Used to zero (reset) the data on timeout
+ void zeroIRQ();
+
+private:
+ float frequency();
+ float duty();
+ uint32_t startTime;
+ uint32_t widthTicks;
+ uint32_t periodTicks;
+ bool first;
+};
+
+#endif
\ No newline at end of file
--- a/LPCDigitalIn.lib Tue Oct 21 23:44:15 2014 +0000 +++ b/LPCDigitalIn.lib Fri Oct 24 22:09:04 2014 +0000 @@ -1,1 +1,1 @@ -https://mbed.org/teams/Penn-Electric-Racing/code/LPCDigitalIn/#fbd18a1431cf +https://mbed.org/teams/Penn-Electric-Racing/code/LPCDigitalIn/#963ce3b85931
--- a/RTCStore/Store_RTC.h Tue Oct 21 23:44:15 2014 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,51 +0,0 @@
-/* Test Code
- #include "Battery_Status.h"
- #include"mbed.h"
- BatteryStatus battery;
-
- int main()
- {
- //battery.write(6.92,0);
- printf("LPC_RTC->GPREG0:%f\n\r",battery.read(0));
- //battery.write(7.92,1);
- printf("LPC_RTC->GPREG1:%f\n\r",battery.read(1));
- //battery.write(8.92,2);
- printf("LPC_RTC->GPREG2:%f\n\r",battery.read(2));
- //battery.write(9.92,3);
- printf("LPC_RTC->GPREG3:%f\n\r",battery.read(3));
- //battery.write(10.92,4);
- printf("LPC_RTC->GPREG4:%f\n\r",battery.read(4));
- }
-*/
-
-#ifndef _BATTERY_STATUS_
-#define _BATTERY_STATUS_
-#include"mbed.h"
-
-// General purpose register 0
-#define _GPREG_BASE 0x40024044
-
-// RTC = Real-Time Clock
-
-class RTCStore
-{
- public:
- RTCStore()
- {
- LPC_SC->PCONP |= (1<<9); //Enable RTC Peripheral
- }
-
- void write(float data, int block)
- {
- *(uint32_t*)(_GPREG_BASE + (0x04*block)) = *((uint32_t*)&data);
- //LPC_RTC->GPREG0 = *((uint32_t*)&data);
- }
-
- float read(int block)
- {
- return *((float*)(uint32_t*)(_GPREG_BASE + (0x04*block)));
- //return *((float*)&(LPC_RTC->GPREG0));
- }
-};
-#endif /* _BATTERY_STATUS_ */
-
\ No newline at end of file
--- a/SysManagement_kiran_full.lib Tue Oct 21 23:44:15 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1 +0,0 @@ -http://developer.mbed.org/users/martydd3/code/SystemManagement/#e02eb179aed3
--- a/SysMngmt.cpp Tue Oct 21 23:44:15 2014 +0000
+++ b/SysMngmt.cpp Fri Oct 24 22:09:04 2014 +0000
@@ -4,7 +4,6 @@
Revised Oct 19, 2014: First team repository version
*/
-#include "Store_RTC.h"
#include "XBee_Lib.h"
#include "CANBuffer.h"
--- a/Watchdog.lib Tue Oct 21 23:44:15 2014 +0000 +++ b/Watchdog.lib Fri Oct 24 22:09:04 2014 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/teams/Penn-Electric-Racing/code/Watchdog/#390a291e8c4b +http://developer.mbed.org/teams/Penn-Electric-Racing/code/Watchdog/#cb296650f43e
--- a/mbed-rtos.lib Tue Oct 21 23:44:15 2014 +0000 +++ b/mbed-rtos.lib Fri Oct 24 22:09:04 2014 +0000 @@ -1,1 +1,1 @@ -http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#631c0f1008c3 +http://developer.mbed.org/users/mbed_official/code/mbed-rtos/#aaa1b2c7c64c
--- a/mbed.bld Tue Oct 21 23:44:15 2014 +0000 +++ b/mbed.bld Fri Oct 24 22:09:04 2014 +0000 @@ -1,1 +1,1 @@ -http://mbed.org/users/mbed_official/code/mbed/builds/0b3ab51c8877 \ No newline at end of file +http://mbed.org/users/mbed_official/code/mbed/builds/552587b429a1 \ No newline at end of file
