Andrew R
/
Power_Sequencer_Nov_10_2022
Power control and management
Embed:
(wiki syntax)
Show/hide line numbers
main.cpp
00001 /****************************** Power Sequencer and Controller V1.0 *************************/ 00002 /* Andrew C. Russell (c) 2015 */ 00003 /* The controller pin definitions are set in Pindef1114.h file. */ 00004 /* The main loop is driven by an interrupt on ACDET1 - 16.66ms for 60 Hz and 20ms for 50 Hz */ 00005 /* The WDT is set for a 25ms timeout. If AC power is removed, the MCU resets in 25ms */ 00006 /* and all relays de-energized. If the ERROR input goes LOW after power-up cycle, the */ 00007 /* program disconnects the speaker. During the power up cycle - 150 mains cycles for */ 00008 /* pre-charge and 250 mains cycles for the output to DC settle - and whenever an error */ 00009 /* condition is encountered, the power LED is flashed at 0.5 Hz */ 00010 /* The latency between the loss of ACDET1 and the SPKR being disengaged is ~25ms */ 00011 /* Provision for two 10k NTC thermistor sensors is also provided. The NTC is in the lower */ 00012 /* leg of a divider with the upper leg a 10k resistor. The trip temp (TRIPON), */ 00013 /* reset temp (TRIPOFF) and the temperature alarm (TEMPHIGH) are directly set in Volts */ 00014 /* A low on the clip input will cause the clip LED to flash on for 1s. Note CLIP has to */ 00015 /* recycle HIGH and then LOW again to retrigger the CLIP output - it does not flash */ 00016 /* continuosly if held LOW */ 00017 /* Note: if the amp clips for too long, the DC offset interuppt will be triggered because */ 00018 /* the clip input and the DC offset detect inputs are connected. */ 00019 00020 #include "mbed.h" 00021 #include "WDT.h" // Watch Dog Timer 00022 #include "Pindef1114.h" // all microcontroller I/O pin assignments defined here 00023 #include "AnalogIn.h" // standard mbed supplied analog driver header file 00024 #include "math.h" 00025 00026 #define AC_LOSS 0.025 // this is the wdt set value in seconds 00027 #define TRUE 1 00028 #define FALSE 0 00029 #define HIGH 1 00030 #define LOW 0 00031 #define INDIC 25 // the number of mains cycles between LED illumination flip 00032 #define inrush_t 200 //# of mains cycles to wait before bypassing the NTC 00033 #define amp_settle 300 //# of mains cycles to let amp module OP settle 00034 #define CLIP_ON 20 // the clip LED goes on for n ACDET1 periods 00035 #define TEMPHIGH 65 // temperature alarm in Volts - 65 deg C 00036 #define TRIPON 70 // this is the trip temperature in volts - 70 deg C 00037 #define TRIPOFF 62 // this is the lower re-activate amplifier temperature in volts - 64 deg C 00038 00039 //Following used in the calculation of temp in deg C from an NTC 00040 #define Vref 3.31 // this is the A-D reference voltage 00041 #define Ref 10000 // the upper reference resistor from VREF to the NTC [was 2.2k] 00042 #define To 298 // coefficiants required for Steinhart-Hart equation 00043 #define B 3900 // from NTC data sheet 00044 #define Ro 10000 00045 #define cal65 3.3 // cal out any error at 65deg C - determined by applying 00046 // required offset at 65 deg C - so at 65C the temp is accurate 00047 00048 #define e 2.718281828459 00049 00050 int F1; // test flag used in trip() TRUE if overtemp has tripped 00051 int mains_cnt; // mains cycle counter 00052 int FLAG1; // TRUE if power-up process is completed otherwise FALSE 00053 int indi_flip; // counts mains cycles - used in indicator status 00054 int clip_cnt; // ACDET1 int derived counter for the clip indicator 00055 float templ; // left and right channel temperature read in by A-D in deg C 00056 float tempr; 00057 float t_left; 00058 float t_right; 00059 00060 Ticker flipper; // this is the ACDET1 WDT ticker timer 00061 00062 // declare function prototypes here 00063 void trip(void); // assess what actions to take based on temperature 00064 void temp_measure(void); // measure the temparature 00065 void output_clip(void); // clip indicator 00066 void indi_flash (void); // universal indicator flash 00067 void temp_trip (void); // action to be taken when overtemp 00068 void acdetect(void); // triggers the counter 00069 00070 /************************************ analog_input *********************************/ 00071 void trip(void) { 00072 00073 00074 // temp alarm on either input 00075 if ((t_left >= TEMPHIGH) || (t_right >= TEMPHIGH)) { 00076 clip = HIGH; } 00077 00078 00079 if ((t_left < TEMPHIGH) && (t_right < TEMPHIGH) && (FLAG1 == TRUE)) { 00080 SPKR = HIGH; } 00081 00082 if ((t_left > TRIPON) || (t_right > TRIPON)) { //temp trip 00083 SPKR = LOW; 00084 F1 = TRUE; } 00085 00086 // below is to turn speaker relay back ON if the temperature has fallen BELOW TRIPOFF 00087 00088 if (((t_left < TRIPOFF) && (t_right < TRIPOFF)) && (FLAG1 == TRUE)){ 00089 SPKR = HIGH; 00090 clip = LOW; 00091 F1 = FALSE; } 00092 00093 00094 } 00095 /*********************************** ACDET1 Interrupt ******************************/ 00096 void acdetect(void) 00097 { 00098 ACDET1.rise(NULL); // prevent accidental re-entry 00099 00100 if (mains_cnt < amp_settle) { 00101 mains_cnt++; 00102 FLAG1 = FALSE; // FLAG1 only becomes TRUE after power up process is complete 00103 } 00104 00105 else if (mains_cnt >= amp_settle) { 00106 FLAG1 = TRUE; // fully powered up at this point 00107 mains_cnt = amp_settle; // after power up mains_cnt is held to amp_settle 00108 } 00109 00110 ACDET1.rise(&acdetect); // reinstate the interrupt 00111 } 00112 /******************************** output clip ****************************************/ 00113 00114 void output_clip(void) { 00115 clip_cnt = CLIP_ON; } 00116 00117 /******************************** indi_flash ***************************************/ 00118 // this just flashes the power LED to indicate amp is in power-up cycle 00119 // or a temperature shutdown 00120 00121 void indi_flash(void) 00122 { 00123 if (indi_flip > INDIC) { 00124 INDI = !INDI; 00125 indi_flip = 0; 00126 } 00127 } 00128 /************************************ temp_measure **********************************/ 00129 /* This routine fetches the NTC resistance as measured at the A-D inputs left_temp */ 00130 /* and right Temp. It uses the Steinhart-Hart NTC R>T equation to compute the */ 00131 /* temperature.left_temp and right_temp are A-D inputs defined in the pindef.h file */ 00132 00133 void temp_measure(void) { 00134 00135 float vo_left; 00136 float vo_right; 00137 float r_left; 00138 float r_right; 00139 float l_roh; 00140 float r_roh; 00141 00142 // first, fetch the NTC resistances 00143 00144 vo_left = left_temp*Vref; //scale the A-D reading for Vref = 3.3V 00145 vo_right = right_temp*Vref; 00146 00147 r_left = vo_left/((Vref-vo_left)/Ref); 00148 r_right = vo_right/((Vref-vo_right)/Ref); 00149 00150 // from the NTC resistance, calculate the temperature in Kelvin using the 00151 // simplified Steinhart-Hart Equation. 00152 00153 l_roh = Ro*(pow(e,(-B/To))); 00154 t_left = (B/(log(r_left/l_roh)))-(273+cal65); 00155 00156 r_roh = Ro*(pow(e,(-B/To))); 00157 t_right = (B/(log(r_right/r_roh)))-(273+cal65); 00158 00159 //printf used for temp debugging. Clock must be slowed to ~ 1Hz 00160 //printf("t_left = %f t_right = %f \n\r", t_left, t_right); 00161 00162 } 00163 00164 00165 /************************************* main() ***************************************/ 00166 int main(void) 00167 { 00168 __disable_irq(); // just to make sure we can set up correctly without problems 00169 INRUSH = LOW; // power bypass disabled 00170 SPKR = LOW; // speakers muted 00171 PWR_R = LOW; // power ON/OFF relay is OFF - only used if TRIGGER is used 00172 INDI = HIGH; // open drain indicator output is deactivated - active LOW 00173 clip = LOW; // clip LED driver output 00174 clip_in.mode(PullUp); // clip input 00175 clip_in.fall(&output_clip); 00176 clip_cnt = 0; 00177 ERROR.mode(PullUp); 00178 PWR_D.mode(PullDown); // used to detect power down 00179 ACDET1.mode(PullDown); 00180 ACDET1.rise(&acdetect); // trigger counter on rising edge 00181 SYNC = LOW; // SYNC flips once every mains cycle - 20ms period @ 50 Hz 00182 00183 FLAG1 = FALSE; // force a fault condition until first pass through main loop 00184 F1 = TRUE; // assume we are over temperature until our first sensor reading 00185 INDI = HIGH; // power LED is ON steady 00186 __enable_irq(); 00187 00188 Watchdog wdt; // enable the WDT just before we start the main loop 00189 wdt.kick(AC_LOSS); // kick the WDT at regular 25 ms intervals (set by AC_LOSS) 00190 00191 LOOP: // this main loop is driven by the 20ms/16.6ms interrupts 00192 // generated by the ACDET1 input 00193 // if the INT's fail to arrive after 25ms, the AC power 00194 // is assumed lost and the WDT will reset the system = power down 00195 // de-engergizing all relays 00196 __WFI(); // waiting for ACDET1 INT 00197 wait_ms(1); // make sure we are away from the zero crossing 50 Hz or 60 Hz 00198 wdt.kick(); 00199 00200 if ((mains_cnt >= amp_settle) && (ERROR == HIGH) && (FLAG1 == FALSE)) { 00201 INDI = HIGH; 00202 SPKR = HIGH; } // inrush and amp settle complete - enable SPKR if no ERROR 00203 00204 if (mains_cnt > inrush_t) { 00205 INRUSH = HIGH;} 00206 00207 // make sure the clip LED goes OFF if all is ok 00208 if((clip_cnt <= 0) && (SPKR == HIGH) && (ERROR == HIGH)) { 00209 INDI = HIGH; } 00210 00211 if (clip_cnt <= 0) { // note: clip flashes on change of state 00212 clip = LOW;} // i.e on edges 00213 else if (clip_cnt > 0) { 00214 clip = HIGH; 00215 INDI = LOW; } // so LED is RED on clip and not ORANGE 00216 00217 if ((ERROR == LOW) || (FLAG1 == FALSE)) { 00218 SPKR = LOW; 00219 indi_flash(); } 00220 00221 temp_measure(); 00222 trip(); 00223 00224 if (F1 == TRUE) { 00225 indi_flash(); } 00226 00227 SYNC = !SYNC; // ACDET1 sync output for debugging 00228 indi_flip++; 00229 clip_cnt--; 00230 goto LOOP; 00231 00232 } 00233 00234 00235
Generated on Fri Nov 18 2022 15:57:35 by 1.7.2