Подключение к WiFi с использованием микроконтроллера ESP8266 NodeMCU

Цель работы

Научиться подключаться к WiFi сети с микроконтроллера Arduino и передавать данные по WiFi.

Задачи работы

  1. Добавить поддержку микроконтроллера NodeMCU на базе WiFi-модуля ESP8266
  2. Разработать скетч для подключения к WiFi сети и передачи данных по беспроводному каналу связи.

Инструменты для выполения работы

  1. Компьютер с подключением к сети Internet
  2. Микроконтроллер NodeMCU V3 на базе EPS8266-12E

Теоретическая часть

Плата NodeMCU построена на базе модуля WiFi ESP8266.

Распиновка платы:

Для работы с этой платой была добавлена поддержка среды разработки Arduino IDE. Практически все библиотеки для обычной Arduino так же работают и для этой платы, однако ее распиновка отличается от распиновки плат Arduino. Так, на плате есть один аналоговый вход (A0), на котором работает 10-битный АЦП. Цифровым пинам 0-15 Arduino соответствуют выходы, обозначенные GPIO1-GPIO16. Например, если в Arduino IDE используется пин 12, ему будет соответствовать контакт, обозначенный на плате как D6 (GPIO12). Пины GPIO1 — GPIO5, GPIO10, GPIO12-GPIO15 поддерживают ШИМ.
Характеристики платы:
поддержка WiFi протоколов 802.11 b/g/n
Wi-Fi Direct (P2P), soft-AP
встроенный стек TCP/IP
SDIO 2.0, SPI, UART
встроенный PLL, регуляторы, и система управления питанием
Номинальное напряжение: 3,3 В
Входное напряжение: 3,7–20 В
Максимальный потребляемый ток: 220 мА
D9, D10 — UART
D1, D2 — I²C (D1 - SCL(SCK), D2 - SDA)
D5–D8 — SPI

Основной сайт проекта: https://github.com/esp8266/Arduino

 

Выполнение работы

Добавление поддержки микроконтроллера NodeMCU на базе WiFi-модуля ESP8266


Для добавления поддержки NodeMCU в среду Arduino IDE нужно выполнить следующие шаги:

  1. Открываем настройки (Файл -> Настройки)
  2. Находим дополнительные ссылки для менеджера плат и нажимаем справа кнопку редактирования (выделена на скриншоте)
  3. Добавляем URL: http://arduino.esp8266.com/stable/package_esp8266com_index.json
  4. Сохраняем и заходим в менеджер плат (Инструменты -> Плата: -> Менеджер плат)
  5. Вводим в поиск "esp8266" и устанавливаем пакет esp8266
  6. Создаем новый скетч и сохраняем его как Esp8266Test.
  7. Выбираем плату "NodeMCU 1.0 (ESP-12E Module)" (Инструменты -> Плата:). Ниже в меню "Инструменты" вводим настройки для CPU Frequency, Flash Size и Upload Speed как показано на скриншоте (скорее всего, будут стоять именно такие, если плата отличается от изображенной выше, настройки могут отличаться).
  8. Выбираем нужный порт.

Разработка скетча для подключения к WiFi сети и передачи данных по беспроводному каналу связи.

Скетч для работы с WiFi используем библиотеки, аналогичные стандартной библиотеке WiFi для обычных Arduino. При работе с обычной Arduino и каким-либо WiFi шилдом будут подключаться аналогичные заголовочные файлы, только без префикса "ESP8266".
Подключаем заголовочные файлы

#include <ESP8266WiFi.h>
#include <ESP8266HTTPClient.h>

Указываем параметры WiFi сети

const char *essid="WIFI_ESSID";
const char *key="WIFI_KEY";

WIFI_ESSID и WIFI_KEY заменяем на имя и пароль используемой WiFi сети.
В функции setup() запускаем Serial и подключаемся к WiFi

Serial.begin(9600);
WiFi.begin(essid,key);
while(WiFi.status() != WL_CONNECTED)
{
    delay(500);
    Serial.print(".");
}
Serial.println("WiFi connected");

В функции loop выполняем GET запрос на WEB-страницу удаленного сервера. Для этого подключаемся к серверу

WiFiClient client;
if(!client.connect("wl.unn.ru",80))
{
    Serial.println("connection failed");
    return;

Отправляем сгенерированный вручную GET запрос

client.print("GET /laboratory/?page=1 HTTP/1.1\r\nConnection: close\r\n\r\n");

Ждем ответа от сервера

unsigned long timeout = millis();
while(client.available()==0)
{
    if(millis()-timeout>5000)
    {
        Serial.println(">>> Client Timeout !");
        client.stop();
        return;
    }
}

Выводим ответ и спим 10 секунд

while(client.available())
{
    String line=client.readStringUntil('\r');
    Serial.print(line);
}
delay(10000);

Загружаем скетч на плату и открываем менеджер порта. Там раз в десять секунд должен появляться код веб-страницы, пришедший в ответ от сервера wl.unn.ru.

Дополнительное задание: разработать скетч для сканирования доступных WiFi сетей
 
КОД СКЕТЧА
#include <ARpc.h>
#include <ARpcBase.h>
#include <ARpcSrvReady.h>




const char *deviceName="led_blink_test";//имя устройства
const char *deviceId="{9c7ea7a4-5276-476a-914c-e95736ee304e}";//идентификатор устройства

int ledPin=13;//пин светодиода
unsigned long blinksCount=0;//число миганий

const char *interfaceStr="<controls><group title=\"Device controls\"><control sync=\"0\" title=\"Blink\" command=\"blink\"/></group></controls>";

//для получения данных с устройства необходимо подготовить описание датчиков
const char *sensorsDef="<sensors>"
"<sensor name=\"blinks_count\" type=\"single\"/>"//датчик blinks_count
"<sensor name=\"sin_x\" type=\"single\"><constraints dims=\"2\"/></sensor>"//датчик sin_x (двумерный)
"</sensors>";

//Определяем функцию обработки команд, передаваемых устройству. 
//Библиотека будет вызывать эту функцию, когда на устройство будут 
//приходить команды, например, введенные нами в мониторе порта. 
//Эта функция принимает команду, аргументы команды, количество аргументов
//и указатель на объект класса ARpc, от которого пришла команда

void processCommand(const char *cmd,const char *args[],int argsCount,ARpc *parser)
{
    if(strcmp(cmd,"blink")==0)//проверяем, что cmd == "blink"
    {
        //мигаем
        digitalWrite(13,HIGH);
        delay(200);
        digitalWrite(13,LOW);
        delay(200);
        ++blinksCount;
        //генерируем "измерение"
        parser->writeMeasurement("blinks_count",String(blinksCount).c_str());
        //сообщаем библиотеке что команда обработана
        parser->writeOk();
    }
    else parser->writeErr("Unknown cmd");//неизвестная команда
}

//Определяем функцию для передачи сообщений к ПК через последовательный пор
void arpcWriteCallback(const char *str)
{
    Serial.print(str);
}

//объявляем объект класса ARpc и передаем ему ссылки на созданные
//выше переменные и функции

ARpc parser(300,&processCommand,&arpcWriteCallback,deviceId,deviceName);
int t=0;
void writeSinVal()
{
    String sinVal;
    sinVal+=String(sin(0.1*t));
    sinVal+="|";
    sinVal+=String(cos(0.1*t));
    parser.writeMeasurement("sin_x",sinVal.c_str());
    ++t;
}

//Проихводим инициальзацию пина и последовательного порта в функции setup() 
//и установить описание датчиков и интерфейса управления

void setup() {
  // put your setup code here, to run once:

    Serial.begin(9600);
    pinMode(13,OUTPUT);
    parser.setControlsInterface(interfaceStr);
    parser.setSensorsDescription(sensorsDef);

}


//необходимо проверять последовательный порт на наличие новых данных, передавать их объекту parser, сгенерировать новый отсчет sin, после чего сделать 
//задержку на пол-секунды, чтобы отсчеты не генерировались слишком часто

void loop() {
  // put your main code here, to run repeatedly:
while(Serial.available())
        parser.putChar(Serial.read());
    writeSinVal();
    delay(500);
}