Moran Z. / Mbed OS Fan_Ctlr_PWM_HF
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 /*
00002     Copyright (c) 2018 - Moran ZALTSMAN
00003 
00004     This program is free software: you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation, either version 3 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program.  If not, see <https://www.gnu.org/licenses/>.
00016 */
00017 
00018 #include "mbed.h"
00019 #include "mbed_mem_trace.h"
00020 /*#include "hal/pinmap.h"*/
00021 #include "DebounceIn.h"
00022 
00023 // a Polling-based (IRQ-less) Edge-Detection Mechanism - Using DebounceIn Class & mBed-OS Thread(s) :
00024 
00025 // [ 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/ ) ]
00026 
00027 DebounceIn      btn_1(PA_11, PullUp), btn_2(PA_12, PullUp); // Inverted Logic : On -> "0", Off -> "1"
00028 
00029 PwmOut          pwm_out_1(PA_8);
00030 
00031 BusOut          bus_out_1(PA_15, PB_3, PB_4, PB_5); // a 4-bit Bus - For a 4 LED Status-Display Setup
00032 
00033 
00034 class PwmOut_Elevator
00035 {
00036 public:
00037 
00038 PwmOut_Elevator(DebounceIn *debounce_in, PwmOut *pwm_out, float step) { _debounce_in = debounce_in; _pwm_out = pwm_out; _step = step; };
00039 
00040 void PwmOut_Elevator_Operator() /* To Be Run Inside a Thread */
00041 {
00042     while (1)
00043     {
00044     ThisThread::sleep_for((_debounce_in->get_debounce_us() / 1000) - 1); // Sleep for a Single (1) DebounceIn Sampling-Period
00045 
00046     if ((_debounce_in->get_edge_direction() == 0) && (_debounce_in->get_edge_direction_acted_upon() == 0))
00047         {
00048         if ((_pwm_out->read() + _step) >= 0.65f) { _pwm_out->write(_pwm_out->read() + _step); }
00049         else { _pwm_out->write(0.65f); } // <- a Fail-Safe Default
00050 
00051         _debounce_in->set_edge_direction_acted_upon();
00052         }
00053     }
00054 }
00055 
00056 protected:
00057 
00058 DebounceIn *_debounce_in;
00059 PwmOut *_pwm_out;
00060 float _step;
00061 
00062 }; // class PwmOut_Elevator - Ends
00063 
00064 
00065 class Display
00066 {
00067 public:
00068 
00069 Display(BusOut *bus_out, PwmOut *pwm_out) { _bus_out = bus_out; _pwm_out = pwm_out; };
00070 
00071 void Display_Operator(void) /* To Be Run Inside a Thread */
00072 {
00073     while (1)
00074     {
00075     ThisThread::sleep_for(10); // 10ms -> a Projected 100-Hz Update Rate
00076 
00077     _bus_out->write( (uint8_t ((_pwm_out->read() - 0.65f)/0.05f)) + 1 ); // (65% -> 1) .. (100% -> 8), 5% Step
00078     }
00079 }
00080 
00081 protected:
00082 
00083 PwmOut *_pwm_out;
00084 BusOut *_bus_out;
00085 
00086 }; // class Display - Ends
00087 
00088 
00089 PwmOut_Elevator btn_1_pwmout_elevator(&btn_1, &pwm_out_1, 0.05f), btn_2_pwmout_elevator(&btn_2, &pwm_out_1, -0.05f);
00090 
00091 Display         display_1(&bus_out_1, &pwm_out_1);
00092 
00093 
00094 // for Debugging
00095 Semaphore       smph_debug_output(1, 1); // (a Binary Semaphore - e.g. : Effectively a Mutex)
00096 
00097 Serial port_serial_1(PA_9, PA_10);
00098 
00099 class Debug
00100 {
00101 public:
00102 
00103 Debug(Serial *port_serial) { _serial = port_serial; }
00104 
00105 void Debug_Output_Mem_Stats(void) /* To Be Run Inside a Thread */
00106 {
00107     // allocate enough room for every thread's stack statistics
00108 //    int8_t cnt = osThreadGetCount();
00109 //    mbed_stats_stack_t *stats = (mbed_stats_stack_t*) malloc(cnt * sizeof(mbed_stats_stack_t));
00110     int8_t cnt;
00111  
00112     _serial->printf("Debug::Debug_Output_Mem_Stats() : Hello ! :)\r\n\r\n");
00113 
00114     while (1)
00115     {
00116     smph_debug_output.wait();
00117     
00118     cnt = osThreadGetCount();
00119 
00120 //    mbed_stats_stack_t *stats = (mbed_stats_stack_t*) malloc(cnt * sizeof(mbed_stats_stack_t));
00121     mbed_stats_stack_t *stats = new mbed_stats_stack_t[cnt];
00122 
00123     cnt = mbed_stats_stack_get_each(stats, cnt);
00124     
00125     for (int8_t i = 0; i < cnt; i++) {
00126         _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);
00127     }
00128 
00129 //    free(stats);
00130     delete stats;
00131 
00132     // Grab the heap statistics
00133     mbed_stats_heap_t heap_stats;
00134     mbed_stats_heap_get(&heap_stats);
00135     _serial->printf("Debug::Debug_Output_Mem_Stats(): Heap size: %lu / %lu bytes\r\n\r\n", heap_stats.current_size, heap_stats.reserved_size);
00136 
00137     smph_debug_output.release();
00138 
00139     ThisThread::sleep_for(250);
00140     }
00141 
00142 }
00143 
00144 void Debug_Output_General(void) /* To Be Run Inside a Thread */
00145 {
00146     _serial->printf("Debug::Debug_Output_General() : Hello ! :)\r\n\r\n");
00147 
00148     while (1)
00149     {
00150     smph_debug_output.wait();
00151 
00152     _serial->printf("Debug::Debug_Output_General() : 'btn_1' Current Value = %d\r\n", btn_1.read());
00153     _serial->printf("Debug::Debug_Output_General() : 'btn_1/edge_direction' Current Value = %d\r\n", btn_1.get_edge_direction());
00154     _serial->printf("Debug::Debug_Output_General() : 'btn_1/edge_direction_acted_upon' Current Value = %d\r\n", btn_1.get_edge_direction_acted_upon());
00155     _serial->printf("Debug::Debug_Output_General() : 'btn_2' Current Value = %d\r\n", btn_2.read());
00156     _serial->printf("Debug::Debug_Output_General() : 'btn_2/edge_direction' Current Value = %d\r\n", btn_2.get_edge_direction());
00157     _serial->printf("Debug::Debug_Output_General() : 'btn_2/edge_direction_acted_upon' Current Value = %d\r\n", btn_2.get_edge_direction_acted_upon());
00158     _serial->printf("Debug::Debug_Output_General() : 'pwm_out_1' Current Value = %f\r\n", pwm_out_1.read());
00159     _serial->printf("Debug::Debug_Output_General() : 'bus_out_1' Current Value = %d\r\n\r\n", bus_out_1.read());
00160 
00161     smph_debug_output.release();
00162 
00163     ThisThread::sleep_for(250);    
00164     }
00165 }
00166 
00167 protected:
00168 
00169 Serial *_serial;
00170 
00171 }; // class Debug - Ends
00172 
00173 Debug          debug_1(&port_serial_1);
00174 ///
00175 
00176 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);
00177 
00178 
00179 int main()
00180 {
00181     mbed_mem_trace_set_callback(mbed_mem_trace_default_callback);
00182     
00183     // Set PWM
00184     pwm_out_1.period_us(40); // 25 kHz Period
00185     pwm_out_1.write(0.65f); // 65% Duty-Cycle (65% Fan Speed : a Safe Default)
00186     ///
00187 
00188     debug_general_thr.start(callback(&debug_1, &Debug::Debug_Output_General));
00189 
00190     port_serial_1.printf("main(): 'debug_general_thr' Started.\r\n");
00191 
00192     debug_mem_stats_thr.start(callback(&debug_1, &Debug::Debug_Output_Mem_Stats));
00193 
00194     port_serial_1.printf("main(): 'debug_mem_stats_thr' Started.\r\n");
00195 
00196     port_serial_1.printf("main(): Going To Sleep For a %dms\r\n", ((btn_1.get_debounce_us()*btn_1.get_samples()/1000)+1));
00197 
00198     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
00199 
00200     btn_1_thr.start(callback(&btn_1_pwmout_elevator, &PwmOut_Elevator::PwmOut_Elevator_Operator));
00201 
00202     port_serial_1.printf("main(): 'btn_1_thr' Started.\r\n");
00203 
00204     ThisThread::sleep_for(100);
00205     
00206     btn_2_thr.start(callback(&btn_2_pwmout_elevator, &PwmOut_Elevator::PwmOut_Elevator_Operator));
00207 
00208     port_serial_1.printf("main(): 'btn_2_thr' Started.\r\n");
00209 
00210     ThisThread::sleep_for(100);
00211 
00212     display_thr.start(callback(&display_1, &Display::Display_Operator));
00213 
00214     port_serial_1.printf("main(): 'display_thr' Started.\r\n");
00215 
00216     ThisThread::sleep_for(osWaitForever);
00217 }