Power control and management

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
andrewcrussell
Date:
Thu Nov 10 11:11:58 2022 +0000
Parent:
1:a8f96f76bd8a
Child:
3:92148e16d530
Commit message:
Nov 10 2022

Changed in this revision

Pindef1114.lib Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/Pindef1114.lib	Thu Feb 16 13:39:39 2017 +0000
+++ b/Pindef1114.lib	Thu Nov 10 11:11:58 2022 +0000
@@ -1,1 +1,1 @@
-https://developer.mbed.org/users/andrewcrussell/code/Pindef1114/#65d86f38bafb
+https://developer.mbed.org/users/andrewcrussell/code/Pindef1114/#e84a8f21a441
--- 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;