Power control and management

Dependencies:   mbed

Revision:
2:c449cfb7752c
Parent:
0:36494271e31a
--- a/main.cpp	Thu Feb 16 13:39:39 2017 +0000
+++ b/main.cpp	Thu Nov 10 11:11:58 2022 +0000
@@ -2,125 +2,121 @@
 /*                                  Andrew C. Russell (c) 2015                              */
 /* The controller pin definitions are set in Pindef1114.h file.                             */
 /* The main loop is driven by an interrupt on ACDET1 - 16.66ms for 60 Hz and 20ms for 50 Hz */
-/* The WDT is set for a 25ms timeout. If AC power is removed, the SPKR and INRUSH outputs   */
-/* are driven LOW immediately. The power supply to the uC is supported by a 100uF 6.3V      */
-/* capacityor to facilitate this.  If the ERROR input goes LOW after power-up cycle,  the   */
+/* The WDT is set for a 25ms timeout. If AC power is removed, the MCU resets in 25ms        */
+/* and all relays de-energized. If the ERROR input goes LOW after power-up cycle,  the      */
 /* program disconnects the speaker. During the power up cycle  - 150 mains cycles for       */
-/* pre-charge and 150 mains cycles for the output to DC settle - and whenever an error      */
+/* pre-charge and 250 mains cycles for the output to DC settle - and whenever an error      */
 /* condition is encountered, the power LED is flashed at 0.5 Hz                             */
 /* The latency between the loss of ACDET1 and the SPKR being disengaged is ~25ms            */ 
-/* Note that if the TRIGGER input is used, the +12V actually powers up the controller       */
-/* which then bootstraps itself by applying AC power via the PWR_R                          */
+/* Provision for two 10k NTC thermistor sensors is also provided. The NTC is in the lower   */
+/* leg of a divider with the upper leg a 10k resistor. The trip temp (TRIPON),              */
+/* reset temp (TRIPOFF) and the temperature alarm (TEMPHIGH) are directly set in Volts      */
+/* A low on the clip input will cause the clip LED to flash on for 1s. Note CLIP has to     */
+/* recycle HIGH and then LOW again to retrigger the CLIP output - it does not flash         */ 
+/* continuosly if held LOW                                                                  */
+/* Note: if the amp clips for too long, the DC offset interuppt will be triggered because   */
+/* the clip input and the DC offset detect inputs are connected.                            */
 
 #include "mbed.h"
-#include "WDT.h"
+#include "WDT.h"            // Watch Dog Timer 
 #include "Pindef1114.h"     // all microcontroller I/O pin assignments defined here    
-#include "AnalogIn.h"
+#include "AnalogIn.h"       // standard mbed supplied analog driver header file
+#include "math.h"
+
 #define AC_LOSS 0.025       // this is the wdt set value in seconds
 #define TRUE 1
 #define FALSE 0
 #define HIGH 1
 #define LOW 0
-#define BAD 0
-#define OK 1
-#define INDIC 25            // the number of mains cycles between indicator lamp flip
-#define inrush_t 150        //# of mains cycles to wait before bypassing the NTC
+#define INDIC 25            // the number of mains cycles between LED illumination flip
+#define inrush_t 200        //# of mains cycles to wait before bypassing the NTC
 #define amp_settle 300      //# of mains cycles to let amp module OP settle
-#define CLIP_ON 5           // the clip LED goes on for ACDET1 periodes
-#define TEMPHIGH  0.7       // temperature alarm
-#define TRIPON 0.83         // this is the trip temperature - 830mV = 65 deg C on LM60
-#define TRIPOFF 0.75        // this is the lower re-activate amplifier 
-                            //temperature - ~59 deg C LM60
-                            
-int T1;
-int T2;
-int T3;
-int T4;
+#define CLIP_ON 20          // the clip LED goes on for n ACDET1 periods
+#define TEMPHIGH  65        // temperature alarm in Volts - 65 deg C
+#define TRIPON 70           // this is the trip temperature in volts - 70 deg C
+#define TRIPOFF 62          // this is the lower re-activate amplifier temperature in volts - 64 deg C
+
+//Following used in the calculation of temp in deg C from an NTC
+#define Vref 3.31           // this is the A-D reference voltage
+#define Ref 10000            // the upper reference resistor from VREF to the NTC [was 2.2k]
+#define To 298              // coefficiants required for Steinhart-Hart equation
+#define B 3900              // from NTC data sheet
+#define Ro 10000  
+#define cal65 3.3           // cal out any error at 65deg C  - determined by applying
+                            // required offset at 65 deg C - so at 65C the temp is accurate           
+
+#define e 2.718281828459
+
+int F1;                     // test flag used in trip() TRUE if overtemp has tripped
 int mains_cnt;              // mains cycle counter
-int FLAG1;                  // used to detect if we are in or out of power up process
-int FLAG_TRIGGER;           // TRUE if power up was via the trigger input
+int FLAG1;                  // TRUE if power-up process is completed otherwise FALSE
 int indi_flip;              // counts mains cycles  - used in indicator status
 int clip_cnt;               // ACDET1 int derived counter for the clip indicator
-float templ;
+float templ;                // left and right channel temperature read in by A-D in deg C
 float tempr;
-int temp_status;
-
-Ticker flipper;             // this is the ACDET timer - runs at 13.2 or 20ms
-// ref 60 Hz or 50 Hz mains frequency
+float t_left;
+float t_right;
 
+Ticker flipper;             // this is the ACDET1 WDT ticker timer
+                            
 // declare function prototypes here
-void analog_input(void);    // measure the temperature    
-void output_clip(void);     // clip indicator 
-void indi_flash (void);     // universal indicator flash
-void temp_trip (void);      // action to be taken when overtemp
-void acdetect(void);        // triggers the counter
+void trip(void);                    // assess what actions to take based on temperature    
+void temp_measure(void);            // measure the temparature
+void output_clip(void);             // clip indicator 
+void indi_flash (void);             // universal indicator flash
+void temp_trip (void);              // action to be taken when overtemp
+void acdetect(void);                // triggers the counter
 
 /************************************ analog_input *********************************/
+void trip(void) {
 
-void analog_input (void) {
-    
-    templ = left_temp*3.3;
-    tempr = right_temp*3.3;
-    
-    //if ((templ > TRIPOFF) || (tempr > TRIPOFF)) {
-    //    temp_status = BAD; } else (temp_status = OK);
-   
-        if ((templ > TEMPHIGH) || (tempr > TEMPHIGH)) {
-        clip = HIGH;}
-                else (clip = LOW);
+        
+        // temp alarm on either input 
+        if ((t_left >= TEMPHIGH) || (t_right >= TEMPHIGH)) {   
+            clip = HIGH; }
         
-        if (((templ > TRIPON) || (tempr > TRIPON))) {  // && ((templ > TRIPOFF) || (tempr > TRIPOFF)) && (FLAG1 == TRUE)) {
-            SPKR = LOW;
-            indi_flash();
-             }
             
-                    
-        if ((templ <= TRIPOFF) && (tempr <= TRIPOFF) && (FLAG1 == TRUE)){
-            SPKR = HIGH;}
-            }
-
+        if ((t_left < TEMPHIGH) && (t_right < TEMPHIGH) && (FLAG1 == TRUE)) {
+                       SPKR = HIGH; }
+                       
+        if ((t_left > TRIPON) || (t_right > TRIPON)) { //temp trip
+            SPKR = LOW; 
+            F1 = TRUE; }
+        
+        // below is to turn speaker relay back ON if the temperature has fallen BELOW TRIPOFF
+     
+        if (((t_left < TRIPOFF) && (t_right < TRIPOFF)) && (FLAG1 == TRUE)){
+            SPKR = HIGH;
+            clip = LOW; 
+            F1 = FALSE; }
+            
+           
+    }
 /*********************************** ACDET1 Interrupt ******************************/
 void acdetect(void)
 {
-    ACDET1.rise(NULL);
+    ACDET1.rise(NULL);              // prevent accidental re-entry
+    
     if (mains_cnt < amp_settle) {
         mains_cnt++;
-        FLAG1 = FALSE;
+        FLAG1 = FALSE;              // FLAG1 only becomes TRUE after power up process is complete
     }
 
     else if (mains_cnt >= amp_settle) {
-        FLAG1 = TRUE;           // fully powered up at this point
-        mains_cnt = amp_settle;
-    }       // after power up mains_cnt is held to amp_settle
-    ACDET1.rise(&acdetect);
+        FLAG1 = TRUE;               // fully powered up at this point
+        mains_cnt = amp_settle;     // after power up mains_cnt is held to amp_settle
+            }
+          
+    ACDET1.rise(&acdetect);         // reinstate the interrupt
 }
 /******************************** output clip ****************************************/
 
 void output_clip(void) {
-      clip_cnt = CLIP_ON;          
-   
-   }
+      clip_cnt = CLIP_ON;  }
     
-/********************** power down routine for Trigger input *************************/
-void power_down(void)
-{
-    __disable_irq();
-    SPKR = LOW;
-    INDI = HIGH;
-    wait_ms(2);
-    INRUSH = LOW;
-    if (FLAG_TRIGGER == TRUE) {
-        FLAG_TRIGGER = FALSE;
-        PWR_R = LOW;
-    }
-    FLAG1 = FALSE;
-    do {
-        continue;
-    } while(1);     // just wait here unit all power is gone
-    // amplifier is in power down mode
-}
-
 /******************************** indi_flash ***************************************/
+// this just flashes the power LED to indicate amp is in power-up cycle 
+// or a temperature shutdown
 
 void indi_flash(void)
 {
@@ -129,72 +125,106 @@
         indi_flip = 0;
             }
      }
+/************************************ temp_measure **********************************/
+/* This routine fetches the NTC resistance as measured at the A-D inputs left_temp  */
+/* and right Temp. It uses the Steinhart-Hart NTC R>T equation to compute the       */
+/* temperature.left_temp and right_temp are A-D inputs defined in the pindef.h file */
 
-/************************************ main() ***************************************/
+void temp_measure(void) {
+
+float vo_left;
+float vo_right;    
+float r_left;
+float r_right;
+float l_roh;
+float r_roh;
+
+// first, fetch the NTC resistances
+
+    vo_left = left_temp*Vref;               //scale the A-D reading for Vref = 3.3V
+    vo_right = right_temp*Vref;
+
+    r_left = vo_left/((Vref-vo_left)/Ref);
+    r_right = vo_right/((Vref-vo_right)/Ref);
+    
+// from the NTC resistance, calculate the temperature in Kelvin using the 
+// simplified Steinhart-Hart Equation. 
+
+        l_roh = Ro*(pow(e,(-B/To)));  
+        t_left = (B/(log(r_left/l_roh)))-(273+cal65);
+  
+        r_roh = Ro*(pow(e,(-B/To)));
+        t_right = (B/(log(r_right/r_roh)))-(273+cal65);
+        
+    //printf used for temp debugging. Clock must be slowed to ~ 1Hz 
+    //printf("t_left = %f        t_right =  %f          \n\r", t_left, t_right);
+    
+    }
+
+
+/************************************* main() ***************************************/
 int main(void)
 {
-    __disable_irq();            // just to make sure we can set up correctly without problems
-    INRUSH = LOW;               // power bypass disabled
-    SPKR = LOW;                 // speakers muted
-    PWR_R = LOW;                // power ON/OFF relay is OFF
-    INDI = HIGH;                // open drain indicator output is deactivated - take LOW
-    clip = LOW;
-    clip_in.mode(PullUp);       // clip input
+    __disable_irq();                // just to make sure we can set up correctly without problems
+    INRUSH = LOW;                   // power bypass disabled
+    SPKR = LOW;                     // speakers muted
+    PWR_R = LOW;                    // power ON/OFF relay is OFF - only used if TRIGGER is used
+    INDI = HIGH;                    // open drain indicator output is deactivated - active LOW
+    clip = LOW;                     // clip LED driver output
+    clip_in.mode(PullUp);           // clip input
     clip_in.fall(&output_clip);
     clip_cnt = 0;
+    ERROR.mode(PullUp);
+    PWR_D.mode(PullDown);           // used to detect power down
     ACDET1.mode(PullDown);
-    ACDET1.rise(&acdetect);     // trigger counter on rising edge
+    ACDET1.rise(&acdetect);         // trigger counter on rising edge
+    SYNC = LOW;                     // SYNC flips once every mains cycle - 20ms period @ 50 Hz
+                                 
+    FLAG1 = FALSE;                  // force a fault condition until first pass through main loop
+    F1 = TRUE;                      // assume we are over temperature until our first sensor reading   
+    INDI = HIGH;                    // power LED is ON steady
+    __enable_irq();
     
-    SYNC = LOW;
-    wait_ms(500);               // let PSU etc settle in first ~1 mains cycles
-
-//  if (PWR_D == HIGH) {        // power came in via TRIGGER input
-//      FLAG_TRIGGER = TRUE;
-//      PWR_R = HIGH;           // turn the main power relay ON - only used
-//       }                      // with amplifiers with TRIGGER input facility
-    INDI = HIGH;                // power LED is ON
-    __enable_irq();
-    Watchdog wdt;               // enable the WDT just before we start the main loop
-    wdt.kick(AC_LOSS);
+    Watchdog wdt;                   // enable the WDT just before we start the main loop
+    wdt.kick(AC_LOSS);              // kick the WDT at regular 25 ms intervals (set by AC_LOSS)
 
-LOOP:                           // this main loop is driven by the 20ms/16.6ms interrupts
-                                // generated by the ACDET1 input
-                                // if the INT's fail to arrive after 25ms, the AC power
-                                // is lost and the WDT will reset the system = power down
-    __WFI();                    // waiting for ACDET1 INT
-    wait_ms(5);                 // make sure we are away from the zero crossing 50 Hz or 60 Hz
-    wdt.kick();
-        acdetect();
-           
-        if (PWR_D == HIGH) {        // check if input power detector is HIGH
-        FLAG_TRIGGER = TRUE;
-        PWR_R = HIGH; }         // turn on main power relay
-
-        if ((ERROR == LOW) && (FLAG1 == TRUE)) {        // we have a fault condition but will
-        SPKR = LOW;                                     // skip this if the error clears itself
+LOOP:                               // this main loop is driven by the 20ms/16.6ms interrupts
+                                    // generated by the ACDET1 input
+                                    // if the INT's fail to arrive after 25ms, the AC power
+                                    // is assumed lost and the WDT will reset the system = power down
+                                    // de-engergizing all relays
+    __WFI();                        // waiting for ACDET1 INT
+    wait_ms(1);                     // make sure we are away from the zero crossing 50 Hz or 60 Hz
+     wdt.kick();
+       
+       if ((mains_cnt >= amp_settle) && (ERROR == HIGH) && (FLAG1 == FALSE)) {
+            INDI = HIGH;
+            SPKR = HIGH; }          // inrush and amp settle complete - enable SPKR if no ERROR
+       
+       if (mains_cnt > inrush_t) {
+          INRUSH = HIGH;}
+       
+       // make sure the clip LED goes OFF if all is ok   
+       if((clip_cnt <= 0) && (SPKR == HIGH) && (ERROR == HIGH)) {  
+                     INDI = HIGH; }    
+                        
+       if (clip_cnt <= 0) {                     // note: clip flashes on change of state
+            clip = LOW;}                        // i.e on edges
+                else if (clip_cnt > 0) {
+                        clip = HIGH;
+                        INDI = LOW; }           // so LED is RED on clip and not ORANGE
+    
+        if ((ERROR == LOW) || (FLAG1 == FALSE)) {
+            SPKR  = LOW;
+                indi_flash(); }
+       
+    temp_measure();
+    trip();
+    
+    if (F1 == TRUE) {
         indi_flash(); }
-
-        if ((ERROR == HIGH) && (FLAG1 == TRUE)){
-            INDI = HIGH; }
-
-        if(mains_cnt < amp_settle) {
-        INRUSH = HIGH;
-        indi_flash(); }
-
-        if ((mains_cnt >= inrush_t) && (mains_cnt >= amp_settle) == TRUE) {
-        SPKR = HIGH; }
-
-        if ((PWR_D == LOW) && (FLAG_TRIGGER == TRUE)) {
-        power_down(); }
-        
-        if (clip_cnt <= 0) {
-        clip = LOW;}
-        else if (clip_cnt != 0) {
-        clip = HIGH;}
     
-    analog_input();
-            
-    SYNC = !SYNC;               // ACDET1 sync output for debugging
+    SYNC = !SYNC;          // ACDET1 sync output for debugging
     indi_flip++;
     clip_cnt--;
     goto LOOP;