Facebook
From dwdw, 1 Month ago, written in Plain Text.
Embed
Download Paste or View Raw
Hits: 139
  1. //----------------------------------------------------------------------------------------------------------------------------
  2. // CRYPTO CURRENCY PRICE TICKER with 24 candlesticks chart for M5Stack
  3. //
  4. // ###SD-Card Version with configuation file###
  5. // only needs config file "ccticker.cfg" on root of SD-Card
  6. //
  7. // receiving WiFi data from Binance.US (!) API/Websocket_v3 - by frittna (https://github.com/frittna/Crypto_Coin_Ticker)
  8. //
  9. // This will show 24 candles, the min/max price and the volume as line, date and time are from time.nist.gov timeserver.
  10. // For M5-Stack MCU , coded in ArduinoIDE 1.8.13 - last modified Dec.07.2021 12:12 CET - Version 1.0.53 fix using spiffs + SDconfig
  11. //
  12. //
  13. // single change:    -> made a seperate version that uses binance.us instead of .com server if you are blocked from the .com server
  14. // previous edits:   -> added cycling function (ButtonA+ButtonC together) which steps through your currencies after a certain time (default: 15sec for each)
  15. //                                   -> added Timezone for Singapore (UTC+8)
  16. //                                   -> minor changings: - code merged to one version, so there is no need to have different versions anymore !
  17. //                                                       - autodetect the optional room sensor and show a 12x high sensor panel in case
  18. //                                                       - temperature unit C or F and an temperature offset is set from SD-Config file and not hardcoded anymore
  19. //                                                       (because the M5-Stack is heating up itself it will never be accurate and has only limited expressiveness)
  20. //
  21. //
  22. //
  23. // ----------------------------------------------------------------------------------------------------------------------------
  24.  
  25. // #Using the App:
  26. // ###############
  27. // This version needs a SD-Card whith the your WiFi credentials, favourite coinpairs, timezone and language(eng/ger/esp) in a textfile - see installation
  28. // ButtonA: switches through your favourite Coinpair (as many you want) e.g: BTC/USDT etc. which are available on Binance.us (!)
  29. // ButtonB: changes the LCD-Brightness in 4 levels
  30. // ButtonC: 9 changeable Timeframes from 1 Minute to 1 Month
  31. // turn OFF the device pressing the red Button once OR by holding ButtonC for over 1 second
  32. // Press ButtonC, then, within 2 sec press ButtonA to switch down, or ButtonB to switch up through the timeframes: 1min->15mins->1hour->..
  33. // available timeframes are 1minute, 3m, 5m, 15m, 1h, 4h, 1d, 1w, 1Month
  34. // if you hold ButtonC at Startup: it will start with alternative SSID2/WiFi2-password instead (e.g your mobile phone's hotspot)
  35. // press ButtonA and ButtonC together to enable/disable cycling through all currencies after a set time (default:off, when turned on default:15sec)
  36.  
  37. // #Further description:
  38. // #####################
  39. // The top infoPanel shows the WiFi-strength, batterylevel, colored indicators for "busy", SleepTimer, price moving and if charging from usb (can have delay up to 30s)
  40. // right now: english, german, spanish Language (day and month names)
  41. // SleepTimer: when holding ButtonB longer than 1,5 seconds it will start a user defined timer to powerOFF the device
  42. // If WiFi is failing more than 2 minutes it reduces the reconnect interval and brightness level, after 10 minutes -> shutdown device
  43. // Menu Loader compatible, if SD-Updater (menu.bin) is installed in your SD-Card hold ButtonA while booting up to start MenuLoader to load your apps
  44. // It is prepared for the use of a Neopixel RGB-LED bar (i use the built-in one in the Battery-Bottom Module for M5Stack/Fire with rgb 10 LEDs)
  45. // All settings will remain stored in internal memory after a reset so you can eject the SD-Card after setting up you favourites.
  46. // If you want to clear all stored settings from internal memory hold ButtonB at start-up.
  47. // If M5-Stack is in his BTC stand (the original grey vertical stand) the internal room sensor is found and shows temp and humidity.
  48.  
  49. // INSTALLATION INSTRUCTIONS
  50. // #########################
  51. // - find a way to transfer this APP into your M5 Device. A very easy way is to load "M5Burner_Crypto_Coin_Ticker.zip" from https://github.com/frittna/Crypto_Coin_Ticker
  52. // - ! IMPORTANT ! - To run the app correctly you have to put "ccticker.cfg" into the root of your SD-Card. (FAT32 filesystem is good)
  53. //   Modify "ccticker.cfg" with your personal wifi ssid/password, timezone, favorite currency pair - use a simple text editor
  54. //   On the SD-Card you should have something like "G:ccticker.cfg"
  55. // - When you're done, safe-remove the SD-Card and insert into the M5Stack -> go, boot it up.
  56. // - You can eject the SD-Card after the use, the settings will be stored until you update them again with SD-Card
  57.  
  58.  
  59.  
  60.  
  61. // (*INSTALLATION INSTRUCTIONS from skratch) ->> only for those who compile by their own in Arduino IDE <<--
  62. //   note: you can adjust basically all main settings in the conig file from SD-Card. But if you want to build
  63. //         it on your own or if you want to modify something special or even extend this cool gadget go for it!
  64. // - download Arduino IDE from their homepage https://www.arduino.cc/en/Main/Software
  65. // - like instructed in the M5-Stack mini-manual be sure to add the additional boards manager url at Arduino preferencies:
  66. //   file -> preferencies: https://dl.espressif.com/dl/package_esp32_index.json  -  then restart Arduino
  67. // - install the M5-Stack board in Arduino: Tools -> Board -> Boards Manager -> search for esp32 and install ver.1.0.4
  68. //   ---> !! use ESP32 Board Manager Version 1.0.4 since higher versions are reported to fail !! <<---
  69. //   afterwards select the right board at the tools menu called M5-Stack-Core-ESP32, then select your actual COM port (restart Arduino
  70. //   with USB connected to your M5-Stack if no COM-port is shown, also be shure to try the USB connector the other way round if you can't get it done)
  71. // - open new sketch, save it to create a sketch folder and paste all of this code into the code window
  72. // - install all included librarys in your Arduino: Sketch -> Include Library -> Manage Libraries -> search for the correct ones (look very carefully)
  73. // - for the esp32fs tool (for uploading the SPIFFS data files) you have to search with google or use the github link https://github.com/me-no-dev/arduino-esp32fs-plugin,
  74. //   (i have also put all needed files into a folder called "public" on my github site)
  75. // - to install the esp32fs tool correctly you have to copy the folder called ESP32FS inside the ESP32FS-1.0.zip archive into your Arduino's sketchbook folder
  76. //   so first create a tools folder if there is no and paste the ESP32FS folder in it (it should look like C:UsersyourNameDocumentsArduinotoolsESP32FStoolesp32fs.jar )
  77. //   (for the standalone verion of Arduino put the esp32fs tool into your current arduino program folder like C:arduino-1.8.13toolsESP32FStoolesp32fs.jar )
  78. // - if esp32fs is loaded correctly you can see after a restart of Arduino a tool called "ESP32 Sketch Data Uploader" in you tools menu
  79. // - you have to download all my png picture files from my "data" folder on github and put it into your sketch subfolder "data". (open your sketch folder quickly with CTRL+K)
  80. // - click verify, afterwards you can click "ESP32 Sketch Data Uploader" from the tools menu to flash the data into the M5Stack embedded memory
  81. // - when you followed everything click compile, when finished upload
  82. // - last step is to see the instructions for adjusting the personal configuration file "ccticker.cfg"
  83. // --------------------------------------------------------------------------------------------------------------------------------------------------------
  84. //------------------------------------------------------------------------------------------------------------------------------------
  85. //------------------------------------------------------------------------------------------------------------------------------------
  86. // The core for the candlestick view and binance api was from: https://github.com/olbed/bitcoin-ticker on SPI TFT display ILI9341 and NodeMCU Board, from 2019
  87. // Known bugs to fix: ButtonC debouncing, battery symbol could be more precise, untested format if price will pass the 100k ;)
  88. //                    maybe some inefficient code since this is my first public release
  89. //------------------------------------------------------------------------------------------------------------------------------------
  90. //------------------------------------------------------------------------------------------------------------------------------------
  91.  
  92.  
  93.  
  94.  
  95.  
  96. // ##BEGIN##
  97.  
  98. // ---->> for THIS SD-Card Version nothing has to be edited here - use the "ccticker.cfg" textfile on the SD-Card root folder <<----
  99.  
  100. // Wi-Fi connection settings:
  101. String ssid = "";      // change here to "myName" or whatever you have as Wifi SSID name (127 characters max.)
  102. String password = "";  // enter your password like "myPassword"
  103. //optional:
  104. String ssid2 = "";      // alternative wi-fi network to connect when ButtonC is held at startup
  105. String password2 = "";  //
  106. //       name:                                     from:                             version                search library manager exactly for:
  107. // ---------------------------------------+------------------------------------------+------ + --------------------------------------------------------------|
  108. //#include "C:UserskevinbriceAppDataLocalArduino15packagesesp32hardwareesp321.0.4librariesSDsrcSD.h"
  109. #include "Free_Fonts.h"         // Library  | Arduino built-in                         |       |                                                               |
  110. #include <Preferences.h>        // Library  | Arduino built-in                         |       |                                                               |
  111. #include <WiFi.h>               // Board-pkg| ESP32 Board Manager -> problems on start?|1.0.4**|                                                               |
  112. #include <SDConfig.h>           // Library  | Arduino Librarymanager Claus Mancini     | 1.1.0 | "SDConfig"                                                    |
  113. #include <M5Stack.h>            // Library  | Arduino Librarymanager M5Stack           | 0.3.1 | "M5Stack"                                                     |
  114. #include <Timezone.h>           // Library  | Arduino Librarymanager Jack Christensen  | 1.2.4 | "Timezone"                                                    |
  115. #include <time.h>               // Library  | Arduino Librarymanager Michael Margolis  |  1.6  | "timekeeping"                                                 |
  116. #include <WebSocketsClient.h>   // Library  | Arduino Librarymanager Markus Sattler    | 2.3.0 | "Websockets"                                                  |
  117. #include <ArduinoJson.h>        // Library  | Arduino Librarymanager Benoit Blanchon   | 6.17.3| "ArduinoJson"                                                 |
  118. #include "M5StackUpdater.h"     // Library  | Arduino Librarymanager SD-Menu Loader    | 0.5.2!| "M5Stack SD"  i use 0.5.2 , not new 1.0.2 because of problems |
  119. #include <Adafruit_NeoPixel.h>  // Library  | Arduino Librarymanager Adafruit NeoPixel | 1.7.0 | "Adafriut Neopixel"                                           |
  120. #include "FS.h"                 // Prog-Tool| github: esp32fs for SPIFFS filesystem    |  1.0  | https://github.com/me-no-dev/arduino-esp32fs-plugin           |
  121. #include "SHT3X.h"              // Library  | M5Stack-Examples for base with SHT30
  122.  
  123. //Kevin Changes
  124. #include <WiFiManager.h>  // Library  | Arduino Librarymanager Adafruit NeoPixel | 2.0.17** | "WifiManager by tapzu Version Matters"
  125. //#include "lib/WiFiManager/WiFiManager.h"  // Adjust the path according to your folder structure.
  126.  
  127.  
  128. // ---------------------------------------+------------------------------------------+-------+----------------------------------------------------------------
  129. //  **if you compile and have problems resulting a reset or no proper connection to WiFi after powering up you schould check
  130. //    all versions again if they are really identical to the ones from this instruction above.
  131. //    ---->>  especially for the ESP32 Board Manager use Version 1.0.4 since higher versions are reported to fail !!
  132.  
  133.  
  134. //NOTE: all settings below are only the default values when no configurations are loaded from SD-Card (the ccticker.cfg file), no change needed here in the Code!
  135.  
  136. char configFile[] = "/ccticker.cfg";  // filename for configuration file on root of your SD-Card - if no file/card is found last settings will be loaded
  137. char* welcome = "Hey You! ;)";
  138. int myTimeZone = 4;                                                                       //use 4 if nothing else instructed = US Eastern Time Zone EST (New York, Detroit)
  139. int myLanguage = 0;                                                                       //use 0 if nothing else instructed = english
  140. int pairs = 4;                                                                            //total numbers of coin pairs to load, default: 4, max. 25
  141. const int max_pairs_arrsize = 25;                                                         // number of max.possible coinpairs recognized by configuration file (do not adjust this without extendig the routine for SD-Card reading)
  142. String pair_STRING[max_pairs_arrsize] = { "BTCUSDT", "ETHUSDT", "DOTUSDT", "LINKUSDT" };  //default values if no external config file exists
  143. String pair_name[max_pairs_arrsize] = { " Bitcoin", "   ETH", "   DOT", "  LINK" };
  144. String pair_col_str[max_pairs_arrsize] = { "0xFD20", "0x03EF", "0xC618", "0x001F" };
  145. uint16_t rgb565_pair_color[max_pairs_arrsize] = { 0xFD20, 0x03EF, 0xC618, 0x001F };
  146. // Notes for color names: use hex in rgb565 format like: 0x07FF not rgb888 0x07FF88
  147. const char* weekDay_Language0[] = { "", "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" };                                              // english language
  148. const char* monthName_Language0[] = { "", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };  // english language
  149. const char* weekDay_Language1[] = { "", "So", "Mo", "Di", "Mi", "Do", "Fr", "Sa" };                                              // translated to german
  150. const char* monthName_Language1[] = { "", "Jan", "Feb", "Mar", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez" };  // translated to german
  151. const char* weekDay_Language2[] = { "", "do", "lu", "ma", "mi", "ju", "vi", "sá" };                                              // translated to spanish
  152. const char* monthName_Language2[] = { "", "ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic" };  // translated to spanish
  153. const byte timeframes = 9;
  154. const char* candlesTimeframes[timeframes] = { "1m", "3m", "5m", "15m", "1h", "4h", "1d", "1w", "1M" };
  155. const char* weekDay_MyLang[8];
  156. const char* monthName_MyLang[13];
  157. // you can define your own color names for use in code only. with #define my_col M5.Lcd.color565(80,50,125) /* uint16_t color565(0-255, 0-255, 0-255) for RGB, */
  158. #define DARKERGREEN M5.Lcd.color565(146, 217, 0) /* uint16_t color565(uint8_t r, uint8_t g, uint8_t b), */
  159. #define MYRED M5.Lcd.color565(255, 0, 28)        /* uint16_t color565(uint8_t r, uint8_t g, uint8_t b), */
  160. int pinSelectSD = 4;                             // SD shield Chip Select pin. (4 for M5Stack)
  161. boolean readConfiguration();
  162. int maxLineLength = 127;  //Length of the longest line expected in the config file
  163. // REST API DOCS: https://github.com/binance-exchange/binance-official-api-docs/blob/master/rest-api.md
  164. const char* restApiHost = "api.binance.us";
  165. const byte candlesLimit = 24;
  166. String pair_STRING_mem[max_pairs_arrsize];
  167. String pair_name_mem[max_pairs_arrsize];
  168. String pair_col_str_mem[max_pairs_arrsize];
  169. String pair_string[max_pairs_arrsize];
  170. int current_Currency;
  171. byte current_Timeframe;
  172. byte custom_Timezone = 8;  // if no timezone matches you can set a custom difference from utc in hours (+ or -) When this is used there is no summer / standart time change rule!
  173. unsigned int last_stored_Brightness_value;
  174. unsigned int last_stored_Brightness_level;
  175. unsigned int last_stored_Currency;
  176. unsigned int last_stored_Timeframe;
  177. String ssid_mem;
  178. String ssid2_mem;
  179. String password_mem;
  180. String password2_mem;
  181. int mySleeptime_mem;
  182. int myTimeZone_mem;
  183. int myTempUnit;  //if 1 is read from sd-card config use for Fahrenheit, otherwise use Celsius as default temperature unit
  184. int myTempOffset;
  185. int myCyclingIntervall;
  186. int myTempUnit_mem;
  187. float myTempOffset_mem;
  188. int myCyclingIntervall_mem;
  189. int myLanguage_mem;
  190. int pairs_mem;
  191. int change_count = 0;
  192. const uint32_t volColor = 0x22222a;
  193. // WS API DOCS: https://github.com/binance-exchange/binance-official-api-docs/blob/master/web-socket-streams.md
  194. const char* wsApiHost = "stream.binance.us";
  195. const int wsApiPort = 9443;
  196. // Layout: The space between the info and the bottom panel is for candlechart => 240px minus top+info+bottom
  197. const byte topPanel = 20;
  198. const byte infoPanel = 16;  //16px in height;
  199. byte sensorPanel;           //16px or 0px in height when no sensor found
  200. const byte bottomPanel = 36;
  201. Preferences preferences;  //the last read-in SD-Card settings are saved in internal memory
  202. WiFiClient client;
  203. WebSocketsClient webSocket;
  204. StaticJsonDocument<8750> jsonDoc;
  205. TimeChangeRule summer_aedt = { "AEDT", First, Sun, Oct, 2, 660 };  // 0: Australia Eastern Time Zone (Sydney, Melbourne)
  206. TimeChangeRule standard_aest = { "AEST", First, Sun, Apr, 3, 600 };
  207. TimeChangeRule summer_bst = { "BST", Last, Sun, Mar, 1, 60 };  // 1: United Kingdom (London, Belfast)
  208. TimeChangeRule standard_gmt = { "GMT", Last, Sun, Oct, 2, 0 };
  209. TimeChangeRule summer_eest = { "EEST", Last, Sun, Mar, 3, 180 };  // 2: Eastern European Time (Bulgaria, Greece, Romania, Ukraine, Egypt)
  210. TimeChangeRule standard_eet = { "EET ", Last, Sun, Oct, 4, 120 };
  211. TimeChangeRule summer_cest = { "CEST", Last, Sun, Mar, 2, 120 };  // 3: Central European Time Zone (Frankfurt, Paris)
  212. TimeChangeRule standard_cet = { "CET ", Last, Sun, Oct, 3, 60 };
  213. TimeChangeRule summer_edt = { "EDT", Second, Sun, Mar, 2, -240 };  // 4: US Eastern Time Zone (New York, Detroit)
  214. TimeChangeRule standard_est = { "EST", First, Sun, Nov, 2, -300 };
  215. TimeChangeRule summer_cdt = { "CDT", Second, dowSunday, Mar, 2, -300 };  // 5: US Central Time Zone (Chicago, Houston)
  216. TimeChangeRule standard_cst = { "CST", First, dowSunday, Nov, 2, -360 };
  217. TimeChangeRule summer_mdt = { "MDT", Second, dowSunday, Mar, 2, -360 };  // 6: US Mountain Time Zone (Denver, Salt Lake City)
  218. TimeChangeRule standard_mst = { "MST", First, dowSunday, Nov, 2, -420 };
  219. TimeChangeRule summer_pdt = { "PDT", Second, dowSunday, Mar, 2, -420 };  // 7: US Pacific Time Zone (Las Vegas, Los Angeles);
  220. TimeChangeRule standard_pst = { "PST", First, dowSunday, Nov, 2, -480 };
  221. TimeChangeRule summer_sgt = { "SGT", Last, Sun, Oct, 4, 480 };  // 8: Singapore Time Zone (UTC + 8) - no TimeChange for Summer/Standart Time
  222. TimeChangeRule standard_sgt = { "SGT", Last, Sun, Mar, 3, 480 };
  223. TimeChangeRule utcRule = { "UTC", Last, Sun, Mar, 1, 0 };  // UTC
  224. TimeChangeRule msk = { "MSK", Last, Sun, Mar, 1, 180 };    // Moscow Standard Time (MSK, no DST)
  225.  
  226. Timezone myTZ0(summer_aedt, standard_aest);  // myTZ0: 0 Australia Eastern Time Zone (Sydney, Melbourne)
  227. Timezone myTZ1(summer_bst, standard_gmt);    // myTZ1: 1 United Kingdom (London, Belfast)
  228. Timezone myTZ2(summer_eest, standard_eet);   // myTZ2: 2 Eastern European Time (Bulgaria, Greece, Romania, Ukraine, Egypt)
  229. Timezone myTZ3(summer_cest, standard_cet);   // myTZ3: 3 Central European Time Zone (Frankfurt, Paris)
  230. Timezone myTZ4(summer_edt, standard_est);    // myTZ4: 4 US Eastern Time Zone (New York, Detroit)
  231. Timezone myTZ5(summer_cdt, standard_cst);    // myTZ5: 5 US Central Time Zone (Chicago, Houston)
  232. Timezone myTZ6(summer_mdt, standard_mst);    // myTZ6: 6 US Mountain Time Zone (Denver, Salt Lake City)
  233. Timezone myTZ7(summer_pdt, standard_pst);    // myTZ7: 7 US Pacific Time Zone (Las Vegas, Los Angeles);
  234. Timezone myTZ8(summer_sgt, standard_sgt);    // myTZ8: 8 Singapore Time Zone UTC +8
  235. Timezone myTZ9(utcRule);                     // myTZ9: 9 UTC Time, no DST
  236. Timezone myTZ10(summer_mdt);                 // myTZ10: 10 Arizona is US Mountain Time Zone, no DST
  237. Timezone myTZ11(msk);                        // myTZ11: 11 Moscow Standard Time, no DST
  238.  
  239. // LED-Pixel bar(see bottom of this file for further details)
  240. #define PIN 15        // use the built-in LED bar in the M5-Stack/Fire Battery-Bottom-Module (10xLED on Pin15)
  241. #define NUMPIXELS 10  // 10 LEDs
  242. Adafruit_NeoPixel LEDbar(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
  243. int mySleeptime = 45;
  244. unsigned long sleeptime = mySleeptime * 60;  // SLEEPTIMER: in minutes - hold ButtonB long for sleeptimer to start or stop
  245. unsigned long currentMs;
  246. byte Brightness_level;
  247. int Brightness_value;
  248. unsigned long sleeptimer_counter;
  249. bool sleeptimer_bool;
  250. unsigned int lastPrintTime;
  251. float lastPrice = -1;
  252. float lastLow = -1;
  253. float lastHigh = -1;
  254. bool candleIsNew;
  255. float openTime;
  256. float last_correct_openTime;
  257. float w = 320.0 / candlesLimit;
  258. float center;
  259. int lastTimeframe = -1;
  260. unsigned int wsFails;
  261. byte empty_candles;
  262. unsigned int currency_cycling_counter;
  263. bool currency_cycling = false;
  264. bool cycling_change_triggered = false;
  265. bool current_Currency_changed;
  266. bool current_bright_changed;
  267. bool current_timeframe_changed;
  268. bool timeframe_really_changed;
  269. unsigned long currency_btn_timeout_counter = 4294966295;  // = max
  270. unsigned long bright_btn_timeout_counter = 4294966295;
  271. unsigned long timeframe_btn_timeout_counter1 = 4294966295;
  272. unsigned long timeframe_btn_timeout_counter2 = 4294966295;
  273. String strname_api;
  274. String strname_ws;
  275. String strname_currency;
  276. uint16_t strname_color;
  277. int err_count;
  278. long multi = 1;
  279. byte multi_level;
  280. bool ws_error;
  281. bool alt_hotspot = false;
  282. bool wifi_error;
  283. typedef struct {
  284.   float l;  // Low
  285.   float h;  // High
  286.   float o;  // Open
  287.   float c;  // Close
  288.   float v;  // Volume
  289. } Candle;
  290. Candle candles[candlesLimit];
  291. float lastCandleOpenTime;
  292. float ph;          // Price High
  293. float pl;          // Price Low
  294. float vh;          // Volume High
  295. float vl;          // Volume Low
  296. SHT3X sht30;       // (optional) for the grey vertical base with built in sensor
  297. float tmpC = 0.0;  // for temperature sensor Celsius
  298. float tmpF = 0.0;  // for temperature sensor Fahrenheit
  299. float hum = 0.0;   // for humidity sensor
  300. //-----------------------------------------------------------------------------------------------------------------------------
  301.  
  302. void setup() {
  303.   //Kevin Change
  304.     Serial.println("WifiManager Starting..");
  305.  
  306.   WiFiManager wifiManager;
  307.   //first parameter is name of access point, second is the password
  308.   WiFi.disconnect()
  309.   wifiManager.autoConnect("Setup Crypto Display", "01234567890");
  310.  
  311.  
  312.  
  313.   // load last settings from memory on startup
  314.   preferences.begin("settings", false);
  315.     preferences.clear();
  316.  
  317.  
  318.   M5.begin();
  319.   Wire.begin();
  320.   M5.lcd.setBrightness(0);
  321.   Serial.begin(115200);
  322.   pinMode(pinSelectSD, OUTPUT);
  323.  
  324.   // an additional sensorPanel between topPanel and infoPanel is visible if room sensor is found
  325.   if (sht30.get() == 0) {
  326.     sensorPanel = 16;
  327.   } else (sensorPanel = 0);
  328.  
  329.   // Setup the SD-Card
  330.   delay(200);
  331.   Serial.println();
  332.   Serial.println("POWER ON DEVICE");
  333.   Serial.println();
  334.   Serial.println("accessing SD-Card..");
  335.   if (!SD.begin(pinSelectSD)) {
  336.     Serial.println("SD-Card access failed !");
  337.     Serial.println("is card inserted ?");
  338.     Serial.println("supported: FAT&FAT32; only");
  339.   }
  340.   Serial.println("successfully..");
  341.  
  342.  
  343.  
  344.  
  345.   // spiffs filesystem for pictures or maybe sound data
  346.   if (!SPIFFS.begin(true)) {
  347.     Serial.println("SPIFFS Mount Failed");
  348.     return;
  349.   }
  350.  
  351.   // setting alternative WiFi2-settings
  352.   if (digitalRead(BUTTON_C_PIN) == 0) {
  353.     alt_hotspot = true;
  354.   }
  355.  
  356.   // for optional M5 Stack SD-Menu-Loader
  357.   if (digitalRead(BUTTON_A_PIN) == 0) {
  358.     Serial.println("Will Load menu binary");
  359.     updateFromFS(SD);
  360.     ESP.restart();
  361.   }
  362.   M5.update();
  363.  
  364.  
  365.  
  366.   // startup with splashscreen on LCD Display and start up RGB LCD-pixel-bar (Neopixel)
  367.   M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  368.   for (int i = 0; i < 22; i++) {
  369.     Brightness_value += 1;
  370.     M5.lcd.setBrightness(Brightness_value);
  371.     delay(45);  // end of fading-in Lcd brightness
  372.   }
  373.   M5.Lcd.fillScreen(TFT_BLACK);
  374.   LEDbar.begin();
  375.   LEDbar.setBrightness(35);  // Set LED BRIGHTNESS to about 1/5 (max = 255)
  376.   LEDbar.clear();
  377.   colorWipe(LEDbar.Color(0, 255, 0), 30);  // Green    // fill LEDbar in various colors...(delay in ms)
  378.   LEDbar.clear();
  379.   rainbow_effect(3);  // Rainbow cycle along the LEDbar..(delay in ms)
  380.   LEDbar.clear();
  381.   LEDbar.show();  // update LED status
  382.   M5.Lcd.setTextDatum(MC_DATUM);
  383.   M5.Lcd.setTextSize(1);
  384.   M5.Lcd.setTextColor(TFT_WHITE);
  385.   M5.Lcd.setFreeFont(FSS12);
  386.   M5.Lcd.setTextWrap(false);
  387.  
  388.   // update settings if SD config file is found
  389.   updateSDSettings();
  390.   M5.lcd.setBrightness(Brightness_value);
  391.   yield();
  392.  
  393.   // Setting Power:   see for details: https://github.com/m5stack/m5-docs/blob/master/docs/en/api/power.md
  394.   if (!M5.Power.canControl()) M5.Lcd.printf("IP5306 is not i2c versionn");
  395.   M5.Power.setPowerBtnEn(true);     //allow red power Button
  396.   M5.Power.setPowerBoostSet(true);  //one press on red turns on/off device
  397.   M5.Power.setPowerVin(false);      //no reset when usb calbe is plugged in
  398.  
  399.  
  400.  
  401.  
  402. //removed conflicting with wifimanager
  403. /*
  404.   // Connecting to WiFi:
  405.   M5.Lcd.print("nnConnecting to ");
  406.   if (alt_hotspot == false) {
  407.     M5.Lcd.println(ssid);
  408.     WiFi.begin(ssid.c_str(), password.c_str());
  409.   } else {
  410.     M5.Lcd.println(ssid2);
  411.     WiFi.begin(ssid2.c_str(), password2.c_str());
  412.   }
  413. */
  414.  
  415.  
  416.   while (WiFi.status() != WL_CONNECTED) {
  417.     M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_RED);  //busy light red
  418.     M5.Lcd.setTextWrap(true);
  419.     M5.Lcd.print(".");
  420.     err_count++;
  421.     // Power Off Button (ButtonC long press) - needed because on usb power, depending on the type of battery bottom you maybe cant turn off with red Button as usual
  422.     if (M5.BtnC.pressedFor(1333)) {
  423.       M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  424.       delay(500);
  425.       for (int i = Brightness_value; i > 0; i--) {  // dimm LCD slowly before shutdown
  426.         Brightness_value -= 1;
  427.         M5.lcd.setBrightness(Brightness_value);
  428.         delay(50);
  429.       }
  430.       M5.Lcd.fillScreen(TFT_BLACK);
  431.       delay(500);
  432.       M5.Power.powerOFF();
  433.     }
  434.     if (err_count > 288) {  // if 10 minutes no wifi -> power off device !
  435.       M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  436.       delay(1000);
  437.       M5.Lcd.fillScreen(TFT_BLACK);
  438.       delay(1000);
  439.       M5.Power.powerOFF();         // shut down
  440.     } else if (err_count > 240) {  // if 2 minutes no wifi error persists reduce
  441.       LEDbar.clear();
  442.       colorWipe(LEDbar.Color(255, 255, 0), 30);  // flash yellow twice with LED bar every 10s
  443.       LEDbar.show();                             // update LED status
  444.       LEDbar.clear();
  445.       LEDbar.show();  // update LED status
  446.       delay(100);
  447.       colorWipe(LEDbar.Color(255, 255, 0), 30);
  448.       LEDbar.show();  // update LED status
  449.       LEDbar.clear();
  450.       LEDbar.show();            // update LED status
  451.       delay(10000);             // the reconnect interval from 0.5s to 10s
  452.       M5.lcd.setBrightness(1);  // and lower the LCD brighness to lowest value (1)
  453.     } else {
  454.       delay(500);
  455.     }
  456.   }
  457.   showWifiStrength();
  458.   err_count = 0;
  459.   M5.lcd.setBrightness(Brightness_value);
  460.   M5.Lcd.println("nWiFi connected");
  461.   M5.Lcd.setTextWrap(false);
  462.  
  463.   // startup promt to lcd:
  464.   M5.Lcd.println("getting time");
  465.   M5.Lcd.println("drawing chart");
  466.   if (!SD.begin(pinSelectSD)) {
  467.     M5.Lcd.println();
  468.     M5.Lcd.println("no SD-Card used");
  469.  
  470.   } else {
  471.     M5.Lcd.println();
  472.     M5.Lcd.println("..reading SD-Card");
  473.   }
  474.  
  475.   // Setting time:
  476.   configTime(0, 0, "pool.ntp.org", "time.nist.gov");
  477.   while (true) {
  478.     time_t now = time(nullptr);
  479.     if (now && year(now) > 2017) break;
  480.   }
  481.   delay(400);
  482.   M5.Lcd.fillScreen(TFT_BLACK);
  483.   yield();
  484.   showWifiStrength();
  485.   printTime();  //routine to print the time on lcd screen,  adjusted to your local timzone
  486.  
  487.   // load battery meter and draw all candles, and sensor values
  488.   showBatteryLevel();
  489.   while (!requestRestApi()) {}
  490.   drawCandles();
  491.   drawSensorValues();
  492.  
  493.   // Connecting to WS:
  494.   webSocket.beginSSL(wsApiHost, wsApiPort, getWsApiUrl());
  495.   webSocket.onEvent(webSocketEvent);
  496.   webSocket.setReconnectInterval(1000);
  497. }
  498.  
  499.  
  500. // ***************************************BEGIN LOOP**************************************************
  501. void loop() {
  502.   currentMs = millis();
  503.   buttonActions();                                                                       // check for Buttons
  504.   M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_BLACK);  //reset busy light
  505.   if (currency_cycling) {
  506.     if (currentMs - currency_cycling_counter >= (4 + myCyclingIntervall) * 1000) {  //change every x (user defined) seconds, adds +4s to intervall the long loading time
  507.       currency_cycling_counter = currentMs;
  508.       cycling_change_triggered = true;
  509.     }
  510.   }
  511.   if (currentMs - lastPrintTime >= 35000 && second(time(nullptr)) < 25) {  // draw new date and candles regularly
  512.     lastPrintTime = currentMs;
  513.     printTime();
  514.     drawSensorValues();
  515.     multi_level = 0;
  516.     webSocket.disconnect();
  517.     webSocket.beginSSL(wsApiHost, wsApiPort, getWsApiUrl());
  518.     while (!requestRestApi()) {}
  519.     drawCandles();
  520.     showBatteryLevel();
  521.   }
  522.   webSocket.loop();
  523.   M5.update();  // update Button checks
  524. }
  525. // ****************************************END LOOP***************************************************
  526.  
  527.  
  528.  
  529. void printTime() {
  530.   M5.Lcd.fillRect(0, 0, 320, topPanel - 1, TFT_BLACK);
  531.   M5.Lcd.setFreeFont(FSSB12);
  532.   M5.Lcd.setCursor(1, 19);
  533.   M5.Lcd.setTextSize(1);
  534.   M5.Lcd.setTextColor(strname_color);
  535.   M5.Lcd.print(strname_currency);
  536.   M5.Lcd.setFreeFont(FMB12);
  537.   M5.Lcd.setCursor(111, 14);
  538.   M5.Lcd.setTextColor(TFT_LIGHTGREY);
  539.   TimeChangeRule* tcr;
  540.    if (myTimeZ 0) {
  541.     time_t now = myTZ0.toLocal(time(nullptr), &tcr;);
  542.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  543.    } else if (myTimeZ 1) {
  544.     time_t now = myTZ1.toLocal(time(nullptr), &tcr;);
  545.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  546.    } else if (myTimeZ 2) {
  547.     time_t now = myTZ2.toLocal(time(nullptr), &tcr;);
  548.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  549.    } else if (myTimeZ 3) {
  550.     time_t now = myTZ3.toLocal(time(nullptr), &tcr;);
  551.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  552.    } else if (myTimeZ 4) {
  553.     time_t now = myTZ4.toLocal(time(nullptr), &tcr;);
  554.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  555.    } else if (myTimeZ 5) {
  556.     time_t now = myTZ5.toLocal(time(nullptr), &tcr;);
  557.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  558.    } else if (myTimeZ 6) {
  559.     time_t now = myTZ6.toLocal(time(nullptr), &tcr;);
  560.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  561.    } else if (myTimeZ 7) {
  562.     time_t now = myTZ7.toLocal(time(nullptr), &tcr;);
  563.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  564.    } else if (myTimeZ 8) {
  565.     time_t now = myTZ8.toLocal(time(nullptr), &tcr;);
  566.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  567.    } else if (myTimeZ 9) {
  568.     time_t now = myTZ9.toLocal(time(nullptr), &tcr;);
  569.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  570.    } else if (myTimeZ 10) {
  571.     time_t now = myTZ10.toLocal(time(nullptr), &tcr;);
  572.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  573.    } else if (myTimeZ 11) {
  574.     time_t now = myTZ11.toLocal(time(nullptr), &tcr;);
  575.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  576.   } else {  // default: MyTZ4 english
  577.     time_t now = myTZ4.toLocal(time(nullptr), &tcr;);
  578.     M5.Lcd.printf("%s -.%s d:d", weekDay_MyLang[weekday(now)], day(now), monthName_MyLang[month(now)], hour(now), minute(now));
  579.   }
  580. }
  581.  
  582.  
  583.  
  584. String getRestApiUrl() {
  585.   return "/api/v3/klines?symbol=" + strname_api + "&interval;=" + String(candlesTimeframes[current_Timeframe]) + "&limit;=" + String(candlesLimit);
  586. }
  587.  
  588.  
  589.  
  590. String getWsApiUrl() {
  591.   return "/ws/" + strname_ws + "@kline_" + String(candlesTimeframes[current_Timeframe]);
  592. }
  593.  
  594.  
  595.  
  596. void webSocketEvent(WStype_t type, uint8_t* payload, size_t length) {
  597.   M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_DARKGREY);  //busy light darkgrey
  598.   showWifiStrength();
  599.   switch (type) {
  600.     case WStype_DISCONNECTED:
  601.       wsFails++;
  602.       if (wsFails > 3) error("WS disconnected!");
  603.       ws_error = true;
  604.       break;
  605.     case WStype_CONNECTED:
  606.       break;
  607.     case WStype_TEXT:
  608.       wsFails = 0;
  609.       DeserializationError err = deserializeJson(jsonDoc, payload);
  610.       if (err) {
  611.         error(err.c_str());
  612.         ws_error = true;
  613.         break;
  614.       }
  615.       openTime = jsonDoc["k"]["t"];
  616.       openTime = openTime / 1000;  // opentime is sent in milliseconds
  617.       if (openTime == 0) {
  618.         error("empty WS object");
  619.         break;
  620.       }
  621.       candleIsNew = openTime > lastCandleOpenTime;
  622.       if (candleIsNew) {
  623.         lastCandleOpenTime = openTime;
  624.         for (int i = 1; i < candlesLimit; i++) {
  625.           candles[i - 1] = candles[i];
  626.         }
  627.       }
  628.       candles[candlesLimit - 1].o = jsonDoc["k"]["o"];
  629.       candles[candlesLimit - 1].h = jsonDoc["k"]["h"];
  630.       candles[candlesLimit - 1].l = jsonDoc["k"]["l"];
  631.       candles[candlesLimit - 1].c = jsonDoc["k"]["c"];
  632.       candles[candlesLimit - 1].v = jsonDoc["k"]["v"];
  633.  
  634.       // If we get new low/high we need to redraw all candles, otherwise just last one:
  635.       if (candleIsNew || candles[candlesLimit - 1].l < pl || candles[candlesLimit - 1].h > ph || candles[candlesLimit - 1].v < vl || candles[candlesLimit - 1].v > vh) {
  636.         drawCandles();
  637.       } else {
  638.         drawPrice();
  639.         drawCandle(candlesLimit - 1);
  640.       }
  641.       break;
  642.   }
  643. }
  644.  
  645.  
  646.  
  647. bool requestRestApi() {
  648.   WiFiClientSecure client;
  649.   if (!client.connect(restApiHost, 443)) {
  650.     error("nnWiFi connection lost!");
  651.     wifi_error = true;
  652.     return false;
  653.   }
  654.   client.print("GET " + getRestApiUrl() + " HTTP/1.1rn" + "Host: " + restApiHost + "rn" + "Accept: application/jsonrn" + "User-Agent: BuildFailureDetectorESP8266rn" + "Connection: closernrn");
  655.  
  656.   while (client.connected()) {
  657.     M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_YELLOW);  //busy light yellow
  658.     String line = client.readStringUntil('r');
  659.     line.trim();
  660.     if (line.startsWith("[") && line.endsWith("]")) {
  661.       DeserializationError err = deserializeJson(jsonDoc, line);
  662.       if (err) {
  663.         error(err.c_str());
  664.         ws_error = true;
  665.         return false;
  666.       } else if (jsonDoc.as<JsonArray>().size() == 0) {
  667.         error("Empty JSON array");
  668.         ws_error = true;
  669.         return false;
  670.       }
  671.  
  672.       // Data format: [[TS, OPEN, HIGH, LOW, CLOSE, VOL, ...], ...]
  673.       JsonArray _candles = jsonDoc.as<JsonArray>();
  674.       for (int i = 0; i < candlesLimit; i++) {
  675.         candles[i].o = _candles[i][1];
  676.         candles[i].h = _candles[i][2];
  677.         candles[i].l = _candles[i][3];
  678.         candles[i].c = _candles[i][4];
  679.         candles[i].v = _candles[i][5];
  680.       }
  681.  
  682.       // if pair is not listed long enought to draw all requested candles take only the last valid values to not get confused with zeros
  683.       empty_candles = 0;
  684.       for (int i = 0; i < candlesLimit; i++) {
  685.         if (candles[i].c == 0) {
  686.           empty_candles++;
  687.           candles[i].o = candles[i - 1].o;
  688.           candles[i].h = candles[i - 1].h;
  689.           candles[i].l = candles[i - 1].l;
  690.           candles[i].c = candles[i - 1].c;
  691.           candles[i].v = candles[i - 1].v;
  692.           openTime = last_correct_openTime;
  693.         } else {
  694.           last_correct_openTime = openTime;
  695.         }
  696.       }
  697.       lastCandleOpenTime = _candles[candlesLimit - 1 - empty_candles][0];
  698.       lastCandleOpenTime = lastCandleOpenTime / 1000;  // because time is sent in milliseconds !
  699.       return true;
  700.     }
  701.   }
  702.   ws_error = true;
  703.   error("no JSON in response");
  704. }
  705.  
  706.  
  707.  
  708. // format price:
  709. void formatPrice() {
  710.   for (int i = 0; i < candlesLimit; i++) {
  711.     if (multi_level == 0) {
  712.       if (candles[i].l < 0.001) {
  713.         multi = 100000000;  // if old price is under 0.001$ use exponent format X.XXe-XX
  714.         multi_level = 3;
  715.       }
  716.     }
  717.     if (multi_level < 3) {
  718.       if (candles[i].l < 1) {
  719.         multi = 100000;  // multiply old price if price is under 1$ for higher resolution
  720.         multi_level = 2;
  721.       }
  722.     }
  723.     if (multi_level < 2) {
  724.       if (candles[i].l < 1000) {
  725.         multi = 100;  // multiply old price if price is under 1000$ for higher resolution
  726.         multi_level = 1;
  727.       }
  728.     }
  729.     if (multi_level < 1) {
  730.       if (candles[i].l > 1000) {
  731.         multi = 1;  // if old price is over 1000$? change nothing
  732.         multi_level = 0;
  733.       }
  734.     }
  735.   }
  736. }
  737.  
  738.  
  739.  
  740. void drawCandles() {
  741.   M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_MAGENTA);  //busy light magenta
  742.   // Find highs and lows
  743.   ph = candles[0 + empty_candles].h;
  744.   pl = candles[0 + empty_candles].l;
  745.   vh = candles[0 + empty_candles].v;
  746.   vl = candles[0 + empty_candles].v;
  747.   for (int i = 0; i < candlesLimit; i++) {
  748.     if (candles[i].h > ph) ph = candles[i].h;
  749.     if (candles[i].l < pl) pl = candles[i].l;
  750.     if (candles[i].v > vh) vh = candles[i].v;
  751.     if (candles[i].v < vl) vl = candles[i].v;
  752.   }
  753.  
  754.   // format Price for candle drawing if over 1000, under 1000, under 1, or under 0.001
  755.   formatPrice();
  756.  
  757.   // Draw bottom panel with price, high and low:
  758.   drawPrice();
  759.  
  760.   // Draw empty candle:
  761.   for (int i = 0; i < empty_candles; i++) {
  762.     drawEmptyCandle(i);
  763.   }
  764.  
  765.   // Draw candles:
  766.   for (int i = 0; i < candlesLimit - empty_candles; i++) {
  767.     drawCandle(i);
  768.   }
  769.   M5.Lcd.fillCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 4, TFT_DARKGREY);  // reset magenta busy light;
  770. }
  771.  
  772.  
  773.  
  774. // Remap dollars data to pixels
  775. int getY(float val, float minVal, float maxVal) {
  776.   // function copied from of 'map' math function  (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
  777.   return round((val - minVal) * (topPanel + infoPanel + sensorPanel + 2 - 162 - bottomPanel) / (maxVal - minVal) + 235 - bottomPanel);
  778. }
  779.  
  780.  
  781.  
  782. void drawEmptyCandle(int i) {
  783.   center = w / 2.0;
  784.   center += ((i)*w);
  785.   M5.Lcd.fillRect((center - w) + 5, topPanel + infoPanel + sensorPanel, ceil(w), 240 - (topPanel + infoPanel + sensorPanel + bottomPanel), TFT_BLACK);
  786. }
  787.  
  788.  
  789.  
  790. // Data format: [[TS, OPEN, HIGH, LOW, CLOSE, VOL, ...]]
  791. void drawCandle(int i) {
  792.   int oy = getY(candles[i].o * multi, pl * multi, ph * multi);
  793.   int hy = getY(candles[i].h * multi, pl * multi, ph * multi);
  794.   int ly = getY(candles[i].l * multi, pl * multi, ph * multi);
  795.   int cy = getY(candles[i].c * multi, pl * multi, ph * multi);
  796.   int vy = getY(candles[i].v, vl, vh);
  797.   int prevVY = vy;
  798.   if (i != 0) {
  799.     prevVY = getY(candles[i - 1].v, vl, vh);
  800.   }
  801.   center = w / 2.0;
  802.   center += ((i + empty_candles) * w);
  803.   uint32_t color = cy < oy ? DARKERGREEN : MYRED;
  804.  
  805.   // Background:
  806.   M5.Lcd.fillRect((center - w) + 5, topPanel + infoPanel + sensorPanel, ceil(w), 240 - (topPanel + infoPanel + sensorPanel + bottomPanel), TFT_BLACK);
  807.  
  808.   // Volume line:
  809.   M5.Lcd.drawLine((center - w) + 5, prevVY, center - 5, vy, volColor);
  810.   M5.Lcd.drawLine(center - 4, vy, center + 4, vy, volColor);
  811.   if (i == candlesLimit - 1) {
  812.     M5.Lcd.fillRect(center + 5, topPanel + infoPanel + sensorPanel, w / 2, 240 - (topPanel + infoPanel + bottomPanel), TFT_BLACK);
  813.     M5.Lcd.drawLine(center + 5, vy, 320, vy, volColor);
  814.   }
  815.  
  816.   // Head and tail:
  817.   M5.Lcd.drawLine(center, hy, center, ly, color);
  818.  
  819.   // Candle body:
  820.   int bodyHeight = abs(cy - oy);
  821.   if (bodyHeight < 1) bodyHeight = 1;  // show at least 1px, if candle body was not formed yet
  822.   M5.Lcd.fillRect(center - 3, min(oy, cy), 7, bodyHeight, color);
  823.  
  824.   // show actual price as small line in the last candle
  825.   if (i + empty_candles == candlesLimit - 1) M5.Lcd.drawLine(center - 4, cy, center + 4, cy, TFT_WHITE);
  826.  
  827.   // calculate PrizeChanings for the infoPanel
  828.   PriceChangings();
  829. }
  830.  
  831.  
  832.  
  833. // show remaining battery power (0-100) and draw the matching battery status picture
  834. void showBatteryLevel() {
  835.   uint8_t battery = M5.Power.getBatteryLevel();
  836.   M5.Lcd.fillRect(34, topPanel + 2, 60, infoPanel + sensorPanel, TFT_BLACK);
  837.   if (M5.Power.isCharging()) M5.Lcd.drawPngFile(SPIFFS, "/batt_gre.png", 34, topPanel + 2);  // show a green battery icon
  838.   else M5.Lcd.drawPngFile(SPIFFS, "/batt_gry.png", 34, topPanel + 2);                        // show a grey battery icon
  839.   if (battery == -1) M5.Lcd.drawPngFile(SPIFFS, "/batt_nc.png", 34, topPanel + 2);           // 60 x 60 px
  840.   else if (battery < 12) M5.Lcd.drawPngFile(SPIFFS, "/batt0.png", 34, topPanel + 2);
  841.   else if (battery < 32) M5.Lcd.drawPngFile(SPIFFS, "/batt25.png", 34, topPanel + 2);
  842.   else if (battery < 64) M5.Lcd.drawPngFile(SPIFFS, "/batt50.png", 34, topPanel + 2);
  843.   else if (battery < 78) M5.Lcd.drawPngFile(SPIFFS, "/batt75.png", 34, topPanel + 2);
  844.   else if (battery > 90) M5.Lcd.drawPngFile(SPIFFS, "/batt100.png", 34, topPanel + 2);
  845. }
  846.  
  847.  
  848. void drawPrice() {
  849.   float price = (candles[candlesLimit - 1].c);
  850.   float oy_var2(candles[candlesLimit - 1].o);
  851.   if (lastPrice != price) {
  852.     M5.Lcd.fillRect(0, 240 - bottomPanel, 202, bottomPanel, TFT_BLACK);
  853.     M5.Lcd.setTextSize(1);
  854.     M5.Lcd.setFreeFont(FSSB24);
  855.     M5.Lcd.setCursor(0, 273 - bottomPanel);
  856.     M5.Lcd.setTextColor(price > oy_var2 ? DARKERGREEN : MYRED);
  857.     lastPrice = price;
  858.     if (multi_level == 1) {
  859.       M5.Lcd.printf("%.4f", price);
  860.     } else if (multi_level == 2) {
  861.       M5.Lcd.printf("%.6f", price);
  862.     } else if (multi_level == 3) {
  863.       M5.Lcd.printf("%.2e", price);
  864.     } else {
  865.       M5.Lcd.printf("%.2f", price);
  866.     }
  867.   }
  868.   if (ph != lastHigh) {
  869.     M5.Lcd.fillRect(202, 240 - bottomPanel, 99, bottomPanel / 2, TFT_BLACK);
  870.     M5.Lcd.setTextColor(DARKERGREEN);
  871.     M5.Lcd.setFreeFont(FSSB9);
  872.     M5.Lcd.setCursor(202, 254 - bottomPanel);
  873.     M5.Lcd.setTextSize(1);
  874.     lastHigh = ph;
  875.     if (multi == 100) {
  876.       M5.Lcd.printf("H %.4f", ph);
  877.     } else if (multi == 100000) {
  878.       M5.Lcd.printf("H %.6f", ph);
  879.     } else if (multi == 100000000) {
  880.       M5.Lcd.printf("H %.2e", ph);
  881.     } else {
  882.       M5.Lcd.printf("H %.2f", ph);
  883.     }
  884.   }
  885.   if (pl != lastLow) {
  886.     M5.Lcd.fillRect(202, 240 - bottomPanel / 2, 99, bottomPanel / 2, TFT_BLACK);
  887.     M5.Lcd.setTextColor(MYRED);
  888.     M5.Lcd.setFreeFont(FSSB9);
  889.     M5.Lcd.setCursor(202, 256 - floor(bottomPanel / 2));
  890.     M5.Lcd.setTextSize(1);
  891.     lastLow = pl;
  892.     if (multi == 100) {
  893.       M5.Lcd.printf("L %.4f", pl);
  894.     } else if (multi == 100000) {
  895.       M5.Lcd.printf("L %.6f", pl);
  896.     } else if (multi == 100000000) {
  897.       M5.Lcd.printf("L %.2e", pl);
  898.     } else {
  899.       M5.Lcd.printf("L %.2f", pl);
  900.     }
  901.   }
  902.   if (lastTimeframe != current_Timeframe) {
  903.     lastTimeframe = current_Timeframe;
  904.     String timeframe = candlesTimeframes[current_Timeframe];
  905.     M5.Lcd.fillRect(301, 240 - bottomPanel, 19, bottomPanel, TFT_BLACK);
  906.     M5.Lcd.setFreeFont(FSSB9);
  907.     M5.Lcd.setTextSize(1);
  908.     M5.Lcd.setTextColor(TFT_CYAN);
  909.     M5.Lcd.setCursor(301, 254 - bottomPanel);
  910.     M5.Lcd.print(timeframe[0]);
  911.     M5.Lcd.setCursor(301, 255 - floor(bottomPanel / 2));
  912.     M5.Lcd.print(timeframe[1]);
  913.   }
  914. }
  915.  
  916.  
  917.  
  918. // price changings for info panel: changings relative to the 24th past candles close price in percent (with exceptions):
  919. void PriceChangings() {
  920.   if (!timeframe_really_changed) {
  921.     M5.Lcd.fillRect(108, topPanel + sensorPanel, 212, infoPanel, TFT_BLACK);
  922.     M5.Lcd.setFreeFont(FM9);
  923.     M5.Lcd.setCursor(108, topPanel + sensorPanel + infoPanel - 3);
  924.     M5.Lcd.setTextSize(1);
  925.     if (current_Timeframe == 0) {  //1m
  926.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 21].c) {
  927.         M5.Lcd.setTextColor(DARKERGREEN);
  928.         if (multi_level == 1) {
  929.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);  //+%.1f shows prefix even if positive with 1 digit after comma
  930.         } else if (multi_level == 2) {
  931.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  932.         } else if (multi_level == 3) {
  933.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  934.         } else {
  935.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  936.         }
  937.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 21].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 21].c)) * 100));
  938.         M5.Lcd.print("%)");
  939.         M5.Lcd.setTextColor(TFT_WHITE);
  940.         M5.Lcd.print(":20m");
  941.       } else {
  942.         M5.Lcd.setTextColor(MYRED);
  943.         if (multi_level == 1) {
  944.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  945.         } else if (multi_level == 2) {
  946.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  947.         } else if (multi_level == 3) {
  948.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  949.         } else {
  950.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  951.         }
  952.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 21].c / (candles[candlesLimit - 21].c - candles[candlesLimit - 1].c)) * 100));
  953.         M5.Lcd.print("%)");
  954.         M5.Lcd.setTextColor(TFT_WHITE);
  955.         M5.Lcd.print(":20m");
  956.       }
  957.     } else if (current_Timeframe == 1) {  //3m
  958.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 21].c) {
  959.         M5.Lcd.setTextColor(DARKERGREEN);
  960.         if (multi_level == 1) {
  961.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  962.         } else if (multi_level == 2) {
  963.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  964.         } else if (multi_level == 3) {
  965.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  966.         } else {
  967.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 21].c);
  968.         }
  969.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 21].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 21].c)) * 100));
  970.         M5.Lcd.print("%)");
  971.         M5.Lcd.setTextColor(TFT_WHITE);
  972.         M5.Lcd.print(":60m");
  973.       } else {
  974.         M5.Lcd.setTextColor(MYRED);
  975.         if (multi_level == 1) {
  976.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  977.         } else if (multi_level == 2) {
  978.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  979.         } else if (multi_level == 3) {
  980.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  981.         } else {
  982.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 21].c - candles[candlesLimit - 1].c);
  983.         }
  984.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 21].c / (candles[candlesLimit - 21].c - candles[candlesLimit - 1].c)) * 100));
  985.         M5.Lcd.print("%)");
  986.         M5.Lcd.setTextColor(TFT_WHITE);
  987.         M5.Lcd.print(":60m");
  988.       }
  989.     } else if (current_Timeframe == 2) {  //5m
  990.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  991.         M5.Lcd.setTextColor(DARKERGREEN);
  992.         if (multi_level == 1) {
  993.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  994.         } else if (multi_level == 2) {
  995.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  996.         } else if (multi_level == 3) {
  997.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  998.         } else {
  999.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1000.         }
  1001.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1002.         M5.Lcd.print("%)");
  1003.         M5.Lcd.setTextColor(TFT_WHITE);
  1004.         M5.Lcd.print(":2h");
  1005.       } else {
  1006.         M5.Lcd.setTextColor(MYRED);
  1007.         if (multi_level == 1) {
  1008.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1009.         } else if (multi_level == 2) {
  1010.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1011.         } else if (multi_level == 3) {
  1012.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1013.         } else {
  1014.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1015.         }
  1016.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1017.         M5.Lcd.print("%)");
  1018.         M5.Lcd.setTextColor(TFT_WHITE);
  1019.         M5.Lcd.print(":2h");
  1020.       }
  1021.     } else if (current_Timeframe == 3) {  //15m
  1022.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  1023.         M5.Lcd.setTextColor(DARKERGREEN);
  1024.         if (multi_level == 1) {
  1025.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1026.         } else if (multi_level == 2) {
  1027.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1028.         } else if (multi_level == 3) {
  1029.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1030.         } else {
  1031.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1032.         }
  1033.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1034.         M5.Lcd.print("%)");
  1035.         M5.Lcd.setTextColor(TFT_WHITE);
  1036.         M5.Lcd.print(":6h");
  1037.       } else {
  1038.         M5.Lcd.setTextColor(MYRED);
  1039.         if (multi_level == 1) {
  1040.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1041.         } else if (multi_level == 2) {
  1042.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1043.         } else if (multi_level == 3) {
  1044.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1045.         } else {
  1046.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1047.         }
  1048.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1049.         M5.Lcd.print("%)");
  1050.         M5.Lcd.setTextColor(TFT_WHITE);
  1051.         M5.Lcd.print(":6h");
  1052.       }
  1053.     } else if (current_Timeframe == 4) {  //1h
  1054.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  1055.         M5.Lcd.setTextColor(DARKERGREEN);
  1056.         if (multi_level == 1) {
  1057.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1058.         } else if (multi_level == 2) {
  1059.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1060.         } else if (multi_level == 3) {
  1061.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1062.         } else {
  1063.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1064.         }
  1065.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1066.         M5.Lcd.print("%)");
  1067.         M5.Lcd.setTextColor(TFT_WHITE);
  1068.         M5.Lcd.print(":24h");
  1069.       } else {
  1070.         M5.Lcd.setTextColor(MYRED);
  1071.         if (multi_level == 1) {
  1072.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1073.         } else if (multi_level == 2) {
  1074.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1075.         } else if (multi_level == 3) {
  1076.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1077.         } else {
  1078.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1079.         }
  1080.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1081.         M5.Lcd.print("%)");
  1082.         M5.Lcd.setTextColor(TFT_WHITE);
  1083.         M5.Lcd.print(":24h");
  1084.       }
  1085.     } else if (current_Timeframe == 5) {  //4h
  1086.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  1087.         M5.Lcd.setTextColor(DARKERGREEN);
  1088.         if (multi_level == 1) {
  1089.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1090.         } else if (multi_level == 2) {
  1091.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1092.         } else if (multi_level == 3) {
  1093.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1094.         } else {
  1095.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1096.         }
  1097.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1098.         M5.Lcd.print("%)");
  1099.         M5.Lcd.setTextColor(TFT_WHITE);
  1100.         M5.Lcd.print(":4d");
  1101.       } else {
  1102.         M5.Lcd.setTextColor(MYRED);
  1103.         if (multi_level == 1) {
  1104.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1105.         } else if (multi_level == 2) {
  1106.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1107.         } else if (multi_level == 3) {
  1108.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1109.         } else {
  1110.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1111.         }
  1112.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1113.         M5.Lcd.print("%)");
  1114.         M5.Lcd.setTextColor(TFT_WHITE);
  1115.         M5.Lcd.print(":4d");
  1116.       }
  1117.     } else if (current_Timeframe == 6) {  //1d
  1118.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 22].c) {
  1119.         M5.Lcd.setTextColor(DARKERGREEN);
  1120.         if (multi_level == 1) {
  1121.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 22].c);
  1122.         } else if (multi_level == 2) {
  1123.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 22].c);
  1124.         } else if (multi_level == 3) {
  1125.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 22].c);
  1126.         } else {
  1127.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 22].c);
  1128.         }
  1129.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 22].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 22].c)) * 100));
  1130.         M5.Lcd.print("%)");
  1131.         M5.Lcd.setTextColor(TFT_WHITE);
  1132.         M5.Lcd.print(":3w");
  1133.       } else {
  1134.         M5.Lcd.setTextColor(MYRED);
  1135.         if (multi_level == 1) {
  1136.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 22].c - candles[candlesLimit - 1].c);
  1137.         } else if (multi_level == 2) {
  1138.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 22].c - candles[candlesLimit - 1].c);
  1139.         } else if (multi_level == 3) {
  1140.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 22].c - candles[candlesLimit - 1].c);
  1141.         } else {
  1142.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 22].c - candles[candlesLimit - 1].c);
  1143.         }
  1144.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 22].c / (candles[candlesLimit - 22].c - candles[candlesLimit - 1].c)) * 100));
  1145.         M5.Lcd.print("%)");
  1146.         M5.Lcd.setTextColor(TFT_WHITE);
  1147.         M5.Lcd.print(":3w");
  1148.       }
  1149.     } else if (current_Timeframe == 7) {  //1w
  1150.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  1151.         M5.Lcd.setTextColor(DARKERGREEN);
  1152.         if (multi_level == 1) {
  1153.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1154.         } else if (multi_level == 2) {
  1155.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1156.         } else if (multi_level == 3) {
  1157.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1158.         } else {
  1159.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1160.         }
  1161.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1162.         M5.Lcd.print("%)");
  1163.         M5.Lcd.setTextColor(TFT_WHITE);
  1164.         M5.Lcd.print(":5M");
  1165.       } else {
  1166.         M5.Lcd.setTextColor(MYRED);
  1167.         if (multi_level == 1) {
  1168.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1169.         } else if (multi_level == 2) {
  1170.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1171.         } else if (multi_level == 3) {
  1172.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1173.         } else {
  1174.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1175.         }
  1176.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1177.         M5.Lcd.print("%)");
  1178.         M5.Lcd.setTextColor(TFT_WHITE);
  1179.         M5.Lcd.print(":5M");
  1180.       }
  1181.     } else if (current_Timeframe == 8) {  //1M
  1182.       if (candles[candlesLimit - 1].c > candles[candlesLimit - 24].c) {
  1183.         M5.Lcd.setTextColor(DARKERGREEN);
  1184.         if (multi_level == 1) {
  1185.           M5.Lcd.printf("+%.3f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1186.         } else if (multi_level == 2) {
  1187.           M5.Lcd.printf("+%.5f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1188.         } else if (multi_level == 3) {
  1189.           M5.Lcd.printf("+%.1e", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1190.         } else {
  1191.           M5.Lcd.printf("+%4.1f", candles[candlesLimit - 1].c - candles[candlesLimit - 24].c);
  1192.         }
  1193.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 1].c - candles[candlesLimit - 24].c)) * 100));
  1194.         M5.Lcd.print("%)");
  1195.         M5.Lcd.setTextColor(TFT_WHITE);
  1196.         M5.Lcd.print(":2y");
  1197.       } else {
  1198.         M5.Lcd.setTextColor(MYRED);
  1199.         if (multi_level == 1) {
  1200.           M5.Lcd.printf("-%.3f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1201.         } else if (multi_level == 2) {
  1202.           M5.Lcd.printf("-%.5f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1203.         } else if (multi_level == 3) {
  1204.           M5.Lcd.printf("-%.1e", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1205.         } else {
  1206.           M5.Lcd.printf("-%4.1f", candles[candlesLimit - 24].c - candles[candlesLimit - 1].c);
  1207.         }
  1208.         M5.Lcd.printf("(%4.1f", (1 / (candles[candlesLimit - 24].c / (candles[candlesLimit - 24].c - candles[candlesLimit - 1].c)) * 100));
  1209.         M5.Lcd.print("%)");
  1210.         M5.Lcd.setTextColor(TFT_WHITE);
  1211.         M5.Lcd.print(":2y");
  1212.       }
  1213.     }
  1214.   }
  1215. }
  1216.  
  1217.  
  1218.  
  1219. // show Wifi-RSSI level (signal strength)
  1220. void showWifiStrength() {
  1221.   int WifiRSSI = WiFi.RSSI();
  1222.   //  M5.Lcd.fillRect(2, 2 + topPanel + infoPanel + 8, 69, 15, TFT_BLACK);
  1223.   //  M5.Lcd.setCursor(2, 2 +  topPanel + infoPanel + 20); M5.Lcd.setFreeFont(FM9); M5.Lcd.setTextSize(1); M5.Lcd.setTextColor(TFT_WHITE);
  1224.   //  M5.Lcd.print(String(WifiRSSI) + "dBm");
  1225.   if (WifiRSSI > -50 & !WifiRSSI == 0) M5.Lcd.fillRoundRect(26, 2 + topPanel, 5, 12, 1, TFT_WHITE);
  1226.   else M5.Lcd.fillRoundRect(26, 2 + topPanel, 5, 12, 1, TFT_DARKGREY);
  1227.   if (WifiRSSI > -70 & !WifiRSSI == 0) M5.Lcd.fillRoundRect(18, 2 + topPanel + 2, 5, 10, 1, TFT_WHITE);
  1228.   else M5.Lcd.fillRoundRect(18, 2 + topPanel + 2, 5, 10, 1, TFT_DARKGREY);
  1229.   if (WifiRSSI > -80 & !WifiRSSI == 0) M5.Lcd.fillRoundRect(10, 2 + topPanel + 4, 5, 8, 1, TFT_WHITE);
  1230.   else M5.Lcd.fillRoundRect(10, 2 + topPanel + 4, 5, 8, 1, TFT_DARKGREY);
  1231.   if (WifiRSSI > -90 & !WifiRSSI == 0) M5.Lcd.fillRoundRect(2, 2 + topPanel + 6, 5, 6, 1, TFT_WHITE);
  1232.   else M5.Lcd.fillRoundRect(2, 2 + topPanel + 6, 5, 6, 1, TFT_RED);
  1233. }
  1234.  
  1235.  
  1236.  
  1237. // visual error outputs
  1238. void error(String text) {
  1239.   drawCandles();
  1240.   M5.Lcd.setTextWrap(true);
  1241.   M5.Lcd.setTextColor(TFT_WHITE);
  1242.   M5.Lcd.setFreeFont(FSSB12);
  1243.   M5.Lcd.setTextSize(1);
  1244.   M5.Lcd.setCursor(3, topPanel + infoPanel + sensorPanel + 73);
  1245.   if (ws_error) {
  1246.     M5.Lcd.drawPngFile(SPIFFS, "/ws_error_small.png", 100, topPanel + infoPanel + sensorPanel + 5);  // show a 50x50px png
  1247.     M5.Lcd.print(text);
  1248.     ws_error = false;
  1249.     M5.Lcd.setTextWrap(false);
  1250.   }
  1251.   if (wifi_error) {
  1252.     M5.Lcd.print(text);
  1253.     M5.Lcd.drawPngFile(SPIFFS, "/wifi_error_small.png", 155, topPanel + infoPanel + sensorPanel + 5);  // show a 50x50px png
  1254.     wifi_error = false;
  1255.     M5.Lcd.print("nconnecting to ");
  1256.     if (alt_hotspot == false) {
  1257.       M5.Lcd.print(ssid);
  1258.       WiFi.begin(ssid.c_str(), password.c_str());
  1259.     } else {
  1260.       M5.Lcd.print(ssid);
  1261.       WiFi.begin(ssid2.c_str(), password2.c_str());
  1262.     }
  1263.     M5.Lcd.setTextWrap(false);
  1264.     while (WiFi.status() != WL_CONNECTED) {  // after a wifi error occured try to reconnect
  1265.       M5.Lcd.print(".");
  1266.       err_count++;
  1267.       if (err_count > 288) {  // if 10 minutes no wifi -> power off device !
  1268.         M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  1269.         delay(1000);
  1270.         M5.Lcd.fillScreen(TFT_BLACK);
  1271.         delay(1000);
  1272.         M5.Power.powerOFF();         // shut down
  1273.       } else if (err_count > 240) {  // if 2 minutes constant wifi error persists
  1274.         LEDbar.clear();
  1275.         colorWipe(LEDbar.Color(255, 255, 0), 30);  // flash yellow twice with LED bar every 10s
  1276.         LEDbar.show();                             // update LED status
  1277.         LEDbar.clear();
  1278.         LEDbar.show();  // update LED status
  1279.         delay(100);
  1280.         colorWipe(LEDbar.Color(255, 255, 0), 30);
  1281.         LEDbar.show();  // update LED status
  1282.         LEDbar.clear();
  1283.         LEDbar.show();            // update LED status
  1284.         delay(10000);             // the reconnect interval from 0.5s to 10s
  1285.         M5.lcd.setBrightness(1);  // and lower the LCD brighness to lowest value (1)
  1286.       } else {
  1287.         delay(500);
  1288.       }
  1289.     }
  1290.     err_count = 0;
  1291.     M5.lcd.setBrightness(Brightness_value);
  1292.   }
  1293.   // Reset last data to make it redraw after error screen
  1294.   delay(2000);
  1295.   lastPrice = lastLow = lastHigh = lastTimeframe = -1;
  1296.   drawCandles();
  1297. }
  1298.  
  1299.  
  1300.  
  1301. // BUTTON ACTIONS
  1302. void buttonActions() {
  1303.  
  1304.   // Power Off Button (ButtonC long press) - needed because if on usb power there is no option to turn off the unit except by powerOFF command
  1305.   if (M5.BtnC.pressedFor(1333)) {
  1306.     M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  1307.     delay(500);
  1308.     for (int i = Brightness_value; i > 0; i--) {  // dimm LCD slowly before shutdown
  1309.       Brightness_value -= 1;
  1310.       M5.lcd.setBrightness(Brightness_value);
  1311.       delay(50);
  1312.     }
  1313.     M5.Lcd.fillScreen(TFT_BLACK);
  1314.     delay(500);
  1315.     M5.Power.powerOFF();
  1316.   }
  1317.  
  1318.  
  1319.   // cycle through all currencies by pressing ButtonA + ButtonB together
  1320.   if ((M5.BtnA.pressedFor(10) && (M5.BtnC.pressedFor(10)))) {
  1321.     if (!currency_cycling) {
  1322.       currency_cycling = true;
  1323.       Serial.println("auto-cycle currencies on");
  1324.       currency_cycling_counter = currentMs;  //start currency_cycling_counter
  1325.       drawCandles();
  1326.       M5.Lcd.drawPngFile(SPIFFS, "/cycling_on.png", (320 / 2) - (155 / 2), (240 / 2) - (155 / 2));  // center for 155x155px png
  1327.       delay(1000);
  1328.       drawCandles();
  1329.     } else {
  1330.       currency_cycling = false;
  1331.       Serial.println("auto-cycle currencies off");
  1332.       drawCandles();
  1333.       M5.Lcd.drawPngFile(SPIFFS, "/cycling_off.png", (320 / 2) - (155 / 2), (240 / 2) - (155 / 2));  // center for 155x155px png
  1334.       delay(1000);
  1335.       drawCandles();
  1336.     }
  1337.   }
  1338.  
  1339.  
  1340.   // change current currency ButtonA
  1341.   if (((M5.BtnA.wasPressed() && !current_timeframe_changed) && !M5.BtnC.read()) || cycling_change_triggered) {
  1342.     cycling_change_triggered = false;
  1343.     currency_cycling_counter = currentMs;  //restart cycling_timer to not change to early after a button press when in cycling mode)
  1344.     current_Currency_changed = true;
  1345.     currency_btn_timeout_counter = currentMs + 2000;
  1346.     ++current_Currency;
  1347.     if (current_Currency > pairs) current_Currency = 1;
  1348.     strname_color = rgb565_pair_color[current_Currency - 1];
  1349.     strname_currency = pair_name[current_Currency - 1];
  1350.     M5.Lcd.fillRect(0, 0, 106, topPanel, TFT_BLACK);
  1351.     M5.Lcd.setCursor(1, 19);
  1352.     M5.Lcd.setTextColor(strname_color);
  1353.     M5.Lcd.setFreeFont(FSSB12);
  1354.     ;
  1355.     M5.Lcd.setTextSize(1);
  1356.     M5.Lcd.print(strname_currency);
  1357.     drawCandles();
  1358.     M5.Lcd.drawPngFile(SPIFFS, "/currency.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2));  // center for 100x100px png
  1359.   }
  1360.  
  1361.  
  1362.   // brighness ButtonB
  1363.   if (M5.BtnB.wasPressed() && !current_Currency_changed && !current_timeframe_changed) {
  1364.     current_bright_changed = true;
  1365.     bright_btn_timeout_counter = currentMs + 750;
  1366.     Brightness_level++;
  1367.     if (Brightness_level > 4) Brightness_level = 1;  // center for 75x75px Png
  1368.     drawCandles();
  1369.     if (Brightness_level == 1) M5.Lcd.drawPngFile(SPIFFS, "/brightness_low.png", (320 / 2) - (75 / 2), (240 / 2) - (75 / 2));
  1370.     if (Brightness_level == 2) M5.Lcd.drawPngFile(SPIFFS, "/brightness_medlow.png", (320 / 2) - (75 / 2), (240 / 2) - (75 / 2));
  1371.     if (Brightness_level == 3) M5.Lcd.drawPngFile(SPIFFS, "/brightness_med.png", (320 / 2) - (75 / 2), (240 / 2) - (75 / 2));
  1372.     if (Brightness_level == 4) M5.Lcd.drawPngFile(SPIFFS, "/brightness_high.png", (320 / 2) - (75 / 2), (240 / 2) - (75 / 2));
  1373.     switch (Brightness_level) {
  1374.       case 1:
  1375.         Brightness_value = 1;  // low LCD brightness
  1376.         break;
  1377.       case 2:
  1378.         Brightness_value = 22;  // medium low LCD brightness
  1379.         break;
  1380.       case 3:
  1381.         Brightness_value = 64;  // medium LCD brightness
  1382.         break;
  1383.       case 4:
  1384.         Brightness_value = 150;  // high LCD brightness
  1385.         break;
  1386.     }
  1387.     M5.lcd.setBrightness(Brightness_value);
  1388.   }
  1389.  
  1390.  
  1391.   //  timeframe change Buttons: after C was pressed press A or B for - and +
  1392.   if (M5.BtnC.wasPressed() && !current_timeframe_changed && !current_Currency_changed && !current_bright_changed) {
  1393.     delay(105);  //attempt to debounce ButtonC
  1394.     current_timeframe_changed = true;
  1395.     timeframe_btn_timeout_counter1 = currentMs + 2000;
  1396.     String timeframe = candlesTimeframes[current_Timeframe];
  1397.     M5.Lcd.fillRect(301, 240 - bottomPanel, 19, bottomPanel, TFT_BLACK);
  1398.     M5.Lcd.setFreeFont(FSSB9);
  1399.     M5.Lcd.setTextSize(1);
  1400.     M5.Lcd.setTextColor(TFT_CYAN);
  1401.     M5.Lcd.setCursor(301, 254 - bottomPanel);
  1402.     M5.Lcd.print(timeframe[0]);
  1403.     M5.Lcd.setCursor(301, 255 - floor(bottomPanel / 2));
  1404.     M5.Lcd.print(timeframe[1]);
  1405.     drawCandles();
  1406.     M5.Lcd.drawPngFile(SPIFFS, "/timeframe.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2));  // center for 100x100px Png
  1407.   }
  1408.   if (M5.BtnB.wasPressed() && current_timeframe_changed && !current_Currency_changed && !current_bright_changed) {  // set a higher timeframe
  1409.     if (current_Timeframe <= 7 && current_Timeframe >= 0) {
  1410.       timeframe_really_changed = true;
  1411.       timeframe_btn_timeout_counter1 = currentMs + 2000;
  1412.       timeframe_btn_timeout_counter2 = currentMs + 2000;
  1413.       current_Timeframe++;
  1414.       String timeframe = candlesTimeframes[current_Timeframe];
  1415.       M5.Lcd.fillRect(301, 240 - bottomPanel, 19, bottomPanel, TFT_BLACK);
  1416.       M5.Lcd.setFreeFont(FSSB9);
  1417.       M5.Lcd.setTextSize(1);
  1418.       M5.Lcd.setTextColor(TFT_CYAN);
  1419.       M5.Lcd.setCursor(301, 254 - bottomPanel);
  1420.       M5.Lcd.print(timeframe[0]);
  1421.       M5.Lcd.setCursor(301, 255 - floor(bottomPanel / 2));
  1422.       M5.Lcd.print(timeframe[1]);
  1423.       drawCandles();
  1424.       switch (current_Timeframe) {
  1425.         case 0: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1_m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;  // center for 100x100px
  1426.         case 1: M5.Lcd.drawPngFile(SPIFFS, "/timeframe3m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1427.         case 2: M5.Lcd.drawPngFile(SPIFFS, "/timeframe5m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1428.         case 3: M5.Lcd.drawPngFile(SPIFFS, "/timeframe15m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1429.         case 4: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1H.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1430.         case 5: M5.Lcd.drawPngFile(SPIFFS, "/timeframe4H.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1431.         case 6: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1D.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1432.         case 7: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1W.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1433.         case 8: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1M.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1434.       }
  1435.     }
  1436.   }
  1437.   if (M5.BtnA.wasPressed() && current_timeframe_changed && !current_Currency_changed && !current_bright_changed) {  // set a lower timeframe
  1438.     if (current_Timeframe <= 8 && current_Timeframe >= 1) {
  1439.       timeframe_really_changed = true;
  1440.       timeframe_btn_timeout_counter1 = currentMs + 2000;
  1441.       timeframe_btn_timeout_counter2 = currentMs + 2000;
  1442.       current_Timeframe--;
  1443.       String timeframe = candlesTimeframes[current_Timeframe];
  1444.       M5.Lcd.fillRect(301, 240 - bottomPanel, 19, bottomPanel, TFT_BLACK);
  1445.       M5.Lcd.setFreeFont(FSSB9);
  1446.       M5.Lcd.setTextSize(1);
  1447.       M5.Lcd.setTextColor(TFT_CYAN);
  1448.       M5.Lcd.setCursor(301, 254 - bottomPanel);
  1449.       M5.Lcd.print(timeframe[0]);
  1450.       M5.Lcd.setCursor(301, 255 - floor(bottomPanel / 2));
  1451.       M5.Lcd.print(timeframe[1]);
  1452.       drawCandles();
  1453.       switch (current_Timeframe) {
  1454.         case 0: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1_m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;  // center for 100x100px
  1455.         case 1: M5.Lcd.drawPngFile(SPIFFS, "/timeframe3m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1456.         case 2: M5.Lcd.drawPngFile(SPIFFS, "/timeframe5m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1457.         case 3: M5.Lcd.drawPngFile(SPIFFS, "/timeframe15m.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1458.         case 4: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1H.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1459.         case 5: M5.Lcd.drawPngFile(SPIFFS, "/timeframe4H.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1460.         case 6: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1D.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1461.         case 7: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1W.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1462.         case 8: M5.Lcd.drawPngFile(SPIFFS, "/timeframe1M.png", (320 / 2) - (100 / 2), (240 / 2) - (100 / 2)); break;
  1463.       }
  1464.     }
  1465.   }
  1466.   // do after a delay of a Button press..
  1467.   if (current_Currency_changed && currency_btn_timeout_counter < currentMs) {
  1468.     current_Currency_changed = false;
  1469.     currency_btn_timeout_counter = 4294966295;
  1470.     strname_api = pair_STRING[current_Currency - 1];
  1471.     strname_ws = pair_string[current_Currency - 1];
  1472.     lastPrintTime = currentMs;
  1473.     printTime();
  1474.     multi_level = 0;
  1475.     webSocket.disconnect();
  1476.     webSocket.beginSSL(wsApiHost, wsApiPort, getWsApiUrl());
  1477.     while (!requestRestApi()) {}
  1478.     if (!currency_cycling)
  1479.       preferences.putUInt("currency", current_Currency);  // store setting to memory when not in cycling mode
  1480.     showBatteryLevel();
  1481.     drawCandles();
  1482.   }
  1483.   if (current_bright_changed && bright_btn_timeout_counter < currentMs) {  // clear png icon with drawCandles()
  1484.     current_bright_changed = false;
  1485.     preferences.putUInt("bright", Brightness_value);  // store setting to memory
  1486.     preferences.putUInt("briglv", Brightness_level);  // store setting to memory
  1487.     bright_btn_timeout_counter = 4294966295;
  1488.     drawCandles();
  1489.   }
  1490.   if (current_timeframe_changed && timeframe_really_changed && timeframe_btn_timeout_counter1 < currentMs) {
  1491.     current_timeframe_changed = false;
  1492.     timeframe_really_changed = false;
  1493.     timeframe_btn_timeout_counter1 = 4294966295;
  1494.     multi_level = 0;
  1495.     webSocket.disconnect();
  1496.     webSocket.beginSSL(wsApiHost, wsApiPort, getWsApiUrl());
  1497.     preferences.putUInt("timeframe", current_Timeframe);  // store setting to memory
  1498.     while (!requestRestApi()) {}
  1499.     showBatteryLevel();
  1500.     drawCandles();
  1501.   }
  1502.   if (current_timeframe_changed && !timeframe_really_changed && timeframe_btn_timeout_counter1 < currentMs) {
  1503.     current_timeframe_changed = false;
  1504.     timeframe_btn_timeout_counter1 = 4294966295;
  1505.     drawCandles();
  1506.   }
  1507.   if (current_timeframe_changed && !timeframe_really_changed && timeframe_btn_timeout_counter2 < currentMs) {
  1508.     current_timeframe_changed = false;
  1509.     timeframe_btn_timeout_counter2 = 4294966295;
  1510.     drawCandles();
  1511.   }
  1512.  
  1513.   // Button for Sleep Timer zzz zzZ..ZZ.Z.ZZ..Zzz zzz
  1514.   if (M5.BtnB.pressedFor(1700)) {
  1515.     if (!sleeptimer_bool) {  // enables sleeptimer if ButtonB is long pressed
  1516.       sleeptimer_bool = true;
  1517.       sleeptimer_counter = now();
  1518.       Brightness_level--;  // because brighness and sleeptimer are on same ButtonA correct brightness one level back
  1519.       if (Brightness_level < 1) Brightness_level = 4;
  1520.       switch (Brightness_level) {
  1521.         case 1:
  1522.           Brightness_value = 1;  // lowest LCD brightness
  1523.           break;
  1524.         case 2:
  1525.           Brightness_value = 22;  // medium low LCD brightness
  1526.           break;
  1527.         case 3:
  1528.           Brightness_value = 64;  // medium high LCD brightness
  1529.           break;
  1530.         case 4:
  1531.           Brightness_value = 150;  // highest LCD brightness
  1532.           break;
  1533.       }
  1534.       M5.lcd.setBrightness(Brightness_value);
  1535.       preferences.putUInt("bright", Brightness_value);                                      // store setting to memory
  1536.       preferences.putUInt("briglv", Brightness_level);                                      // store setting to memory
  1537.       M5.Lcd.drawCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 5, TFT_BLUE);  // set blue status light when sleeptimer was activated
  1538.       drawCandles();
  1539.       M5.Lcd.drawPngFile(SPIFFS, "/sleep.png", (320 / 2) - (100 / 2), (240 / 2) - ((100 / 2)));  // sleep.png is 100x100px
  1540.       LEDbar.clear();
  1541.       colorWipe(LEDbar.Color(0, 0, 255), 35);  // Blue             // fill LEDbar in various colors...(delay in ms)
  1542.       LEDbar.clear();
  1543.       LEDbar.show();  // update LED status
  1544.       delay(1300);
  1545.       drawCandles();
  1546.     } else if (sleeptimer_bool) {  // disables sleeptimer if it is already enabled
  1547.       sleeptimer_bool = false;
  1548.       sleeptimer_counter = 0;
  1549.       Brightness_level--;  // because brighness and sleeptimer are on same ButtonA correct brightness one level back
  1550.       if (Brightness_level < 1) Brightness_level = 4;
  1551.       switch (Brightness_level) {
  1552.         case 1:
  1553.           Brightness_value = 1;  // low LCD brightness
  1554.           break;
  1555.         case 2:
  1556.           Brightness_value = 22;  // medium low LCD brightness
  1557.           break;
  1558.         case 3:
  1559.           Brightness_value = 64;  // medium LCD brightness
  1560.           break;
  1561.         case 4:
  1562.           Brightness_value = 150;  // high LCD brightness
  1563.           break;
  1564.       }
  1565.       M5.lcd.setBrightness(Brightness_value);
  1566.       preferences.putUInt("bright", Brightness_value);                                       // store setting to memory
  1567.       M5.Lcd.drawCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 5, TFT_BLACK);  // reset blue status light when sleeptimer was deactivated
  1568.       drawCandles();
  1569.       M5.Lcd.drawPngFile(SPIFFS, "/cancel_sleep.png", (320 / 2) - (120 / 2), (240 / 2) - ((120 / 2)));  //sleep.png is 120x120px
  1570.       LEDbar.clear();
  1571.       colorWipe(LEDbar.Color(255, 255, 255), 35);  // White        // fill LEDbar in various colors...(delay in ms)
  1572.       LEDbar.clear();
  1573.       LEDbar.show();  // update LED status
  1574.       delay(1300);
  1575.       drawCandles();
  1576.     }
  1577.   }
  1578.   if (sleeptimer_bool == true && (now() > (sleeptimer_counter + sleeptime))) {
  1579.     sleeptimer_bool = false;
  1580.     M5.Lcd.drawCircle(101, topPanel + ((infoPanel + sensorPanel) / 2 - 7), 5, TFT_BLACK);  // reset status light when sleeptimer was finished
  1581.     M5.Lcd.drawPngFile(SPIFFS, "/m5_logo_dark.png", 0, 0);
  1582.     delay(1000);
  1583.     for (int i = Brightness_value; i > 0; i--) {  // dimm LCD slowly before shutdown
  1584.       Brightness_value -= 1;
  1585.       M5.lcd.setBrightness(Brightness_value);
  1586.       delay(50);
  1587.     }
  1588.     M5.Lcd.fillScreen(TFT_BLACK);
  1589.     delay(1000);
  1590.     M5.Power.powerOFF();
  1591.   }
  1592. }
  1593.  
  1594.  
  1595.  
  1596. // update settings from SD config file
  1597. void updateSDSettings() {
  1598.   // check for configuration from SD-Card file
  1599.   SDConfig cfg;
  1600.   // Open the configuration file.
  1601.   if (!cfg.begin(configFile, maxLineLength)) {
  1602.     Serial.println("failed to open configuration file: ");
  1603.     Serial.println(configFile);
  1604.     Serial.println("using last good setting from memory or defaults");
  1605.   }
  1606.   // from here i did it one by one as i don't get it to work with a 'for' loop
  1607.   while (cfg.readNextSetting()) {  //at the moment are up to 36 pairs possible
  1608.     // Put a nameIs() block here for each setting you have.
  1609.     if (cfg.nameIs("welcome")) {  // welcome string (char *)
  1610.       welcome = cfg.copyValue();
  1611.       Serial.print("Read welcome: ");
  1612.       Serial.println(welcome);
  1613.     } else if (cfg.nameIs("ssid")) {
  1614.       ssid = cfg.copyValue();
  1615.       Serial.print("Read ssid: ");
  1616.       Serial.println(ssid);
  1617.     } else if (cfg.nameIs("password")) {
  1618.       password = cfg.copyValue();
  1619.       Serial.print("Read password: ");
  1620.       Serial.println(password);
  1621.     } else if (cfg.nameIs("ssid2")) {
  1622.       ssid2 = cfg.copyValue();
  1623.       Serial.print("Read ssid2: ");
  1624.       Serial.println(ssid2);
  1625.     } else if (cfg.nameIs("password2")) {
  1626.       password2 = cfg.copyValue();
  1627.       Serial.print("Read password2: ");
  1628.       Serial.println(password2);
  1629.     } else if (cfg.nameIs("pairs")) {
  1630.       pairs = cfg.getIntValue();
  1631.       Serial.print("Read pairs: ");
  1632.       Serial.println(pairs);
  1633.     } else if (cfg.nameIs("pair_name01")) {
  1634.       pair_name[0] = cfg.copyValue();
  1635.       Serial.print("Read pair_name01: ");
  1636.       Serial.println(pair_name[0]);
  1637.     } else if (cfg.nameIs("pair_name02")) {
  1638.       pair_name[1] = cfg.copyValue();
  1639.       Serial.print("Read pair_name02: ");
  1640.       Serial.println(pair_name[1]);
  1641.     } else if (cfg.nameIs("pair_name03")) {
  1642.       pair_name[2] = cfg.copyValue();
  1643.       Serial.print("Read pair_name03: ");
  1644.       Serial.println(pair_name[2]);
  1645.     } else if (cfg.nameIs("pair_name04")) {
  1646.       pair_name[3] = cfg.copyValue();
  1647.       Serial.print("Read pair_name04: ");
  1648.       Serial.println(pair_name[3]);
  1649.     } else if (cfg.nameIs("pair_name05")) {
  1650.       pair_name[4] = cfg.copyValue();
  1651.       Serial.print("Read pair_name05: ");
  1652.       Serial.println(pair_name[4]);
  1653.     } else if (cfg.nameIs("pair_name06")) {
  1654.       pair_name[5] = cfg.copyValue();
  1655.       Serial.print("Read pair_name06: ");
  1656.       Serial.println(pair_name[5]);
  1657.     } else if (cfg.nameIs("pair_name07")) {
  1658.       pair_name[6] = cfg.copyValue();
  1659.       Serial.print("Read pair_name07: ");
  1660.       Serial.println(pair_name[6]);
  1661.     } else if (cfg.nameIs("pair_name08")) {
  1662.       pair_name[7] = cfg.copyValue();
  1663.       Serial.print("Read pair_name08: ");
  1664.       Serial.println(pair_name[7]);
  1665.     } else if (cfg.nameIs("pair_name09")) {
  1666.       pair_name[8] = cfg.copyValue();
  1667.       Serial.print("Read pair_name09: ");
  1668.       Serial.println(pair_name[8]);
  1669.     } else if (cfg.nameIs("pair_name10")) {
  1670.       pair_name[9] = cfg.copyValue();
  1671.       Serial.print("Read pair_name10: ");
  1672.       Serial.println(pair_name[9]);
  1673.     } else if (cfg.nameIs("pair_name11")) {
  1674.       pair_name[10] = cfg.copyValue();
  1675.       Serial.print("Read pair_name11: ");
  1676.       Serial.println(pair_name[10]);
  1677.     } else if (cfg.nameIs("pair_name12")) {
  1678.       pair_name[11] = cfg.copyValue();
  1679.       Serial.print("Read pair_name12: ");
  1680.       Serial.println(pair_name[11]);
  1681.     } else if (cfg.nameIs("pair_name13")) {
  1682.       pair_name[12] = cfg.copyValue();
  1683.       Serial.print("Read pair_name13: ");
  1684.       Serial.println(pair_name[12]);
  1685.     } else if (cfg.nameIs("pair_name14")) {
  1686.       pair_name[13] = cfg.copyValue();
  1687.       Serial.print("Read pair_name14: ");
  1688.       Serial.println(pair_name[13]);
  1689.     } else if (cfg.nameIs("pair_name15")) {
  1690.       pair_name[14] = cfg.copyValue();
  1691.       Serial.print("Read pair_name15: ");
  1692.       Serial.println(pair_name[14]);
  1693.     } else if (cfg.nameIs("pair_name16")) {
  1694.       pair_name[15] = cfg.copyValue();
  1695.       Serial.print("Read pair_name16: ");
  1696.       Serial.println(pair_name[15]);
  1697.     } else if (cfg.nameIs("pair_name17")) {
  1698.       pair_name[16] = cfg.copyValue();
  1699.       Serial.print("Read pair_name17: ");
  1700.       Serial.println(pair_name[16]);
  1701.     } else if (cfg.nameIs("pair_name18")) {
  1702.       pair_name[17] = cfg.copyValue();
  1703.       Serial.print("Read pair_name18: ");
  1704.       Serial.println(pair_name[17]);
  1705.     } else if (cfg.nameIs("pair_name19")) {
  1706.       pair_name[18] = cfg.copyValue();
  1707.       Serial.print("Read pair_name19: ");
  1708.       Serial.println(pair_name[18]);
  1709.     } else if (cfg.nameIs("pair_name20")) {
  1710.       pair_name[19] = cfg.copyValue();
  1711.       Serial.print("Read pair_name20: ");
  1712.       Serial.println(pair_name[19]);
  1713.     } else if (cfg.nameIs("pair_name21")) {
  1714.       pair_name[20] = cfg.copyValue();
  1715.       Serial.print("Read pair_name21: ");
  1716.       Serial.println(pair_name[20]);
  1717.     } else if (cfg.nameIs("pair_name22")) {
  1718.       pair_name[21] = cfg.copyValue();
  1719.       Serial.print("Read pair_name22: ");
  1720.       Serial.println(pair_name[21]);
  1721.     } else if (cfg.nameIs("pair_name23")) {
  1722.       pair_name[22] = cfg.copyValue();
  1723.       Serial.print("Read pair_name23: ");
  1724.       Serial.println(pair_name[22]);
  1725.     } else if (cfg.nameIs("pair_name24")) {
  1726.       pair_name[23] = cfg.copyValue();
  1727.       Serial.print("Read pair_name24: ");
  1728.       Serial.println(pair_name[23]);
  1729.     } else if (cfg.nameIs("pair_name25")) {
  1730.       pair_name[24] = cfg.copyValue();
  1731.       Serial.print("Read pair_name25: ");
  1732.       Serial.println(pair_name[24]);
  1733.     } else if (cfg.nameIs("pair_STRING01")) {
  1734.       pair_STRING[0] = cfg.copyValue();
  1735.       Serial.print("Read pair_STRING01: ");
  1736.       Serial.println(pair_STRING[0]);
  1737.     } else if (cfg.nameIs("pair_STRING02")) {
  1738.       pair_STRING[1] = cfg.copyValue();
  1739.       Serial.print("Read pair_STRING02: ");
  1740.       Serial.println(pair_STRING[1]);
  1741.     } else if (cfg.nameIs("pair_STRING03")) {
  1742.       pair_STRING[2] = cfg.copyValue();
  1743.       Serial.print("Read pair_STRING03: ");
  1744.       Serial.println(pair_STRING[2]);
  1745.     } else if (cfg.nameIs("pair_STRING04")) {
  1746.       pair_STRING[3] = cfg.copyValue();
  1747.       Serial.print("Read pair_STRING04: ");
  1748.       Serial.println(pair_STRING[3]);
  1749.     } else if (cfg.nameIs("pair_STRING05")) {
  1750.       pair_STRING[4] = cfg.copyValue();
  1751.       Serial.print("Read pair_STRING05: ");
  1752.       Serial.println(pair_STRING[4]);
  1753.     } else if (cfg.nameIs("pair_STRING06")) {
  1754.       pair_STRING[5] = cfg.copyValue();
  1755.       Serial.print("Read pair_STRING06: ");
  1756.       Serial.println(pair_STRING[5]);
  1757.     } else if (cfg.nameIs("pair_STRING07")) {
  1758.       pair_STRING[6] = cfg.copyValue();
  1759.       Serial.print("Read pair_STRING07: ");
  1760.       Serial.println(pair_STRING[6]);
  1761.     } else if (cfg.nameIs("pair_STRING08")) {
  1762.       pair_STRING[7] = cfg.copyValue();
  1763.       Serial.print("Read pair_STRING08: ");
  1764.       Serial.println(pair_STRING[7]);
  1765.     } else if (cfg.nameIs("pair_STRING09")) {
  1766.       pair_STRING[8] = cfg.copyValue();
  1767.       Serial.print("Read pair_STRING09: ");
  1768.       Serial.println(pair_STRING[8]);
  1769.     } else if (cfg.nameIs("pair_STRING10")) {
  1770.       pair_STRING[9] = cfg.copyValue();
  1771.       Serial.print("Read pair_STRING10: ");
  1772.       Serial.println(pair_STRING[9]);
  1773.     } else if (cfg.nameIs("pair_STRING11")) {
  1774.       pair_STRING[10] = cfg.copyValue();
  1775.       Serial.print("Read pair_STRING11: ");
  1776.       Serial.println(pair_STRING[10]);
  1777.     } else if (cfg.nameIs("pair_STRING12")) {
  1778.       pair_STRING[11] = cfg.copyValue();
  1779.       Serial.print("Read pair_STRING12: ");
  1780.       Serial.println(pair_STRING[11]);
  1781.     } else if (cfg.nameIs("pair_STRING13")) {
  1782.       pair_STRING[12] = cfg.copyValue();
  1783.       Serial.print("Read pair_STRING13: ");
  1784.       Serial.println(pair_STRING[12]);
  1785.     } else if (cfg.nameIs("pair_STRING14")) {
  1786.       pair_STRING[13] = cfg.copyValue();
  1787.       Serial.print("Read pair_STRING14: ");
  1788.       Serial.println(pair_STRING[13]);
  1789.     } else if (cfg.nameIs("pair_STRING15")) {
  1790.       pair_STRING[14] = cfg.copyValue();
  1791.       Serial.print("Read pair_STRING15: ");
  1792.       Serial.println(pair_STRING[14]);
  1793.     } else if (cfg.nameIs("pair_STRING16")) {
  1794.       pair_STRING[15] = cfg.copyValue();
  1795.       Serial.print("Read pair_STRING16: ");
  1796.       Serial.println(pair_STRING[15]);
  1797.     } else if (cfg.nameIs("pair_STRING17")) {
  1798.       pair_STRING[16] = cfg.copyValue();
  1799.       Serial.print("Read pair_STRING17: ");
  1800.       Serial.println(pair_STRING[16]);
  1801.     } else if (cfg.nameIs("pair_STRING18")) {
  1802.       pair_STRING[17] = cfg.copyValue();
  1803.       Serial.print("Read pair_STRING18: ");
  1804.       Serial.println(pair_STRING[17]);
  1805.     } else if (cfg.nameIs("pair_STRING19")) {
  1806.       pair_STRING[18] = cfg.copyValue();
  1807.       Serial.print("Read pair_STRING19: ");
  1808.       Serial.println(pair_STRING[18]);
  1809.     } else if (cfg.nameIs("pair_STRING20")) {
  1810.       pair_STRING[19] = cfg.copyValue();
  1811.       Serial.print("Read pair_STRING20: ");
  1812.       Serial.println(pair_STRING[19]);
  1813.     } else if (cfg.nameIs("pair_STRING21")) {
  1814.       pair_STRING[20] = cfg.copyValue();
  1815.       Serial.print("Read pair_STRING21: ");
  1816.       Serial.println(pair_STRING[20]);
  1817.     } else if (cfg.nameIs("pair_STRING22")) {
  1818.       pair_STRING[21] = cfg.copyValue();
  1819.       Serial.print("Read pair_STRING22: ");
  1820.       Serial.println(pair_STRING[21]);
  1821.     } else if (cfg.nameIs("pair_STRING23")) {
  1822.       pair_STRING[22] = cfg.copyValue();
  1823.       Serial.print("Read pair_STRING23: ");
  1824.       Serial.println(pair_STRING[22]);
  1825.     } else if (cfg.nameIs("pair_STRING24")) {
  1826.       pair_STRING[23] = cfg.copyValue();
  1827.       Serial.print("Read pair_STRING24: ");
  1828.       Serial.println(pair_STRING[23]);
  1829.     } else if (cfg.nameIs("pair_STRING25")) {
  1830.       pair_STRING[24] = cfg.copyValue();
  1831.       Serial.print("Read pair_STRING25: ");
  1832.       Serial.println(pair_STRING[24]);
  1833.     } else if (cfg.nameIs("pair_color01")) {
  1834.       pair_col_str[0] = cfg.copyValue();
  1835.       Serial.print("Read pair_color01: ");
  1836.       Serial.println(pair_col_str[0]);
  1837.     } else if (cfg.nameIs("pair_color02")) {
  1838.       pair_col_str[1] = cfg.copyValue();
  1839.       Serial.print("Read pair_color02: ");
  1840.       Serial.println(pair_col_str[1]);
  1841.     } else if (cfg.nameIs("pair_color03")) {
  1842.       pair_col_str[2] = cfg.copyValue();
  1843.       Serial.print("Read pair_color03: ");
  1844.       Serial.println(pair_col_str[2]);
  1845.     } else if (cfg.nameIs("pair_color04")) {
  1846.       pair_col_str[3] = cfg.copyValue();
  1847.       Serial.print("Read pair_color04: ");
  1848.       Serial.println(pair_col_str[3]);
  1849.     } else if (cfg.nameIs("pair_color05")) {
  1850.       pair_col_str[4] = cfg.copyValue();
  1851.       Serial.print("Read pair_color05: ");
  1852.       Serial.println(pair_col_str[4]);
  1853.     } else if (cfg.nameIs("pair_color06")) {
  1854.       pair_col_str[5] = cfg.copyValue();
  1855.       Serial.print("Read pair_color06: ");
  1856.       Serial.println(pair_col_str[5]);
  1857.     } else if (cfg.nameIs("pair_color07")) {
  1858.       pair_col_str[6] = cfg.copyValue();
  1859.       Serial.print("Read pair_color07: ");
  1860.       Serial.println(pair_col_str[6]);
  1861.     } else if (cfg.nameIs("pair_color08")) {
  1862.       pair_col_str[7] = cfg.copyValue();
  1863.       Serial.print("Read pair_color08: ");
  1864.       Serial.println(pair_col_str[7]);
  1865.     } else if (cfg.nameIs("pair_color09")) {
  1866.       pair_col_str[8] = cfg.copyValue();
  1867.       Serial.print("Read pair_color09: ");
  1868.       Serial.println(pair_col_str[8]);
  1869.     } else if (cfg.nameIs("pair_color10")) {
  1870.       pair_col_str[9] = cfg.copyValue();
  1871.       Serial.print("Read pair_color10: ");
  1872.       Serial.println(pair_col_str[9]);
  1873.     } else if (cfg.nameIs("pair_color11")) {
  1874.       pair_col_str[10] = cfg.copyValue();
  1875.       Serial.print("Read pair_color11: ");
  1876.       Serial.println(pair_col_str[10]);
  1877.     } else if (cfg.nameIs("pair_color12")) {
  1878.       pair_col_str[11] = cfg.copyValue();
  1879.       Serial.print("Read pair_color12: ");
  1880.       Serial.println(pair_col_str[11]);
  1881.     } else if (cfg.nameIs("pair_color13")) {
  1882.       pair_col_str[12] = cfg.copyValue();
  1883.       Serial.print("Read pair_color13: ");
  1884.       Serial.println(pair_col_str[12]);
  1885.     } else if (cfg.nameIs("pair_color14")) {
  1886.       pair_col_str[13] = cfg.copyValue();
  1887.       Serial.print("Read pair_color14: ");
  1888.       Serial.println(pair_col_str[13]);
  1889.     } else if (cfg.nameIs("pair_color15")) {
  1890.       pair_col_str[14] = cfg.copyValue();
  1891.       Serial.print("Read pair_color15: ");
  1892.       Serial.println(pair_col_str[14]);
  1893.     } else if (cfg.nameIs("pair_color16")) {
  1894.       pair_col_str[15] = cfg.copyValue();
  1895.       Serial.print("Read pair_color16: ");
  1896.       Serial.println(pair_col_str[15]);
  1897.     } else if (cfg.nameIs("pair_color17")) {
  1898.       pair_col_str[16] = cfg.copyValue();
  1899.       Serial.print("Read pair_color17: ");
  1900.       Serial.println(pair_col_str[16]);
  1901.     } else if (cfg.nameIs("pair_color18")) {
  1902.       pair_col_str[17] = cfg.copyValue();
  1903.       Serial.print("Read pair_color18: ");
  1904.       Serial.println(pair_col_str[17]);
  1905.     } else if (cfg.nameIs("pair_color19")) {
  1906.       pair_col_str[18] = cfg.copyValue();
  1907.       Serial.print("Read pair_color19: ");
  1908.       Serial.println(pair_col_str[18]);
  1909.     } else if (cfg.nameIs("pair_color20")) {
  1910.       pair_col_str[19] = cfg.copyValue();
  1911.       Serial.print("Read pair_color20: ");
  1912.       Serial.println(pair_col_str[19]);
  1913.     } else if (cfg.nameIs("pair_color21")) {
  1914.       pair_col_str[20] = cfg.copyValue();
  1915.       Serial.print("Read pair_color21: ");
  1916.       Serial.println(pair_col_str[20]);
  1917.     } else if (cfg.nameIs("pair_color22")) {
  1918.       pair_col_str[21] = cfg.copyValue();
  1919.       Serial.print("Read pair_color22: ");
  1920.       Serial.println(pair_col_str[21]);
  1921.     } else if (cfg.nameIs("pair_color23")) {
  1922.       pair_col_str[22] = cfg.copyValue();
  1923.       Serial.print("Read pair_color23: ");
  1924.       Serial.println(pair_col_str[22]);
  1925.     } else if (cfg.nameIs("pair_color24")) {
  1926.       pair_col_str[23] = cfg.copyValue();
  1927.       Serial.print("Read pair_color24: ");
  1928.       Serial.println(pair_col_str[23]);
  1929.     } else if (cfg.nameIs("pair_color25")) {
  1930.       pair_col_str[24] = cfg.copyValue();
  1931.       Serial.print("Read pair_color25: ");
  1932.       Serial.println(pair_col_str[24]);
  1933.     } else if (cfg.nameIs("myTimeZone")) {
  1934.       myTimeZone = cfg.getIntValue();
  1935.       Serial.print("Read myTimeZone: ");
  1936.       Serial.println(myTimeZone);
  1937.     } else if (cfg.nameIs("myLanguage")) {
  1938.       myLanguage = cfg.getIntValue();
  1939.       Serial.print("Read myLanguage: ");
  1940.       Serial.println(myLanguage);
  1941.     } else if (cfg.nameIs("myTempUnit")) {
  1942.       myTempUnit = cfg.getIntValue();
  1943.       Serial.print("Read myTempUnit: ");
  1944.       Serial.println(myTempUnit);
  1945.     } else if (cfg.nameIs("myTempOffset")) {
  1946.       myTempOffset = cfg.getIntValue();
  1947.       Serial.print("Read myTempOffset: ");
  1948.       Serial.println(myTempOffset);
  1949.     } else if (cfg.nameIs("myCyclingIntervall")) {
  1950.       myCyclingIntervall = cfg.getIntValue();
  1951.       Serial.print("Read myCyclingIntervall: ");
  1952.       Serial.println(myCyclingIntervall);
  1953.     } else if (cfg.nameIs("mySleeptime")) {
  1954.       mySleeptime = cfg.getIntValue();
  1955.       Serial.print("Read mySleeptime: ");
  1956.       Serial.println(mySleeptime);
  1957.     } else {
  1958.       // report unrecognized names.
  1959.       Serial.print("unknown contend in configfile: ");
  1960.       Serial.println(cfg.getName());
  1961.       M5.Lcd.print("nunknown contend in SD confg file");
  1962.       delay(1750);
  1963.     }
  1964.   }
  1965.   cfg.end();  // end of sd reading
  1966.  
  1967.   // load last settings from memory on startup
  1968.   preferences.begin("settings", false);
  1969.   if (M5.BtnB.isPressed()) {  //if you want to clear all stored settings from internal memory hold ButtonB at start-up
  1970.     preferences.clear();
  1971.     M5.Lcd.print("nn*** Memory cleared by user ***");
  1972.     Serial.println("*** Memory cleared by user ***");
  1973.     delay(2000);
  1974.     M5.Lcd.fillScreen(TFT_BLACK);
  1975.   }
  1976.  
  1977.   ssid_mem = preferences.getString("ssid", "");
  1978.   ssid2_mem = preferences.getString("ssid2", "");
  1979.   password_mem = preferences.getString("password", "");
  1980.   password2_mem = preferences.getString("password2", "");
  1981.   mySleeptime_mem = preferences.getInt("mySleeptime", 45);
  1982.   myTimeZone_mem = preferences.getInt("myTimeZone", 4);
  1983.   myLanguage_mem = preferences.getInt("myLanguage", 0);
  1984.   myTempUnit_mem = preferences.getInt("myTempUnit", 0);
  1985.   myTempOffset_mem = preferences.getInt("myTempOffset", 0);
  1986.   myCyclingIntervall_mem = preferences.getInt("myCyclingIntervall", 15);
  1987.   pairs_mem = preferences.getInt("pairs", 4);
  1988.   pair_name_mem[0] = preferences.getString("pair_name01", "");
  1989.   pair_name_mem[1] = preferences.getString("pair_name02", "");
  1990.   pair_name_mem[2] = preferences.getString("pair_name03", "");
  1991.   pair_name_mem[3] = preferences.getString("pair_name04", "");
  1992.   pair_name_mem[4] = preferences.getString("pair_name05", "");
  1993.   pair_name_mem[5] = preferences.getString("pair_name06", "");
  1994.   pair_name_mem[6] = preferences.getString("pair_name07", "");
  1995.   pair_name_mem[7] = preferences.getString("pair_name08", "");
  1996.   pair_name_mem[8] = preferences.getString("pair_name09", "");
  1997.   pair_name_mem[9] = preferences.getString("pair_name10", "");
  1998.   pair_name_mem[10] = preferences.getString("pair_name11", "");
  1999.   pair_name_mem[11] = preferences.getString("pair_name12", "");
  2000.   pair_name_mem[12] = preferences.getString("pair_name13", "");
  2001.   pair_name_mem[13] = preferences.getString("pair_name14", "");
  2002.   pair_name_mem[14] = preferences.getString("pair_name15", "");
  2003.   pair_name_mem[15] = preferences.getString("pair_name16", "");
  2004.   pair_name_mem[16] = preferences.getString("pair_name17", "");
  2005.   pair_name_mem[17] = preferences.getString("pair_name18", "");
  2006.   pair_name_mem[18] = preferences.getString("pair_name19", "");
  2007.   pair_name_mem[19] = preferences.getString("pair_name20", "");
  2008.   pair_name_mem[20] = preferences.getString("pair_name21", "");
  2009.   pair_name_mem[21] = preferences.getString("pair_name22", "");
  2010.   pair_name_mem[22] = preferences.getString("pair_name23", "");
  2011.   pair_name_mem[23] = preferences.getString("pair_name24", "");
  2012.   pair_name_mem[24] = preferences.getString("pair_name25", "");
  2013.   pair_STRING_mem[0] = preferences.getString("pair_STRING01", "");
  2014.   pair_STRING_mem[1] = preferences.getString("pair_STRING02", "");
  2015.   pair_STRING_mem[2] = preferences.getString("pair_STRING03", "");
  2016.   pair_STRING_mem[3] = preferences.getString("pair_STRING04", "");
  2017.   pair_STRING_mem[4] = preferences.getString("pair_STRING05", "");
  2018.   pair_STRING_mem[5] = preferences.getString("pair_STRING06", "");
  2019.   pair_STRING_mem[6] = preferences.getString("pair_STRING07", "");
  2020.   pair_STRING_mem[7] = preferences.getString("pair_STRING08", "");
  2021.   pair_STRING_mem[8] = preferences.getString("pair_STRING09", "");
  2022.   pair_STRING_mem[9] = preferences.getString("pair_STRING10", "");
  2023.   pair_STRING_mem[10] = preferences.getString("pair_STRING11", "");
  2024.   pair_STRING_mem[11] = preferences.getString("pair_STRING12", "");
  2025.   pair_STRING_mem[12] = preferences.getString("pair_STRING13", "");
  2026.   pair_STRING_mem[13] = preferences.getString("pair_STRING14", "");
  2027.   pair_STRING_mem[14] = preferences.getString("pair_STRING15", "");
  2028.   pair_STRING_mem[15] = preferences.getString("pair_STRING16", "");
  2029.   pair_STRING_mem[16] = preferences.getString("pair_STRING17", "");
  2030.   pair_STRING_mem[17] = preferences.getString("pair_STRING18", "");
  2031.   pair_STRING_mem[18] = preferences.getString("pair_STRING19", "");
  2032.   pair_STRING_mem[19] = preferences.getString("pair_STRING20", "");
  2033.   pair_STRING_mem[20] = preferences.getString("pair_STRING21", "");
  2034.   pair_STRING_mem[21] = preferences.getString("pair_STRING22", "");
  2035.   pair_STRING_mem[22] = preferences.getString("pair_STRING23", "");
  2036.   pair_STRING_mem[23] = preferences.getString("pair_STRING24", "");
  2037.   pair_STRING_mem[24] = preferences.getString("pair_STRING25", "");
  2038.   pair_col_str_mem[0] = preferences.getString("pair_col_str01", "");
  2039.   pair_col_str_mem[1] = preferences.getString("pair_col_str02", "");
  2040.   pair_col_str_mem[2] = preferences.getString("pair_col_str03", "");
  2041.   pair_col_str_mem[3] = preferences.getString("pair_col_str04", "");
  2042.   pair_col_str_mem[4] = preferences.getString("pair_col_str05", "");
  2043.   pair_col_str_mem[5] = preferences.getString("pair_col_str06", "");
  2044.   pair_col_str_mem[6] = preferences.getString("pair_col_str07", "");
  2045.   pair_col_str_mem[7] = preferences.getString("pair_col_str08", "");
  2046.   pair_col_str_mem[8] = preferences.getString("pair_col_str09", "");
  2047.   pair_col_str_mem[9] = preferences.getString("pair_col_str10", "");
  2048.   pair_col_str_mem[10] = preferences.getString("pair_col_str11", "");
  2049.   pair_col_str_mem[11] = preferences.getString("pair_col_str12", "");
  2050.   pair_col_str_mem[12] = preferences.getString("pair_col_str13", "");
  2051.   pair_col_str_mem[13] = preferences.getString("pair_col_str14", "");
  2052.   pair_col_str_mem[14] = preferences.getString("pair_col_str15", "");
  2053.   pair_col_str_mem[15] = preferences.getString("pair_col_str16", "");
  2054.   pair_col_str_mem[16] = preferences.getString("pair_col_str17", "");
  2055.   pair_col_str_mem[17] = preferences.getString("pair_col_str18", "");
  2056.   pair_col_str_mem[18] = preferences.getString("pair_col_str19", "");
  2057.   pair_col_str_mem[19] = preferences.getString("pair_col_str20", "");
  2058.   pair_col_str_mem[20] = preferences.getString("pair_col_str21", "");
  2059.   pair_col_str_mem[21] = preferences.getString("pair_col_str22", "");
  2060.   pair_col_str_mem[22] = preferences.getString("pair_col_str23", "");
  2061.   pair_col_str_mem[23] = preferences.getString("pair_col_str24", "");
  2062.   pair_col_str_mem[24] = preferences.getString("pair_col_str25", "");
  2063.  
  2064.   // when processed SD-Card config is other than the saved ones, save new value to memory
  2065.   if (SD.begin(pinSelectSD)) {  //main settings
  2066.     if (ssid != ssid_mem) {
  2067.       Serial.print("old ssid_mem was: ");
  2068.       Serial.println(ssid_mem);
  2069.       preferences.putString("ssid", ssid);
  2070.       Serial.print("new ssid save is: ");
  2071.       Serial.println(ssid);
  2072.       change_count++;
  2073.     }
  2074.     if (ssid2 != ssid2_mem) {
  2075.       Serial.print("old ssid2_mem was: ");
  2076.       Serial.println(ssid2_mem);
  2077.       preferences.putString("ssid2", ssid2);
  2078.       Serial.print("new ssid2 save is: ");
  2079.       Serial.println(ssid2);
  2080.       change_count++;
  2081.     }
  2082.     if (password != password_mem) {
  2083.       Serial.print("old password_mem was: ");
  2084.       Serial.println(password_mem);
  2085.       preferences.putString("password", password);
  2086.       Serial.print("new password save is: ");
  2087.       Serial.println(password);
  2088.       change_count++;
  2089.     }
  2090.     if (password2 != password2_mem) {
  2091.       Serial.print("old password2_mem was: ");
  2092.       Serial.println(password2_mem);
  2093.       preferences.putString("password2", password2);
  2094.       Serial.print("new password2 save is: ");
  2095.       Serial.println(password2);
  2096.       change_count++;
  2097.     }
  2098.     if (mySleeptime != mySleeptime_mem) {
  2099.       Serial.print("old mySleeptime_mem was: ");
  2100.       Serial.println(mySleeptime_mem);
  2101.       preferences.putInt("mySleeptime", mySleeptime);
  2102.       Serial.print("new mySleeptime save is: ");
  2103.       Serial.println(mySleeptime);
  2104.       change_count++;
  2105.     }
  2106.     if (myTimeZone != myTimeZone_mem) {
  2107.       Serial.print("old myTimeZone_mem was: ");
  2108.       Serial.println(myTimeZone_mem);
  2109.       preferences.putInt("myTimeZone", myTimeZone);
  2110.       Serial.print("new myTimeZone save is: ");
  2111.       Serial.println(myTimeZone);
  2112.       change_count++;
  2113.     }
  2114.     if (myTempUnit != myTempUnit_mem) {
  2115.       Serial.print("old myTempUnit_mem was: ");
  2116.       Serial.println(myTempUnit_mem);
  2117.       preferences.putInt("myTempUnit", myTempUnit);
  2118.       Serial.print("new myTempUnit save is: ");
  2119.       Serial.println(myTempUnit);
  2120.       change_count++;
  2121.     }
  2122.     if (myTempOffset != myTempOffset_mem) {
  2123.       Serial.print("old myTempOffset_mem was: ");
  2124.       Serial.println(myTempOffset_mem);
  2125.       preferences.putInt("myTempOffset", myTempOffset);
  2126.       Serial.print("new myTempOffset save is: ");
  2127.       Serial.println(myTempOffset);
  2128.       change_count++;
  2129.     }
  2130.     if (myCyclingIntervall != myCyclingIntervall_mem) {
  2131.       Serial.print("old myCyclingIntervall_mem was: ");
  2132.       Serial.println(myCyclingIntervall_mem);
  2133.       preferences.putInt("myCyclingIntervall", myCyclingIntervall);
  2134.       Serial.print("new myCyclingIntervall save is: ");
  2135.       Serial.println(myCyclingIntervall);
  2136.       change_count++;
  2137.     }
  2138.     if (myLanguage != myLanguage_mem) {
  2139.       Serial.print("old myLanguage_mem was: ");
  2140.       Serial.println(myLanguage_mem);
  2141.       preferences.putInt("myLanguage", myLanguage);
  2142.       Serial.print("new myLanguage save is: ");
  2143.       Serial.println(myLanguage);
  2144.       change_count++;
  2145.     }
  2146.     if (pairs != pairs_mem) {
  2147.       Serial.print("old pairs_mem was: ");
  2148.       Serial.println(pairs_mem);
  2149.       preferences.putInt("pairs", pairs);
  2150.       Serial.print("new pairs save is: ");
  2151.       Serial.println(pairs);
  2152.       change_count++;
  2153.     }
  2154.     if (pair_name[0] != pair_name_mem[0]) {  //pair name for top bar
  2155.       Serial.print("old pair_name01_mem was: ");
  2156.       Serial.println(pair_name_mem[0]);
  2157.       preferences.putString("pair_name01", pair_name[0]);
  2158.       Serial.print("new pair_name01 save is: ");
  2159.       Serial.println(pair_name[0]);
  2160.       change_count++;
  2161.     }
  2162.     if (pair_name[1] != pair_name_mem[1]) {
  2163.       Serial.print("old pair_name02_mem was: ");
  2164.       Serial.println(pair_name_mem[1]);
  2165.       preferences.putString("pair_name02", pair_name[1]);
  2166.       Serial.print("new pair_name02 save is: ");
  2167.       Serial.println(pair_name[1]);
  2168.       change_count++;
  2169.     }
  2170.     if (pair_name[2] != pair_name_mem[2]) {
  2171.       Serial.print("old pair_name03_mem was: ");
  2172.       Serial.println(pair_name_mem[2]);
  2173.       preferences.putString("pair_name03", pair_name[2]);
  2174.       Serial.print("new pair_name03 save is: ");
  2175.       Serial.println(pair_name[2]);
  2176.       change_count++;
  2177.     }
  2178.     if (pair_name[3] != pair_name_mem[3]) {
  2179.       Serial.print("old pair_name04_mem was: ");
  2180.       Serial.println(pair_name_mem[3]);
  2181.       preferences.putString("pair_name04", pair_name[3]);
  2182.       Serial.print("new pair_name04 save is: ");
  2183.       Serial.println(pair_name[3]);
  2184.       change_count++;
  2185.     }
  2186.     if (pair_name[4] != pair_name_mem[4]) {
  2187.       Serial.print("old pair_name05_mem was: ");
  2188.       Serial.println(pair_name_mem[4]);
  2189.       preferences.putString("pair_name05", pair_name[4]);
  2190.       Serial.print("new pair_name05 save is: ");
  2191.       Serial.println(pair_name[4]);
  2192.       change_count++;
  2193.     }
  2194.     if (pair_name[5] != pair_name_mem[5]) {
  2195.       Serial.print("old pair_name06_mem was: ");
  2196.       Serial.println(pair_name_mem[5]);
  2197.       preferences.putString("pair_name06", pair_name[5]);
  2198.       Serial.print("new pair_name06 save is: ");
  2199.       Serial.println(pair_name[5]);
  2200.       change_count++;
  2201.     }
  2202.     if (pair_name[6] != pair_name_mem[6]) {
  2203.       Serial.print("old pair_name07_mem was: ");
  2204.       Serial.println(pair_name_mem[6]);
  2205.       preferences.putString("pair_name07", pair_name[6]);
  2206.       Serial.print("new pair_name07 save is: ");
  2207.       Serial.println(pair_name[6]);
  2208.       change_count++;
  2209.     }
  2210.     if (pair_name[7] != pair_name_mem[7]) {
  2211.       Serial.print("old pair_name08_mem was: ");
  2212.       Serial.println(pair_name_mem[7]);
  2213.       preferences.putString("pair_name08", pair_name[7]);
  2214.       Serial.print("new pair_name08 save is: ");
  2215.       Serial.println(pair_name[7]);
  2216.       change_count++;
  2217.     }
  2218.     if (pair_name[8] != pair_name_mem[8]) {
  2219.       Serial.print("old pair_name09_mem was: ");
  2220.       Serial.println(pair_name_mem[8]);
  2221.       preferences.putString("pair_name09", pair_name[8]);
  2222.       Serial.print("new pair_name09 save is: ");
  2223.       Serial.println(pair_name[8]);
  2224.       change_count++;
  2225.     }
  2226.     if (pair_name[9] != pair_name_mem[9]) {
  2227.       Serial.print("old pair_name10_mem was: ");
  2228.       Serial.println(pair_name_mem[9]);
  2229.       preferences.putString("pair_name10", pair_name[9]);
  2230.       Serial.print("new pair_name10 save is: ");
  2231.       Serial.println(pair_name[9]);
  2232.       change_count++;
  2233.     }
  2234.     if (pair_name[10] != pair_name_mem[10]) {
  2235.       Serial.print("old pair_name11_mem was: ");
  2236.       Serial.println(pair_name_mem[10]);
  2237.       preferences.putString("pair_name11", pair_name[10]);
  2238.       Serial.print("new pair_name11 save is: ");
  2239.       Serial.println(pair_name[10]);
  2240.       change_count++;
  2241.     }
  2242.     if (pair_name[11] != pair_name_mem[11]) {
  2243.       Serial.print("old pair_name12_mem was: ");
  2244.       Serial.println(pair_name_mem[11]);
  2245.       preferences.putString("pair_name12", pair_name[11]);
  2246.       Serial.print("new pair_name12 save is: ");
  2247.       Serial.println(pair_name[11]);
  2248.       change_count++;
  2249.     }
  2250.     if (pair_name[12] != pair_name_mem[12]) {
  2251.       Serial.print("old pair_name13_mem was: ");
  2252.       Serial.println(pair_name_mem[12]);
  2253.       preferences.putString("pair_name13", pair_name[12]);
  2254.       Serial.print("new pair_name13 save is: ");
  2255.       Serial.println(pair_name[12]);
  2256.       change_count++;
  2257.     }
  2258.     if (pair_name[13] != pair_name_mem[13]) {
  2259.       Serial.print("old pair_name14_mem was: ");
  2260.       Serial.println(pair_name_mem[13]);
  2261.       preferences.putString("pair_name14", pair_name[13]);
  2262.       Serial.print("new pair_name14 save is: ");
  2263.       Serial.println(pair_name[13]);
  2264.       change_count++;
  2265.     }
  2266.     if (pair_name[14] != pair_name_mem[14]) {
  2267.       Serial.print("old pair_name15_mem was: ");
  2268.       Serial.println(pair_name_mem[14]);
  2269.       preferences.putString("pair_name15", pair_name[14]);
  2270.       Serial.print("new pair_name15 save is: ");
  2271.       Serial.println(pair_name[14]);
  2272.       change_count++;
  2273.     }
  2274.     if (pair_name[15] != pair_name_mem[15]) {
  2275.       Serial.print("old pair_name16_mem was: ");
  2276.       Serial.println(pair_name_mem[15]);
  2277.       preferences.putString("pair_name16", pair_name[15]);
  2278.       Serial.print("new pair_name16 save is: ");
  2279.       Serial.println(pair_name[15]);
  2280.       change_count++;
  2281.     }
  2282.     if (pair_name[16] != pair_name_mem[16]) {
  2283.       Serial.print("old pair_name17_mem was: ");
  2284.       Serial.println(pair_name_mem[16]);
  2285.       preferences.putString("pair_name17", pair_name[16]);
  2286.       Serial.print("new pair_name17 save is: ");
  2287.       Serial.println(pair_name[16]);
  2288.       change_count++;
  2289.     }
  2290.     if (pair_name[17] != pair_name_mem[17]) {
  2291.       Serial.print("old pair_name18_mem was: ");
  2292.       Serial.println(pair_name_mem[17]);
  2293.       preferences.putString("pair_name18", pair_name[17]);
  2294.       Serial.print("new pair_name18 save is: ");
  2295.       Serial.println(pair_name[17]);
  2296.       change_count++;
  2297.     }
  2298.     if (pair_name[18] != pair_name_mem[18]) {
  2299.       Serial.print("old pair_name19_mem was: ");
  2300.       Serial.println(pair_name_mem[18]);
  2301.       preferences.putString("pair_name19", pair_name[18]);
  2302.       Serial.print("new pair_name19 save is: ");
  2303.       Serial.println(pair_name[18]);
  2304.       change_count++;
  2305.     }
  2306.     if (pair_name[19] != pair_name_mem[19]) {
  2307.       Serial.print("old pair_name20_mem was: ");
  2308.       Serial.println(pair_name_mem[19]);
  2309.       preferences.putString("pair_name20", pair_name[19]);
  2310.       Serial.print("new pair_name20 save is: ");
  2311.       Serial.println(pair_name[19]);
  2312.       change_count++;
  2313.     }
  2314.     if (pair_name[20] != pair_name_mem[20]) {
  2315.       Serial.print("old pair_name21_mem was: ");
  2316.       Serial.println(pair_name_mem[20]);
  2317.       preferences.putString("pair_name21", pair_name[20]);
  2318.       Serial.print("new pair_name21 save is: ");
  2319.       Serial.println(pair_name[20]);
  2320.       change_count++;
  2321.     }
  2322.     if (pair_name[21] != pair_name_mem[21]) {
  2323.       Serial.print("old pair_name22_mem was: ");
  2324.       Serial.println(pair_name_mem[21]);
  2325.       preferences.putString("pair_name22", pair_name[21]);
  2326.       Serial.print("new pair_name22 save is: ");
  2327.       Serial.println(pair_name[21]);
  2328.       change_count++;
  2329.     }
  2330.     if (pair_name[22] != pair_name_mem[22]) {
  2331.       Serial.print("old pair_name23_mem was: ");
  2332.       Serial.println(pair_name_mem[22]);
  2333.       preferences.putString("pair_name23", pair_name[22]);
  2334.       Serial.print("new pair_name23 save is: ");
  2335.       Serial.println(pair_name[22]);
  2336.       change_count++;
  2337.     }
  2338.     if (pair_name[23] != pair_name_mem[23]) {
  2339.       Serial.print("old pair_name24_mem was: ");
  2340.       Serial.println(pair_name_mem[23]);
  2341.       preferences.putString("pair_name24", pair_name[23]);
  2342.       Serial.print("new pair_name24 save is: ");
  2343.       Serial.println(pair_name[23]);
  2344.       change_count++;
  2345.     }
  2346.     if (pair_name[24] != pair_name_mem[24]) {
  2347.       Serial.print("old pair_name25_mem was: ");
  2348.       Serial.println(pair_name_mem[24]);
  2349.       preferences.putString("pair_name25", pair_name[24]);
  2350.       Serial.print("new pair_name25 save is: ");
  2351.       Serial.println(pair_name[24]);
  2352.       change_count++;
  2353.     }
  2354.     if (pair_STRING[0] != pair_STRING_mem[0]) {  //pair STRING in capitals for the binance api url
  2355.       Serial.print("old pair_STRING01_mem was: ");
  2356.       Serial.println(pair_STRING_mem[0]);
  2357.       preferences.putString("pair_STRING01", pair_STRING[0]);
  2358.       Serial.print("new pair_STRING01 save is: ");
  2359.       Serial.println(pair_STRING[0]);
  2360.       change_count++;
  2361.     }
  2362.     if (pair_STRING[1] != pair_STRING_mem[1]) {
  2363.       Serial.print("old pair_STRING02_mem was: ");
  2364.       Serial.println(pair_STRING_mem[1]);
  2365.       preferences.putString("pair_STRING02", pair_STRING[1]);
  2366.       Serial.print("new pair_STRING02 save is: ");
  2367.       Serial.println(pair_STRING[1]);
  2368.       change_count++;
  2369.     }
  2370.     if (pair_STRING[2] != pair_STRING_mem[2]) {
  2371.       Serial.print("old pair_STRING03_mem was: ");
  2372.       Serial.println(pair_STRING_mem[2]);
  2373.       preferences.putString("pair_STRING03", pair_STRING[2]);
  2374.       Serial.print("new pair_STRING03 save is: ");
  2375.       Serial.println(pair_STRING[2]);
  2376.       change_count++;
  2377.     }
  2378.     if (pair_STRING[3] != pair_STRING_mem[3]) {
  2379.       Serial.print("old pair_STRING04_mem was: ");
  2380.       Serial.println(pair_STRING_mem[3]);
  2381.       preferences.putString("pair_STRING04", pair_STRING[3]);
  2382.       Serial.print("new pair_STRING04 save is: ");
  2383.       Serial.println(pair_STRING[3]);
  2384.       change_count++;
  2385.     }
  2386.     if (pair_STRING[4] != pair_STRING_mem[4]) {
  2387.       Serial.print("old pair_STRING05_mem was: ");
  2388.       Serial.println(pair_STRING_mem[4]);
  2389.       preferences.putString("pair_STRING05", pair_STRING[4]);
  2390.       Serial.print("new pair_STRING05 save is: ");
  2391.       Serial.println(pair_STRING[4]);
  2392.       change_count++;
  2393.     }
  2394.     if (pair_STRING[5] != pair_STRING_mem[5]) {
  2395.       Serial.print("old pair_STRING06_mem was: ");
  2396.       Serial.println(pair_STRING_mem[5]);
  2397.       preferences.putString("pair_STRING06", pair_STRING[5]);
  2398.       Serial.print("new pair_STRING06 save is: ");
  2399.       Serial.println(pair_STRING[5]);
  2400.       change_count++;
  2401.     }
  2402.     if (pair_STRING[6] != pair_STRING_mem[6]) {
  2403.       Serial.print("old pair_STRING07_mem was: ");
  2404.       Serial.println(pair_STRING_mem[6]);
  2405.       preferences.putString("pair_STRING07", pair_STRING[6]);
  2406.       Serial.print("new pair_STRING07 save is: ");
  2407.       Serial.println(pair_STRING[6]);
  2408.       change_count++;
  2409.     }
  2410.     if (pair_STRING[7] != pair_STRING_mem[7]) {
  2411.       Serial.print("old pair_STRING08_mem was: ");
  2412.       Serial.println(pair_STRING_mem[7]);
  2413.       preferences.putString("pair_STRING08", pair_STRING[7]);
  2414.       Serial.print("new pair_STRING08 save is: ");
  2415.       Serial.println(pair_STRING[7]);
  2416.       change_count++;
  2417.     }
  2418.     if (pair_STRING[8] != pair_STRING_mem[8]) {
  2419.       Serial.print("old pair_STRING09_mem was: ");
  2420.       Serial.println(pair_STRING_mem[8]);
  2421.       preferences.putString("pair_STRING09", pair_STRING[8]);
  2422.       Serial.print("new pair_STRING09 save is: ");
  2423.       Serial.println(pair_STRING[8]);
  2424.       change_count++;
  2425.     }
  2426.     if (pair_STRING[9] != pair_STRING_mem[9]) {
  2427.       Serial.print("old pair_STRING10_mem was: ");
  2428.       Serial.println(pair_STRING_mem[9]);
  2429.       preferences.putString("pair_STRING10", pair_STRING[9]);
  2430.       Serial.print("new pair_STRING10 save is: ");
  2431.       Serial.println(pair_STRING[9]);
  2432.       change_count++;
  2433.     }
  2434.     if (pair_STRING[10] != pair_STRING_mem[10]) {
  2435.       Serial.print("old pair_STRING11_mem was: ");
  2436.       Serial.println(pair_STRING_mem[10]);
  2437.       preferences.putString("pair_STRING11", pair_STRING[10]);
  2438.       Serial.print("new pair_STRING11 save is: ");
  2439.       Serial.println(pair_STRING[10]);
  2440.       change_count++;
  2441.     }
  2442.     if (pair_STRING[11] != pair_STRING_mem[11]) {
  2443.       Serial.print("old pair_STRING12_mem was: ");
  2444.       Serial.println(pair_STRING_mem[11]);
  2445.       preferences.putString("pair_STRING12", pair_STRING[11]);
  2446.       Serial.print("new pair_STRING12 save is: ");
  2447.       Serial.println(pair_STRING[11]);
  2448.       change_count++;
  2449.     }
  2450.     if (pair_STRING[12] != pair_STRING_mem[12]) {
  2451.       Serial.print("old pair_STRING13_mem was: ");
  2452.       Serial.println(pair_STRING_mem[12]);
  2453.       preferences.putString("pair_STRING13", pair_STRING[12]);
  2454.       Serial.print("new pair_STRING13 save is: ");
  2455.       Serial.println(pair_STRING[12]);
  2456.       change_count++;
  2457.     }
  2458.     if (pair_STRING[13] != pair_STRING_mem[13]) {
  2459.       Serial.print("old pair_STRING14_mem was: ");
  2460.       Serial.println(pair_STRING_mem[13]);
  2461.       preferences.putString("pair_STRING14", pair_STRING[13]);
  2462.       Serial.print("new pair_STRING14 save is: ");
  2463.       Serial.println(pair_STRING[13]);
  2464.       change_count++;
  2465.     }
  2466.     if (pair_STRING[14] != pair_STRING_mem[14]) {
  2467.       Serial.print("old pair_STRING15_mem was: ");
  2468.       Serial.println(pair_STRING_mem[14]);
  2469.       preferences.putString("pair_STRING15", pair_STRING[14]);
  2470.       Serial.print("new pair_STRING15 save is: ");
  2471.       Serial.println(pair_STRING[14]);
  2472.       change_count++;
  2473.     }
  2474.     if (pair_STRING[15] != pair_STRING_mem[15]) {
  2475.       Serial.print("old pair_STRING16_mem was: ");
  2476.       Serial.println(pair_STRING_mem[15]);
  2477.       preferences.putString("pair_STRING16", pair_STRING[15]);
  2478.       Serial.print("new pair_STRING16 save is: ");
  2479.       Serial.println(pair_STRING[15]);
  2480.       change_count++;
  2481.     }
  2482.     if (pair_STRING[16] != pair_STRING_mem[16]) {
  2483.       Serial.print("old pair_STRING17_mem was: ");
  2484.       Serial.println(pair_STRING_mem[16]);
  2485.       preferences.putString("pair_STRING17", pair_STRING[16]);
  2486.       Serial.print("new pair_STRING17 save is: ");
  2487.       Serial.println(pair_STRING[16]);
  2488.       change_count++;
  2489.     }
  2490.     if (pair_STRING[17] != pair_STRING_mem[17]) {
  2491.       Serial.print("old pair_STRING18_mem was: ");
  2492.       Serial.println(pair_STRING_mem[17]);
  2493.       preferences.putString("pair_STRING18", pair_STRING[17]);
  2494.       Serial.print("new pair_STRING18 save is: ");
  2495.       Serial.println(pair_STRING[17]);
  2496.       change_count++;
  2497.     }
  2498.     if (pair_STRING[18] != pair_STRING_mem[18]) {
  2499.       Serial.print("old pair_STRING19_mem was: ");
  2500.       Serial.println(pair_STRING_mem[18]);
  2501.       preferences.putString("pair_STRING19", pair_STRING[18]);
  2502.       Serial.print("new pair_STRING19 save is: ");
  2503.       Serial.println(pair_STRING[18]);
  2504.       change_count++;
  2505.     }
  2506.     if (pair_STRING[19] != pair_STRING_mem[19]) {
  2507.       Serial.print("old pair_STRING20_mem was: ");
  2508.       Serial.println(pair_STRING_mem[19]);
  2509.       preferences.putString("pair_STRING20", pair_STRING[19]);
  2510.       Serial.print("new pair_STRING20 save is: ");
  2511.       Serial.println(pair_STRING[19]);
  2512.       change_count++;
  2513.     }
  2514.     if (pair_STRING[20] != pair_STRING_mem[20]) {
  2515.       Serial.print("old pair_STRING21_mem was: ");
  2516.       Serial.println(pair_STRING_mem[20]);
  2517.       preferences.putString("pair_STRING21", pair_STRING[20]);
  2518.       Serial.print("new pair_STRING21 save is: ");
  2519.       Serial.println(pair_STRING[20]);
  2520.       change_count++;
  2521.     }
  2522.     if (pair_STRING[21] != pair_STRING_mem[21]) {
  2523.       Serial.print("old pair_STRING22_mem was: ");
  2524.       Serial.println(pair_STRING_mem[21]);
  2525.       preferences.putString("pair_STRING22", pair_STRING[21]);
  2526.       Serial.print("new pair_STRING22 save is: ");
  2527.       Serial.println(pair_STRING[21]);
  2528.       change_count++;
  2529.     }
  2530.     if (pair_STRING[22] != pair_STRING_mem[22]) {
  2531.       Serial.print("old pair_STRING23_mem was: ");
  2532.       Serial.println(pair_STRING_mem[22]);
  2533.       preferences.putString("pair_STRING23", pair_STRING[22]);
  2534.       Serial.print("new pair_STRING23 save is: ");
  2535.       Serial.println(pair_STRING[22]);
  2536.       change_count++;
  2537.     }
  2538.     if (pair_STRING[23] != pair_STRING_mem[23]) {
  2539.       Serial.print("old pair_STRING24_mem was: ");
  2540.       Serial.println(pair_STRING_mem[23]);
  2541.       preferences.putString("pair_STRING24", pair_STRING[23]);
  2542.       Serial.print("new pair_STRING24 save is: ");
  2543.       Serial.println(pair_STRING[23]);
  2544.       change_count++;
  2545.     }
  2546.     if (pair_STRING[24] != pair_STRING_mem[24]) {
  2547.       Serial.print("old pair_STRING25_mem was: ");
  2548.       Serial.println(pair_STRING_mem[24]);
  2549.       preferences.putString("pair_STRING25", pair_STRING[24]);
  2550.       Serial.print("new pair_STRING25 save is: ");
  2551.       Serial.println(pair_STRING[24]);
  2552.       change_count++;
  2553.     }
  2554.     if (pair_col_str[0] != pair_col_str_mem[0]) {  //pair color in hex for the names
  2555.       Serial.print("old pair_col_str01_mem was: ");
  2556.       Serial.println(pair_col_str_mem[0]);
  2557.       preferences.putString("pair_col_str01", pair_col_str[0]);
  2558.       Serial.print("new pair_col_str01 save is: ");
  2559.       Serial.println(pair_col_str[0]);
  2560.       change_count++;
  2561.     }
  2562.     if (pair_col_str[1] != pair_col_str_mem[1]) {
  2563.       Serial.print("old pair_col_str02_mem was: ");
  2564.       Serial.println(pair_col_str_mem[1]);
  2565.       preferences.putString("pair_col_str02", pair_col_str[1]);
  2566.       Serial.print("new pair_col_str02 save is: ");
  2567.       Serial.println(pair_col_str[1]);
  2568.       change_count++;
  2569.     }
  2570.     if (pair_col_str[2] != pair_col_str_mem[2]) {
  2571.       Serial.print("old pair_col_str03_mem was: ");
  2572.       Serial.println(pair_col_str_mem[2]);
  2573.       preferences.putString("pair_col_str03", pair_col_str[2]);
  2574.       Serial.print("new pair_col_str03 save is: ");
  2575.       Serial.println(pair_col_str[2]);
  2576.       change_count++;
  2577.     }
  2578.     if (pair_col_str[3] != pair_col_str_mem[3]) {
  2579.       Serial.print("old pair_col_str04_mem was: ");
  2580.       Serial.println(pair_col_str_mem[3]);
  2581.       preferences.putString("pair_col_str04", pair_col_str[3]);
  2582.       Serial.print("new pair_col_str04 save is: ");
  2583.       Serial.println(pair_col_str[3]);
  2584.       change_count++;
  2585.     }
  2586.     if (pair_col_str[4] != pair_col_str_mem[4]) {
  2587.       Serial.print("old pair_col_str05_mem was: ");
  2588.       Serial.println(pair_col_str_mem[4]);
  2589.       preferences.putString("pair_col_str05", pair_col_str[4]);
  2590.       Serial.print("new pair_col_str05 save is: ");
  2591.       Serial.println(pair_col_str[4]);
  2592.       change_count++;
  2593.     }
  2594.     if (pair_col_str[5] != pair_col_str_mem[5]) {
  2595.       Serial.print("old pair_col_str06_mem was: ");
  2596.       Serial.println(pair_col_str_mem[5]);
  2597.       preferences.putString("pair_col_str06", pair_col_str[5]);
  2598.       Serial.print("new pair_col_str06 save is: ");
  2599.       Serial.println(pair_col_str[5]);
  2600.       change_count++;
  2601.     }
  2602.     if (pair_col_str[6] != pair_col_str_mem[6]) {
  2603.       Serial.print("old pair_col_str07_mem was: ");
  2604.       Serial.println(pair_col_str_mem[6]);
  2605.       preferences.putString("pair_col_str07", pair_col_str[6]);
  2606.       Serial.print("new pair_col_str07 save is: ");
  2607.       Serial.println(pair_col_str[6]);
  2608.       change_count++;
  2609.     }
  2610.     if (pair_col_str[7] != pair_col_str_mem[7]) {
  2611.       Serial.print("old pair_col_str08_mem was: ");
  2612.       Serial.println(pair_col_str_mem[7]);
  2613.       preferences.putString("pair_col_str08", pair_col_str[7]);
  2614.       Serial.print("new pair_col_str08 save is: ");
  2615.       Serial.println(pair_col_str[7]);
  2616.       change_count++;
  2617.     }
  2618.     if (pair_col_str[8] != pair_col_str_mem[8]) {
  2619.       Serial.print("old pair_col_str09_mem was: ");
  2620.       Serial.println(pair_col_str_mem[8]);
  2621.       preferences.putString("pair_col_str09", pair_col_str[8]);
  2622.       Serial.print("new pair_col_str09 save is: ");
  2623.       Serial.println(pair_col_str[8]);
  2624.       change_count++;
  2625.     }
  2626.     if (pair_col_str[9] != pair_col_str_mem[9]) {
  2627.       Serial.print("old pair_col_str10_mem was: ");
  2628.       Serial.println(pair_col_str_mem[9]);
  2629.       preferences.putString("pair_col_str10", pair_col_str[9]);
  2630.       Serial.print("new pair_col_str10 save is: ");
  2631.       Serial.println(pair_col_str[9]);
  2632.       change_count++;
  2633.     }
  2634.     if (pair_col_str[10] != pair_col_str_mem[10]) {
  2635.       Serial.print("old pair_col_str11_mem was: ");
  2636.       Serial.println(pair_col_str_mem[10]);
  2637.       preferences.putString("pair_col_str11", pair_col_str[10]);
  2638.       Serial.print("new pair_col_str11 save is: ");
  2639.       Serial.println(pair_col_str[10]);
  2640.       change_count++;
  2641.     }
  2642.     if (pair_col_str[11] != pair_col_str_mem[11]) {
  2643.       Serial.print("old pair_col_str12_mem was: ");
  2644.       Serial.println(pair_col_str_mem[11]);
  2645.       preferences.putString("pair_col_str12", pair_col_str[11]);
  2646.       Serial.print("new pair_col_str12 save is: ");
  2647.       Serial.println(pair_col_str[11]);
  2648.       change_count++;
  2649.     }
  2650.     if (pair_col_str[12] != pair_col_str_mem[12]) {
  2651.       Serial.print("old pair_col_str13_mem was: ");
  2652.       Serial.println(pair_col_str_mem[12]);
  2653.       preferences.putString("pair_col_str13", pair_col_str[12]);
  2654.       Serial.print("new pair_col_str13 save is: ");
  2655.       Serial.println(pair_col_str[12]);
  2656.       change_count++;
  2657.     }
  2658.     if (pair_col_str[13] != pair_col_str_mem[13]) {
  2659.       Serial.print("old pair_col_str14_mem was: ");
  2660.       Serial.println(pair_col_str_mem[13]);
  2661.       preferences.putString("pair_col_str14", pair_col_str[13]);
  2662.       Serial.print("new pair_col_str14 save is: ");
  2663.       Serial.println(pair_col_str[13]);
  2664.       change_count++;
  2665.     }
  2666.     if (pair_col_str[14] != pair_col_str_mem[14]) {
  2667.       Serial.print("old pair_col_str15_mem was: ");
  2668.       Serial.println(pair_col_str_mem[14]);
  2669.       preferences.putString("pair_col_str15", pair_col_str[14]);
  2670.       Serial.print("new pair_col_str15 save is: ");
  2671.       Serial.println(pair_col_str[14]);
  2672.       change_count++;
  2673.     }
  2674.     if (pair_col_str[15] != pair_col_str_mem[15]) {
  2675.       Serial.print("old pair_col_str16_mem was: ");
  2676.       Serial.println(pair_col_str_mem[15]);
  2677.       preferences.putString("pair_col_str16", pair_col_str[15]);
  2678.       Serial.print("new pair_col_str16 save is: ");
  2679.       Serial.println(pair_col_str[15]);
  2680.       change_count++;
  2681.     }
  2682.     if (pair_col_str[16] != pair_col_str_mem[16]) {
  2683.       Serial.print("old pair_col_str17_mem was: ");
  2684.       Serial.println(pair_col_str_mem[16]);
  2685.       preferences.putString("pair_col_str17", pair_col_str[16]);
  2686.       Serial.print("new pair_col_str17 save is: ");
  2687.       Serial.println(pair_col_str[16]);
  2688.       change_count++;
  2689.     }
  2690.     if (pair_col_str[17] != pair_col_str_mem[17]) {
  2691.       Serial.print("old pair_col_str18_mem was: ");
  2692.       Serial.println(pair_col_str_mem[17]);
  2693.       preferences.putString("pair_col_str18", pair_col_str[17]);
  2694.       Serial.print("new pair_col_str18 save is: ");
  2695.       Serial.println(pair_col_str[17]);
  2696.       change_count++;
  2697.     }
  2698.     if (pair_col_str[18] != pair_col_str_mem[18]) {
  2699.       Serial.print("old pair_col_str19_mem was: ");
  2700.       Serial.println(pair_col_str_mem[18]);
  2701.       preferences.putString("pair_col_str19", pair_col_str[18]);
  2702.       Serial.print("new pair_col_str19 save is: ");
  2703.       Serial.println(pair_col_str[18]);
  2704.       change_count++;
  2705.     }
  2706.     if (pair_col_str[19] != pair_col_str_mem[19]) {
  2707.       Serial.print("old pair_col_str20_mem was: ");
  2708.       Serial.println(pair_col_str_mem[19]);
  2709.       preferences.putString("pair_col_str20", pair_col_str[19]);
  2710.       Serial.print("new pair_col_str20 save is: ");
  2711.       Serial.println(pair_col_str[19]);
  2712.       change_count++;
  2713.     }
  2714.     if (pair_col_str[20] != pair_col_str_mem[20]) {
  2715.       Serial.print("old pair_col_str21_mem was: ");
  2716.       Serial.println(pair_col_str_mem[20]);
  2717.       preferences.putString("pair_col_str21", pair_col_str[20]);
  2718.       Serial.print("new pair_col_str21 save is: ");
  2719.       Serial.println(pair_col_str[20]);
  2720.       change_count++;
  2721.     }
  2722.     if (pair_col_str[21] != pair_col_str_mem[21]) {
  2723.       Serial.print("old pair_col_str22_mem was: ");
  2724.       Serial.println(pair_col_str_mem[21]);
  2725.       preferences.putString("pair_col_str22", pair_col_str[21]);
  2726.       Serial.print("new pair_col_str22 save is: ");
  2727.       Serial.println(pair_col_str[21]);
  2728.       change_count++;
  2729.     }
  2730.     if (pair_col_str[22] != pair_col_str_mem[22]) {
  2731.       Serial.print("old pair_col_str23_mem was: ");
  2732.       Serial.println(pair_col_str_mem[22]);
  2733.       preferences.putString("pair_col_str23", pair_col_str[22]);
  2734.       Serial.print("new pair_col_str23 save is: ");
  2735.       Serial.println(pair_col_str[22]);
  2736.       change_count++;
  2737.     }
  2738.     if (pair_col_str[23] != pair_col_str_mem[23]) {
  2739.       Serial.print("old pair_col_str24_mem was: ");
  2740.       Serial.println(pair_col_str_mem[23]);
  2741.       preferences.putString("pair_col_str24", pair_col_str[23]);
  2742.       Serial.print("new pair_col_str24 save is: ");
  2743.       Serial.println(pair_col_str[23]);
  2744.       change_count++;
  2745.     }
  2746.     if (pair_col_str[24] != pair_col_str_mem[24]) {
  2747.       Serial.print("old pair_col_str25_mem was: ");
  2748.       Serial.println(pair_col_str_mem[24]);
  2749.       preferences.putString("pair_col_str25", pair_col_str[24]);
  2750.       Serial.print("new pair_col_str25 save is: ");
  2751.       Serial.println(pair_col_str[24]);
  2752.       change_count++;
  2753.     }
  2754.     if (change_count != 0) {
  2755.       M5.Lcd.setCursor(20, 60);
  2756.       M5.Lcd.printf("nupdated %i settings from SD", change_count);
  2757.       Serial.printf("updated %i settings from SD-Card", change_count);
  2758.       Serial.println();
  2759.       change_count = 0;
  2760.       delay(1750);
  2761.     }
  2762.   } else {  //when no SD-Card is loaded load last saved preferences from internal memory
  2763.     ssid = ssid_mem;
  2764.     ssid2 = ssid2_mem;
  2765.     password = password_mem;
  2766.     password2 = password2_mem;
  2767.     mySleeptime = mySleeptime_mem;
  2768.     myTimeZone = myTimeZone_mem;
  2769.     myLanguage = myLanguage_mem;
  2770.     myTempUnit = myTempUnit_mem;
  2771.     myTempOffset = myTempOffset_mem;
  2772.     myCyclingIntervall = myCyclingIntervall_mem;
  2773.     pairs = pairs_mem;
  2774.     for (int i = 0; i < pairs; i++) {
  2775.       pair_name[i] = pair_name_mem[i];
  2776.       pair_STRING[i] = pair_STRING_mem[i];
  2777.       pair_col_str[i] = pair_col_str_mem[i];
  2778.     }
  2779.   }
  2780.   //preferences.end();
  2781.  
  2782.   // Setting Language
  2783.   int arrsize_mn = sizeof(monthName_MyLang) / sizeof(int);
  2784.   int arrsize_wd = sizeof(weekDay_MyLang) / sizeof(int);
  2785.   if (myLanguage == 1) {  // select weekday and month names from different languages (selected by e.g.: "myLanguage=1" in Config file)
  2786.     for (int i = 0; i < arrsize_mn; i++) {
  2787.       monthName_MyLang[i] = monthName_Language1[i];
  2788.     }
  2789.     for (int i = 0; i < arrsize_wd; i++) {
  2790.       weekDay_MyLang[i] = weekDay_Language1[i];
  2791.     }
  2792.   } else if (myLanguage == 2) {
  2793.     for (int i = 0; i < arrsize_mn; i++) {
  2794.       monthName_MyLang[i] = monthName_Language2[i];
  2795.     }
  2796.     for (int i = 0; i < arrsize_wd; i++) {
  2797.       weekDay_MyLang[i] = weekDay_Language2[i];
  2798.     }
  2799.   }
  2800.   //  else if (myLanguage == 3) {              // ---> append here if you want to extend more languages for day and month names (Mo Tu We .. Jan Feb ..)
  2801.   //    for (int i = 0; i < arrsize_mn; i++) { //      3 would represent the "MyLanguage=value" from the config file (0=english, 1=german, 2=spanish, 3=up to you)
  2802.   //      monthName_MyLang[i] = monthName_Language3[i];
  2803.   //    }
  2804.   //    for (int i = 0; i < arrsize_wd; i++) {
  2805.   //      weekDay_MyLang[i] = weekDay_Language3[i];
  2806.   //    }
  2807.   //  }
  2808.   else {
  2809.     for (int i = 0; i < arrsize_mn; i++) {
  2810.       monthName_MyLang[i] = monthName_Language0[i];
  2811.     }
  2812.     for (int i = 0; i < arrsize_wd; i++) {
  2813.       weekDay_MyLang[i] = weekDay_Language0[i];
  2814.     }
  2815.   }
  2816.  
  2817.   // make a copy of the pair names in LowerCase for the binance api url
  2818.   for (int i = 0; i < pairs; i++) {
  2819.     pair_string[i] = pair_STRING[i];
  2820.     pair_string[i].toLowerCase();
  2821.     //    Serial.print("LowerCase pair_string"); Serial.print(i + 1); Serial.print(": "); Serial.println(pair_string[i]);   //debug
  2822.   }
  2823.  
  2824.   // change pair_colors from sd-cfg file from string to uint16_t for M5.Lcd
  2825.   for (int i = 0; i < pairs; i++) {
  2826.     //    Serial.print("String color code"); Serial.print(i + 1); Serial.print(": "); Serial.println(pair_col_str[i]);    //debug
  2827.     rgb565_pair_color[i] = strtol(pair_col_str[i].c_str(), NULL, 0);
  2828.     //    Serial.print("RGB565 color code"); Serial.print(i + 1); Serial.print(": "); Serial.println(rgb565_pair_color[i], HEX);    //debug
  2829.   }
  2830.  
  2831.   //prevents loading a coinpair number from flash that is higher than the default max pairs value when no SD config file is loaded
  2832.   if (last_stored_Currency > pairs) {
  2833.     last_stored_Currency = 1;
  2834.   }
  2835.  
  2836.   //finally use the settings
  2837.   last_stored_Brightness_value = preferences.getUInt("bright", 22);
  2838.   last_stored_Brightness_level = preferences.getUInt("briglv", 2);
  2839.   last_stored_Currency = preferences.getUInt("currency", 1);
  2840.   last_stored_Timeframe = preferences.getUInt("timeframe", 4);
  2841.   Brightness_value = last_stored_Brightness_value;
  2842.   Brightness_level = last_stored_Brightness_level;
  2843.   current_Currency = last_stored_Currency;
  2844.   current_Timeframe = last_stored_Timeframe;
  2845.   strname_api = pair_STRING[current_Currency - 1];
  2846.   strname_ws = pair_string[current_Currency - 1];
  2847.   strname_currency = pair_name[current_Currency - 1];
  2848.   strname_color = rgb565_pair_color[current_Currency - 1];
  2849. }
  2850.  
  2851.  
  2852.  
  2853. // colorWipe (the leds flash up sequentially, very fast, in one color)
  2854. void colorWipe(uint32_t color, int wait) {
  2855.   for (int i = 0; i < LEDbar.numPixels(); i++) {  // For each pixel in LEDbar...
  2856.     LEDbar.setPixelColor(i, color);               // Set pixel's color (in RAM)
  2857.     LEDbar.show();                                // Update LEDbar to match
  2858.     delay(wait);                                  // Pause for a moment
  2859.   }
  2860. }
  2861.  
  2862.  
  2863.  
  2864. // Rainbow cycle along whole LEDbar. Pass delay time (in ms) between frames.
  2865. void rainbow_effect(int wait) {
  2866.   // Hue of first pixel runs 1* complete loops through the color wheel.  *modified from 5
  2867.   // Color wheel has a range of 65536 but it's OK if we roll over, so
  2868.   // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  2869.   // means we'll make 5*65536/256 = 1280 passes through this outer loop:
  2870.   for (long firstPixelHue = 0; firstPixelHue < 1 * 65536; firstPixelHue += 256) {
  2871.     for (int i = 0; i < LEDbar.numPixels(); i++) {  // For each pixel in LEDbar...
  2872.       // Offset pixel hue by an amount to make one full revolution of the
  2873.       // color wheel (range of 65536) along the length of the LEDbar
  2874.       // (LEDbar.numPixels() steps):
  2875.       int pixelHue = firstPixelHue + (i * 65536L / LEDbar.numPixels());
  2876.       // LEDbar.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
  2877.       // optionally add saturation and value (brightness) (each 0 to 255).
  2878.       // Here we're using just the single-argument hue variant. The result
  2879.       // is passed through LEDbar.gamma32() to provide 'truer' colors
  2880.       // before assigning to each pixel:
  2881.       LEDbar.setPixelColor(i, LEDbar.gamma32(LEDbar.ColorHSV(pixelHue)));
  2882.     }
  2883.     LEDbar.show();  // Update LED-bar with new contents
  2884.     delay(wait);    // Pause for a moment
  2885.   }
  2886. }
  2887.  
  2888.  
  2889. // ## LED functions - for details see: https://github.com/adafruit/Adafruit_NeoPixel
  2890. // Fill LEDbar pixels one after another with a color. LEDbar is NOT cleared
  2891. // first; anything there will be covered pixel by pixel. Pass in color
  2892. // (as a single 'packed' 32-bit value, which you can get by calling
  2893. // LEDbar.Color(red, green, blue) as shown in the loop() function above),
  2894. // and a delay time (in milliseconds) between pixels.
  2895.  
  2896.  
  2897. void drawSensorValues() {  //only if you have it in the grey vertical base stand with SHT30 Sensor)
  2898.   if (sensorPanel != 0) {
  2899.     if (sht30.get() == 0) {
  2900.       tmpC = sht30.cTemp;  //sensor value in degree celsius
  2901.       hum = sht30.humidity;
  2902.       M5.Lcd.fillRect(108, topPanel, 212, sensorPanel, TFT_BLACK);
  2903.       M5.Lcd.setCursor(112, topPanel + sensorPanel - 3);
  2904.       M5.Lcd.setFreeFont(FM9);
  2905.       M5.Lcd.setTextSize(1);
  2906.       M5.Lcd.setTextColor(TFT_LIGHTGREY);
  2907.       if (myTempUnit == 1) {                                                 // if sd-config reads myTempUnit=1 use Fahrenheit, otherwise use Celsius instead
  2908.         tmpF = (tmpC * 1.8) + 32;                                            //formula to convert C to F -->    98,6 °F = (37 °C × 9/5) + 32
  2909.         M5.Lcd.printf("Tmp:%3.1fF  Hum:%2.0f%%", tmpF + myTempOffset, hum);  //show in Fahrenheit , 3 digits + 1 decimal
  2910.       } else
  2911.         M5.Lcd.printf("Temp:%2.1fC  Hum:%2.0f%%", tmpC + myTempOffset, hum);  //show in Celsius    , 2 digits + 1 decimal
  2912.     }
  2913.     if (sht30.get() != 0) {
  2914.       M5.Lcd.fillRect(108, topPanel, 212, sensorPanel, TFT_BLACK);
  2915.       M5.Lcd.setCursor(112, topPanel + sensorPanel - 3);
  2916.       M5.Lcd.setFreeFont(FM9);
  2917.       M5.Lcd.setTextSize(1);
  2918.       M5.Lcd.setTextColor(TFT_DARKGREY);
  2919.       M5.Lcd.printf(" no sensor values");
  2920.     }
  2921.   }
  2922. }
  2923.  
  2924. // ##END##
  2925.