Andrew Russell / Mbed 2 deprecated Power_Sequencer_Nov_10_2022

Dependencies:   mbed

Committer:
andrewcrussell
Date:
Thu Feb 16 13:38:31 2017 +0000
Revision:
0:36494271e31a
Child:
2:c449cfb7752c
private

Who changed what in which revision?

UserRevisionLine numberNew contents of line
andrewcrussell 0:36494271e31a 1 /****************************** Power Sequencer and Controller V1.0 *************************/
andrewcrussell 0:36494271e31a 2 /* Andrew C. Russell (c) 2015 */
andrewcrussell 0:36494271e31a 3 /* The controller pin definitions are set in Pindef1114.h file. */
andrewcrussell 0:36494271e31a 4 /* The main loop is driven by an interrupt on ACDET1 - 16.66ms for 60 Hz and 20ms for 50 Hz */
andrewcrussell 0:36494271e31a 5 /* The WDT is set for a 25ms timeout. If AC power is removed, the SPKR and INRUSH outputs */
andrewcrussell 0:36494271e31a 6 /* are driven LOW immediately. The power supply to the uC is supported by a 100uF 6.3V */
andrewcrussell 0:36494271e31a 7 /* capacityor to facilitate this. If the ERROR input goes LOW after power-up cycle, the */
andrewcrussell 0:36494271e31a 8 /* program disconnects the speaker. During the power up cycle - 150 mains cycles for */
andrewcrussell 0:36494271e31a 9 /* pre-charge and 150 mains cycles for the output to DC settle - and whenever an error */
andrewcrussell 0:36494271e31a 10 /* condition is encountered, the power LED is flashed at 0.5 Hz */
andrewcrussell 0:36494271e31a 11 /* The latency between the loss of ACDET1 and the SPKR being disengaged is ~25ms */
andrewcrussell 0:36494271e31a 12 /* Note that if the TRIGGER input is used, the +12V actually powers up the controller */
andrewcrussell 0:36494271e31a 13 /* which then bootstraps itself by applying AC power via the PWR_R */
andrewcrussell 0:36494271e31a 14
andrewcrussell 0:36494271e31a 15 #include "mbed.h"
andrewcrussell 0:36494271e31a 16 #include "WDT.h"
andrewcrussell 0:36494271e31a 17 #include "Pindef1114.h" // all microcontroller I/O pin assignments defined here
andrewcrussell 0:36494271e31a 18 #include "AnalogIn.h"
andrewcrussell 0:36494271e31a 19 #define AC_LOSS 0.025 // this is the wdt set value in seconds
andrewcrussell 0:36494271e31a 20 #define TRUE 1
andrewcrussell 0:36494271e31a 21 #define FALSE 0
andrewcrussell 0:36494271e31a 22 #define HIGH 1
andrewcrussell 0:36494271e31a 23 #define LOW 0
andrewcrussell 0:36494271e31a 24 #define BAD 0
andrewcrussell 0:36494271e31a 25 #define OK 1
andrewcrussell 0:36494271e31a 26 #define INDIC 25 // the number of mains cycles between indicator lamp flip
andrewcrussell 0:36494271e31a 27 #define inrush_t 150 //# of mains cycles to wait before bypassing the NTC
andrewcrussell 0:36494271e31a 28 #define amp_settle 300 //# of mains cycles to let amp module OP settle
andrewcrussell 0:36494271e31a 29 #define CLIP_ON 5 // the clip LED goes on for ACDET1 periodes
andrewcrussell 0:36494271e31a 30 #define TEMPHIGH 0.7 // temperature alarm
andrewcrussell 0:36494271e31a 31 #define TRIPON 0.83 // this is the trip temperature - 830mV = 65 deg C on LM60
andrewcrussell 0:36494271e31a 32 #define TRIPOFF 0.75 // this is the lower re-activate amplifier
andrewcrussell 0:36494271e31a 33 //temperature - ~59 deg C LM60
andrewcrussell 0:36494271e31a 34
andrewcrussell 0:36494271e31a 35 int T1;
andrewcrussell 0:36494271e31a 36 int T2;
andrewcrussell 0:36494271e31a 37 int T3;
andrewcrussell 0:36494271e31a 38 int T4;
andrewcrussell 0:36494271e31a 39 int mains_cnt; // mains cycle counter
andrewcrussell 0:36494271e31a 40 int FLAG1; // used to detect if we are in or out of power up process
andrewcrussell 0:36494271e31a 41 int FLAG_TRIGGER; // TRUE if power up was via the trigger input
andrewcrussell 0:36494271e31a 42 int indi_flip; // counts mains cycles - used in indicator status
andrewcrussell 0:36494271e31a 43 int clip_cnt; // ACDET1 int derived counter for the clip indicator
andrewcrussell 0:36494271e31a 44 float templ;
andrewcrussell 0:36494271e31a 45 float tempr;
andrewcrussell 0:36494271e31a 46 int temp_status;
andrewcrussell 0:36494271e31a 47
andrewcrussell 0:36494271e31a 48 Ticker flipper; // this is the ACDET timer - runs at 13.2 or 20ms
andrewcrussell 0:36494271e31a 49 // ref 60 Hz or 50 Hz mains frequency
andrewcrussell 0:36494271e31a 50
andrewcrussell 0:36494271e31a 51 // declare function prototypes here
andrewcrussell 0:36494271e31a 52 void analog_input(void); // measure the temperature
andrewcrussell 0:36494271e31a 53 void output_clip(void); // clip indicator
andrewcrussell 0:36494271e31a 54 void indi_flash (void); // universal indicator flash
andrewcrussell 0:36494271e31a 55 void temp_trip (void); // action to be taken when overtemp
andrewcrussell 0:36494271e31a 56 void acdetect(void); // triggers the counter
andrewcrussell 0:36494271e31a 57
andrewcrussell 0:36494271e31a 58 /************************************ analog_input *********************************/
andrewcrussell 0:36494271e31a 59
andrewcrussell 0:36494271e31a 60 void analog_input (void) {
andrewcrussell 0:36494271e31a 61
andrewcrussell 0:36494271e31a 62 templ = left_temp*3.3;
andrewcrussell 0:36494271e31a 63 tempr = right_temp*3.3;
andrewcrussell 0:36494271e31a 64
andrewcrussell 0:36494271e31a 65 //if ((templ > TRIPOFF) || (tempr > TRIPOFF)) {
andrewcrussell 0:36494271e31a 66 // temp_status = BAD; } else (temp_status = OK);
andrewcrussell 0:36494271e31a 67
andrewcrussell 0:36494271e31a 68 if ((templ > TEMPHIGH) || (tempr > TEMPHIGH)) {
andrewcrussell 0:36494271e31a 69 clip = HIGH;}
andrewcrussell 0:36494271e31a 70 else (clip = LOW);
andrewcrussell 0:36494271e31a 71
andrewcrussell 0:36494271e31a 72 if (((templ > TRIPON) || (tempr > TRIPON))) { // && ((templ > TRIPOFF) || (tempr > TRIPOFF)) && (FLAG1 == TRUE)) {
andrewcrussell 0:36494271e31a 73 SPKR = LOW;
andrewcrussell 0:36494271e31a 74 indi_flash();
andrewcrussell 0:36494271e31a 75 }
andrewcrussell 0:36494271e31a 76
andrewcrussell 0:36494271e31a 77
andrewcrussell 0:36494271e31a 78 if ((templ <= TRIPOFF) && (tempr <= TRIPOFF) && (FLAG1 == TRUE)){
andrewcrussell 0:36494271e31a 79 SPKR = HIGH;}
andrewcrussell 0:36494271e31a 80 }
andrewcrussell 0:36494271e31a 81
andrewcrussell 0:36494271e31a 82 /*********************************** ACDET1 Interrupt ******************************/
andrewcrussell 0:36494271e31a 83 void acdetect(void)
andrewcrussell 0:36494271e31a 84 {
andrewcrussell 0:36494271e31a 85 ACDET1.rise(NULL);
andrewcrussell 0:36494271e31a 86 if (mains_cnt < amp_settle) {
andrewcrussell 0:36494271e31a 87 mains_cnt++;
andrewcrussell 0:36494271e31a 88 FLAG1 = FALSE;
andrewcrussell 0:36494271e31a 89 }
andrewcrussell 0:36494271e31a 90
andrewcrussell 0:36494271e31a 91 else if (mains_cnt >= amp_settle) {
andrewcrussell 0:36494271e31a 92 FLAG1 = TRUE; // fully powered up at this point
andrewcrussell 0:36494271e31a 93 mains_cnt = amp_settle;
andrewcrussell 0:36494271e31a 94 } // after power up mains_cnt is held to amp_settle
andrewcrussell 0:36494271e31a 95 ACDET1.rise(&acdetect);
andrewcrussell 0:36494271e31a 96 }
andrewcrussell 0:36494271e31a 97 /******************************** output clip ****************************************/
andrewcrussell 0:36494271e31a 98
andrewcrussell 0:36494271e31a 99 void output_clip(void) {
andrewcrussell 0:36494271e31a 100 clip_cnt = CLIP_ON;
andrewcrussell 0:36494271e31a 101
andrewcrussell 0:36494271e31a 102 }
andrewcrussell 0:36494271e31a 103
andrewcrussell 0:36494271e31a 104 /********************** power down routine for Trigger input *************************/
andrewcrussell 0:36494271e31a 105 void power_down(void)
andrewcrussell 0:36494271e31a 106 {
andrewcrussell 0:36494271e31a 107 __disable_irq();
andrewcrussell 0:36494271e31a 108 SPKR = LOW;
andrewcrussell 0:36494271e31a 109 INDI = HIGH;
andrewcrussell 0:36494271e31a 110 wait_ms(2);
andrewcrussell 0:36494271e31a 111 INRUSH = LOW;
andrewcrussell 0:36494271e31a 112 if (FLAG_TRIGGER == TRUE) {
andrewcrussell 0:36494271e31a 113 FLAG_TRIGGER = FALSE;
andrewcrussell 0:36494271e31a 114 PWR_R = LOW;
andrewcrussell 0:36494271e31a 115 }
andrewcrussell 0:36494271e31a 116 FLAG1 = FALSE;
andrewcrussell 0:36494271e31a 117 do {
andrewcrussell 0:36494271e31a 118 continue;
andrewcrussell 0:36494271e31a 119 } while(1); // just wait here unit all power is gone
andrewcrussell 0:36494271e31a 120 // amplifier is in power down mode
andrewcrussell 0:36494271e31a 121 }
andrewcrussell 0:36494271e31a 122
andrewcrussell 0:36494271e31a 123 /******************************** indi_flash ***************************************/
andrewcrussell 0:36494271e31a 124
andrewcrussell 0:36494271e31a 125 void indi_flash(void)
andrewcrussell 0:36494271e31a 126 {
andrewcrussell 0:36494271e31a 127 if (indi_flip > INDIC) {
andrewcrussell 0:36494271e31a 128 INDI = !INDI;
andrewcrussell 0:36494271e31a 129 indi_flip = 0;
andrewcrussell 0:36494271e31a 130 }
andrewcrussell 0:36494271e31a 131 }
andrewcrussell 0:36494271e31a 132
andrewcrussell 0:36494271e31a 133 /************************************ main() ***************************************/
andrewcrussell 0:36494271e31a 134 int main(void)
andrewcrussell 0:36494271e31a 135 {
andrewcrussell 0:36494271e31a 136 __disable_irq(); // just to make sure we can set up correctly without problems
andrewcrussell 0:36494271e31a 137 INRUSH = LOW; // power bypass disabled
andrewcrussell 0:36494271e31a 138 SPKR = LOW; // speakers muted
andrewcrussell 0:36494271e31a 139 PWR_R = LOW; // power ON/OFF relay is OFF
andrewcrussell 0:36494271e31a 140 INDI = HIGH; // open drain indicator output is deactivated - take LOW
andrewcrussell 0:36494271e31a 141 clip = LOW;
andrewcrussell 0:36494271e31a 142 clip_in.mode(PullUp); // clip input
andrewcrussell 0:36494271e31a 143 clip_in.fall(&output_clip);
andrewcrussell 0:36494271e31a 144 clip_cnt = 0;
andrewcrussell 0:36494271e31a 145 ACDET1.mode(PullDown);
andrewcrussell 0:36494271e31a 146 ACDET1.rise(&acdetect); // trigger counter on rising edge
andrewcrussell 0:36494271e31a 147
andrewcrussell 0:36494271e31a 148 SYNC = LOW;
andrewcrussell 0:36494271e31a 149 wait_ms(500); // let PSU etc settle in first ~1 mains cycles
andrewcrussell 0:36494271e31a 150
andrewcrussell 0:36494271e31a 151 // if (PWR_D == HIGH) { // power came in via TRIGGER input
andrewcrussell 0:36494271e31a 152 // FLAG_TRIGGER = TRUE;
andrewcrussell 0:36494271e31a 153 // PWR_R = HIGH; // turn the main power relay ON - only used
andrewcrussell 0:36494271e31a 154 // } // with amplifiers with TRIGGER input facility
andrewcrussell 0:36494271e31a 155 INDI = HIGH; // power LED is ON
andrewcrussell 0:36494271e31a 156 __enable_irq();
andrewcrussell 0:36494271e31a 157 Watchdog wdt; // enable the WDT just before we start the main loop
andrewcrussell 0:36494271e31a 158 wdt.kick(AC_LOSS);
andrewcrussell 0:36494271e31a 159
andrewcrussell 0:36494271e31a 160 LOOP: // this main loop is driven by the 20ms/16.6ms interrupts
andrewcrussell 0:36494271e31a 161 // generated by the ACDET1 input
andrewcrussell 0:36494271e31a 162 // if the INT's fail to arrive after 25ms, the AC power
andrewcrussell 0:36494271e31a 163 // is lost and the WDT will reset the system = power down
andrewcrussell 0:36494271e31a 164 __WFI(); // waiting for ACDET1 INT
andrewcrussell 0:36494271e31a 165 wait_ms(5); // make sure we are away from the zero crossing 50 Hz or 60 Hz
andrewcrussell 0:36494271e31a 166 wdt.kick();
andrewcrussell 0:36494271e31a 167 acdetect();
andrewcrussell 0:36494271e31a 168
andrewcrussell 0:36494271e31a 169 if (PWR_D == HIGH) { // check if input power detector is HIGH
andrewcrussell 0:36494271e31a 170 FLAG_TRIGGER = TRUE;
andrewcrussell 0:36494271e31a 171 PWR_R = HIGH; } // turn on main power relay
andrewcrussell 0:36494271e31a 172
andrewcrussell 0:36494271e31a 173 if ((ERROR == LOW) && (FLAG1 == TRUE)) { // we have a fault condition but will
andrewcrussell 0:36494271e31a 174 SPKR = LOW; // skip this if the error clears itself
andrewcrussell 0:36494271e31a 175 indi_flash(); }
andrewcrussell 0:36494271e31a 176
andrewcrussell 0:36494271e31a 177 if ((ERROR == HIGH) && (FLAG1 == TRUE)){
andrewcrussell 0:36494271e31a 178 INDI = HIGH; }
andrewcrussell 0:36494271e31a 179
andrewcrussell 0:36494271e31a 180 if(mains_cnt < amp_settle) {
andrewcrussell 0:36494271e31a 181 INRUSH = HIGH;
andrewcrussell 0:36494271e31a 182 indi_flash(); }
andrewcrussell 0:36494271e31a 183
andrewcrussell 0:36494271e31a 184 if ((mains_cnt >= inrush_t) && (mains_cnt >= amp_settle) == TRUE) {
andrewcrussell 0:36494271e31a 185 SPKR = HIGH; }
andrewcrussell 0:36494271e31a 186
andrewcrussell 0:36494271e31a 187 if ((PWR_D == LOW) && (FLAG_TRIGGER == TRUE)) {
andrewcrussell 0:36494271e31a 188 power_down(); }
andrewcrussell 0:36494271e31a 189
andrewcrussell 0:36494271e31a 190 if (clip_cnt <= 0) {
andrewcrussell 0:36494271e31a 191 clip = LOW;}
andrewcrussell 0:36494271e31a 192 else if (clip_cnt != 0) {
andrewcrussell 0:36494271e31a 193 clip = HIGH;}
andrewcrussell 0:36494271e31a 194
andrewcrussell 0:36494271e31a 195 analog_input();
andrewcrussell 0:36494271e31a 196
andrewcrussell 0:36494271e31a 197 SYNC = !SYNC; // ACDET1 sync output for debugging
andrewcrussell 0:36494271e31a 198 indi_flip++;
andrewcrussell 0:36494271e31a 199 clip_cnt--;
andrewcrussell 0:36494271e31a 200 goto LOOP;
andrewcrussell 0:36494271e31a 201
andrewcrussell 0:36494271e31a 202 }
andrewcrussell 0:36494271e31a 203
andrewcrussell 0:36494271e31a 204
andrewcrussell 0:36494271e31a 205