{"id":271743,"date":"2016-01-07T19:05:02","date_gmt":"2016-01-07T16:05:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=271743"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=271743","title":{"rendered":"\u0411\u043b\u043e\u043a \u0442\u0435\u0440\u043c\u043e\u043a\u043e\u043d\u0442\u0440\u043e\u043b\u044f \u0434\u043b\u044f \u044d\u043b\u0435\u043a\u0442\u0440\u043e\u043d\u043d\u043e\u0439 \u0441\u0438\u0433\u0430\u0440\u0435\u0442\u044b \u043d\u0430 Arduino"},"content":{"rendered":"<p>       \u042d\u0442\u043e\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c \u0442\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u044b \u0442\u0438\u0442\u0430\u043d\u043e\u0432\u043e\u0439 \u0441\u043f\u0438\u0440\u0430\u043b\u0438 (\u0434\u043b\u044f \u043d\u0438\u043a\u0435\u043b\u0435\u0432\u043e\u0439 \u0438\u043b\u0438 \u0436\u0435\u043b\u0435\u0437\u043d\u043e\u0439 \u2014 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 RTCHANGE), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e (\u0438\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u0444\u0438\u0442\u0438\u043b\u044c \u043f\u043e\u0434\u0432\u043e\u0434\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0436\u0438\u0434\u043a\u043e\u0441\u0442\u0438) \u043f\u0430\u0440\u0430 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0435\u0432\u0430 \u0441 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0432\u0435\u0449\u0435\u0441\u0442\u0432, \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432 \u0440\u0430\u0441\u043f\u0430\u0434\u0430 \u0433\u043b\u0438\u0446\u0435\u0440\u0438\u043d\u0430, \u043f\u0440\u043e\u043f\u0438\u043b\u0435\u043d\u0433\u043b\u0438\u043a\u043e\u043b\u044f \u0438 \u0430\u0440\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<p>  \u0421\u0445\u0435\u043c\u0430 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0442\u0430\u0440\u0435\u0435\u0439 \u0434\u043b\u044f RC-\u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0438\u0437 \u0434\u0432\u0443\u0445 Li-\u044f\u0447\u0435\u0435\u043a. \u041c\u043d\u043e\u0439 \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440 500 mAh 25C \u043d\u0430\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u0435 7.4V. \u0422\u043e\u043a \u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0432\u0430\u0440\u044c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0448\u0438\u0440\u043e\u043a\u0438\u0445 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445, \u043b\u0438\u0448\u044c \u0431\u044b \u0432\u044b\u0434\u0430\u0432\u0430\u043b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u0442\u043e\u043a \u0441 \u0445\u043e\u043b\u043e\u0434\u043d\u043e\u0439 \u0441\u043f\u0438\u0440\u0430\u043b\u044c\u044e, \u043a\u043e\u0433\u0434\u0430 \u0435\u0435 \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/05b\/f0a\/609\/05bf0a609e084ff29dfbe42d7cdbb053.jpg\"\/><\/p>\n<p>  <a name=\"habracut\"><\/a><br \/>  \u0422\u0435\u043e\u0440\u0435\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0434\u0435\u043b\u0430\u0442\u044c \u0438 \u043f\u043e\u0434 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440 \u0441 \u043e\u0434\u043d\u043e\u0439 \u044f\u0447\u0435\u0439\u043a\u043e\u0439, \u043d\u043e \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0431\u0438\u0440\u0430\u0442\u044c \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 MOSFET-\u043a\u043b\u044e\u0447\u0438 \u2014 \u0441 \u043d\u0438\u0437\u043a\u0438\u043c \u043d\u0430\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u0435\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u0438 \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435\u043c \u0432 \u043e\u0442\u043a\u0440\u044b\u0442\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u041c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0434\u0430\u0436\u0435 \u0443\u0431\u0440\u0430\u0442\u044c \u0434\u0435\u043b\u0438\u0442\u0435\u043b\u0438 R1+R2 \u0438 R3+R4, \u043f\u043e\u0432\u044b\u0441\u0438\u0432 \u0442\u043e\u0447\u043d\u043e\u0441\u0442\u044c \u0438\u0437\u043c\u0435\u0440\u0435\u043d\u0438\u044f \u0432 \u0434\u0432\u0430 \u0440\u0430\u0437\u0430 (\u0445\u043e\u0442\u044f \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u044d\u0444\u0444\u0435\u043a\u0442\u0430 \u0431\u0443\u0434\u0435\u0442 \u043d\u0435\u043c\u043d\u043e\u0433\u043e).<\/p>\n<p>  \u0420\u0435\u0437\u0438\u0441\u0442\u043e\u0440\u044b R5 \u0438 R6 \u2014 \u0434\u043e\u043b\u0436\u043d\u044b \u0431\u044b\u0442\u044c \u043c\u043e\u0449\u043d\u043e\u0441\u0442\u044c\u044e \u043d\u0435 \u043c\u0435\u043d\u0435\u0435 0.25 \u0432\u0430\u0442\u0442 (\u0430 \u043b\u0443\u0447\u0448\u0435 \u0438 \u0431\u043e\u043b\u044c\u0448\u0435). \u0412\u044b\u0445\u043e\u0434 LED \u2014 \u0434\u043b\u044f \u043f\u0430\u0440\u044b \u0431\u0435\u043b\u044b\u0445 \u0441\u0432\u0435\u0442\u043e\u0434\u0438\u043e\u0434\u043e\u0432, \u0447\u0442\u043e\u0431\u044b \u043c\u043e\u0433 \u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u043a\u0430\u043a \u0430\u0432\u0430\u0440\u0438\u0439\u043d\u044b\u0439 \u0444\u043e\u043d\u0430\u0440\u0438\u043a.<\/p>\n<p>  \u041e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u0430\u043f\u043f\u0430\u0440\u0430\u0442\u043d\u044b\u0439 \u0432\u044b\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u044c, \u0447\u0442\u043e \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442 \u043a \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0431\u044b\u0441\u0442\u0440\u043e\u043c\u0443 \u0440\u0430\u0437\u0440\u044f\u0434\u0443 \u0431\u0430\u0442\u0430\u0440\u0435\u0438 (\u0437\u0430 \u0434\u0435\u043d\u044c \u0438\u043b\u0438 \u043e\u043a\u043e\u043b\u043e \u0442\u043e\u0433\u043e), \u043d\u0435\u0441\u043c\u043e\u0442\u0440\u044f \u043d\u0430 \u0441\u043f\u044f\u0449\u0438\u0439 \u0440\u0435\u0436\u0438\u043c. \u0422\u043e \u043b\u0438 \u044f \u0435\u0433\u043e \u043d\u0435\u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e, \u0442\u043e \u043b\u0438 \u0430\u0440\u0434\u0443\u0438\u043d\u043a\u0430 \u0441 \u0440\u0435\u0433\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u043c\u0438 \u043d\u0430\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u044f \u0432 \u043d\u0435\u0439 \u0438 \u044d\u043a\u0440\u0430\u043d\u0435 \u2014 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u044e\u0442 \u0441\u043b\u0438\u0448\u043a\u043e\u043c \u043c\u043d\u043e\u0433\u043e \u0434\u0430\u0436\u0435 \u0432 \u043d\u0435\u0430\u043a\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0438. \u041d\u0430\u0434\u043e \u0431\u044b\u043b\u043e, \u043d\u0430\u0432\u0435\u0440\u043d\u043e\u0435, \u043f\u043e\u0441\u0442\u0430\u0432\u0438\u0442\u044c \u0435\u0449\u0435 \u043e\u0434\u0438\u043d MOSFET-\u043a\u043b\u044e\u0447 \u043d\u0430 \u0432\u0441\u044e \u0441\u0445\u0435\u043c\u0443, \u0441 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u043c \u043f\u0435\u0440\u0435\u043a\u043b\u044e\u0447\u0430\u0442\u0435\u043b\u0435\u043c, \u0434\u043b\u044f \u0432\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f\/\u043e\u0442\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u044f \u043d\u0430\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u044f \u043f\u0438\u0442\u0430\u043d\u0438\u044f.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/607\/86b\/a48\/60786ba480464ca79a94df2b339bf29d.png\"\/><\/p>\n<p>  \u041a\u043e\u0440\u043f\u0443\u0441 \u0431\u044b\u043b \u043d\u0430\u043f\u0435\u0447\u0430\u0442\u0430\u043d \u043d\u0430 3D \u043f\u0440\u0438\u043d\u0442\u0435\u0440\u0435 \u0438\u0437 PLA. \u041f\u0443\u0441\u0442\u043e\u0435 \u043c\u0435\u0441\u0442\u043e \u043f\u043e\u0434 \u0440\u0430\u0437\u044a\u0435\u043c\u043e\u043c \u0430\u0442\u043e\u043c\u0430\u0439\u0437\u0435\u0440\u0430 \u2014 \u0434\u043b\u044f \u043f\u0440\u043e\u0432\u043e\u0434\u043e\u0432 \u0431\u0430\u0442\u0430\u0440\u0435\u0439\u043a\u0438, \u0438\u0445 \u043d\u0430 \u043c\u043e\u0434\u0435\u043b\u044c\u043d\u044b\u0445 \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440\u0430\u0445 \u0434\u0435\u043b\u0430\u044e\u0442 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u0434\u043b\u0438\u043d\u043d\u044b\u043c\u0438, \u0430 \u043e\u0431\u0440\u0435\u0437\u0430\u0442\u044c \u043d\u0435 \u0445\u043e\u0442\u0435\u043b\u043e\u0441\u044c.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/040\/a27\/05b\/040a2705bf784cfa997e5e8f36e4c3c0.jpg\"\/><\/p>\n<pre><code class=\"cpp\">\/\/ Temperature controller for cigarette, schematics in ard-smoke.sch \/\/ \/\/    Copyright (C) 2015  Vasim V. \/\/ \/\/    This program is free software: you can redistribute it and\/or modify \/\/    it under the terms of the GNU General Public License as published by \/\/    the Free Software Foundation, either version 3 of the License, or \/\/    (at your option) any later version. \/\/ \/\/    This program is distributed in the hope that it will be useful, \/\/    but WITHOUT ANY WARRANTY; without even the implied warranty of \/\/    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the \/\/    GNU General Public License for more details. \/\/ \/\/    You should have received a copy of the GNU General Public License \/\/    along with this program.  If not, see &lt;http:\/\/www.gnu.org\/licenses\/&gt;.  #include &lt;U8glib.h&gt; #include &lt;MsTimer2.h&gt; #include &lt;TimerOne.h&gt; #include &lt;EEPROM.h&gt; #include &lt;avr\/sleep.h&gt;  \/\/ Additional info to console \/\/ #define DEBUG  \/\/ Temperature ADC pin - ITEMP #define P_ITEMP 0 \/\/ Battery ADC pin - CHECK #define P_VMAIN 1 \/\/ Coil N-FET gate - OOn #define P_OON 9 \/\/ Temperature check N-FET gate - OTest #define P_OTEST 3  #define NBUTTONS 3 \/\/ Coil button #define P_BCOIL 10 \/\/ Plus button *\/ #define P_BPLUS 11 \/\/ Minus button *\/ #define P_BMINUS 12  \/\/ Delay for FET change, microseconds #define FETSW_DELAY 10  \/\/ Interrupt period (timer2), microseconds #define TIMER_PERIOD 10000  \/\/ PWM Period, microseconds #define PWM_PERIOD 1024  \/\/ Test resistor resistance, in Ohm #define RTEST 4.7f  \/\/ Temparture-resistance koefficient \/\/ Titan #define RTCHANGE 0.0035f \/\/ Kantal - not working (too low resolution) \/\/ #define RTCHANGE 0.0001f  \/\/ Default zero (when no difference between rcoil_zero and rcoil) temperature #define TEMP_ZERO 25  \/\/ Sleep timer (in timer2 cycles, seconds*100), activate if coil button was pressed for #define SLEEP_TIME 12000  \/\/ How long you should keep button pressed to change temperature, in time2 cycles (seconds*100) #define BUTTON_SENS_TIME 100  #define PID_P 60.0 #define PID_I 0.75 #define PID_D 20.0  U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);  \/\/ Coil is on or not boolean coil_on; \/\/ Voltage readings from ADCs int coilv; int vmainv; \/\/ Calculated from vmainv, in volts float vbat; \/\/ Calculated from coilv, in volts and ohms float voff; float rcoil;  \/\/ Coil resistance at 25C float rcoil_zero = 0.0f;  \/\/ Current temperature in celsius double tcur;  \/\/ Cut-off temperature in celsius double tcut;  \/\/ PID regulator stuff double Output;  \/\/ Buttons debounce stuff #define I_BCOIL 0 #define I_BPLUS 1 #define I_BMINUS 2 uint8_t pbuttons[NBUTTONS] = {P_BCOIL, P_BPLUS, P_BMINUS}; uint8_t sw_check[NBUTTONS];  \/\/ Buttons state after debouncing boolean sbuttons[NBUTTONS] = {false, false, false};  \/\/ How long buttons state wasn't changed (in timer2 cycles) uint32_t idlebuttons[NBUTTONS] = {0, 0, 0};  \/\/ Ignore if buttons were pressed at startup boolean ignore_buttons = false;  \/\/ In deep sleep boolean sleeping;  double errSum, lastErr; double outputLast = 0.0; #define MAX_CHANGE 1023.0  void MyPIDStart() {   errSum = lastErr = outputLast = 0.0;   MyPIDCompute(); }  \/\/ Calculate output void MyPIDCompute() {    double timeChange = TIMER_PERIOD \/ 1000;    double error = tcut - tcur;    errSum += (error * timeChange);    double dErr = (error - lastErr) \/ timeChange;    double preOutput;       \/*Compute PID Output*\/    preOutput = PID_P * error + PID_I * errSum + PID_D * dErr;    if ((preOutput - outputLast) &gt; MAX_CHANGE)      preOutput = outputLast + MAX_CHANGE;    else if ((outputLast - preOutput) &gt; MAX_CHANGE)      preOutput = outputLast - MAX_CHANGE;       Output = preOutput - outputLast;    if (Output &lt; 0)      Output = 0;       \/*Remember some variables for next time*\/    outputLast = preOutput;    lastErr = error; }  \/\/ Calculate coil resistance and temperature void update_temp() {   rcoil = (vmainv * RTEST) \/ (coilv * 1.0f + 1) - RTEST;   if (rcoil &lt; 0)     rcoil = 0;   if (rcoil_zero &gt; 0.01)      tcur = double((rcoil \/ rcoil_zero - 1) \/ RTCHANGE);   else     tcur = 0; }  void eeprom_writef(int addr, float x) {   uint8_t i;    for (i = 0; i &lt; sizeof(float); i++) {     EEPROM.update(addr + i, *((char *) &x + i));   } }  float eeprom_readf(int addr) {   float x;   int i;    for (i = 0; i &lt; sizeof(float); i++) {     *((char *) &x + i) = EEPROM.read(addr + i);   }   \/\/ Test if we did read float really, not &quot;NAN&quot;   if ((x+1.0) &gt; x)     return x;   return 0; }  \/\/ Timer interrupt - Test buttons, check temperature and fire coil, etc void intcallback() {   uint8_t i;  \/\/ Debounce buttons   for (i = 0; i &lt; NBUTTONS; i++) {     if (sbuttons[i] != (digitalRead(pbuttons[i]) == LOW)) {       if (sw_check[i] &gt; 5) {         sw_check[i] = 0;         sbuttons[i] = (digitalRead(pbuttons[i]) == LOW);         idlebuttons[i] = 0;       } else {         sw_check[i]++;         idlebuttons[i]++;       }     } else {       sw_check[i] = 0;       idlebuttons[i]++;     }   }      \/\/ Measuring temperature - turning off main coil FET before   if (coil_on || ignore_buttons) {     Timer1.disablePwm(P_OON);     digitalWrite(P_OON, LOW);     delayMicroseconds(FETSW_DELAY);   }      \/\/ Don't do anything else   if (sleeping || ignore_buttons)     return;        digitalWrite(P_OTEST, HIGH);   delayMicroseconds(FETSW_DELAY);   coilv = analogRead(P_ITEMP);   vmainv = analogRead(P_VMAIN);   digitalWrite(P_OTEST, LOW);   delayMicroseconds(FETSW_DELAY);   \/\/ Measuring is done, turning on coil back   if (coil_on)     Timer1.pwm(P_OON, Output, PWM_PERIOD);   else {     Timer1.disablePwm(P_OON);     digitalWrite(P_OON, LOW);   }     \/\/ Calculate temperature   update_temp();      if (coil_on)     \/\/ PID processing (calculate output)     MyPIDCompute();  #ifdef DEBUG   Serial.print(&quot;Temp: &quot;);   Serial.print(tcur+TEMP_ZERO);   Serial.print(&quot;C, rcoil: &quot;);   Serial.print(rcoil);   Serial.print(&quot;Ohm, Output: &quot;);   Serial.println(Output); #endif   \/\/ Fire coil if button pressed   if (!coil_on && sbuttons[I_BCOIL] && !ignore_buttons && (tcut &gt;= tcur)) {     MyPIDStart();     coil_on = true;     Timer1.pwm(P_OON, Output, PWM_PERIOD);   }    \/\/ Coil shutdown if button is released or more than 50 celsius above   if (!sbuttons[I_BCOIL] || ((tcur - 5) &gt; tcut)) {     coil_on = false;     Output = 0;     Timer1.setPwmDuty(P_OON, 0);     Timer1.disablePwm(P_OON);     digitalWrite(P_OON, LOW);   } }  void setup() {   Serial.begin(115200);    ignore_buttons = true;   sleeping = false;   \/\/ ADC pins   pinMode(P_ITEMP, INPUT);   pinMode(P_VMAIN, INPUT);   \/\/ Coil\/check FETs   pinMode(P_OON, OUTPUT);   digitalWrite(P_OON, LOW);   coil_on = false;   pinMode(P_OTEST, OUTPUT);   digitalWrite(P_OTEST, LOW);   \/\/ Configuring buttons pins   pinMode(P_BCOIL, INPUT_PULLUP);   pinMode(P_BPLUS, INPUT_PULLUP);   pinMode(P_BMINUS, INPUT_PULLUP);    \/\/ Display init   \/\/ Rotate if needed   \/\/ u8g.setRot180();   \/\/ From u8g_lib example - assign default color value   if ( u8g.getMode() == U8G_MODE_R3G3B2 ) {     u8g.setColorIndex(255);     \/\/ white   }   else if ( u8g.getMode() == U8G_MODE_GRAY2BIT ) {     u8g.setColorIndex(3);         \/\/ max intensity   }   else if ( u8g.getMode() == U8G_MODE_BW ) {     u8g.setColorIndex(1);         \/\/ pixel on   }   else if ( u8g.getMode() == U8G_MODE_HICOLOR ) {     u8g.setHiColorByRGB(255,255,255);   }    \/\/ Read coil resistance at 25C from eeprom, update current values \/\/  rcoil_zero = eeprom_readf(0);     tcut = eeprom_readf(4);   if ((tcut &lt; 100.0) || (tcut &gt; 300.0))     tcut = 180;    \/\/ Disable buttons until released if any of it pressed at startup   if ((digitalRead(P_BPLUS) == LOW) || (digitalRead(P_BMINUS) == LOW) || (digitalRead(P_BCOIL) == LOW)) {     int i;          ignore_buttons = true;     for (i = 0; i &lt; NBUTTONS; i++)       sbuttons[i] = (digitalRead(pbuttons[i]) == LOW);   } else     ignore_buttons = false;    \/\/ Timers initialize   MsTimer2::set(TIMER_PERIOD \/ 1000, intcallback);   MsTimer2::start();      Timer1.initialize(1000);   Timer1.pwm(9, 0, PWM_PERIOD); }  static int loopcycle = 0; static int showtemp; static float showrcoil;  void draw() {   char tmpbuf[16];    if (!sleeping && idlebuttons[I_BCOIL] &gt; SLEEP_TIME)     return;        u8g.setFont(u8g_font_helvR12);    memcpy(tmpbuf, &quot;Batt&quot;, 4);   if (vmainv &lt; 1022) {     dtostrf(vbat, 4, 1, tmpbuf+4);     memcpy(tmpbuf+8, &quot;V - &quot;, 4);   } else     memcpy(tmpbuf+4, &quot; MAX&quot;, 5);    if (vbat &gt; 6.3)      memcpy(tmpbuf+12, &quot;OK&quot;, 3);   else {     if (loopcycle %  2)       u8g.setFont(u8g_font_helvB12);     memcpy(tmpbuf+12, &quot;LOW!&quot;, 5);   }   u8g.drawStr(0, 64, tmpbuf);   u8g.setFont(u8g_font_helvR12);      if (sbuttons[I_BCOIL])     u8g.drawStr(90, 16, &quot;C&quot;);   else     u8g.drawStr(90, 16, &quot;.&quot;);    if (sbuttons[I_BPLUS])     u8g.drawStr(99, 16, &quot;+&quot;);   else     u8g.drawStr(99, 16, &quot;.&quot;);    if (sbuttons[I_BMINUS])     u8g.drawStr(108, 16, &quot;-&quot;);   else     u8g.drawStr(108, 16, &quot;.&quot;);    memcpy(tmpbuf, &quot;= &quot;, 3);   dtostrf(tcut+25.0f, 4, 0, tmpbuf+2);   u8g.drawStr(0, 48, tmpbuf);      tmpbuf[0] = 'R';   dtostrf(rcoil, 5, 2, tmpbuf+1);   memcpy(tmpbuf+6, &quot;Ohm&quot;, 4);   u8g.drawStr(0, 32, tmpbuf);      dtostrf(float(showtemp), 4, 0, tmpbuf);   tmpbuf[4] = 'C';   tmpbuf[5] = '\\0';   u8g.drawStr(18, 16, tmpbuf);   if (coil_on)     u8g.drawStr(0, 16, &quot;&gt;&gt;&quot;);   else     u8g.drawStr(0, 16, &quot;  &quot;);    dtostrf(float(Output), 5, 0, tmpbuf);   u8g.drawStr(64, 48, tmpbuf); }  \/\/ To test if minus button was pressed 3 times in 6 seconds - exit sleep mode boolean last_b_state; int nchanges; int ncycles;  \/\/ Update EEPROM with temperature limit  boolean update_eeprom = false;  void loop() {   int i;      vbat = (10.0 * vmainv) \/ 1024.0;   voff = (10.0 * coilv) \/ 1024.0;   showtemp = tcur + TEMP_ZERO;    \/\/ Redraw screen   if (!sleeping) {     \/\/ u8g_lib picture loop     u8g.firstPage();       do {       draw();     } while( u8g.nextPage() );   }    \/\/ Change temperature limit if MINUS or PLUS pressed   if (!ignore_buttons) {     if (sbuttons[I_BMINUS] && idlebuttons[I_BMINUS] &gt; BUTTON_SENS_TIME) {       tcut = tcut - 5;       idlebuttons[I_BMINUS] = 0;       update_eeprom = true;     }     if (sbuttons[I_BPLUS] && idlebuttons[I_BPLUS] &gt; BUTTON_SENS_TIME) {       tcut = tcut + 5;       idlebuttons[I_BPLUS] = 0;       update_eeprom = true;     }   }      \/\/ Sleep after turning off screen   if (!sleeping && (idlebuttons[I_BCOIL] &gt; SLEEP_TIME)) {     sleeping = true;     ignore_buttons = true;     u8g.sleepOn();   }    \/\/ Check if should wake up (MINUS button pressed few times)   if (sleeping) {     ncycles++;     if (last_b_state != sbuttons[I_BMINUS]) {       ncycles = 0;       last_b_state = sbuttons[I_BMINUS];       nchanges++;       if (nchanges &gt;= 6) {         rcoil_zero = 0;         sleeping = false;         u8g.sleepOff();         for (i = 0; i &lt; NBUTTONS; i++)           idlebuttons[i] = 0;       }     } else {       if (ncycles &gt; 20) {         ncycles = 0;         nchanges = 0;       }     }   }      \/\/ Check if all buttons are released   if (ignore_buttons && !sleeping) {     int i;     boolean pressed = false;      for (i = 0; i &lt; NBUTTONS; i++) {       if (sbuttons[i])         pressed = true;     }     if (!pressed)       ignore_buttons = false;   }   loopcycle++;    \/\/  Serial.println(vmainv);   if (sleeping) {     ignore_buttons = true;     set_sleep_mode(SLEEP_MODE_PWR_SAVE);     sleep_enable();   }   if (((rcoil_zero &lt; 0.01) && (rcoil &gt; 0.01)) || (showtemp &lt; -50)) {     rcoil_zero = rcoil; \/\/    update_eeprom = true;   }    if (update_eeprom) {     eeprom_writef(0, rcoil_zero);     eeprom_writef(4, tcut);     update_eeprom = false;   }   delay(333); } <\/code><\/pre>\n<p>                 <\/p>\n<div class=\"clear\"><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/geektimes.ru\/post\/268872\/\"> http:\/\/geektimes.ru\/post\/268872\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>       \u042d\u0442\u043e\u0442 \u0443\u0441\u0442\u0440\u043e\u0439\u0441\u0442\u0432\u043e \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u043e \u0434\u043b\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u043f\u0430\u0440\u0430 \u0441 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0435\u043c \u0442\u0435\u043c\u043f\u0435\u0440\u0430\u0442\u0443\u0440\u044b \u0442\u0438\u0442\u0430\u043d\u043e\u0432\u043e\u0439 \u0441\u043f\u0438\u0440\u0430\u043b\u0438 (\u0434\u043b\u044f \u043d\u0438\u043a\u0435\u043b\u0435\u0432\u043e\u0439 \u0438\u043b\u0438 \u0436\u0435\u043b\u0435\u0437\u043d\u043e\u0439 \u2014 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u043c\u0435\u043d\u044f\u0442\u044c \u043a\u043e\u044d\u0444\u0444\u0438\u0446\u0438\u0435\u043d\u0442 RTCHANGE), \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0442\u044c \u043c\u043d\u043e\u0433\u043e (\u0438\u043b\u0438 \u043e\u0447\u0435\u043d\u044c \u043c\u043d\u043e\u0433\u043e, \u0435\u0441\u043b\u0438 \u0444\u0438\u0442\u0438\u043b\u044c \u043f\u043e\u0434\u0432\u043e\u0434\u0438\u0442 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0436\u0438\u0434\u043a\u043e\u0441\u0442\u0438) \u043f\u0430\u0440\u0430 \u0431\u0435\u0437 \u043f\u0435\u0440\u0435\u0433\u0440\u0435\u0432\u0430 \u0441 \u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u043d\u044b\u0445 \u043d\u0435\u0445\u043e\u0440\u043e\u0448\u0438\u0445 \u0432\u0435\u0449\u0435\u0441\u0442\u0432, \u043f\u0440\u043e\u0434\u0443\u043a\u0442\u043e\u0432 \u0440\u0430\u0441\u043f\u0430\u0434\u0430 \u0433\u043b\u0438\u0446\u0435\u0440\u0438\u043d\u0430, \u043f\u0440\u043e\u043f\u0438\u043b\u0435\u043d\u0433\u043b\u0438\u043a\u043e\u043b\u044f \u0438 \u0430\u0440\u043e\u043c\u0430\u0442\u0438\u0437\u0430\u0442\u043e\u0440\u043e\u0432.<\/p>\n<p>  \u0421\u0445\u0435\u043c\u0430 \u043f\u0440\u0435\u0434\u043d\u0430\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0431\u0430\u0442\u0430\u0440\u0435\u0435\u0439 \u0434\u043b\u044f RC-\u043c\u043e\u0434\u0435\u043b\u0435\u0439, \u0438\u0437 \u0434\u0432\u0443\u0445 Li-\u044f\u0447\u0435\u0435\u043a. \u041c\u043d\u043e\u0439 \u0431\u044b\u043b \u0432\u044b\u0431\u0440\u0430\u043d \u0430\u043a\u043a\u0443\u043c\u0443\u043b\u044f\u0442\u043e\u0440 500 mAh 25C \u043d\u0430\u043f\u0440\u044f\u0436\u0435\u043d\u0438\u0435 7.4V. \u0422\u043e\u043a \u0438 \u043d\u0430\u0433\u0440\u0443\u0437\u043e\u0447\u043d\u0443\u044e \u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c \u043c\u043e\u0436\u043d\u043e \u0432\u0430\u0440\u044c\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 \u0448\u0438\u0440\u043e\u043a\u0438\u0445 \u043f\u0440\u0435\u0434\u0435\u043b\u0430\u0445, \u043b\u0438\u0448\u044c \u0431\u044b \u0432\u044b\u0434\u0430\u0432\u0430\u043b \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u044b\u0439 \u0442\u043e\u043a \u0441 \u0445\u043e\u043b\u043e\u0434\u043d\u043e\u0439 \u0441\u043f\u0438\u0440\u0430\u043b\u044c\u044e, \u043a\u043e\u0433\u0434\u0430 \u0435\u0435 \u0441\u043e\u043f\u0440\u043e\u0442\u0438\u0432\u043b\u0435\u043d\u0438\u0435 \u043c\u0438\u043d\u0438\u043c\u0430\u043b\u044c\u043d\u043e.<\/p>\n<p>  <img decoding=\"async\" src=\"https:\/\/habrastorage.org\/files\/05b\/f0a\/609\/05bf0a609e084ff29dfbe42d7cdbb053.jpg\"\/><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-271743","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/271743","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=271743"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/271743\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=271743"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=271743"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=271743"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}