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:59:48 2015 +0000
Parent:
36:0afc0fc8f86b
Child:
38:8efacce315ae
Commit message:
Tested in car with other systems. Most features working. Xbees need work. DC-DC protection features are glitchy due to spurious current readings. Thresholds may need adjustment.

Changed in this revision

Libs/DC_DC/FanPump/FanPump.cpp Show annotated file Show diff for this revision Revisions of this file
Libs/DC_DC/FanPump/FanPump.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libs/DC_DC/FanPump/FanPump.cpp	Thu Jan 22 07:59:48 2015 +0000
@@ -0,0 +1,101 @@
+#include "FanPump.h"
+
+#define S_ATOMIC __disable_irq();
+#define E_ATOMIC __enable_irq();
+
+static FanPump* instance[6] = { NULL };      // Access pwm object by channel#
+const int PCLK = 24e6;                       // 24Mhz default clock to PWM module
+
+// Interrupt handler, must be called from static context, calls all the slew functions
+void pwmIRQ()
+{
+    int sum = 0, items = 0;
+    if (LPC_PWM1->IR & 1) {                 // Interrupt pending
+        for (int i = 0; i < 6; i++) {       // Check every channel
+            if (instance[i] != NULL) {      // Make sure it exists
+                items++;                    // Count each number serviced
+                sum += instance[i]->slew(); // Add the return values (1 if nothing was done in function)
+            }
+        }
+    }
+    LPC_PWM1->IR = 0x73F;                   // Clear interrupt
+    if (items == sum) {
+        LPC_PWM1->MCR = 0;  // Disable the interrupts, every duty 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
+    if (channel == 1) MR_base = &LPC_PWM1->MR1;
+    if (channel == 2) MR_base = &LPC_PWM1->MR2;
+    if (channel == 3) MR_base = &LPC_PWM1->MR3;
+    if (channel == 4) MR_base = &LPC_PWM1->MR4;
+    if (channel == 5) MR_base = &LPC_PWM1->MR5;
+    if (channel == 6) MR_base = &LPC_PWM1->MR6;
+
+    setPoint_us = 0;
+    period_us = period * 1.0e6;
+    pwm.period_us(period_us);
+    pwm = 0;
+    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);
+}
+
+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()
+{
+    S_ATOMIC                 // Ensure that it happens now, no thread-switching
+    pwm.pulsewidth_us(0);
+    setPoint_us = 0;
+    E_ATOMIC
+}
+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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Libs/DC_DC/FanPump/FanPump.h	Thu Jan 22 07:59:48 2015 +0000
@@ -0,0 +1,33 @@
+#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)
+    #ifdef MBED_OPERATORS
+    operator float() {
+        return read();
+    }
+    FanPump& operator= (float value) {  // Overloaded equals to write function
+        write(value);
+        return *(this);
+    }
+    #endif
+    int slew();         // Slew rate callback function
+private:
+    PwmOut pwm;         // mbed PWM out
+    volatile 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;     // pwm setpoint (goal) in us
+    volatile uint32_t  maxChange_us;    // Max pulsewidth change in us allowed for each PWM period to achieve the slew rate
+};
+
+#endif