Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
main.cpp@0:36494271e31a, 2017-02-16 (annotated)
- Committer:
- andrewcrussell
- Date:
- Thu Feb 16 13:38:31 2017 +0000
- Revision:
- 0:36494271e31a
- Child:
- 2:c449cfb7752c
private
Who changed what in which revision?
User | Revision | Line number | New 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 |