Как стать автором
Обновить

Управление светодиодом с помощью Lolin NodeMCU и Elbear ace-uno: пошаговое руководство

Уровень сложностиСредний
Время на прочтение8 мин
Количество просмотров1.8K
Результат работы
Результат работы

Здравствуйте! В этой статье мы рассмотрим, как создать простой веб-сервер на базе Lolin NodeMCU для управления светодиодом на плате Elbear Ace-uno, которую мы будем называть «мишка». К сожалению, на «мишке» отсутствует встроенный Wi-Fi, поэтому для подключения к сети мы будем использовать ESP8266. Данная статья является первым шагом к проекту «Машинка», в рамках которого функционал будет распределён между этими двумя платами.

Вот несколько интересных фактов о плате ELbear Ace-UNO, которые привлекли моё внимание:

Это российская плата, совместимая с Arduino, построенная на отечественном микроконтроллере MIK32 АМУР, разработанном компанией «Микрон». Она может служить отладочной платой для микроконтроллера к1948вк018.

ELbear Ace-UNO совместима с популярной средой разработки Arduino IDE и позволяет подключать платы расширения функционала Arduino Shield, что открывает новые горизонты для творчества. 

Лицевая сторона платы
Лицевая сторона платы

Технические параметры

  1. Микроконтроллер: MIK32 АМУР, RISC-V, 32 МГц

  2. Память ОПЗУ: 256 бит

  3. Память ОЗУ: 16 Кбайт

  4. Память EEPROM: 8 Кбайт

  5. Память FLASH: 8/16/32 Мбайт

  6. Рабочее напряжение, логические уровни**: 3,3 В

  7. Аналоговые входы: 6 (12 бит, частота дискретизации до 1 МГц)

  8. Цифровые входы/выходы: 14 (6 из них могут использоваться в качестве ШИМ)

  9. Интерфейсы

    • UART - есть, 2 шт.

    • I2C - есть, 2 шт.

    • SPI - есть, 2 шт.

  10. Напряжение питания: 7-12 В

  11. 1 пользовательская кнопка

  12. 1 пользовательский светодиод

  13. USB Type-C для программирования, питания (5 В)

  14. Аппаратная поддержка крипто-алгоритмов ГОСТ 34.12–2018 и AES128

Основные компоненты проекта

  1. Lolin NodeMCU - это плата на основе ESP8266, которая поддерживает Wi-Fi и проста в использовании.

  2. Светодиод на плате "мишка" - для управления.

  3. Библиотеки - для работы с Wi-Fi и веб-сервером необходимо подключить библиотеки ESP8266WiFi.h и ESP8266WebServer.h.

Подключение:

Настройка сети

Первым шагом в процессе настройки сети является задание параметров Wi-Fi. В нашем коде мы указываем SSID (имя сети), пароль и статический IP-адрес для устройства. Это поможет избежать возможных проблем, связанных с изменением IP-адреса при перезагрузке устройства.

Пример кода
const char* ssid = "имя";
const char* password = "пароль";
IPAddress local_IP(192, 168, 1, 3);  // Установите желаемый статический IP
IPAddress gateway(192, 168, 1, 1);      // Шлюз (обычно IP вашего маршрутизатора)
IPAddress subnet(255, 255, 255, 0);     // Подсеть

Настройка веб-сервера

После того как мы настроили сеть, мы запускаем веб-сервер, который будет принимать запросы на порту 80. Затем мы регистрируем маршруты, необходимые для обработки команд, отправляемых через веб-интерфейс.

Пример кода
ESP8266WebServer server(80);
void setup() {
    Serial.begin(9600); // Настройка последовательного порта для связи
    WiFi.mode(WIFI_AP_STA); // Установка режима AP и станции
    WiFi.config(local_IP, gateway, subnet); // Настройка статического IP
    WiFi.begin(ssid, password); // Подключение к Wi-Fi сети
    // Проверка подключения к Wi-Fi
    while (WiFi.status() != WL_CONNECTED) {
        delay(1000);
    }
    // Создание точки доступа
    WiFi.softAP("ESP8266_AP", "password"); // Создание точки доступа с SSID и паролем
    // Регистрация маршрутов
    server.on("/", handleRoot);
    server.on("/sendCommand", handleSendCommand);
    server.on("/sendSerialInput", handleSendSerialInput);
    server.begin();
}

Обработка команд

Веб-интерфейс позволяет пользователю управлять устройством с помощью команд. Например, команды «LED_ON» и «LED_OFF» включают и выключают встроенный светодиод. Каждая команда обрабатывается в функции «processCommand», где также ведётся журнал последних команд.

Пример кода
void processCommand(String command) {
    Serial.println("Processing command: " + command); // Отладочное сообщение
    Serial.print(command); // Отправка команды на другое устройство
    if (command == "LED_ON") {
        digitalWrite(LED_BUILTIN, HIGH); // Включение светодиода
        Serial.println("LED is ON"); // Сообщение о подтверждении
        storeCommand("LED ON");
    } else if (command == "LED_OFF") {
        digitalWrite(LED_BUILTIN, LOW); // Выключение светодиода
        Serial.println("LED is OFF"); // Сообщение о подтверждении
        storeCommand("LED OFF");
    } else {
        Serial.println("Unknown command received: " + command); // Сообщение о неизвестной команде
    }
}

Веб-интерфейс

В рамках функции «handleRoot» мы формируем HTML-страницу, на которой пользователи могут осуществлять ввод команд и наблюдать за последними действиями. Это обеспечивает интуитивное и доступное управление устройством.

Пример кода
void handleRoot() {
    String html = "<html><body><h1>Отправка команды на Elbear ACE-UNO</h1>";
    html += "<form action=\"/sendCommand\" method=\"POST\">";
    html += "<input type=\"text\" name=\"command\" placeholder=\"Введите команду\">";
    html += "<input type=\"submit\" value=\"Отправить команду\">";
    html += "</form>";
    // Отображение последних 5 команд
    html += "<h2>Последние команды:</h2><ul>";
    for (int i = 0; i < 5; i++) {
        if (lastCommands[i] != "") {
            html += "<li>" + lastCommands[i] + "</li>";
        }
    }
    html += "</ul>";
    // Отправка HTML-кода обратно клиенту
    server.send(200, "text/html", html);
}

Заключение

Полный код Lolin NodeMCU
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

const char* ssid = "имя";
const char* password = "пароль";

// Static IP and network settings
IPAddress local_IP(192, 168, 1, 3);  // Set your desired static IP
IPAddress gateway(192, 168, 1, 1);      // Gateway (usually the IP of your router)
IPAddress subnet(255, 255, 255, 0);     // Subnet

ESP8266WebServer server(80);
String lastCommands[5]; // Array to store the last 5 commands
int commandIndex = 0;   // Index for adding new commands
String serialOutput;     // String to store serial output

void setup() {
  Serial.begin(9600);   // Set up the serial port for communication with Elbear ACE-UNO

  // Set up Wi-Fi in client mode
  WiFi.mode(WIFI_AP_STA); // Set to AP and station mode
  WiFi.config(local_IP, gateway, subnet); // Set static IP
  WiFi.begin(ssid, password); // Connect to Wi-Fi network

  // Check for Wi-Fi connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
  }

  // Set up access point
  WiFi.softAP("ESP8266_AP", "password"); // Create access point with SSID and password

  // Register routes
  server.on("/", handleRoot);
  server.on("/sendCommand", handleSendCommand); // Route to send custom command
  server.on("/sendSerialInput", handleSendSerialInput); // Route to send serial input
  server.begin();
}

void loop() {
server.handleClient();
}

void processCommand(String command) {
  Serial.println("Processing command: " + command); // Debug message for command processing

  // Send command to the other device via Serial
  Serial.print(command); // Send the command to the other device
  Serial.println(); // Add newline to separate commands

  if (command == "LED_ON") {
    digitalWrite(LED_BUILTIN, HIGH); // Turn on LED
    Serial.println("LED is ON"); // Confirmation message
    storeCommand("LED ON");
  } else if (command == "LED_OFF") {
    digitalWrite(LED_BUILTIN, LOW); // Turn off LED
    Serial.println("LED is OFF"); // Confirmation message
    storeCommand("LED OFF");
  } else {
    Serial.println("Unknown command received: " + command); // Unknown command message
  }
}

void handleRoot() {
  String html = "<html><body><h1>Send Custom Command to Elbear ACE-UNO</h1>";
  
  // Form to send custom command
  html += "<form action=\"/sendCommand\" method=\"POST\">";
  html += "<input type=\"text\" name=\"command\" placeholder=\"Enter command\">";
  html += "<input type=\"submit\" value=\"Send Command\">";
  html += "</form>";

  // Input for serialInput
  html += "<h2>Serial Input:</h2>";
  html += "<form action=\"/sendSerialInput\" method=\"POST\">";
  html += "<input type=\"text\" name=\"serialInput\" placeholder=\"Enter serial command\">";
  html += "<input type=\"submit\" value=\"Send Serial Command\">";
  html += "</form>";

  // Display the last 5 commands
  html += "<h2>Last Commands:</h2><ul>";
  for (int i = 0; i < 5; i++) {
    if (lastCommands[i] != "") { // Check if there is a command
      html += "<li>" + lastCommands[i] + "</li>";
    }
  }
  html += "</ul>";

  // Display serial output
  html += "<h2>Serial Output:</h2><div>" + serialOutput + "</div>";

  // Display connected devices
  html += "<h2>Connected Devices:</h2><ul>";
  int numDevices = WiFi.softAPgetStationNum(); // Get the number of connected devices
  html += "<li>Number of connected devices: " + String(numDevices) + "</li>";
  
  // Get information about connected devices
  struct station_info *stationList = wifi_softap_get_station_info();
  while (stationList != NULL) {
    html += "<li>Device MAC: " + String(macToString(stationList->bssid)) + "</li>";
    stationList = STAILQ_NEXT(stationList, next);
  }
  html += "</ul></body></html>";
  
  server.send(200, "text/html", html);
}

void handleSendCommand() {
  if (server.hasArg("command")) {
    String command = server.arg("command"); // Get the command from the form
    command.trim(); // Remove extra spaces
    Serial.println("Command from web: " + command); // Debug message
    serialOutput += "Command from web: " + command + "<br>"; // Add to serial output for display
    processCommand(command); // Process the command
    server.send(200, "text/html", "<html><body><h1>Command sent: " + command + "</h1><a href=\"/\">Go back</a></body></html>");
  } else {
    server.send(400, "text/plain", "No command provided");
  }
}

void handleSendSerialInput() {
  if (server.hasArg("serialInput")) {
    String serialInput = server.arg("serialInput"); // Get the serial input from the form
    serialInput.trim(); // Remove extra spaces
    Serial.println("Serial Input from web: " + serialInput); // Send serial input to Serial
    processCommand(serialInput); // Process the command
    server.send(200, "text/html", "<html><body><h1>Serial command sent: " + serialInput + "</h1><a href=\"/\">Go back</a></body></html>");
  } else {
    server.send(400, "text/plain", "No serial command provided");
  }
}

void storeCommand(String command) {
  lastCommands[commandIndex] = command; // Store command in array
  commandIndex = (commandIndex + 1) % 5; // Increment index, reset at 5
}

// Function to convert MAC address to string
String macToString(uint8_t *mac) {
  String macStr = "";
  for (int i = 0; i < 6; i++) {
    macStr += String(mac[i], HEX);
    if (i < 5) macStr += ":";
  }
  return macStr;
}

Полный код "мишки"
void setup() {
  pinMode(LED_BUILTIN, OUTPUT); // Настройка пина как выход
  Serial.begin(9600); // Настройка последовательного порта
  Serial.println("Ready to receive commands..."); // Сообщение о готовности
}

void loop() {
  if (Serial.available()) {
    String command = Serial.readStringUntil('\n'); // Чтение команды
    command.trim(); // Удаление лишних пробелов
    Serial.println("Received command: " + command); // Отладочное сообщение
    if (command == "LED_ON") {
      digitalWrite(LED_BUILTIN, HIGH); // Включение светодиода
      Serial.println("LED is ON"); // Подтверждение включения
    } else if (command == "LED_OFF") {
      digitalWrite(LED_BUILTIN, LOW); // Выключение светодиода
      Serial.println("LED is OFF"); // Подтверждение выключения
    } else {
      Serial.println("Unknown command"); // Сообщение о неизвестной команде
    }
  }
}

Если интересно, подписывайтесь на мой ТГ

Теги:
Хабы:
Всего голосов 7: ↑5 и ↓2+3
Комментарии4

Публикации

Ближайшие события