====== Měření napětí pomocí ADC ====== |**Project owner:**| [[user:Cyberian]] | |**Interested:** | ... | |**Related:**| | | **License:** | [[https://creativecommons.org/licenses/by-sa/3.0/|Uveďte původ-Zachovejte licenci CC BY-SA]] | ===== Úvod ===== Tento projekt vznikl po problémech s pojízdnou plošinou, na které sedí děti, plošina má dvě kamery a ty sledují černou izolační pásku nalepenou na zemi. Pokud díte zmačkne a drží tlačítko, plošina jede po černě vyznačené cestě, dokud se tlačítko neuvolní. Problém nástaval v momentu kdy nám obsluha jezdila i na vybité baterie i přes zvukovou signalizaci. Sice by šla nainstalovat nějaká ochrana baterií, ale proč to řešit tak jednoduše :-), jde mi o to najít člověka, který to dělá a zničil již dva bateriové packy. Napadlo mne tedy využít k měření ESP8266, které u nás v Labce někteří používají, měřit na baterii napětí a pravidelně ho posílat přes wifi spojení na server do grafany. Ideální příležitost, jak se naučit s ESP na něčem reálném. Část, kde bude řešena Grafana a nezbytné služby a protokoly bude v samostatném projektu {{:project:flag-cze.png}} [[:project:esp8266_adc_grafana|Grafana a data z ADC]] **Materiál:** * ESP8266 (Nodemcu nebo např. Wemos mini D1) * 5x rezistor 10K * OLED-091 diymore 128×32 I2C dispej * nepájivé kontaktní pole, případně pájitelné * baterii 12V, nebo ideálně zdroj napětí 15V ===== Interní AD převodník ESP8266 ===== ESP8266 má interní 10 bitový AD převodník. Jeho vstup je na pinu A0 a dá se číst pomocí funkce analogRead(0). Vstupní napětí, které je schopen měřit je od 0 V do 3,3 V. Baterie jsou sice 2x 12 V v sérii, ale bude stačit měřit jen jednu. Pro měření napětí od 0 do 15V, což je pro mne maximální předpokládané napětí na baterii použijeme dělič napětí v poměru 10K ku 40K. Pokud by si někdo chtěl spočítat bez práce vlastní, pak může využít [[http://www.ti.com/download/kbase/volt/volt_div3.htm|Webový kalkulátor]] (díky Ivane za link :-)). K internímu převodníku je dobré poznamenat, že má dva módy. Jeden pro měření napětí 3,3 V přicházejícího do ESP8266, který se nastavuje zavoláním ADC_MODE(ADC_VCC); a jeden pro externí měření na pinu A0. Tento pin má někdy označení i jako TOUT. Rozsah hodnot převodníku 0 až 1024 namapujeme na rozsah napětí 0 až 15 V pomocí funkce map. Při měření multimetrem se zjistilo, že AD převodník není přesný, jak by měl být. Byla tam odchylka cca 6%, což je hodně. Jednoduše se zvětšil interval(rozsah) hodnot ve funkci map. Funkce map je velmi šikovná, udělá spread hodnot z jednoho rozsahu hodnot na jiný rozsah. Zvláštní je, že podle různých zkušeností ostatních lidí se interní AD převodníky různých ESP8266 pletou o téměř stejnou hodnotu. Nepřesnost převoníku má být cca 1%. Viz následující kód: int adcread=(analogRead(0)); float napeti= (float)(map(adcread, 0, 1024, 0, 16055))/1000; //adcread je int, měřená hodnota je v mV Za zmíňku stojí část dokumentace k ADC od Espresiffu, kde se zmiňují o 107. bytu z počátku romky, kterým by se měl AD převodník dokalibrovat. Otázkou je zda to pomůže a tohle se musí ještě ozkoušet. Na ukázku uvedu citaci z dokumentace: **esp_init_data_default.bin** is provided in SDK package which contains RF initialization parameters (0 ~ 127 bytes). The name of the 107th byte in esp_init_data_default.bin is vdd33_const, which is defined as below: * When vdd33_const = 0xff, the power voltage of Pin3 and Pin4 will be tested by the internal self-calibration process of ESP8266EX itself. RF circuit conditions should be optimized according to the testing results. * When 18 =< vdd33_const =< 36, ESP8266EX RF Calibration and optimization process is implemented via (vdd33_const/10). * When vdd33_const < 18 or 36 < vdd33_const < 255, vdd33_const is invalid. ESP8266EX RF Calibration and optimization process is implemented via the default value 3.3V ---- ===== Zapojení obvodu ===== Jen drobnou poznámku. Pull up odpory pro displej mají chybku. Oba přivádějí pull up napájení 3.3 V jen na pin D2. Přehoďte si jeden znich tak, aby přiváděl pull up napájení na pin D1, kde chybí. Správně jsou vidět na předchozím projektu se zapojením OLED displeje. {{ :project:esp8266_adc_web.jpg?400 |}} ===== Kód programu ===== Zde je prozatimní kód, který pouze ukazuje na displeji přidělenou IP adresu a naměřené napětí, na displej i do sériové konzole. Je potřeba nastavit si SSID wifi sítě. {{ :project:esp8266_adc01.jpg?nolink |}} // ADC_MODE(ADC_VCC); <--- tento kód by se použil na přepnutí módu z externího měření na interní měření napájení, čte pak však jinou funkcí #include #include #include #include // sekce pro displej #define SCREEN_WIDTH 128 // OLED display width, in pixels #define SCREEN_HEIGHT 32 // OLED display height, in pixels #define OLED_RESET -1 // Reset pin # (or -1 if sharing Arduino reset pin) Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET); // použít PROGMEM makro je důležité proto, aby se tato proměnná zapsala do ROM a nikoliv do velmi omezené RAM // stejně tak funguje funkce F() static const unsigned char PROGMEM zoja [] = { 0x20,0x0,0x0,0x20, 0x70,0x0,0x0,0x70, 0x50,0x0,0x0,0x50, 0xd8,0x0,0x0,0xd8, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x1,0xc0,0x0,0x0, 0x3,0x60,0x0,0x0, 0x2,0x20,0x78,0x0, 0x2,0x20,0x48,0x0, 0x2,0x20,0x48,0x0, 0x3,0x60,0x48,0x0, 0x1,0xc0,0x38,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x0,0x0,0x0,0x0, 0x1,0x0,0x8,0x0, 0x1,0x80,0x8,0x0, 0x0,0x88,0x98,0x0, 0x0,0xc5,0x10,0x0, 0x0,0x42,0x10,0x0, 0x0,0x65,0x30,0x0, 0x0,0x28,0xa0,0x0, 0x0,0x20,0x20,0x0 }; void setup() { Serial.begin(9600); Serial.println(F("Nastavuji piny pro I2C sběrnici...")); Wire.begin(); Serial.println(F("Inicializuji displej")); // SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { // Address 0x3C for 128x32 Serial.println(F("SSD1306 allocation failed")); for(;;); // prasecká nekonečná smyčka :-P } delay(2000); display.clearDisplay(); //Wifi sekce WiFi.begin("nejakeSSID", "nejakeheslo"); Serial.print(F("Verze jádra: ")); Serial.println(ESP.getCoreVersion()); // vypiš verzi ESP jádra Serial.print("Connecting"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println(); Serial.print("Connected, IP address: "); Serial.println(WiFi.localIP()); WiFi.printDiag(Serial); display.clearDisplay(); display.setTextSize(1); // Normal 1:1 pixel scale display.setTextColor(WHITE); // Draw white text display.setCursor(0,0); // Start at top-left corner display.print(F("IP: "));display.println(WiFi.localIP()); display.drawBitmap(98,0,zoja, 29, 32, 1); (x,y,pole, display.display(); } void loop() { int adcread=(analogRead(0)); float napeti= (float)(map(adcread, 0, 1024, 0, 16055))/1000; // adcread je int, hodnota je tedy v mV Serial.print(F("ADC A0: "));Serial.print(adcread);Serial.print(F(" DEC, ")); Serial.print(F("Napětí: "));Serial.print(napeti);Serial.println(F(" V")); display.setTextSize(1); display.setCursor(0,10); display.setTextColor(WHITE,BLACK); // pokud by bylo pouze WHITE, tak by se nepřepisovalo pozadí. Pozor Toto nefunguje u user fontů display.print(F("Napeti: "));display.print(napeti);display.println(F(" V")); display.display(); // vypis obsah bufferu na displej. Pokud není posláno, obraz se neaktualizuje delay(1000); } ===== Reference ===== - Dokumenty k ESP8266 od výrobce: https://www.espressif.com/en/support/download/documents?keys=esp8266 - Datasheet k ESP8266 v6.0: https://www.espressif.com/sites/default/files/documentation/0a-esp8266ex_datasheet_en.pdf