Fan Controller - PWM HF (25kHz) Type, w/ a Two Button Escalator & a 4-LED Binary State-Display for UI.

The Circuit, as Built on an Universal PCB, Ready For Installation (in a '3.5 Drive-Slot) - Using a Thermoplastic Carrier :

/media/uploads/mzcs/img_20181108_073655_hdr-a.jpg

Committer:
mzcs
Date:
Sun Nov 04 17:00:46 2018 +0000
Revision:
1:0a2f89da0616
Parent:
0:437bb8e2f8a7
.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mzcs 1:0a2f89da0616 1 /*
mzcs 1:0a2f89da0616 2 Copyright (c) 2018 - Moran ZALTSMAN
mzcs 1:0a2f89da0616 3
mzcs 1:0a2f89da0616 4 This program is free software: you can redistribute it and/or modify
mzcs 1:0a2f89da0616 5 it under the terms of the GNU General Public License as published by
mzcs 1:0a2f89da0616 6 the Free Software Foundation, either version 3 of the License, or
mzcs 1:0a2f89da0616 7 (at your option) any later version.
mzcs 1:0a2f89da0616 8
mzcs 1:0a2f89da0616 9 This program is distributed in the hope that it will be useful,
mzcs 1:0a2f89da0616 10 but WITHOUT ANY WARRANTY; without even the implied warranty of
mzcs 1:0a2f89da0616 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
mzcs 1:0a2f89da0616 12 GNU General Public License for more details.
mzcs 1:0a2f89da0616 13
mzcs 1:0a2f89da0616 14 You should have received a copy of the GNU General Public License
mzcs 1:0a2f89da0616 15 along with this program. If not, see <https://www.gnu.org/licenses/>.
mzcs 1:0a2f89da0616 16 */
mzcs 1:0a2f89da0616 17
mzcs 0:437bb8e2f8a7 18 #include "mbed.h"
mzcs 0:437bb8e2f8a7 19 #include "mbed_mem_trace.h"
mzcs 0:437bb8e2f8a7 20 /*#include "hal/pinmap.h"*/
mzcs 0:437bb8e2f8a7 21 #include "DebounceIn.h"
mzcs 0:437bb8e2f8a7 22
mzcs 0:437bb8e2f8a7 23 // a Polling-based (IRQ-less) Edge-Detection Mechanism - Using DebounceIn Class & mBed-OS Thread(s) :
mzcs 0:437bb8e2f8a7 24
mzcs 0:437bb8e2f8a7 25 // [ Note : Shared-Resource (e.g. : PWMOut, BusOut) Are At Least Thread-Safe ( See : https://docs.mbed.com/docs/mbed-os-handbook/en/latest/concepts/thread_safety/ ) ]
mzcs 0:437bb8e2f8a7 26
mzcs 0:437bb8e2f8a7 27 DebounceIn btn_1(PA_11, PullUp), btn_2(PA_12, PullUp); // Inverted Logic : On -> "0", Off -> "1"
mzcs 0:437bb8e2f8a7 28
mzcs 0:437bb8e2f8a7 29 PwmOut pwm_out_1(PA_8);
mzcs 0:437bb8e2f8a7 30
mzcs 0:437bb8e2f8a7 31 BusOut bus_out_1(PA_15, PB_3, PB_4, PB_5); // a 4-bit Bus - For a 4 LED Status-Display Setup
mzcs 0:437bb8e2f8a7 32
mzcs 0:437bb8e2f8a7 33
mzcs 0:437bb8e2f8a7 34 class PwmOut_Elevator
mzcs 0:437bb8e2f8a7 35 {
mzcs 0:437bb8e2f8a7 36 public:
mzcs 0:437bb8e2f8a7 37
mzcs 0:437bb8e2f8a7 38 PwmOut_Elevator(DebounceIn *debounce_in, PwmOut *pwm_out, float step) { _debounce_in = debounce_in; _pwm_out = pwm_out; _step = step; };
mzcs 0:437bb8e2f8a7 39
mzcs 0:437bb8e2f8a7 40 void PwmOut_Elevator_Operator() /* To Be Run Inside a Thread */
mzcs 0:437bb8e2f8a7 41 {
mzcs 0:437bb8e2f8a7 42 while (1)
mzcs 0:437bb8e2f8a7 43 {
mzcs 0:437bb8e2f8a7 44 ThisThread::sleep_for((_debounce_in->get_debounce_us() / 1000) - 1); // Sleep for a Single (1) DebounceIn Sampling-Period
mzcs 0:437bb8e2f8a7 45
mzcs 0:437bb8e2f8a7 46 if ((_debounce_in->get_edge_direction() == 0) && (_debounce_in->get_edge_direction_acted_upon() == 0))
mzcs 0:437bb8e2f8a7 47 {
mzcs 0:437bb8e2f8a7 48 if ((_pwm_out->read() + _step) >= 0.65f) { _pwm_out->write(_pwm_out->read() + _step); }
mzcs 0:437bb8e2f8a7 49 else { _pwm_out->write(0.65f); } // <- a Fail-Safe Default
mzcs 0:437bb8e2f8a7 50
mzcs 0:437bb8e2f8a7 51 _debounce_in->set_edge_direction_acted_upon();
mzcs 0:437bb8e2f8a7 52 }
mzcs 0:437bb8e2f8a7 53 }
mzcs 0:437bb8e2f8a7 54 }
mzcs 0:437bb8e2f8a7 55
mzcs 0:437bb8e2f8a7 56 protected:
mzcs 0:437bb8e2f8a7 57
mzcs 0:437bb8e2f8a7 58 DebounceIn *_debounce_in;
mzcs 0:437bb8e2f8a7 59 PwmOut *_pwm_out;
mzcs 0:437bb8e2f8a7 60 float _step;
mzcs 0:437bb8e2f8a7 61
mzcs 0:437bb8e2f8a7 62 }; // class PwmOut_Elevator - Ends
mzcs 0:437bb8e2f8a7 63
mzcs 0:437bb8e2f8a7 64
mzcs 0:437bb8e2f8a7 65 class Display
mzcs 0:437bb8e2f8a7 66 {
mzcs 0:437bb8e2f8a7 67 public:
mzcs 0:437bb8e2f8a7 68
mzcs 0:437bb8e2f8a7 69 Display(BusOut *bus_out, PwmOut *pwm_out) { _bus_out = bus_out; _pwm_out = pwm_out; };
mzcs 0:437bb8e2f8a7 70
mzcs 0:437bb8e2f8a7 71 void Display_Operator(void) /* To Be Run Inside a Thread */
mzcs 0:437bb8e2f8a7 72 {
mzcs 0:437bb8e2f8a7 73 while (1)
mzcs 0:437bb8e2f8a7 74 {
mzcs 0:437bb8e2f8a7 75 ThisThread::sleep_for(10); // 10ms -> a Projected 100-Hz Update Rate
mzcs 0:437bb8e2f8a7 76
mzcs 0:437bb8e2f8a7 77 _bus_out->write( (uint8_t ((_pwm_out->read() - 0.65f)/0.05f)) + 1 ); // (65% -> 1) .. (100% -> 8), 5% Step
mzcs 0:437bb8e2f8a7 78 }
mzcs 0:437bb8e2f8a7 79 }
mzcs 0:437bb8e2f8a7 80
mzcs 0:437bb8e2f8a7 81 protected:
mzcs 0:437bb8e2f8a7 82
mzcs 0:437bb8e2f8a7 83 PwmOut *_pwm_out;
mzcs 0:437bb8e2f8a7 84 BusOut *_bus_out;
mzcs 0:437bb8e2f8a7 85
mzcs 0:437bb8e2f8a7 86 }; // class Display - Ends
mzcs 0:437bb8e2f8a7 87
mzcs 0:437bb8e2f8a7 88
mzcs 0:437bb8e2f8a7 89 PwmOut_Elevator btn_1_pwmout_elevator(&btn_1, &pwm_out_1, 0.05f), btn_2_pwmout_elevator(&btn_2, &pwm_out_1, -0.05f);
mzcs 0:437bb8e2f8a7 90
mzcs 0:437bb8e2f8a7 91 Display display_1(&bus_out_1, &pwm_out_1);
mzcs 0:437bb8e2f8a7 92
mzcs 0:437bb8e2f8a7 93
mzcs 0:437bb8e2f8a7 94 // for Debugging
mzcs 0:437bb8e2f8a7 95 Semaphore smph_debug_output(1, 1); // (a Binary Semaphore - e.g. : Effectively a Mutex)
mzcs 0:437bb8e2f8a7 96
mzcs 0:437bb8e2f8a7 97 Serial port_serial_1(PA_9, PA_10);
mzcs 0:437bb8e2f8a7 98
mzcs 0:437bb8e2f8a7 99 class Debug
mzcs 0:437bb8e2f8a7 100 {
mzcs 0:437bb8e2f8a7 101 public:
mzcs 0:437bb8e2f8a7 102
mzcs 0:437bb8e2f8a7 103 Debug(Serial *port_serial) { _serial = port_serial; }
mzcs 0:437bb8e2f8a7 104
mzcs 0:437bb8e2f8a7 105 void Debug_Output_Mem_Stats(void) /* To Be Run Inside a Thread */
mzcs 0:437bb8e2f8a7 106 {
mzcs 0:437bb8e2f8a7 107 // allocate enough room for every thread's stack statistics
mzcs 0:437bb8e2f8a7 108 // int8_t cnt = osThreadGetCount();
mzcs 0:437bb8e2f8a7 109 // mbed_stats_stack_t *stats = (mbed_stats_stack_t*) malloc(cnt * sizeof(mbed_stats_stack_t));
mzcs 0:437bb8e2f8a7 110 int8_t cnt;
mzcs 0:437bb8e2f8a7 111
mzcs 0:437bb8e2f8a7 112 _serial->printf("Debug::Debug_Output_Mem_Stats() : Hello ! :)\r\n\r\n");
mzcs 0:437bb8e2f8a7 113
mzcs 0:437bb8e2f8a7 114 while (1)
mzcs 0:437bb8e2f8a7 115 {
mzcs 0:437bb8e2f8a7 116 smph_debug_output.wait();
mzcs 0:437bb8e2f8a7 117
mzcs 0:437bb8e2f8a7 118 cnt = osThreadGetCount();
mzcs 0:437bb8e2f8a7 119
mzcs 0:437bb8e2f8a7 120 // mbed_stats_stack_t *stats = (mbed_stats_stack_t*) malloc(cnt * sizeof(mbed_stats_stack_t));
mzcs 0:437bb8e2f8a7 121 mbed_stats_stack_t *stats = new mbed_stats_stack_t[cnt];
mzcs 0:437bb8e2f8a7 122
mzcs 0:437bb8e2f8a7 123 cnt = mbed_stats_stack_get_each(stats, cnt);
mzcs 0:437bb8e2f8a7 124
mzcs 0:437bb8e2f8a7 125 for (int8_t i = 0; i < cnt; i++) {
mzcs 0:437bb8e2f8a7 126 _serial->printf("Debug::Debug_Output_Mem_Stats(): Thread: 0x%lX, Stack size: %lu / %lu\r\n", stats[i].thread_id, stats[i].max_size, stats[i].reserved_size);
mzcs 0:437bb8e2f8a7 127 }
mzcs 0:437bb8e2f8a7 128
mzcs 0:437bb8e2f8a7 129 // free(stats);
mzcs 0:437bb8e2f8a7 130 delete stats;
mzcs 0:437bb8e2f8a7 131
mzcs 0:437bb8e2f8a7 132 // Grab the heap statistics
mzcs 0:437bb8e2f8a7 133 mbed_stats_heap_t heap_stats;
mzcs 0:437bb8e2f8a7 134 mbed_stats_heap_get(&heap_stats);
mzcs 0:437bb8e2f8a7 135 _serial->printf("Debug::Debug_Output_Mem_Stats(): Heap size: %lu / %lu bytes\r\n\r\n", heap_stats.current_size, heap_stats.reserved_size);
mzcs 0:437bb8e2f8a7 136
mzcs 0:437bb8e2f8a7 137 smph_debug_output.release();
mzcs 0:437bb8e2f8a7 138
mzcs 0:437bb8e2f8a7 139 ThisThread::sleep_for(250);
mzcs 0:437bb8e2f8a7 140 }
mzcs 0:437bb8e2f8a7 141
mzcs 0:437bb8e2f8a7 142 }
mzcs 0:437bb8e2f8a7 143
mzcs 0:437bb8e2f8a7 144 void Debug_Output_General(void) /* To Be Run Inside a Thread */
mzcs 0:437bb8e2f8a7 145 {
mzcs 0:437bb8e2f8a7 146 _serial->printf("Debug::Debug_Output_General() : Hello ! :)\r\n\r\n");
mzcs 0:437bb8e2f8a7 147
mzcs 0:437bb8e2f8a7 148 while (1)
mzcs 0:437bb8e2f8a7 149 {
mzcs 0:437bb8e2f8a7 150 smph_debug_output.wait();
mzcs 0:437bb8e2f8a7 151
mzcs 0:437bb8e2f8a7 152 _serial->printf("Debug::Debug_Output_General() : 'btn_1' Current Value = %d\r\n", btn_1.read());
mzcs 0:437bb8e2f8a7 153 _serial->printf("Debug::Debug_Output_General() : 'btn_1/edge_direction' Current Value = %d\r\n", btn_1.get_edge_direction());
mzcs 0:437bb8e2f8a7 154 _serial->printf("Debug::Debug_Output_General() : 'btn_1/edge_direction_acted_upon' Current Value = %d\r\n", btn_1.get_edge_direction_acted_upon());
mzcs 0:437bb8e2f8a7 155 _serial->printf("Debug::Debug_Output_General() : 'btn_2' Current Value = %d\r\n", btn_2.read());
mzcs 0:437bb8e2f8a7 156 _serial->printf("Debug::Debug_Output_General() : 'btn_2/edge_direction' Current Value = %d\r\n", btn_2.get_edge_direction());
mzcs 0:437bb8e2f8a7 157 _serial->printf("Debug::Debug_Output_General() : 'btn_2/edge_direction_acted_upon' Current Value = %d\r\n", btn_2.get_edge_direction_acted_upon());
mzcs 0:437bb8e2f8a7 158 _serial->printf("Debug::Debug_Output_General() : 'pwm_out_1' Current Value = %f\r\n", pwm_out_1.read());
mzcs 0:437bb8e2f8a7 159 _serial->printf("Debug::Debug_Output_General() : 'bus_out_1' Current Value = %d\r\n\r\n", bus_out_1.read());
mzcs 0:437bb8e2f8a7 160
mzcs 0:437bb8e2f8a7 161 smph_debug_output.release();
mzcs 0:437bb8e2f8a7 162
mzcs 0:437bb8e2f8a7 163 ThisThread::sleep_for(250);
mzcs 0:437bb8e2f8a7 164 }
mzcs 0:437bb8e2f8a7 165 }
mzcs 0:437bb8e2f8a7 166
mzcs 0:437bb8e2f8a7 167 protected:
mzcs 0:437bb8e2f8a7 168
mzcs 0:437bb8e2f8a7 169 Serial *_serial;
mzcs 0:437bb8e2f8a7 170
mzcs 0:437bb8e2f8a7 171 }; // class Debug - Ends
mzcs 0:437bb8e2f8a7 172
mzcs 0:437bb8e2f8a7 173 Debug debug_1(&port_serial_1);
mzcs 0:437bb8e2f8a7 174 ///
mzcs 0:437bb8e2f8a7 175
mzcs 0:437bb8e2f8a7 176 Thread btn_1_thr(osPriorityNormal, 240), btn_2_thr(osPriorityNormal, 240), display_thr(osPriorityNormal, 240), debug_general_thr(osPriorityNormal, 640), debug_mem_stats_thr(osPriorityNormal, 640);
mzcs 0:437bb8e2f8a7 177
mzcs 0:437bb8e2f8a7 178
mzcs 0:437bb8e2f8a7 179 int main()
mzcs 0:437bb8e2f8a7 180 {
mzcs 0:437bb8e2f8a7 181 mbed_mem_trace_set_callback(mbed_mem_trace_default_callback);
mzcs 0:437bb8e2f8a7 182
mzcs 0:437bb8e2f8a7 183 // Set PWM
mzcs 0:437bb8e2f8a7 184 pwm_out_1.period_us(40); // 25 kHz Period
mzcs 0:437bb8e2f8a7 185 pwm_out_1.write(0.65f); // 65% Duty-Cycle (65% Fan Speed : a Safe Default)
mzcs 0:437bb8e2f8a7 186 ///
mzcs 0:437bb8e2f8a7 187
mzcs 0:437bb8e2f8a7 188 debug_general_thr.start(callback(&debug_1, &Debug::Debug_Output_General));
mzcs 0:437bb8e2f8a7 189
mzcs 0:437bb8e2f8a7 190 port_serial_1.printf("main(): 'debug_general_thr' Started.\r\n");
mzcs 0:437bb8e2f8a7 191
mzcs 0:437bb8e2f8a7 192 debug_mem_stats_thr.start(callback(&debug_1, &Debug::Debug_Output_Mem_Stats));
mzcs 0:437bb8e2f8a7 193
mzcs 0:437bb8e2f8a7 194 port_serial_1.printf("main(): 'debug_mem_stats_thr' Started.\r\n");
mzcs 0:437bb8e2f8a7 195
mzcs 0:437bb8e2f8a7 196 port_serial_1.printf("main(): Going To Sleep For a %dms\r\n", ((btn_1.get_debounce_us()*btn_1.get_samples()/1000)+1));
mzcs 0:437bb8e2f8a7 197
mzcs 0:437bb8e2f8a7 198 ThisThread::sleep_for((btn_1.get_debounce_us()*btn_1.get_samples()/1000)+1); // Sleep for 251ms - To Get Initial Stable Input-Values of Buttons via Their DebounceIn Instances
mzcs 0:437bb8e2f8a7 199
mzcs 0:437bb8e2f8a7 200 btn_1_thr.start(callback(&btn_1_pwmout_elevator, &PwmOut_Elevator::PwmOut_Elevator_Operator));
mzcs 0:437bb8e2f8a7 201
mzcs 0:437bb8e2f8a7 202 port_serial_1.printf("main(): 'btn_1_thr' Started.\r\n");
mzcs 0:437bb8e2f8a7 203
mzcs 0:437bb8e2f8a7 204 ThisThread::sleep_for(100);
mzcs 0:437bb8e2f8a7 205
mzcs 0:437bb8e2f8a7 206 btn_2_thr.start(callback(&btn_2_pwmout_elevator, &PwmOut_Elevator::PwmOut_Elevator_Operator));
mzcs 0:437bb8e2f8a7 207
mzcs 0:437bb8e2f8a7 208 port_serial_1.printf("main(): 'btn_2_thr' Started.\r\n");
mzcs 0:437bb8e2f8a7 209
mzcs 0:437bb8e2f8a7 210 ThisThread::sleep_for(100);
mzcs 0:437bb8e2f8a7 211
mzcs 0:437bb8e2f8a7 212 display_thr.start(callback(&display_1, &Display::Display_Operator));
mzcs 0:437bb8e2f8a7 213
mzcs 0:437bb8e2f8a7 214 port_serial_1.printf("main(): 'display_thr' Started.\r\n");
mzcs 0:437bb8e2f8a7 215
mzcs 0:437bb8e2f8a7 216 ThisThread::sleep_for(osWaitForever);
mzcs 0:437bb8e2f8a7 217 }