====== 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