Energy Manager App
Dependencies: C12832_lcd LM75B mbed-rtos mbed
Fork of rtos_mutex by
main.cpp@6:3b2a6cb895a9, 2013-09-20 (annotated)
- Committer:
- jesstvaldez
- Date:
- Fri Sep 20 04:12:04 2013 +0000
- Revision:
- 6:3b2a6cb895a9
- Parent:
- 1:0f886ffbe0c1
EM100 V1
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
jesstvaldez | 6:3b2a6cb895a9 | 1 | /* ============================================================================ |
jesstvaldez | 6:3b2a6cb895a9 | 2 | JESS VALDEZ |
jesstvaldez | 6:3b2a6cb895a9 | 3 | Class 5381 |
jesstvaldez | 6:3b2a6cb895a9 | 4 | Homework : Final Project |
jesstvaldez | 6:3b2a6cb895a9 | 5 | Instructor: AVNISH AGGARWAL |
jesstvaldez | 6:3b2a6cb895a9 | 6 | |
jesstvaldez | 6:3b2a6cb895a9 | 7 | >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> |
jesstvaldez | 6:3b2a6cb895a9 | 8 | OFF THE GRID ENERGY MANAGER |
jesstvaldez | 6:3b2a6cb895a9 | 9 | <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< |
jesstvaldez | 6:3b2a6cb895a9 | 10 | |
jesstvaldez | 6:3b2a6cb895a9 | 11 | OTHER Resource: |
jesstvaldez | 6:3b2a6cb895a9 | 12 | p27,p28 i2c pins connected to LM75B thermometer; |
jesstvaldez | 6:3b2a6cb895a9 | 13 | tick interrupt uses TIMER0 |
jesstvaldez | 6:3b2a6cb895a9 | 14 | |
jesstvaldez | 6:3b2a6cb895a9 | 15 | OUTPUT MAPPING |
jesstvaldez | 6:3b2a6cb895a9 | 16 | - led1 - blinks = running |
jesstvaldez | 6:3b2a6cb895a9 | 17 | - led2 - source1 or Solar |
jesstvaldez | 6:3b2a6cb895a9 | 18 | - led3 - source2 or battery |
jesstvaldez | 6:3b2a6cb895a9 | 19 | - led4 - generator |
jesstvaldez | 6:3b2a6cb895a9 | 20 | - p22 general control pin |
jesstvaldez | 6:3b2a6cb895a9 | 21 | - display - LCD (SPI) |
jesstvaldez | 6:3b2a6cb895a9 | 22 | |
jesstvaldez | 6:3b2a6cb895a9 | 23 | ADC |
jesstvaldez | 6:3b2a6cb895a9 | 24 | p18 - S1 (Solar prescaled input) |
jesstvaldez | 6:3b2a6cb895a9 | 25 | p19 - S2 (raw scale battery) |
jesstvaldez | 6:3b2a6cb895a9 | 26 | |
jesstvaldez | 6:3b2a6cb895a9 | 27 | JOYSTICK CONTROL |
jesstvaldez | 6:3b2a6cb895a9 | 28 | UP - Start |
jesstvaldez | 6:3b2a6cb895a9 | 29 | RIGHT - Force change source |
jesstvaldez | 6:3b2a6cb895a9 | 30 | DOWN - System down system to OUT - No source selected, used as turn off sequence. |
jesstvaldez | 6:3b2a6cb895a9 | 31 | |
jesstvaldez | 6:3b2a6cb895a9 | 32 | Added: Power saving mode 9-12-2013 |
jesstvaldez | 6:3b2a6cb895a9 | 33 | |
jesstvaldez | 6:3b2a6cb895a9 | 34 | ==============================================================================*/ |
jesstvaldez | 6:3b2a6cb895a9 | 35 | |
emilmont | 1:0f886ffbe0c1 | 36 | #include "mbed.h" |
emilmont | 1:0f886ffbe0c1 | 37 | #include "rtos.h" |
jesstvaldez | 6:3b2a6cb895a9 | 38 | #include "C12832_lcd.h" |
jesstvaldez | 6:3b2a6cb895a9 | 39 | #include "LM75B.h" |
emilmont | 1:0f886ffbe0c1 | 40 | |
jesstvaldez | 6:3b2a6cb895a9 | 41 | Serial pc(USBTX, USBRX); |
jesstvaldez | 6:3b2a6cb895a9 | 42 | AnalogIn a_PD[] = {(p16),(p17),(p18),(p19),(p20)}; |
jesstvaldez | 6:3b2a6cb895a9 | 43 | |
jesstvaldez | 6:3b2a6cb895a9 | 44 | //p19, p20 are pots used for solar + battery simulation - USE_POT=1 |
jesstvaldez | 6:3b2a6cb895a9 | 45 | //p17 true solar sense |
jesstvaldez | 6:3b2a6cb895a9 | 46 | //p18 true batt sense |
jesstvaldez | 6:3b2a6cb895a9 | 47 | #define USE_POT 0 |
jesstvaldez | 6:3b2a6cb895a9 | 48 | |
jesstvaldez | 6:3b2a6cb895a9 | 49 | #define OUT 0 |
jesstvaldez | 6:3b2a6cb895a9 | 50 | #define RUNNING 1 |
jesstvaldez | 6:3b2a6cb895a9 | 51 | #define FAULT 2 |
emilmont | 1:0f886ffbe0c1 | 52 | |
jesstvaldez | 6:3b2a6cb895a9 | 53 | //Defined or available sources of energy |
jesstvaldez | 6:3b2a6cb895a9 | 54 | #define SOLAR 0 |
jesstvaldez | 6:3b2a6cb895a9 | 55 | #define BATTERY 1 |
jesstvaldez | 6:3b2a6cb895a9 | 56 | #define GENERATOR 2 |
jesstvaldez | 6:3b2a6cb895a9 | 57 | |
jesstvaldez | 6:3b2a6cb895a9 | 58 | #define maxSource 3 //adjust to number of sources ablove |
jesstvaldez | 6:3b2a6cb895a9 | 59 | |
jesstvaldez | 6:3b2a6cb895a9 | 60 | float solar_threshold = 0.10; //10 percent |
jesstvaldez | 6:3b2a6cb895a9 | 61 | float battery_threshold = 0.20; //20 percent |
jesstvaldez | 6:3b2a6cb895a9 | 62 | |
jesstvaldez | 6:3b2a6cb895a9 | 63 | |
jesstvaldez | 6:3b2a6cb895a9 | 64 | #include "PowerControl.h" |
jesstvaldez | 6:3b2a6cb895a9 | 65 | //#include "EthernetPowerControl.h" |
jesstvaldez | 6:3b2a6cb895a9 | 66 | // Need PowerControl *.h files from this URL |
jesstvaldez | 6:3b2a6cb895a9 | 67 | // http://mbed.org/users/no2chem/notebook/mbed-power-controlconsumption/ |
jesstvaldez | 6:3b2a6cb895a9 | 68 | |
jesstvaldez | 6:3b2a6cb895a9 | 69 | // Function to power down magic USB interface chip with new firmware |
jesstvaldez | 6:3b2a6cb895a9 | 70 | #define USR_POWERDOWN (0x104) |
jesstvaldez | 6:3b2a6cb895a9 | 71 | int semihost_powerdown() |
jesstvaldez | 6:3b2a6cb895a9 | 72 | { |
jesstvaldez | 6:3b2a6cb895a9 | 73 | uint32_t arg; |
jesstvaldez | 6:3b2a6cb895a9 | 74 | return __semihost(USR_POWERDOWN, &arg); |
emilmont | 1:0f886ffbe0c1 | 75 | } |
emilmont | 1:0f886ffbe0c1 | 76 | |
jesstvaldez | 6:3b2a6cb895a9 | 77 | char statStr[3][50] = {"OFF","RUNNING","FAULT"}; |
jesstvaldez | 6:3b2a6cb895a9 | 78 | char sourceStr[3][50] = {"SOLAR","BATTERY","GENERATOR"}; |
jesstvaldez | 6:3b2a6cb895a9 | 79 | float sourceLev[20]; /* AD result of measured voltage */ |
jesstvaldez | 6:3b2a6cb895a9 | 80 | C12832_LCD lcd; |
jesstvaldez | 6:3b2a6cb895a9 | 81 | LM75B tmp(p28,p27); |
jesstvaldez | 6:3b2a6cb895a9 | 82 | DigitalOut led1(LED1); |
jesstvaldez | 6:3b2a6cb895a9 | 83 | DigitalOut led2(LED2); |
jesstvaldez | 6:3b2a6cb895a9 | 84 | DigitalOut led3(LED3); |
jesstvaldez | 6:3b2a6cb895a9 | 85 | DigitalOut led4(LED4); |
jesstvaldez | 6:3b2a6cb895a9 | 86 | |
jesstvaldez | 6:3b2a6cb895a9 | 87 | DigitalOut generator_control(p22); |
jesstvaldez | 6:3b2a6cb895a9 | 88 | |
jesstvaldez | 6:3b2a6cb895a9 | 89 | |
jesstvaldez | 6:3b2a6cb895a9 | 90 | void running_thread(void const *); |
jesstvaldez | 6:3b2a6cb895a9 | 91 | void get_levels_thread(void const *); |
jesstvaldez | 6:3b2a6cb895a9 | 92 | void temperature_thread(void const *); |
jesstvaldez | 6:3b2a6cb895a9 | 93 | |
jesstvaldez | 6:3b2a6cb895a9 | 94 | // GLOBALS |
jesstvaldez | 6:3b2a6cb895a9 | 95 | int mainSource; |
jesstvaldez | 6:3b2a6cb895a9 | 96 | int prioritySource; |
jesstvaldez | 6:3b2a6cb895a9 | 97 | int mainStatus; |
jesstvaldez | 6:3b2a6cb895a9 | 98 | short int update; |
jesstvaldez | 6:3b2a6cb895a9 | 99 | |
jesstvaldez | 6:3b2a6cb895a9 | 100 | unsigned int tsec, tsec2, seconds, minutes, hours, days; |
jesstvaldez | 6:3b2a6cb895a9 | 101 | //unsigned int setTime, setTime_min; //default cooktime |
jesstvaldez | 6:3b2a6cb895a9 | 102 | double controller_temp; |
jesstvaldez | 6:3b2a6cb895a9 | 103 | Mutex status_mutex; |
jesstvaldez | 6:3b2a6cb895a9 | 104 | |
jesstvaldez | 6:3b2a6cb895a9 | 105 | // Watchdog code from |
jesstvaldez | 6:3b2a6cb895a9 | 106 | // http://mbed.org/forum/mbed/topic/508/ |
jesstvaldez | 6:3b2a6cb895a9 | 107 | class Watchdog |
jesstvaldez | 6:3b2a6cb895a9 | 108 | { |
jesstvaldez | 6:3b2a6cb895a9 | 109 | public: |
jesstvaldez | 6:3b2a6cb895a9 | 110 | // Load timeout value in watchdog timer and enable |
jesstvaldez | 6:3b2a6cb895a9 | 111 | void kick(float s) { |
jesstvaldez | 6:3b2a6cb895a9 | 112 | LPC_WDT->WDCLKSEL = 0x1; // Set CLK src to PCLK |
jesstvaldez | 6:3b2a6cb895a9 | 113 | uint32_t clk = SystemCoreClock / 16; // WD has a fixed /4 prescaler, PCLK default is /4 |
jesstvaldez | 6:3b2a6cb895a9 | 114 | LPC_WDT->WDTC = s * (float)clk; |
jesstvaldez | 6:3b2a6cb895a9 | 115 | LPC_WDT->WDMOD = 0x3; // Enabled and Reset |
jesstvaldez | 6:3b2a6cb895a9 | 116 | kick(); |
jesstvaldez | 6:3b2a6cb895a9 | 117 | } |
jesstvaldez | 6:3b2a6cb895a9 | 118 | // "kick" or "feed" the dog - reset the watchdog timer |
jesstvaldez | 6:3b2a6cb895a9 | 119 | // by writing this required bit pattern |
jesstvaldez | 6:3b2a6cb895a9 | 120 | void kick() { |
jesstvaldez | 6:3b2a6cb895a9 | 121 | LPC_WDT->WDFEED = 0xAA; |
jesstvaldez | 6:3b2a6cb895a9 | 122 | LPC_WDT->WDFEED = 0x55; |
jesstvaldez | 6:3b2a6cb895a9 | 123 | } |
jesstvaldez | 6:3b2a6cb895a9 | 124 | }; |
jesstvaldez | 6:3b2a6cb895a9 | 125 | |
jesstvaldez | 6:3b2a6cb895a9 | 126 | // Setup the watchdog timer |
jesstvaldez | 6:3b2a6cb895a9 | 127 | Watchdog wdt; |
jesstvaldez | 6:3b2a6cb895a9 | 128 | |
jesstvaldez | 6:3b2a6cb895a9 | 129 | /*============================== |
jesstvaldez | 6:3b2a6cb895a9 | 130 | Start INTERRUPT |
jesstvaldez | 6:3b2a6cb895a9 | 131 | ================================*/ |
jesstvaldez | 6:3b2a6cb895a9 | 132 | class Control_start |
jesstvaldez | 6:3b2a6cb895a9 | 133 | { |
jesstvaldez | 6:3b2a6cb895a9 | 134 | public: |
jesstvaldez | 6:3b2a6cb895a9 | 135 | Control_start(PinName pin) : start_interrupt(pin) { |
jesstvaldez | 6:3b2a6cb895a9 | 136 | start_interrupt.rise(this, &Control_start::start_system); |
jesstvaldez | 6:3b2a6cb895a9 | 137 | } |
jesstvaldez | 6:3b2a6cb895a9 | 138 | void start_system() { |
jesstvaldez | 6:3b2a6cb895a9 | 139 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 140 | mainStatus = RUNNING; |
jesstvaldez | 6:3b2a6cb895a9 | 141 | mainSource = SOLAR; |
jesstvaldez | 6:3b2a6cb895a9 | 142 | |
jesstvaldez | 6:3b2a6cb895a9 | 143 | lcd.cls(); |
jesstvaldez | 6:3b2a6cb895a9 | 144 | seconds=0; |
jesstvaldez | 6:3b2a6cb895a9 | 145 | minutes=0; |
jesstvaldez | 6:3b2a6cb895a9 | 146 | hours=0; |
jesstvaldez | 6:3b2a6cb895a9 | 147 | days=0; |
jesstvaldez | 6:3b2a6cb895a9 | 148 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 149 | } |
jesstvaldez | 6:3b2a6cb895a9 | 150 | private: |
jesstvaldez | 6:3b2a6cb895a9 | 151 | InterruptIn start_interrupt; |
jesstvaldez | 6:3b2a6cb895a9 | 152 | }; |
jesstvaldez | 6:3b2a6cb895a9 | 153 | /*============================== |
jesstvaldez | 6:3b2a6cb895a9 | 154 | Stop INTERRUPT |
jesstvaldez | 6:3b2a6cb895a9 | 155 | ================================*/ |
jesstvaldez | 6:3b2a6cb895a9 | 156 | class Control_stop |
jesstvaldez | 6:3b2a6cb895a9 | 157 | { |
jesstvaldez | 6:3b2a6cb895a9 | 158 | public: |
jesstvaldez | 6:3b2a6cb895a9 | 159 | Control_stop(PinName pin) : stop_interrupt(pin) { |
jesstvaldez | 6:3b2a6cb895a9 | 160 | stop_interrupt.rise(this, &Control_stop::stop_system); |
jesstvaldez | 6:3b2a6cb895a9 | 161 | } |
jesstvaldez | 6:3b2a6cb895a9 | 162 | void stop_system() { |
jesstvaldez | 6:3b2a6cb895a9 | 163 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 164 | mainStatus = OUT; |
jesstvaldez | 6:3b2a6cb895a9 | 165 | |
jesstvaldez | 6:3b2a6cb895a9 | 166 | seconds=0; |
jesstvaldez | 6:3b2a6cb895a9 | 167 | minutes=0; |
jesstvaldez | 6:3b2a6cb895a9 | 168 | hours=0; |
jesstvaldez | 6:3b2a6cb895a9 | 169 | days=0; |
jesstvaldez | 6:3b2a6cb895a9 | 170 | |
jesstvaldez | 6:3b2a6cb895a9 | 171 | led1 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 172 | led2 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 173 | led3 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 174 | led4 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 175 | lcd.cls(); |
jesstvaldez | 6:3b2a6cb895a9 | 176 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 177 | } |
jesstvaldez | 6:3b2a6cb895a9 | 178 | private: |
jesstvaldez | 6:3b2a6cb895a9 | 179 | InterruptIn stop_interrupt; |
jesstvaldez | 6:3b2a6cb895a9 | 180 | }; |
jesstvaldez | 6:3b2a6cb895a9 | 181 | |
jesstvaldez | 6:3b2a6cb895a9 | 182 | /*============================== |
jesstvaldez | 6:3b2a6cb895a9 | 183 | Force next Source INTERRUPT |
jesstvaldez | 6:3b2a6cb895a9 | 184 | ================================*/ |
jesstvaldez | 6:3b2a6cb895a9 | 185 | class Control_next |
jesstvaldez | 6:3b2a6cb895a9 | 186 | { |
jesstvaldez | 6:3b2a6cb895a9 | 187 | public: |
jesstvaldez | 6:3b2a6cb895a9 | 188 | Control_next(PinName pin) : next_interrupt(pin) { |
jesstvaldez | 6:3b2a6cb895a9 | 189 | next_interrupt.rise(this, &Control_next::switch_to_next_source); |
jesstvaldez | 6:3b2a6cb895a9 | 190 | } |
jesstvaldez | 6:3b2a6cb895a9 | 191 | void switch_to_next_source() { |
jesstvaldez | 6:3b2a6cb895a9 | 192 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 193 | if (mainStatus == RUNNING) { |
jesstvaldez | 6:3b2a6cb895a9 | 194 | mainSource++; |
jesstvaldez | 6:3b2a6cb895a9 | 195 | if (mainSource>(maxSource-1)) mainSource=0; |
jesstvaldez | 6:3b2a6cb895a9 | 196 | |
jesstvaldez | 6:3b2a6cb895a9 | 197 | } |
jesstvaldez | 6:3b2a6cb895a9 | 198 | lcd.cls(); |
jesstvaldez | 6:3b2a6cb895a9 | 199 | seconds=0; |
jesstvaldez | 6:3b2a6cb895a9 | 200 | minutes=0; |
jesstvaldez | 6:3b2a6cb895a9 | 201 | hours=0; |
jesstvaldez | 6:3b2a6cb895a9 | 202 | days=0; |
jesstvaldez | 6:3b2a6cb895a9 | 203 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 204 | } |
jesstvaldez | 6:3b2a6cb895a9 | 205 | private: |
jesstvaldez | 6:3b2a6cb895a9 | 206 | InterruptIn next_interrupt; |
jesstvaldez | 6:3b2a6cb895a9 | 207 | }; |
jesstvaldez | 6:3b2a6cb895a9 | 208 | |
jesstvaldez | 6:3b2a6cb895a9 | 209 | Control_next next(p16); |
jesstvaldez | 6:3b2a6cb895a9 | 210 | Control_start start(p15); |
jesstvaldez | 6:3b2a6cb895a9 | 211 | Control_stop stop(p12); |
jesstvaldez | 6:3b2a6cb895a9 | 212 | |
jesstvaldez | 6:3b2a6cb895a9 | 213 | unsigned short timer_count, clear_count; |
jesstvaldez | 6:3b2a6cb895a9 | 214 | |
jesstvaldez | 6:3b2a6cb895a9 | 215 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 216 | // TIMER0 IRQ Handler |
jesstvaldez | 6:3b2a6cb895a9 | 217 | //======================================================= |
jesstvaldez | 6:3b2a6cb895a9 | 218 | extern "C" void TIMER0_IRQHandler (void) |
jesstvaldez | 6:3b2a6cb895a9 | 219 | { |
jesstvaldez | 6:3b2a6cb895a9 | 220 | if((LPC_TIM0->IR & 0x01) == 0x01) { // if MR0 interrupt, proceed |
jesstvaldez | 6:3b2a6cb895a9 | 221 | LPC_TIM0->IR |= 1 << 0; // Clear MR0 interrupt flag |
jesstvaldez | 6:3b2a6cb895a9 | 222 | timer_count++; //increment timer_count |
jesstvaldez | 6:3b2a6cb895a9 | 223 | clear_count++; |
jesstvaldez | 6:3b2a6cb895a9 | 224 | } |
jesstvaldez | 6:3b2a6cb895a9 | 225 | } |
jesstvaldez | 6:3b2a6cb895a9 | 226 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 227 | // timer0 initialization |
jesstvaldez | 6:3b2a6cb895a9 | 228 | //======================================================= |
jesstvaldez | 6:3b2a6cb895a9 | 229 | void timer0_init(void) |
jesstvaldez | 6:3b2a6cb895a9 | 230 | { |
jesstvaldez | 6:3b2a6cb895a9 | 231 | LPC_SC->PCONP |=1<1; //timer0 power on |
jesstvaldez | 6:3b2a6cb895a9 | 232 | LPC_TIM0->MR0 = 2398000; //100 msec |
jesstvaldez | 6:3b2a6cb895a9 | 233 | LPC_TIM0->MCR = 3; //interrupt and reset control |
jesstvaldez | 6:3b2a6cb895a9 | 234 | //3 = Interrupt & reset timer0 on match |
jesstvaldez | 6:3b2a6cb895a9 | 235 | //1 = Interrupt only, no reset of timer0 |
jesstvaldez | 6:3b2a6cb895a9 | 236 | NVIC_EnableIRQ(TIMER0_IRQn); //enable timer0 interrupt |
jesstvaldez | 6:3b2a6cb895a9 | 237 | LPC_TIM0->TCR = 1; //enable Timer0 |
jesstvaldez | 6:3b2a6cb895a9 | 238 | // pc.printf("Done timer_init\n\r"); |
jesstvaldez | 6:3b2a6cb895a9 | 239 | } |
jesstvaldez | 6:3b2a6cb895a9 | 240 | |
jesstvaldez | 6:3b2a6cb895a9 | 241 | /* ========================================== |
jesstvaldez | 6:3b2a6cb895a9 | 242 | main() |
jesstvaldez | 6:3b2a6cb895a9 | 243 | - Entry point. |
jesstvaldez | 6:3b2a6cb895a9 | 244 | ============================================*/ |
jesstvaldez | 6:3b2a6cb895a9 | 245 | int main() |
jesstvaldez | 6:3b2a6cb895a9 | 246 | { |
jesstvaldez | 6:3b2a6cb895a9 | 247 | float s_p[2], volts; //calculated levels in percent |
jesstvaldez | 6:3b2a6cb895a9 | 248 | timer0_init(); |
jesstvaldez | 6:3b2a6cb895a9 | 249 | timer_count = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 250 | clear_count = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 251 | generator_control = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 252 | mainStatus = OUT; |
jesstvaldez | 6:3b2a6cb895a9 | 253 | mainSource = SOLAR; |
jesstvaldez | 6:3b2a6cb895a9 | 254 | s_p[0] = 5.0; //give this a value to prevent glitch to generator at startup |
jesstvaldez | 6:3b2a6cb895a9 | 255 | s_p[1] = 5.0; |
jesstvaldez | 6:3b2a6cb895a9 | 256 | |
jesstvaldez | 6:3b2a6cb895a9 | 257 | #ifdef NOETHER |
jesstvaldez | 6:3b2a6cb895a9 | 258 | // Normal mbed power level for this setup is around 690mW |
jesstvaldez | 6:3b2a6cb895a9 | 259 | // assuming 5V used on Vin pin |
jesstvaldez | 6:3b2a6cb895a9 | 260 | // If you don't need networking... |
jesstvaldez | 6:3b2a6cb895a9 | 261 | // Power down Ethernet interface - saves around 175mW |
jesstvaldez | 6:3b2a6cb895a9 | 262 | // Also need to unplug network cable - just a cable sucks power |
jesstvaldez | 6:3b2a6cb895a9 | 263 | PHY_PowerDown(); |
jesstvaldez | 6:3b2a6cb895a9 | 264 | #endif |
jesstvaldez | 6:3b2a6cb895a9 | 265 | |
jesstvaldez | 6:3b2a6cb895a9 | 266 | // On reset, indicate a watchdog reset or a pushbutton reset on LED 4 or 3 |
jesstvaldez | 6:3b2a6cb895a9 | 267 | if ((LPC_WDT->WDMOD >> 2) & 1) |
jesstvaldez | 6:3b2a6cb895a9 | 268 | led4 = 1; |
jesstvaldez | 6:3b2a6cb895a9 | 269 | else led3 = 1; |
jesstvaldez | 6:3b2a6cb895a9 | 270 | |
jesstvaldez | 6:3b2a6cb895a9 | 271 | |
jesstvaldez | 6:3b2a6cb895a9 | 272 | //running thread |
jesstvaldez | 6:3b2a6cb895a9 | 273 | Thread thread1(running_thread, NULL, osPriorityHigh, DEFAULT_STACK_SIZE, NULL); |
jesstvaldez | 6:3b2a6cb895a9 | 274 | |
jesstvaldez | 6:3b2a6cb895a9 | 275 | //measurements |
jesstvaldez | 6:3b2a6cb895a9 | 276 | Thread thread2(get_levels_thread); |
jesstvaldez | 6:3b2a6cb895a9 | 277 | |
jesstvaldez | 6:3b2a6cb895a9 | 278 | //fault monitor thread (temperature) |
jesstvaldez | 6:3b2a6cb895a9 | 279 | Thread thread3(temperature_thread, NULL, osPriorityLow, DEFAULT_STACK_SIZE, NULL); |
jesstvaldez | 6:3b2a6cb895a9 | 280 | |
jesstvaldez | 6:3b2a6cb895a9 | 281 | //main status threads |
emilmont | 1:0f886ffbe0c1 | 282 | while (true) { |
jesstvaldez | 6:3b2a6cb895a9 | 283 | lcd.locate(0,1); |
jesstvaldez | 6:3b2a6cb895a9 | 284 | lcd.printf("%s, %s", statStr[mainStatus], sourceStr[mainSource]); |
jesstvaldez | 6:3b2a6cb895a9 | 285 | |
jesstvaldez | 6:3b2a6cb895a9 | 286 | volts = (sourceLev[0] / 3.04) * 10.0; |
jesstvaldez | 6:3b2a6cb895a9 | 287 | volts = volts * 4.0; //scale to voltage divider of solar sense |
jesstvaldez | 6:3b2a6cb895a9 | 288 | s_p[0] = (volts / 21.0) * 100.0; //percentage of solar current single panel. |
jesstvaldez | 6:3b2a6cb895a9 | 289 | |
jesstvaldez | 6:3b2a6cb895a9 | 290 | s_p[1] = (sourceLev[1] / 3.04) * 10.0; // voltage, sourceLev[1] has no scaling |
jesstvaldez | 6:3b2a6cb895a9 | 291 | s_p[1] = (s_p[1] / 3.3) * 100.0; //percent |
jesstvaldez | 6:3b2a6cb895a9 | 292 | lcd.locate(0,11); |
jesstvaldez | 6:3b2a6cb895a9 | 293 | lcd.printf("S1= %.2f %%, S2= %.2f %%", s_p[0], s_p[1]); |
jesstvaldez | 6:3b2a6cb895a9 | 294 | |
jesstvaldez | 6:3b2a6cb895a9 | 295 | lcd.locate(0,21); |
jesstvaldez | 6:3b2a6cb895a9 | 296 | lcd.printf("Time= %d days, %.2d:%.2d:%.2d", days, hours, minutes, seconds%60); |
jesstvaldez | 6:3b2a6cb895a9 | 297 | |
jesstvaldez | 6:3b2a6cb895a9 | 298 | //refresh lcd every 100 seconds |
jesstvaldez | 6:3b2a6cb895a9 | 299 | if (clear_count > 1000) { |
jesstvaldez | 6:3b2a6cb895a9 | 300 | // Clear LCD Screen |
jesstvaldez | 6:3b2a6cb895a9 | 301 | lcd.cls(); |
jesstvaldez | 6:3b2a6cb895a9 | 302 | clear_count = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 303 | } |
jesstvaldez | 6:3b2a6cb895a9 | 304 | pc.printf("S1= %.2f %%, S2= %.2f %%, %d, %d\n\r", s_p[0], s_p[1], mainStatus, mainSource); |
jesstvaldez | 6:3b2a6cb895a9 | 305 | Thread::wait(500); |
emilmont | 1:0f886ffbe0c1 | 306 | } |
emilmont | 1:0f886ffbe0c1 | 307 | } |
emilmont | 1:0f886ffbe0c1 | 308 | |
jesstvaldez | 6:3b2a6cb895a9 | 309 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 310 | // thread that displays the time elapsed while running on a source |
jesstvaldez | 6:3b2a6cb895a9 | 311 | // also links led1 |
jesstvaldez | 6:3b2a6cb895a9 | 312 | //======================================================= |
jesstvaldez | 6:3b2a6cb895a9 | 313 | void running_thread(void const *args) |
jesstvaldez | 6:3b2a6cb895a9 | 314 | { |
jesstvaldez | 6:3b2a6cb895a9 | 315 | |
jesstvaldez | 6:3b2a6cb895a9 | 316 | while (true) { |
jesstvaldez | 6:3b2a6cb895a9 | 317 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 318 | update=0; |
jesstvaldez | 6:3b2a6cb895a9 | 319 | if (mainStatus == RUNNING) { |
jesstvaldez | 6:3b2a6cb895a9 | 320 | led1 = !led1; |
jesstvaldez | 6:3b2a6cb895a9 | 321 | |
jesstvaldez | 6:3b2a6cb895a9 | 322 | if (timer_count > 9) { |
jesstvaldez | 6:3b2a6cb895a9 | 323 | /* timer_count is 10 per second (so 0-9)*/ |
jesstvaldez | 6:3b2a6cb895a9 | 324 | seconds++; |
jesstvaldez | 6:3b2a6cb895a9 | 325 | minutes = seconds/60.0; |
jesstvaldez | 6:3b2a6cb895a9 | 326 | hours = minutes/60.0; |
jesstvaldez | 6:3b2a6cb895a9 | 327 | days = hours/24.0; |
jesstvaldez | 6:3b2a6cb895a9 | 328 | timer_count=0; |
jesstvaldez | 6:3b2a6cb895a9 | 329 | } |
jesstvaldez | 6:3b2a6cb895a9 | 330 | //led update OK, but not a reliable way to set a power switch |
jesstvaldez | 6:3b2a6cb895a9 | 331 | switch(mainSource) { |
jesstvaldez | 6:3b2a6cb895a9 | 332 | case 0: |
jesstvaldez | 6:3b2a6cb895a9 | 333 | led2=1; |
jesstvaldez | 6:3b2a6cb895a9 | 334 | led3=0; |
jesstvaldez | 6:3b2a6cb895a9 | 335 | led4=0; |
jesstvaldez | 6:3b2a6cb895a9 | 336 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 337 | case 1: |
jesstvaldez | 6:3b2a6cb895a9 | 338 | led2=0; |
jesstvaldez | 6:3b2a6cb895a9 | 339 | led3=1; |
jesstvaldez | 6:3b2a6cb895a9 | 340 | led4=0; |
jesstvaldez | 6:3b2a6cb895a9 | 341 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 342 | case 2: |
jesstvaldez | 6:3b2a6cb895a9 | 343 | led2=0; |
jesstvaldez | 6:3b2a6cb895a9 | 344 | led3=0; |
jesstvaldez | 6:3b2a6cb895a9 | 345 | led4=1; |
jesstvaldez | 6:3b2a6cb895a9 | 346 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 347 | } |
jesstvaldez | 6:3b2a6cb895a9 | 348 | } |
jesstvaldez | 6:3b2a6cb895a9 | 349 | |
jesstvaldez | 6:3b2a6cb895a9 | 350 | if ((mainStatus == OUT)|| (mainStatus == FAULT)) { |
jesstvaldez | 6:3b2a6cb895a9 | 351 | led1 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 352 | led2 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 353 | led3 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 354 | led4 = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 355 | Sleep(); //Save Power |
jesstvaldez | 6:3b2a6cb895a9 | 356 | } |
jesstvaldez | 6:3b2a6cb895a9 | 357 | |
jesstvaldez | 6:3b2a6cb895a9 | 358 | |
jesstvaldez | 6:3b2a6cb895a9 | 359 | //OK decide which source is available as mainSource |
jesstvaldez | 6:3b2a6cb895a9 | 360 | switch(mainSource) { |
jesstvaldez | 6:3b2a6cb895a9 | 361 | case SOLAR: |
jesstvaldez | 6:3b2a6cb895a9 | 362 | if ((sourceLev[0] < solar_threshold) && (sourceLev[1] > battery_threshold)) { |
jesstvaldez | 6:3b2a6cb895a9 | 363 | mainSource++; |
jesstvaldez | 6:3b2a6cb895a9 | 364 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 365 | } |
jesstvaldez | 6:3b2a6cb895a9 | 366 | if ((sourceLev[0] < solar_threshold) && (sourceLev[1] < battery_threshold)) { |
jesstvaldez | 6:3b2a6cb895a9 | 367 | mainSource=GENERATOR; //if both solar and battery are down |
jesstvaldez | 6:3b2a6cb895a9 | 368 | generator_control=1; |
jesstvaldez | 6:3b2a6cb895a9 | 369 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 370 | } |
jesstvaldez | 6:3b2a6cb895a9 | 371 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 372 | |
jesstvaldez | 6:3b2a6cb895a9 | 373 | case BATTERY: |
jesstvaldez | 6:3b2a6cb895a9 | 374 | if (sourceLev[0] > solar_threshold) { |
jesstvaldez | 6:3b2a6cb895a9 | 375 | mainSource=SOLAR; //if solar comes to life |
jesstvaldez | 6:3b2a6cb895a9 | 376 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 377 | } |
jesstvaldez | 6:3b2a6cb895a9 | 378 | if ((sourceLev[0] < solar_threshold) && (sourceLev[1] < battery_threshold)) { |
jesstvaldez | 6:3b2a6cb895a9 | 379 | mainSource=GENERATOR; //solar or batt are low |
jesstvaldez | 6:3b2a6cb895a9 | 380 | generator_control=1; |
jesstvaldez | 6:3b2a6cb895a9 | 381 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 382 | } |
jesstvaldez | 6:3b2a6cb895a9 | 383 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 384 | |
jesstvaldez | 6:3b2a6cb895a9 | 385 | case GENERATOR: |
jesstvaldez | 6:3b2a6cb895a9 | 386 | if (sourceLev[1] > battery_threshold) { |
jesstvaldez | 6:3b2a6cb895a9 | 387 | mainSource=BATTERY; //check if we can switch to battery |
jesstvaldez | 6:3b2a6cb895a9 | 388 | generator_control=0; |
jesstvaldez | 6:3b2a6cb895a9 | 389 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 390 | } |
jesstvaldez | 6:3b2a6cb895a9 | 391 | if (sourceLev[0] > solar_threshold) { |
jesstvaldez | 6:3b2a6cb895a9 | 392 | mainSource=SOLAR; //switch to solar if ever possible |
jesstvaldez | 6:3b2a6cb895a9 | 393 | generator_control=0; |
jesstvaldez | 6:3b2a6cb895a9 | 394 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 395 | } |
jesstvaldez | 6:3b2a6cb895a9 | 396 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 397 | default: |
jesstvaldez | 6:3b2a6cb895a9 | 398 | mainStatus = OUT; |
jesstvaldez | 6:3b2a6cb895a9 | 399 | update=1; |
jesstvaldez | 6:3b2a6cb895a9 | 400 | break; |
jesstvaldez | 6:3b2a6cb895a9 | 401 | } |
jesstvaldez | 6:3b2a6cb895a9 | 402 | |
jesstvaldez | 6:3b2a6cb895a9 | 403 | if (update==1) { |
jesstvaldez | 6:3b2a6cb895a9 | 404 | //if update occurred |
jesstvaldez | 6:3b2a6cb895a9 | 405 | lcd.cls(); |
jesstvaldez | 6:3b2a6cb895a9 | 406 | seconds=0; |
jesstvaldez | 6:3b2a6cb895a9 | 407 | minutes=0; |
jesstvaldez | 6:3b2a6cb895a9 | 408 | hours=0; |
jesstvaldez | 6:3b2a6cb895a9 | 409 | days=0; |
jesstvaldez | 6:3b2a6cb895a9 | 410 | update=0; |
jesstvaldez | 6:3b2a6cb895a9 | 411 | } |
jesstvaldez | 6:3b2a6cb895a9 | 412 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 413 | Thread::wait(500); |
jesstvaldez | 6:3b2a6cb895a9 | 414 | } |
emilmont | 1:0f886ffbe0c1 | 415 | } |
jesstvaldez | 6:3b2a6cb895a9 | 416 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 417 | //get levels thread |
jesstvaldez | 6:3b2a6cb895a9 | 418 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 419 | void get_levels_thread(void const *args) |
jesstvaldez | 6:3b2a6cb895a9 | 420 | { |
jesstvaldez | 6:3b2a6cb895a9 | 421 | while (true) { |
jesstvaldez | 6:3b2a6cb895a9 | 422 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 423 | if (mainStatus == RUNNING) { |
jesstvaldez | 6:3b2a6cb895a9 | 424 | #if USE_POT |
jesstvaldez | 6:3b2a6cb895a9 | 425 | //using pots during development |
jesstvaldez | 6:3b2a6cb895a9 | 426 | sourceLev[0]=a_PD[3]; //pot1 |
jesstvaldez | 6:3b2a6cb895a9 | 427 | sourceLev[1]=a_PD[4]; //pot2 |
jesstvaldez | 6:3b2a6cb895a9 | 428 | #else |
jesstvaldez | 6:3b2a6cb895a9 | 429 | //using actual solar + battery |
jesstvaldez | 6:3b2a6cb895a9 | 430 | sourceLev[0]=a_PD[2]; //p18 of mbed |
jesstvaldez | 6:3b2a6cb895a9 | 431 | sourceLev[1]=a_PD[1]; //p17 of mbed |
jesstvaldez | 6:3b2a6cb895a9 | 432 | |
jesstvaldez | 6:3b2a6cb895a9 | 433 | #endif |
jesstvaldez | 6:3b2a6cb895a9 | 434 | } |
jesstvaldez | 6:3b2a6cb895a9 | 435 | |
jesstvaldez | 6:3b2a6cb895a9 | 436 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 437 | Thread::wait(500); |
jesstvaldez | 6:3b2a6cb895a9 | 438 | } |
jesstvaldez | 6:3b2a6cb895a9 | 439 | } |
jesstvaldez | 6:3b2a6cb895a9 | 440 | |
jesstvaldez | 6:3b2a6cb895a9 | 441 | //====================================================== |
jesstvaldez | 6:3b2a6cb895a9 | 442 | // thread that monitors temperature of the controller PCB |
jesstvaldez | 6:3b2a6cb895a9 | 443 | // generates fault or error when temp reaches threshold 100C |
jesstvaldez | 6:3b2a6cb895a9 | 444 | //======================================================= |
jesstvaldez | 6:3b2a6cb895a9 | 445 | void temperature_thread(void const *args) |
jesstvaldez | 6:3b2a6cb895a9 | 446 | { |
jesstvaldez | 6:3b2a6cb895a9 | 447 | while (true) { |
jesstvaldez | 6:3b2a6cb895a9 | 448 | status_mutex.lock(); |
jesstvaldez | 6:3b2a6cb895a9 | 449 | |
jesstvaldez | 6:3b2a6cb895a9 | 450 | controller_temp = tmp.read(); |
jesstvaldez | 6:3b2a6cb895a9 | 451 | if (controller_temp > 100) { |
jesstvaldez | 6:3b2a6cb895a9 | 452 | mainStatus = FAULT; |
jesstvaldez | 6:3b2a6cb895a9 | 453 | generator_control = 0; |
jesstvaldez | 6:3b2a6cb895a9 | 454 | wdt.kick(); |
jesstvaldez | 6:3b2a6cb895a9 | 455 | } |
jesstvaldez | 6:3b2a6cb895a9 | 456 | status_mutex.unlock(); |
jesstvaldez | 6:3b2a6cb895a9 | 457 | Thread::wait(500); |
jesstvaldez | 6:3b2a6cb895a9 | 458 | } |
jesstvaldez | 6:3b2a6cb895a9 | 459 | } |