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.
phasecontrol.cpp
00001 /* Copyright (c) 2017 Philippe Kalaf, MIT License 00002 * 00003 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00004 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00005 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00006 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00007 * furnished to do so, subject to the following conditions: 00008 * 00009 * The above copyright notice and this permission notice shall be included in all copies or 00010 * substantial portions of the Software. 00011 * 00012 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00013 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00014 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00015 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00016 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00017 */ 00018 00019 // Phase control class (used for pump) 00020 #include "phasecontrol.h" 00021 00022 // estimate of lag caused by ZCD circuit in usec 00023 // measured as per http://espresso-for-geeks.kalaf.net/mod-list/#hw-zero-cross 00024 #define ZCD_DELAY 36 00025 00026 // power frequency half-period in usec 00027 // set to 8333 for 60Hz 00028 // set to 10000 for 50Hz 00029 #define HALF_PERIOD_USEC 8333 00030 00031 // the time in usec to wait after zero-cross before switching off 00032 // this eliminates the back-EMF by waiting for current to drop before switching off 00033 #define DELAY_AFTER_STOP (HALF_PERIOD_USEC / 2) 00034 00035 // TODO PRECACULATE 50Hz numbers 00036 // These are precalculated values (usec) of the required phase delays for 0 to 100% power. 00037 // Equation used is: 1000000 usec / 120 * (acos(2*x/100 - 1) / pi) 00038 const uint16_t PhaseControl::_timeouts_usec[101] = 00039 {0, 531, 753, 924, 1068, 1196, 1313, 1421, 1521, 1616, 00040 1707, 1793, 1877, 1957, 2035, 2110, 2183, 2255, 2324, 00041 2393, 2460, 2525, 2590, 2654, 2716, 2778, 2839, 2899, 00042 2958, 3017, 3075, 3133, 3190, 3246, 3303, 3358, 3414, 00043 3469, 3524, 3578, 3633, 3687, 3740, 3794, 3848, 3901, 00044 3954, 4007, 4061, 4114, 4167, 4220, 4273, 4326, 4379, 00045 4432, 4486, 4539, 4593, 4647, 4701, 4755, 4810, 4864, 00046 4919, 4975, 5031, 5087, 5144, 5201, 5258, 5316, 5375, 00047 5435, 5495, 5556, 5617, 5680, 5743, 5808, 5874, 5941, 00048 6009, 6079, 6150, 6223, 6299, 6376, 6457, 6540, 6626, 00049 6717, 6812, 6913, 7020, 7137, 7265, 7410, 7581, 7802, 00050 8333}; 00051 00052 PhaseControl::PhaseControl(PinName pin, PinName pin2) : _zcd(pin), _control_signal(pin2) { 00053 // if your zcd circuit has it's own pullup, set to None 00054 _zcd.mode(PullUp); 00055 _zcd.fall(callback(this, &PhaseControl::delayed_start)); 00056 _zcd.rise(callback(this, &PhaseControl::delayed_stop)); 00057 _level = 75; 00058 _control_signal = 0; 00059 00060 // This is a workaround until timeouts for 50Hz are calculated 00061 if (HALF_PERIOD_USEC == 8333) 00062 _timeout_usec = HALF_PERIOD_USEC - _timeouts_usec[_level] - ZCD_DELAY; 00063 else 00064 _timeout_usec = HALF_PERIOD_USEC - (_timeouts_usec[_level]*10000/8333) - ZCD_DELAY; 00065 00066 /* debug info 00067 _t.start(); 00068 counter = 0; 00069 */ 00070 } 00071 00072 PhaseControl::~PhaseControl() 00073 { 00074 } 00075 00076 void PhaseControl::stop() 00077 { 00078 /* debug info 00079 if (counter < 2000) 00080 { 00081 times[counter][0] = _t.read_us(); 00082 times[counter][1] = 0; 00083 //times[counter][2] = _level; 00084 counter++; 00085 } 00086 */ 00087 00088 _control_signal = 0; 00089 _control_timeout.detach(); 00090 } 00091 00092 void PhaseControl::start() 00093 { 00094 /* debug info 00095 if (counter < 2000) 00096 { 00097 times[counter][0] = _t.read_us(); 00098 times[counter][1] = 1; 00099 //times[counter][2] = _level; 00100 counter++; 00101 } 00102 */ 00103 00104 _control_signal = 1; 00105 } 00106 00107 void PhaseControl::delayed_start() 00108 { 00109 // Level 100 is full power (minus zcd lag) 00110 if (_level == 100) 00111 start(); 00112 // Level 0 just stop 00113 else if (_level == 0) 00114 stop(); 00115 // otherwise do a delayed start (start after timeout_usec elapses) 00116 else 00117 _control_timeout.attach_us(callback(this, &PhaseControl::start), _timeout_usec); 00118 } 00119 00120 // We wait DELAY_AFTER_STOP before stopping to avoid back-EMF 00121 void PhaseControl::delayed_stop() 00122 { 00123 _test_timeout.attach_us(callback(this, &PhaseControl::stop), DELAY_AFTER_STOP); 00124 } 00125 00126 uint8_t PhaseControl::get_level() 00127 { 00128 return _level; 00129 } 00130 00131 void PhaseControl::set_level(uint8_t level) 00132 { 00133 if (level > 100) 00134 _level = 100; 00135 else 00136 _level = level; 00137 00138 // This is a workaround until timeouts for 50Hz are calculated 00139 if (HALF_PERIOD_USEC == 8333) 00140 _timeout_usec = HALF_PERIOD_USEC - _timeouts_usec[_level] - ZCD_DELAY; 00141 else 00142 _timeout_usec = HALF_PERIOD_USEC - (_timeouts_usec[_level]*10000/8333) - ZCD_DELAY; 00143 } 00144 00145 void PhaseControl::level_up(uint8_t value) 00146 { 00147 if (_level < 100) 00148 set_level(_level + value); 00149 } 00150 00151 void PhaseControl::level_down(uint8_t value) 00152 { 00153 if (_level > 0) 00154 set_level(_level - value); 00155 }
Generated on Thu Jul 14 2022 00:36:34 by
1.7.2