ESP8266 и връзката му с околния свят, I2C накратко

Здравейте,

Ще се опитам накратко да обясня някои основни положения за връзката между микроконтролера с околния свят, с останалите периферни устройства.

Входове / изходи с логическо ниво

Някои от 17-те GPIO порта се използват служебно или имат специално предназначение (връзка с паметта, интерфейс за програмиране и т.н.). Ако на определени портове бъде подадено ниско или високо ниво, контролерът може да не се стартира, така че трябва да се чете и внимава.

НадписПортВходИзходКоментар
D0GPIO16няма прекъсване Няма ШИМ и I2CИма високо ниво при стартиране. Използва се за събуждане от Deep sleep. Не поддържа I2C.
D1 GPIO5Да Да SCL (I2C)
D2 GPIO4Да Да SDA (I2C)
D3 GPIO0към +vcc Да Свързан е към FLASH бутона. Контролерът не стартира ако е свързан към маса.
D4 GPIO2 към +vcc Да Има високо ниво при стартиране. Вграденият светодиод е свързан към него. Контролерът не стартира ако е свързан към маса.
D5 GPIO14 Да Да SPI (SCLK)
D6 GPIO12 Да Да SPI (MISO)
D7 GPIO13 Да Да SPI (MOSI)
D8 GPIO15към маса Да SPI (CS). Контролерът не стартира ако се свърже към +vcc.
RX GPIO3ДаRX изводИма високо ниво при стартиране.
TX GPIO1TX изводДаИма високо ниво при стартиране. Контролерът не стартира ако е свързан към маса.
A0ADC0Аналогов входНе

GPIO6 до GPIO11 са свърани вътрешно към флаш паметта. Не се препоръчва да се ползват.

И така, как да конфигурираме портовете?

Това вече ни е познато от първия пример за мигане на вградения светодиод.

pinMode(port, OUTPUT) - задаваме port да бъде изход
pinMode(port, INPUT) - задаваме port да бъде вход

Протоколът I2C (IIC)

ESP8266 има 17 GPIO – изводи за обща употреба. Всеки от тях може да бъде програмиран като вход или изход, да се ползва I2C, SPI, ШИМ и т.н. Най-често конкретни изводи се ползват за конкретна цел, и ще ги опиша по-долу.

Използването им като обикновени изходи вече го споменах, макар и без подробности.

За онагледяване ще използвам чертеж от статията на electronics hub.

https://www.electronicshub.org/wp-content/uploads/2021/02/NodeMCU-Pinout-Image.jpg

За текущия момент на нас ще ни бъдат интересни GPIO4 и GPIO5, които се използват за I2C протокола.

Когато свързвате някаква периферия, на конекторите е обозначено SCL, SDA, VCC(VIn), GND.

Ако не е указано друго, обикновено:

SCL се свързва към GPIO5 или D1
SDA се свързва към GPIO4 или D2

За удобство и да не бъркам кое къде съм свързал, си измислих една система. За свързване на SCL ползвам цветове, в чието име присъства буквата L – yellow, blue, violet, black. SDA е с цвят, в чието име няма такава буква.

Phillips semiconductors, сега NXP през 1982 година реализират I2C шината с идеята да я използват в техните устройства. Целта е била да се съкрати дължината на използваните медни проводници, както и да се опрости комуникацията между различните интегрални схеми. 2004 година патентът изтича и става общодостъпна.

Връзката се осъществява чрез сериен протокол по 4 проводника. На илюстрацията не са изобразени захранващите проводници.

SDA е съкращение от Serial Data Line, а SCL е съкращение от Serial Clock Line.

Може да има едно или няколко master устройства, както и едно или няколко slave устройства. Всяко от тях притежава собствен 7 битов адрес, чрез който стават обръщенията. От възможните 128 са достъпни 112 адреса. Останалите са резервирани.

Защо ги разправям тия работи? За да може контролерът да комуникира с устройствата трябва да знае адреса им. Докато някои са строго зададени, други може да се различават от общоприетите.

Понякога някой производител на клонирана джаджа решава да ползва собствен вместо оригиналния, от който са копирали.

Понякога се налага да се включат паралелно няколко еднакви I2C устройства, а в такъв случай трябва да се променят адресите им.

Не помня откъде го взех това, но ето пример за pcf8574.

https://ojd.unhidefairness.pw/img/d3ebfbf2c7a41b865033d5e32d88265f.jpg

На живо моята платка изглежда така:

За по-евтинко и по-компактно не се използват джъмпери, а с поялник трябва да се свържат нужните мостчета.

И така. Сдобили сме се с някаква периферия и искаме да я пуснем да работи. В моя случай исках да пусна SSD1306, но с настройките по подразбиране не се получи.

За целта компилираме и качваме i2c_scanner, отваряме терминала и гледаме на кой адрес отговаря джажата.

// --------------------------------------
// i2c_scanner
//
// Version 1
// This program (or code that looks like it)
// can be found in many places.
// For example on the Arduino.cc forum.
// The original author is not know.
// Version 2, Juni 2012, Using Arduino 1.0.1
// Adapted to be as simple as possible by Arduino.cc user Krodal
// Version 3, Feb 26 2013
// V3 by louarnold
// Version 4, March 3, 2013, Using Arduino 1.0.3
// by Arduino.cc user Krodal.
// Changes by louarnold removed.
// Scanning addresses changed from 0…127 to 1…119,
// according to the i2c scanner by Nick Gammon
// https://www.gammon.com.au/forum/?id=10896
// Version 5, March 28, 2013
// As version 4, but address scans now to 127.
// A sensor seems to use address 120.
// Version 6, November 27, 2015.
// Added waiting for the Leonardo serial communication.
//
//
// This sketch tests the standard 7-bit addresses
// Devices with higher bit address might not be seen properly.
//
include
void setup()
{
Wire.begin();
Serial.begin(115200);
while (!Serial); // Leonardo: wait for serial monitor
Serial.println("\nI2C Scanner");
}
void loop()
{
byte error, address;
int nDevices;
Serial.println("Scanning…");
nDevices = 0;
for(address = 1; address < 127; address++ )
{
// The i2c_scanner uses the return value of
// the Write.endTransmisstion to see if
// a device did acknowledge to the address.
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) { Serial.print("I2C device found at address 0x"); if (address<16) Serial.print("0"); Serial.print(address,HEX); Serial.println(" !"); nDevices++; } else if (error==4) { Serial.print("Unknown error at address 0x"); if (address<16) Serial.print("0"); Serial.println(address,HEX); }
}
if (nDevices == 0)
Serial.println("No I2C devices found\n");
else
Serial.println("done\n");
delay(5000); // wait 5 seconds for next scan
}

Бинго! Адресът, който ни трябва е 0x3C. Променяме го в примера по-горе, като в моя случай трябва да се промени и стойността на OLED_RESET да стане -1.

Компилираме, качваме кода и …

Свързване на повече от едно устройства на I2C

Много често ще ни се налага да свързваме повече от едно устройство по I2C шината. Например проста метеорологична станция. Какво да правим?

На илюстрацията по-горе се вижда как всичко е свързано паралелно. Съгласно нея свързваме всичките изводи SDA заедно, всичките изводи SCL заедно, масата на маса (0 В), захранването на захранване. Ако не ползваме бредборд ще се наложи да запоим изводите. Иначе е лесно:

Изходи с широчинно импулсна модулация (ШИМ)

Най-общо казано, широчинно импулсната модулация може да се използва за регулиране на аналогови устройства посредством цифров сигнал. Регулиране на яркостта на осветлението, скоростта на въртене на електродвигатели са два примера, често използвани в ежедневието.

Коефициентът на запълване може да се регулира с 10 битова стойност – от 0 до 1023. По подразбиране максималната стойност е 255. Ако искаме да е до 1023 го задаваме предварително с

cont MAX_VALUE = 1023;
analogWriteRange(MAX_VALUE);

И пак за пример ще ползваме вградения светодиод.

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
analogWriteRange(1023);
delay(2e3);
}
void loop() {
for (int i=0; i<1023; i=i+10) {
analogWrite(LED_BUILTIN, i);
delay(50);
}
for (int i=1023; i>-1; i=i-10) {
analogWrite(LED_BUILTIN, i);
delay(50);
}
}

Аналогов вход

Аналоговият вход на ESP8266 приема напрежения от 0 до 1 В. На NodeMCU има сложен резисторен делител и позволеното напрежение е от 0 до 3,3 В. Стойността се чете по следния начин:

analogRead(analogInPin);

За повече подробности около аналоговия вход ще има следваща статия.

Успех!

NodeMcu, Esp8266, Arduino IDE, интерфейс, примери, библиотеки.

Здравейте,

Сдобили сме се с играчката NodeMCU, ESP8266 или подобните. Откъде да започнем?

Малко прибързах със статията за терминала, но все пак той е важна част от разработката и откриването на грешки в кода. Първо трябваше да започна с интерфейса, с примерите, които да пробваме, за да започнем да навлизаме в средата.

След инсталацията на Arduino IDE, стартираме и виждаме прозореца:

Това са бързите клавиши за достъп на най-ползваните функции. Пишем кода, после проверяваме. Когато сме се уверили, че всичко е наред, можем да го качим в паметта на контролера. Ако подаваме някаква информация към серийния порт, със серийния монитор (терминала) можем да следим какво се случва. Там може да излезе и някаква дебъг информация от самия контролер – например при задействане на “кучето пазач” – watch dog таймерът.

За преминем към опитите. С инсталацията на Arduino IDE идва огромно количество примерен код. Всяка инсталирана библиотека носи със себе си конкретни примери.

В най-горната част са “вградените” примери, много добре документирани, от които може да се видят основни функции, методи, параметри на контролерите. Повечето са приложими директно за ESP8266, или тръгват с малки доработки.

Под тях са общи примери, които могат да се ползват независимо от вида на контролера. Под тях са тези, които са писани конкретно за ESP8266, а когато вече сме инсталирали някакви библиотеки, техните примери са най-отдолу.

Sketchbook съдържа вашите програми, над които сте работили до момента. Обикновено се намира в My documents\Arduino.

А най-важното са библиотеките. Когато трябва да пишем за някаква периферия, инсталираме съответната библиотека от Manage libraries (ctrl+shift+i)

В полето за търсене въвеждаме името на джаджата. Обикновено се появяват няколко библиотеки. Търсене с гугъл помага да подберем правилната. Понякога това не помага и се налага да пробваме докато намерим нашата. Както по-горе писах, идват купчина примери. От наименованието им можем да се ориентираме кой за какво служи.

След като сме се наиграли и сме намерили каквото ни трябва, можем да изтрием ненужните библиотеки като изтрием съответната папка. Всичките, инсталирани от нас, обикновено са в My documents\Arduino\libraries.

Успех!

ESP8266, NodeMCU, Arduino IDE и терминала (конзолата)

Здравейте,

Когато публикувах първата статия във фейсбук, Коцето спомена за терминала на Arduino IDE.

Това е много полезно както за дебъгване, така и за показване на някаква информация по време на разработката, а защо не и след това.

Какво представлява терминалът? При програмиране на ESP8266 се използва серийна връзка. Понеже в момента все по-малко компютри имат сериен порт (COM), се използва конвертор от RS232, какъвто протокол се ползва там, към USB. Терминалът показва получената информация от контролера, а може и да предава обратно.

Извиква се със shift+control+M или от менюто.

ESP8266 поддържа скорост на предаване (baud rate) 115200, така че това трябва да изберете отдолу.

За да активираме серийната връзка, използваме

Serial.begin(baud_rate), където в нашия случай ще бъде:

Serial.begin(115200);

Serial.print(“text”); ще изведе съобщение в терминала, а
Serial.println(“new line”); ще добави и нов ред накрая.

Вземаме за пример предишния тест, с който мигаше вграденият светодиод, и го допълваме така, че да видим какво се случва:

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
Serial.println("Ready!");
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
Serial.println("The lights are on!");
delay(1000);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
Serial.println("The lights are off!");
delay(1000);
}
LED_BUILTIN е константа, указваща на кой извод е свързан вграденият светодиод, в нашия случай е GPIO2, или 2.

pinMode(LED_BUILTIN, OUTPUT); с тази инструкция инициализираме GPIO2 като изход.

digitalWrite(LED_BUILTIN, HIGH); задаваме високо логическо на избрания изход.

delay(1000); генерираме закъснение от 1 секунда (1000 милисекунди).

Записваме, компилираме, качваме и наблюдаваме какво се случва..

Хм. Пише The lights are on, а светодиодът е изгаснал… Значи светодиодът е свързан към плюс и подаването на ниско ниво ще го светне.

Коригираме кода, за да работи правилно.

void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
Serial.println("Ready!");
}
void loop() {
digitalWrite(LED_BUILTIN, LOW); // turn the LED on
Serial.println("The lights are on!");
delay(1000);
digitalWrite(LED_BUILTIN, HIGH); // turn the LED off
Serial.println("The lights are off!");
delay(1000);
}

Записваме, компилираме и сме готови!

Ето как терминалът може да се използва за откриване на грешки.

Arduino IDE и ESP8266 (Lolin, NodeMCU v3)

Здравейте,

От сравнително скоро започнах да се забавлявам с едночиповите микроконтролери на базата на ESP8266. Все се каня да започна да водя дневник на разни дребни проблеми, с които се сблъквам като начинаещ и май настъпи моментът.

Да започваме!
Какво ни трябва за начало? Да започнем с основното – самият микроконтролер. Моите ги купувам от Aliexpress .

Защо конкретно от тоази магазин? Ами продавачът е коректен, при поръчка около 30-тина лева пратката е с проследим номер, независимо, че съм избрал безплатна доставка.

Като за начало трябва да свалим Arduino IDE – редакторът, където ще пишем кода. Инсталацията е “next, next, next, finish”. После отваряме настройките и добавяме в настройките връзка с информация за нашия тип контролери.

http://arduino.esp8266.com/stable/package_esp8266com_index.json

Избираме типа на платката.

До тук добре. При опит за стартиране на каквото и да било, почва рев, че не намира COM порта, или на открития (обикновено този, на дъното) няма нищо закачено.

От сайта на AirBG, в ръководството как да си направим сами станция, намерих връзка за сваляне на USB драйвер за CH340 / CH340. Прилагам я директно.
http://www.wch.cn/downloads/file/5.html

Разархивираме зип файла и стартираме setup.exe. После Install, като приключи затваряме и сме готови.

Забравих… Вземаме един кабел USB – microUSB, такъв, който се ползва за зареждане на телефон, но е със свързани 4те проводника, и свързваме контролера с някой свободен USB вход на компютъра.


Забележка: Може да не е COM3, а COM4, 9 или който е свободен в системата. Ако има порт на дъното, той е COM1.

Избираме порта, на който е закачена платката (ако са два – обикновено е вторият), а след това Get Board info. Би трябвало да се получи нещо такова:

Ако е така, значи всичко е наред и можем да пристъпим към първата проба. Пействате кода по-долу в редактора, а после upload (ctrl+u).

void setup() {
// initialize LED_BUILTIN as an output pin.
pinMode(LED_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
delay(1000);
digitalWrite(LED_BUILTIN, LOW); // turn the LED off
delay(1000);
}

Тук отварям една скоба.
За да се компилира и качи кодът в контролера, първо трябва да се запише на диска. Ако сме започнали от нулата, редакторът ще ни предложи да изберем къде да го съхраним. Избираме как ще се казва, а Arduino IDE създава нова папка със същото име и в нея записва кода като файл с разширение .ino. Чак тогава започва процесът на компилация, а ако всичко мине успешно, се качва към контролера.

Би трябвало да се получи нещо такова:

а вграденият светодиод да започне да мига на всяка секунда.

Това е от мен. Успех!