Simplest wifi car using ESP8266 Motorshield – Hackster.io

Notice: Undefined index: HTTP_ACCEPT in /home/n/newavtjc/radiocopter.ru/public_html/wp-content/plugins/realbig-media/textEditing.php on line 823

Esp motorshield

There’s not so much information on the Internet about this board. First of all this shield for ESP-12E Dev Kit and NodeMcu boards and not for all, because width between pins is 25mm and that’s not enough for some boards like LoLin. In my project I used NodeMcu Amica.

This shield board is driven by the special excent large power full-bridge chip L293DD from the famous Stmicroelectronics company, which can directly drive 2-channels DC motors or one-channel stepper motor. The driven current can be arrived at 1.2A.

Motor power: can be up to 36V.

ESP power: can be up to 9V. Because it goes straight to the esp without any voltage regulators.

Also these pins have common ground, you can connect voltage supply to one pin and use shortcut for other(if voltage less than 9V).

Board uses 4 pins to control motors. PWMA, PWMB- speed of motors. DA, DB-direction of motors(0-straight;1-reverse).

Here pinout for NodeMcu Amica.

  • PWMA-GPIO5.
  • PWMB-GPIO4.
  • DA-GPIO0.
  • DB-GPIO2.

Nodemcu motor shield для wi-fi модуля esp8266 esp-12e

NodeMCU Motor Shield для Wi-Fi модуля ESP8266 ESP-12E

Кажется совсем недавно появились платы на основе WI-FI модуля ESP8266, но они уже стали  настолько популярными, что многие используют их в своих проектах, как замену платам Arduino. И вот новый этап эволюции – появление плат расширения –  шилдов.
Представляем Вашему вниманию NodeMCU Motor Shield for ESP-12E – плата расширения для модулей NodeMCU или ESP12E Dev Kit.
NodeMCU Motor Shield for ESP-12E 
Характеристики:

  • Микросхема – L293;
  • Количество каналов для подключения – 2:
  • 2 двигателя постоянного тока;
  • 1 шаговый двигатель;
  • Напряжения питания логической части – 4.5 – 9 В;
  • Напряжения питания силовой части – 4.5 – 36 В;
  • Продолжительный максимальный ток нагрузки – 600mА на каждый канал;
  • Пиковый максимальный ток –  до 1.2A;
  • Скорость переключения до 5 kHz;
  • Диапазон рабочих температур от -40°C до 150°C;
  • Размеры – 42 x 57 x 10 мм;
  • Вес – 20 г.

 
NodeMCU Motor Shield for ESP-12E имеет выведенные на плату разъёмы типа “мама” с шагом 1 дюйм для подключение к ней по модульному принципу плат NodeMCU (или ESP12E Dev Kit), что значительно экономит место.
NodeMCU Motor Shield for ESP-12E
В качестве драйвера двигателей используется микросхема L293, которая может управлять двумя каналами, что позволяет управлять двумя двигателями постоянного тока или одним шаговым двигателем. Каждый силовой канал рассчитан на нагрузку в 0,6А, и позволяет кратковременную нагрузку не более 1,2 А.
На плате расположены клеммники для подключения двух моторов, питания модуля и питания двигателей. Но возможно и питание от одного источника питания (устанавливается перемычкой shortcut). Cовместное питание не совсем практично, что может вызывать некорректную работу, как подключенных устройств, так и самого микроконтроллера, особенно при максимальных нагрузках. Использовать такое питание лучше только для кратковременной предварительной отладки отдельных силовых узлов. Раздельное питание – правильное решение.
Для управления двигателями используются  следующие контакты NodeMCU (ESP12E Dev Kit):
D0 – motor A direction (направление);
D2 – motor B direction (направление);
D5 – motor A speed (скорость PWM);
D4 – motor B speed (скорость PWM).
NodeMCU Motor Shield for ESP-12E 

Отдельно на штыревые выводы выведены GPIO контакты, интерфейсы UART и SPI управляющего модуля (NodeMCU или ESP12E Dev Kit). Причем каждый из GPIO контактов (D0-D7, SD2, SD3)  сгруппирован с контактими GND и  VCC для удобного подключения разъема сервопривода.
Power switch – кнопка для включения/выключения платы.
В качестве примера рассмотрим создание Robot Car – машинки, управляемой удаленно по WiFi. Нам потребуются:

  • NodeMCU Motor Shield;
  • ESP12E Dev Kit;
  • Набор Kit Smart Car.

NodeMCU Motor Shield for ESP-12E

В сборе получается так:

NodeMCU Motor Shield for ESP-12E 
Писать скетч будем в Arduino IDE для ESP8266. Загружаем в ESP12E Dev Kit следующий код  скачать скетч.

Теперь на планшете открываем браузер и переходим по адресу (возможно у вас свой) http://192.168.1.2 и на странице управляем движением машинки нажатием на соответствующие кнопки на странице.

Машинка, c робо-рукой, управляемая по wifi через телефон, с помощью arduino nodemcu | клуб технического творчества

Добрый день, друзья! Эта статья посвящена электронной поделке, которую давно хотелось реализовать — и вот дошли руки. Идея этой поделки проста — сделать маленькую четырехколесную машинку, на ней стоит робо-рука и их движениями можно управлять с телефона или планшета через wifi.

pic54.jpg

Компоненты, которые было решено использовать для этой задачи следующие:
1) корпус — пластиковые детали, напечатаные на 3D принтере картон;

pic02.jpg

2) робо-рука — робот-манипулятор MeArm;

pic03.jpg

3) электроника — плата NodeMCU, плата ArduinoNano, желтые мотор-редукторы для Arduino, драйвер моторов на основе микросхемы L298N, шесть батареек типа AA на 1.2 В, кнопка включения-выключения.

pic04.jpg

Давайте все по-порядку.

Корпус
Тележка имеет очень простое строение — кусок картона, с прикрепленными к нему по краям пластиковыми деталями, к которым присоединяются два подшипника с передней стороны и два мотора с задней. К моторам и подшипникам прикручиваются колеса.
Модель тележки была разработана в программе трехмерного моделирования — Blender3D.

pic05.jpg

Затем все необходимые пластиковые детали были напечатаны на 3D принтере.
Сначала из куска картона (пятислойного, профиль В), вырезаем прямоугольник, размером 140/180 мм.

pic06.jpg

Затем из напечатанных на 3D принтере деталей нужно собрать такую конструкцию:

pic07.jpg

То есть в каждое из 4х пластиковых колес вставляется диск, у которого с одной стороны – отверстие для винтика (диаметром 3мм), которым колесо будет прикручиваться к пластиковой детали-переходнику, с другой стороны – отверстие в форме шестигранника.
Пластиковые детали-переходники, в свою очередь имеют форму шестигранника с одной стороны, и форму цилиндра с другой, а также внутри отверстие диаметром 3мм. Концом-шестигранником деталь вставляется в диск колеса и с обратной стороны диска прикручивается винтиком.
Эти детали-переходники для передних и задних колес немного отличаются по форме и размерам. Задние колеса присоединяются к моторам, поэтому на том конце, который имеет форму цилиндра есть углубление по форме повторяющее вал мотора. То есть эта деталь нанизывается на вал с этого конца. И по размерам, вся эта деталь поменьше. Деталь для передних колес цилиндрической частью вставляется в подшипник (диаметр внешний — 22 мм, толщина 7 мм, диаметр внутреннего отверстия — 8 мм).
Подшипник вставлен в дополнительную пластиковую деталь, которая поддерживает его и прикрепляется к тележке.
Колеса крепятся к двум пластиковым деталям имеющим горизонтальные пластинки с отверстиями для винтиков, с помощью которых они прикручиваются справа и слева к куску картона.

pic08.jpg

От них вниз отходят вертикальными пластины, спроектированные так, чтобы к задним двум прикручивался мотор, а к двум передним пластиковая деталь, в которую вставляется подшипник передних колес.
Таким образом, размер всей тележки получается 140/180/75 мм.

pic09.jpg

pic10.jpg

Все эти детали печатаются и собираются вместе.

pic11.jpg

pic12.jpg

pic13.jpg

pic14.jpg

pic15.jpg

pic16.jpg

pic17.jpg

Моторы
Два задних колеса тележки присоединяются к моторам-редукторам для Arduino.

pic18.jpg

У них есть возможность реверсивного вращения, то есть и в одну и в другую сторону. Просто подключив моторы к плате Arduino или NodeMCU мы можем запрограммировать их на вращение либо в одну сторону, либо в другую, в зависимости от подключения контактов, но реверсивное вращение обеспечить не сможем. Причем NodeMCU выдает только 3.3В — этого не хватит, чтобы запустить моторы. От Arduino, выдающей 5В — моторы можно запустить, но лучше этого не делать, так как в моменты запуска и остановки моторов могут происходить броски тока, превышающие 5B.
Поэтому, для подключения моторов и управления ими нужен дополнительный модуль — драйвер, который называется H-мостом. С его помощью можно обеспечить реверсивное вращение и питание моторов. В проектах для Arduino часто используется драйвер для мотора на основе микросхемы L298N.

pic19.jpg

Вот схема ее контактов:

pic20.jpg

Что мы видим на этой плате:
1) Клемма мотора A (OUT1 и OUT2) — к этим клеммам подключается первый мотор-редуктор.
2) Клемма мотора В (OUT3 и OUT4) — к этим клеммам подключается второй мотор-редуктор.
3) Питание моторов (VSS) — вход для подключения внешнего источника питания (максимально допустимое напряжение 35 В), в нашем случае это блок батареек на 4.8 В.
4) Земля (GND) — общий провод, к которому подключается отрицательный полюс внешнего источника питания, а также нужно соединить его с GND контактом платы NodeMCU или Arduino, смотря какая из них выбрана для управления моторами. У нас управление моторов будет осуществляться через плату NodeMCU, а управление робо-рукой через Arduino.
5) Питание логики (Vs) ( 5V). Через эту клемму осуществляется питание микросхемы L298N. То есть этот контакт нужно присоединить к контакту 5В платы Arduino. Но если в схеме используется плата NodeMCU, то она выдает только 3.3В — этого не хватает для питания логики L298N. В этом случае есть способ питания логики от стабилизатора напряжения, который располагается на плате драйвера. Он выдает 5В. Тогда клемма Vs никуда не подключается, а подается только ток на клемму VSS, но при этом должна быть установлена перемычка питания от стабилизатора, которая обозначена на картинке выше. Питание на плату NodeMCU при этом должно подаваться не более 12В от внешнего источника, подключив его « » полюс к контакту VIN.
6) Управление мотором A (IN1, IN2) — контакты, управляющие направлениями вращения первого мотора. Подключаются к цифровым контактом управляющей платы (NodeMCU или Arduino). Напряжение на одном вращает мотор в одну сторону, на другом в другую.
7) Управление скоростью мотора А (ENA). Подключается к аналоговым контактам управляющей платы и скорость задается цифрой от 0 до 255.
8) Управление мотором В (IN3, IN4), управление скоростью мотора В (ENВ) — то же самое, но для второго мотора.

Схема подключения моторов через драйвер к плате NodeMCU:

pic21.jpg

В нашем роботе эта схема выглядит иначе. У нас была отдельно микросхема L298N, которую отковыряли из какого-то прибора. С ее помощью мы спаяли свой вариант драйвера моторов.

pic22.jpg

pic23.jpg

Этот драйвер отличается от рассмотренного тем, что в нем отсутствует микросхема 78M05 (стабилизатор напряжения). Роль этого стабилизатора в нашей схеме выполняет плата ArduinoNano. Она подключается к драйверу (VIN и GND), тем самым запитывается энергией и 5В от Arduino подается на питание логики драйвера. В остальном то же самое.
Вот наша схема:

pic24.jpg

ArduinoNano
Платы NodeMCU и ArduinoNano предназначены для управления различными электронными схемами.
ArduinoNano построена на микроконтроллере ATmega328.

pic25.jpg

На ней есть 14 цифровых контактов и 8 аналоговых.
Программируется эта плата при помощи ArduinoIDE — среды разработки программ под Arduino, которую можно скачать с официального сайта и установить. Она содержит в себе список всех возможных видов плат Arduino, какие бывают, так что для программирования ArduinoNano не нужно устанавливать дополнительно никаких библиотек. Нужно только подключить плату к компьютеру через MiniUSB кабель, запустить среду разработки, найти в вписке плат «Инструменты → Плата → Arduino Nano».

pic26.jpg

Также нужно указать последовательный порт «Инструменты → Порт», корорый появится в списке после присоединения платы к компьютеру. И плата готова к программированию.
На данном этапе, в вышеприведенных схемах плата Arduino ничего не делает. В первой схеме с драйвером L298N она вообще отсутствует так как не нужна, в схеме с самодельным драйвером она выполняет роль стабилизатора напряжения и включена в схему, чтобы питать логику микросхемы L298N.
Предлагаю сначала запустить машинку и сделать так, чтобы ее движения управлялись с телефона, а вторым этапом, если все получится, приделать робо-руку. Робо рука будет управляться через плату Arduino, поэтому мы резервируем для нее место в схеме, но пока что она никакой код выполнять не будет. А плата NodeMCU будет управлять движением моторов, так что запрограммируем сейчас ее.

NodeMCU
Плата NodeMCU основана на микросхеме ESP8266MOD, содержащей встроенный Wifi модуль. Благодаря этому факту выбор и пал на нее. Она обеспечивает возможность посылать сигналы в нашу схему по Wifi через программу на телефоне или планшете.

pic27.jpg

Немного о Wifi подключениях…
Устройства, которые подключаются к сетям Wi-Fi, называются станциями (STA). Подключение к Wi-Fi обеспечивается точкой доступа (AP), которая выступает в качестве концентратора для одной или нескольких станций. Точка доступа вашей домашней сети на другом конце подключена к проводной сети. Она обычно интегрируется с маршрутизатором для обеспечения доступа из сети Wi-Fi к Интернету. Каждая точка доступа распознается по SSID (Service Set IDentifier), который по сути является именем сети, которую вы выбираете при подключении устройства (станции) к Wi-Fi.
Модули ESP8266 могут работать как станции, поэтому мы можем подключить их к сети Wi-Fi. Он также может работать как программная точка доступа (soft-AP) для создания собственной сети Wi-Fi. Когда модуль ESP8266 работает как мягкая точка доступа (программная точка доступа), мы можем подключить другие станции к модулю ESP8266.
Вот эту возможность мы и используем в программе. Наша плата NodeMCU при включении будет создавать точку доступа Wifi с возможностью подключения к ней станций (телефонов, планшетов, компьютеров, ноутбуков). Но количество подключений ограничим одним. Мы же не хотим, чтобы к роботу подключились три человека и одновременно начали вращать колесами?!
После создания точки доступа Wifi нужно с помощью специальной библиотеки кода создать веб-сервер на этой точке доступа и программным путем сгенерировать html страницу, отображающую кнопки управления моторами. Устройство-клиент подключается к данному Wifi, затем с этого устройства заходим на сервер по специальному IP адресу (по умолчанию это 192.168.4.1) и эта html страница c отображается. Нажатие на кнопки на этой странице передает информацию в программу, прошитую в NodeMCU и плата меняет состояние контактов, управляющих вращением моторов.
Чтобы запрограммировать плату NodeMCU, нужно установить дополнительную библиотеку — ESP8266WiFi. Она предоставляет широкий набор методов (функций) и свойств C для настройки и работы модуля ESP8266 в режиме станции и / или программной точки доступа. NodeMCU
появится в списке среды разработки ArduinoIDE только после установки этой библиотеки.
О подробностях установки можно узнать на сайте http://arduino.esp8266.com
На этом ресурсе дается ссылка на GitHub:
http://github.com/esp8266/Arduino
Там написано как осуществляется установка библиотеки при помощи Менеджера плат.
1. Нужно установить текущую интегрированную среду разработки Arduino версии 1.8.9 или выше. Текущая версия находится на сайте Arduino.
2. Запустить Arduino и открыть окно настроек «Файл → Настройки».
Ввести: «https://arduino.esp8266.com/stable/package_esp8266com_index.json» в поле URL-адреса диспетчера дополнительных плат.

pic28.png

3. Открыть Менеджер плат из меню «Инструменты → Плата».

pic29.png

В поле поиска нужно вбить esp8266, при этом в списке должен появиться этот модуль.

pic30.png

Затем нужно нажать кнопку «Установка». Какое-то время будет происходить установка библиотеки.
После этого можно подключать плату NodeMCU через MicroUSB к компьютеру, в среде программирования Arduino выбираем порт «Инструменты → Порт» и выбираем плату «NodeMCU 1.0 (ESP-12E Module)», которая появится в списке «Инструменты → Плата».

pic31.png

Плата готова к программированию.

Заливаем в нее такой код (к статье прилагается файл с кодом «sketch_RobokarForNodeMCU.ino»):

/*Программа для платы NodeMCU. К плате подключаются два мотор-редуктора, вращением которых управляют контакты D0-D3. NodeMCU создает программную точку доступа Wifi и запускает сервер, генерит html страницу на этом сервере, содержащую кнопки управления моторами. Через телефон или планшет происходит подключение по Wifi к плате и через эту страницу на сервереуправляются моторы*/#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WebServer.h>//контакты, управляющие вращением моторов#definepin_Moror1_front16//D0 NodeMCU#definepin_Moror1_back5//D1#definepin_Moror2_front4//D2#definepin_Moror2_back0//D3//название и пароль создаваемой программной точки доступа Wificonstchar*ssid="ESP8266Net";constchar*password="ESP12345";//Переменная строка, указывающая какая кнопка нажата в данный моментStringCurentButtonActive="stop";// Устанавливаем свой веб сервер на порт 80ESP8266WebServerserver(80);/* По-умолчанию сервер доступен по IP http://192.168.4.1 */voidsetup(){  delay(100);  /*Устанавливаем параметры контактов - выходный и выключены*/  pinMode(pin_Moror1_front,OUTPUT);  pinMode(pin_Moror1_back,OUTPUT);  pinMode(pin_Moror2_front,OUTPUT);  pinMode(pin_Moror2_back,OUTPUT);  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,LOW);  /*Отладочный код нужен, чтобы смотреть надписи, которые выводятся на порт ввода-вывода  Открываем последовательное соединение через порт со скоростью передачи данных 115200   И выводим надпись. Раскомментировать при необходимости*/  /*Serial.begin(115200);  Serial.println();  Serial.print("Configuring access point...");*/    /* Создаем мягкую точку доступа Wifi.  WiFi.softAP(ssid, password, channel, hidden, max_connection)  ssid - строка, содержащая сетевоt имя Wifi (макс. 31 символ)  password - необязательная символьная строка с паролем.  channel - необязательный параметр для установки канала Wi-Fi, от 1 до 13. Канал по умолчанию = 1.  hidden - необязательный параметр, если установлено значение true, будет скрывать SSID.  max_connection - необязательный параметр для установки макс. одновременных подключенных станций, от 0 до 8.   По умолчанию 4.   После достижения максимального числа любая другая станция, 
которая хочет подключиться, будет вынуждена ждать, пока уже подключенная станция не отключится.
 */  WiFi.softAP(ssid,password,1,0,1);  /*Отладочный вывод информации на монитор порта*/  /*Serial.print("softAP IP address: ");  Serial.println(WiFi.softAPIP());*/  //Привязываем функции-обработчики полученных команд  server.on("/",onRestart);  server.on("/stop",onStop);  server.on("/front",onFront);  server.on("/back",onBack);  server.on("/left",onLeft);  server.on("/right",onRight);  //Запускаем сервер  server.begin();  /*Отладочный вывод информации на монитор порта*/  /*Serial.println("HTTP server started");*/}voidloop(){  //Прослушивание клиентов  server.handleClient();}voidonSendWebPage(){  server.send(200,"text/html",createWebPage());  delay(5);}voidonRestart(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="stop";  onSendWebPage();}voidonStop(){  onRestart();}voidonFront(){    digitalWrite(pin_Moror1_front,HIGH);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,HIGH);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="front";  onSendWebPage();}voidonBack(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,HIGH);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,HIGH);  CurentButtonActive="back";  onSendWebPage();}voidonLeft(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,HIGH);  digitalWrite(pin_Moror2_front,HIGH);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="left";  onSendWebPage();}voidonRight(){  digitalWrite(pin_Moror1_front,HIGH);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,HIGH);  CurentButtonActive="right";  onSendWebPage();}StringcreateWebPage(){  //Создается html страница, которая будет открываться на установленном сервере  StringWebPage="";   // Отображаем страницу HTML   WebPage ="<!DOCTYPE html><html>";   WebPage ="<head><meta name="viewport" content="width=device-width, initial-scale=1">";   WebPage ="<link rel="icon" href="data:,">";            // CSS для стиля кнопок on/off   WebPage ="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}";   WebPage =".button { background-color: #195B6A; border: none; color: white; padding: 10px 40px;";   WebPage ="text-decoration: none; font-size: 15px; margin: 2px; cursor: pointer;}";   WebPage =".button2 {background-color: #77878A;}</style></head>";         // Заголовок для страницы   WebPage =" <body>";//<h1>Robocar</h1>   WebPage ="<div align=center><table><tr><td>";   WebPage ="</td><td>";   WebPage ="<p><a href="/front"><button class=";   if(CurentButtonActive=="front")    WebPage =""button"";   else    WebPage =""button button2"";   WebPage =">Front</button></a></p>";   WebPage ="</td><td>";   WebPage ="</td></tr><tr><td>";   WebPage ="<p><a href="/left"><button class=";   if(CurentButtonActive=="left")    WebPage =""button"";   else    WebPage =""button button2"";   WebPage =">Left</button></a></p>";   WebPage ="</td><td>";   WebPage ="<p><a href="/stop"><button class=";   if(CurentButtonActive=="stop")    WebPage =""button"";   else    WebPage =""button button2"";   WebPage =">Stop</button></a></p>";   WebPage ="</td><td>";   WebPage ="<p><a href="/right"><button class=";   if(CurentButtonActive=="right")    WebPage =""button"";   else    WebPage =""button button2"";   WebPage =">Right</button></a></p>";   WebPage ="</td></tr><tr><td>";   WebPage ="</td><td>";   WebPage ="<p><a href="/back"><button class=";   if(CurentButtonActive=="back")    WebPage =""button"";   else    WebPage =""button button2"";   WebPage =">Back</button></a></p>";   WebPage ="</td><td>";   WebPage ="</td></tr></table></div>";      WebPage ="</body></html>";   returnWebPage;}

Коробка для электроники
После того, как программа зашита в NodeMCU, настало время соединить все детали в схему, описанную выше и разместить ее на тележке.
Для удобного размещения электроники я использовала такую макетную плату.

pic32.jpg

К ней припаяны разъемы, в которые втыкаются контакты плат Arduino и NodeMCU.

pic33.jpg

pic34.jpg

Так что можно собрать всю схему и воткнуть нужные провода в разъемы рядом с контактами платы. Платы, таким образом, свободно можно вытаскивать и прошивать в них программы без необходимости постоянно подключать и отключать провода от их контактов.

Вот вся наша электроника в собранном по схеме выше виде:

pic35.jpg

Теперь нужно как-то аккуратно и красиво разместить ее на тележке.
Для этого из куска картона делаем коробочку с нужными размерами:
140/110/60.

pic36.jpg

Вот что получается в результате.

pic37.jpg

Включаем механизм…
Берем мобильный телефон и находим в нем сеть Wifi «ESP8266Net». Коннектимся к ней, указав пароль «ESP12345».
Открываем в телефоне броузер и в строке адреса набираем номер IP: «192.168.4.1».
Открывается такая страница:

pic38.jpg

Если при нажатии на кнопки машинка реагирует и двигается в нужную сторону — все правильно и можно переходить к установке робо-руки.

Робот-манипулятор MeArm
Это довольно известный робот-манипулятор, который можно купить в магазинах робототехники, радиорынках, Алиэкспрессе и т. д.
Он представляет из себя конструктор из деталей, которые соединяются между собой винтиками по схеме. Им управляют четыре сервомотора «Tower Pro Mikro Servo 9G SG90».

pic39.jpg

Один мотор осуществляет круговое вращение, второй — движение вверх-вниз, третий — вперед-назад, четвёртый — открывает-закрывает клешню.
От каждого из них отходят три провода.
Красный — питание.
Коричневый — земля.
Желтый — сигнальный или информационный провод, по которому подаются команды на какой угол совершить оборот двигателю, а значит должы присоединяться к аналоговым контактам.

pic40.jpg

Питаются моторы от 5В.
Таким образом, теоретически можно их запитать от контакта Arduino 5V. Но на практике этого делать не рекомендуется, потому, что при включении и выключении Arduino могут быть резкие скачки напряжения, а также они наблюдаются если моторы дошли до максимального или минимального угла поворота, а программа подает сигнал вращаться. Чтобы избежать перегорания моторов подключим их к батарейке через стабилизатор.

pic41.jpg

Мы его сами спаяли. Это стабилизатор LM7805. У него 3 контакта. На первый подаем напряжение 7.2В от шести батареек, 2 — GND, 3 — выходной контакт, дающий 5 В, от которого питаем все 4 мотора роборуки. Между 1 и 2 контактом припаян конденсатор на 47мФ, между 2 и 3 на 100мФ.

pic42.jpg

Теперь нужно проверить работу всех моторов роборуки, прежде чем включать ее в схему с тележкой.
Для этого мы берем только плату Arduino, роборуку MeArm, блок батареек на 7.2 В и описанный выше стабилизатор.
Собираем с ними такую схему:

pic43.jpg

pic50.jpg

Заливаем в Arduino программу, по которой роборука по-очереди вращает все моторы. Сначала вращается в одну сторону, потом в другую, потом поднимается вверх, опускается вниз, потом выдвигается вперед-назад, открывает клешню и закрывает (к статье прилагается файл с кодом «sketch_MeArmServoTest.ino»):

/*Программа для робота-манипулятора MeArm. Получает данные от четырёх аналоговых контактов платы Arduino. Каждый из этих контактов задает вращение сервомоторов, управляющих роборукой.*///подключаем библиотеку servo#include<Servo.h>/*определяем ключевые слова (INI — начальное положение мотора, MAX — максимальное положение мотора, MIN — минимальное положение мотора, CUR — текущее положение мотора), которые будут использоваться как индексы для доступа к цифрам, своим для каждого мотора*/#defineINI0#defineMAX1#defineMIN2#defineCUR3/*константные глобальные переменные хранящие время задержки в мс*/constintdelay_move=50;constintdelay_setup=100;constintmotor_step=1;/*Структура, хранящая всю необходимую информацию о моторе*/structSERVO_MOTOR{//объект мотора servo  Servoservo_obj;/*массив целочисленных переменных, у которого  0й элемент   (соответствует INI) — это начальное положение мотора,  1й (MAX) — максимально возможное,  2й (MIN) — минимально возможное,  3й (CUR) — текущее положение.*/  intpositions_data[4]={0,0,0,0};};//создаём четыре объекта структуры SERVO_MOTORSERVO_MOTORservo_round,servo_up,servo_front,servo_hand;/*функция InitServoObjects содержит начальную инициализацию всех четырёх моторов*/voidInitServoObjects(){   //Инициируем объект servo_round    servo_round.positions_data[INI]=90;  //начальный угол поворота  servo_round.positions_data[MAX]=170;//максимальный угол поворота  servo_round.positions_data[MIN]=30;//минимальный угол поворот  servo_round.positions_data[CUR]=servo_round.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_round.servo_obj.attach(A0);//устанавливаем мотор на начальный угол поворота  servo_round.servo_obj.write(servo_round.positions_data[INI]);  //задержка  delay(delay_setup);  //Инициируем объект servo_up  servo_up.positions_data[INI]=110;  //начальный угол поворота  servo_up.positions_data[MAX]=160;//максимальный угол поворота  servo_up.positions_data[MIN]=80;//минимальный угол поворот  servo_up.positions_data[CUR]=servo_round.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_up.servo_obj.attach(A1);//устанавливаем мотор на начальный угол поворота  servo_up.servo_obj.write(servo_up.positions_data[INI]);//задержка  delay(delay_setup);  //Инициируем объект servo_front  servo_front.positions_data[INI]=90;  //начальный угол поворота  servo_front.positions_data[MAX]=160;//максимальный угол поворота  servo_front.positions_data[MIN]=90;//минимальный угол поворот  servo_front.positions_data[CUR]=servo_round.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_front.servo_obj.attach(A2);//устанавливаем мотор на начальный угол поворота  servo_front.servo_obj.write(servo_front.positions_data[INI]);//задержка  delay(delay_setup);   //Инициируем объект servo_hand  servo_hand.positions_data[INI]=40;  //начальный угол поворота  servo_hand.positions_data[MAX]=40;//максимальный угол поворота  servo_hand.positions_data[MIN]=0;//минимальный угол поворот  servo_hand.positions_data[CUR]=servo_round.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino D7  servo_hand.servo_obj.attach(A3);//устанавливаем мотор на начальный угол поворота  servo_hand.servo_obj.write(servo_hand.positions_data[INI]);//задержка  delay(delay_setup);}/*стандартная функция с начальной инициализацией всех компонентов программы*/voidsetup(){  //инициируем все объекты в отдельной функции  InitServoObjects();}/*стандартная функция с реализацией программы, в которой все действия циклически повторяются*/voidloop(){for(inti=servo_round.positions_data[INI];i<=servo_round.positions_data[MAX];i ){   servo_round.servo_obj.write(i);   delay(delay_move);}for(inti=servo_round.positions_data[MAX];i>=servo_round.positions_data[MIN];i--){   servo_round.servo_obj.write(i);     delay(delay_move);}for(inti=servo_round.positions_data[MIN];i<=servo_round.positions_data[INI];i ){   servo_round.servo_obj.write(i);     delay(delay_move);}for(inti=servo_up.positions_data[INI];i<=servo_up.positions_data[MAX];i ){   servo_up.servo_obj.write(i);     delay(delay_move);}for(inti=servo_up.positions_data[MAX];i>=servo_up.positions_data[MIN];i--){   servo_up.servo_obj.write(i);     delay(delay_move);}for(inti=servo_up.positions_data[MIN];i<=servo_up.positions_data[INI];i ){   servo_up.servo_obj.write(i);     delay(delay_move);}for(inti=servo_front.positions_data[INI];i<=servo_front.positions_data[MAX];i ){   servo_front.servo_obj.write(i);     delay(delay_move);}for(inti=servo_front.positions_data[MAX];i>=servo_front.positions_data[MIN];i--){   servo_front.servo_obj.write(i);     delay(delay_move);}for(inti=servo_hand.positions_data[INI];i>=servo_hand.positions_data[MIN];i--){   servo_hand.servo_obj.write(i);     delay(delay_move);}  for(inti=servo_hand.positions_data[MIN];i<=servo_hand.positions_data[MAX];i ){   servo_hand.servo_obj.write(i);     delay(delay_move);}}

Если роборука отрабатывает программу, значит все работает хорошо и пора переходить к программированию передачи сигналов от NodeMCU к Arduino для управления робо-рукой.

SPI интерфейс передачи данных
SPI (serial peripheral interface, последовательный периферийный интерфейс) — это протокол подключения к шине, передающей данные по типу «ведущий-ведомый». Он был разработан корпорацией Motorola. Шина содержит 4 провода для связи. По ней могут взаимодействовать одновременно только 1 ведущее (master) и 1 ведомое устройство (slave). Соответственно, устройства с поддержкой SPI могут работать в одном из двух режимов — Master mode и Slave mode. Главное устройство инициирует связь , генерирует последовательный счетчик времени для синхронной передачи данных и может работать с несколькими ведомыми устройствами, выбирая одно из них.
И NodeMCU и Arduino поддерживают этот интерфейс. У NodeMCU есть две шины SPI — которые называются SPI и HSPI. SPI используется процессором для доступа к флешу с прошивкой, HSPI может использоваться для других устройств.
Связь Arduino и NodeMCU через интерфейс SPI осуществляется через следующие четыре контакта:

Для обеспечения связи по SPI интерфейсу соединяются соответствующие контакты NodeMCU и Arduino (D5-D13, D6 — D12, D7-D11, D8-D10, GND-GND).
Теперь, прежде чем собирать окончательную схему и заливать программы, нужно проверить как работает SPI связь.

Заливаем программу в NodeMCU (к статье прилагается файл с кодом «sketch_SPITestMaster.ino»):

Заливаем программу в ArduinoUNO (к статье прилагается файл с кодом «sketch_SPITestSlave.ino»):

Собираем схему:

pic46.jpg

Затем подключаем обе платы по мини и микро USB к компьютеру.

pic47.jpg

Открываем Монитор порта для Arduino.
На нем должны отображаться команды, передаваемые с платы NodeMCU через SPI шину каждую секунду.

pic48.jpg

Если все отображается, значит SPI интерфейс работает как надо и можно переходить к окончательному сбору схемы робота и его программированию.

Окончательная схема
Окончательная схема робомашинки с самодельным драйвером моторов выглядит так:

pic49.jpg

Та же схема, но с драйвером L298N который можно купить на рынке:

pic50.jpg

Программа для Arduino (к статье прилагается файл с кодом «sketch_RobocarMeArm_ForArduino.ino»):

/*Программа для робота-манипулятора MeArm. Получает данные от четырёх аналоговых контактов платы NodeMCU. Каждый из этих контактов задает вращение сервомоторов, управляющих роборукой.*///подключаем библиотеку servo#include<Servo.h>#include<SPI.h>/*определяем ключевые слова (INI — начальное положение мотора, MAX — максимальное положение мотора, MIN — минимальное положение мотора, CUR — текущее положение мотора), которые будут использоваться как индексы для доступа к цифрам, своим для каждого мотора*/#defineINI0#defineMAX1#defineMIN2#defineCUR3/*константные глобальные переменные хранящие время задержки в мс*/constintdelay_move=10;constintdelay_setup=100;constintmotor_step=1;charbuff[5];volatilebyteindex;volatileboolreceivedone;  /* use reception complete flag */StringcommandSPI="";/*Структура, хранящая всю необходимую информацию о моторе*/structSERVO_MOTOR{//объект мотора servo  Servoservo_obj;/*массив целочисленных переменных, у которого  0й элемент   (соответствует INI) — это начальное положение мотора,  1й (MAX) — максимально возможное,  2й (MIN) — минимально возможное,  3й (STP) — единицы соответствующие шагу в 1 градус,  4й (CUR) — текущее положение.*/  intpositions_data[5]={0,0,0,0};};//создаём четыре объекта структуры SERVO_MOTORSERVO_MOTORservo_round,servo_up,servo_front,servo_hand;/*функция InitServoObjects содержит начальную инициализацию всех четырёх моторов*/voidInitServoObjects(){   //Инициируем объект servo_round    servo_round.positions_data[INI]=90;  //начальный угол поворота  servo_round.positions_data[MAX]=180;//максимальный угол поворота  servo_round.positions_data[MIN]=0;//минимальный угол поворот  servo_round.positions_data[CUR]=servo_round.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_round.servo_obj.attach(A0);//устанавливаем мотор на начальный угол поворота  servo_round.servo_obj.write(servo_round.positions_data[INI]);  //задержка  delay(delay_setup);  //Инициируем объект servo_up  servo_up.positions_data[INI]=100;  //начальный угол поворота  servo_up.positions_data[MAX]=160;//максимальный угол поворота  servo_up.positions_data[MIN]=60;//минимальный угол поворот  servo_up.positions_data[CUR]=servo_up.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_up.servo_obj.attach(A1);//устанавливаем мотор на начальный угол поворота  servo_up.servo_obj.write(servo_up.positions_data[INI]);//задержка  delay(delay_setup);  //Инициируем объект servo_front  servo_front.positions_data[INI]=90;  //начальный угол поворота  servo_front.positions_data[MAX]=160;//максимальный угол поворота  servo_front.positions_data[MIN]=90;//минимальный угол поворот  servo_front.positions_data[CUR]=servo_front.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino  servo_front.servo_obj.attach(A2);//устанавливаем мотор на начальный угол поворота  servo_front.servo_obj.write(servo_front.positions_data[INI]);//задержка  delay(delay_setup);   //Инициируем объект servo_hand  servo_hand.positions_data[INI]=40;  //начальный угол поворота  servo_hand.positions_data[MAX]=40;//максимальный угол поворота  servo_hand.positions_data[MIN]=0;//минимальный угол поворот  servo_hand.positions_data[CUR]=servo_hand.positions_data[INI];//текущий угол поворота//назначаем объекту класса servo контакт Arduino D7  servo_hand.servo_obj.attach(A3);//устанавливаем мотор на начальный угол поворота  servo_hand.servo_obj.write(servo_hand.positions_data[INI]);//задержка  delay(delay_setup);}/*стандартная функция с начальной инициализацией всех компонентов программы*/voidsetup(){//инициируем все объекты в отдельной функции  InitServoObjects();  SPCR|=bit(SPE);         /* Enable SPI */  pinMode(MISO,OUTPUT);    /* Make MISO pin as OUTPUT */  index=0;  receivedone=false;  SPI.attachInterrupt();    /* Attach SPI interrupt */}/*стандартная функция с реализацией программы, в которой все действия циклически повторяются*/voidloop(){  if(receivedone)            {    buff[index]=0;        commandSPI=buff;        index=0;    receivedone=false;  }  if(commandSPI=="stp")  {      }  elseif(commandSPI=="rd1")  {    if((servo_round.positions_data[CUR] motor_step)<=servo_round.positions_data[MAX]  )    {      servo_round.positions_data[CUR]=servo_round.positions_data[CUR] motor_step;      servo_round.servo_obj.write(servo_round.positions_data[CUR]);    }    else      commandSPI="stp";  }  elseif(commandSPI=="rd2")  {   if((servo_round.positions_data[CUR]-motor_step)>=servo_round.positions_data[MIN]  )   {     servo_round.positions_data[CUR]=servo_round.positions_data[CUR]-motor_step;     servo_round.servo_obj.write(servo_round.positions_data[CUR]);   }   else      commandSPI="stp";  }  elseif(commandSPI=="up")  {    if((servo_up.positions_data[CUR] motor_step)<=servo_up.positions_data[MAX]  )    {      servo_up.positions_data[CUR]=servo_up.positions_data[CUR] motor_step;      servo_up.servo_obj.write(servo_up.positions_data[CUR]);    }    else      commandSPI="stp";  }  elseif(commandSPI=="dwn")  {    if((servo_up.positions_data[CUR]-motor_step)>=servo_up.positions_data[MIN]  )    {      servo_up.positions_data[CUR]=servo_up.positions_data[CUR]-motor_step;      servo_up.servo_obj.write(servo_up.positions_data[CUR]);    }        else      commandSPI="stp";  }  elseif(commandSPI=="frt")  {    if((servo_front.positions_data[CUR] motor_step)<=servo_front.positions_data[MAX]  )   {     servo_front.positions_data[CUR]=servo_front.positions_data[CUR] motor_step;     servo_front.servo_obj.write(servo_front.positions_data[CUR]);   }   else      commandSPI="stp";  }  elseif(commandSPI=="bck")  {   if((servo_front.positions_data[CUR]-motor_step)>=servo_front.positions_data[MIN]  )   {     servo_front.positions_data[CUR]=servo_front.positions_data[CUR]-motor_step;     servo_front.servo_obj.write(servo_front.positions_data[CUR]);   }   else      commandSPI="stp";  }  elseif(commandSPI=="opn")  {    if((servo_hand.positions_data[CUR]-motor_step)>=servo_hand.positions_data[MIN]  )   {     servo_hand.positions_data[CUR]=servo_hand.positions_data[CUR]-motor_step;     servo_hand.servo_obj.write(servo_hand.positions_data[CUR]);   }   else      commandSPI="stp";    }  elseif(commandSPI=="cls")  {     if((servo_hand.positions_data[CUR] motor_step)<=servo_hand.positions_data[MAX]  )     {       servo_hand.positions_data[CUR]=servo_hand.positions_data[CUR] motor_step;       servo_hand.servo_obj.write(servo_hand.positions_data[CUR]);     }     else        commandSPI="stp";  }  delay(delay_move);}// Обработчик прерывания по SPIISR(SPI_STC_vect){  uint8_toldsrg=SREG;  cli();  charc=SPDR;  if(index<sizeofbuff)  {    if(c=='n'){     /* Check for newline character as end of msg */     receivedone=true;    }    else      buff[index ]=c;  }  SREG=oldsrg;}

Программа для NodeMCU (к статье прилагается файл с кодом «sketch_RobocarMeArm_ForNodeMCU.ino»):

/*Программа для робота-машинки. Вращается машинка благодаря двум моторам-редукторам, управляемым этой программой для NodeMCU(контакты D0-D3).Еще программа передает команды по SPI интерфейсу плате Arduino для управления четырьмя моторами робота-руки MeArm.NodeMCU создает программную точку доступа Wifi и запускает сервер, генерит html страницу на этом сервере, содержащую кнопки управления моторами. Через телефон или планшет происходит подключение по Wifi к плате и через эту страницу на сервереуправляются моторы*//*Подключаем библиотеки для Wifi, сервера, SPI интерфейса*/#include<ESP8266WiFi.h>#include<WiFiClient.h>#include<ESP8266WebServer.h>#include<SPI.h>//контакты, управляющие вращением моторов тележки#definepin_Moror1_front16//D0 NodeMCU#definepin_Moror1_back5//D1#definepin_Moror2_front4//D2#definepin_Moror2_back0//D3//название и пароль создаваемой программной точки доступа Wificonstchar*ssid="ESP8266Net";constchar*password="ESP12345";//Переменные строки, указывающие какая кнопка нажата в данный моментStringCurentButtonActive="stop";StringCurentArmButtonActive="stop";/* Устанавливаем свой веб сервер на порт 80*//* По-умолчанию сервер доступен по IP http://192.168.4.1 */ESP8266WebServerserver(80);voidsetup(){  /*Устанавливаем параметры контактов - выходный и выключены*/  pinMode(pin_Moror1_front,OUTPUT);  pinMode(pin_Moror1_back,OUTPUT);  pinMode(pin_Moror2_front,OUTPUT);  pinMode(pin_Moror2_back,OUTPUT);    digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,LOW);    /* Создаем мягкую точку доступа Wifi.  WiFi.softAP(ssid, password, channel, hidden, max_connection)  ssid - строка, содержащая сетевоt имя Wifi (макс. 31 символ)  password - необязательная символьная строка с паролем.  channel - необязательный параметр для установки канала Wi-Fi, от 1 до 13. Канал по умолчанию = 1.  hidden - необязательный параметр, если установлено значение true, будет скрывать SSID.  max_connection - необязательный параметр для установки макс. одновременных подключенных станций, от 0 до 8.   По умолчанию 4.   После достижения максимального числа любая другая станция,
которая хочет подключиться, будет вынуждена ждать, пока уже подключенная станция не отключится.  */    WiFi.softAP(ssid,password,1,0,1);  //Привязываем функции-обработчики полученных команд от колес  server.on("/",onRestart);  server.on("/stop",onStop);  server.on("/front",onFront);  server.on("/back",onBack);  server.on("/left",onLeft);  server.on("/right",onRight);  //Привязываем функции-обработчики полученных команд от роборуки  server.on("/armstop",onArmStop);  server.on("/armround1",onArmRound1);  server.on("/armround2",onArmRound2);  server.on("/armup",onArmUp);  server.on("/armdwn",onArmDown);  server.on("/armfront",onArmFront);  server.on("/armback",onArmBack);  server.on("/armopn",onArmOpen);  server.on("/armcls",onArmClose);   //Запускаем сервер  server.begin();  //Запускаем SPI интерфейс  SPI.begin();}voidloop(){  //Прослушивание клиентов  server.handleClient();}voidonSendWebPage(){  /*Вызываем функцию, перерисовывающую html страницу*/  server.send(200,"text/html",createWebPage());  delay(5);}voidonRestart(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="stop";  CurentArmButtonActive="stop";  charbuff[]="armstopn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  onSendWebPage();}voidonStop(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="stop";  onSendWebPage();}voidonFront(){    digitalWrite(pin_Moror1_front,HIGH);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,HIGH);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="front";  onSendWebPage();}voidonBack(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,HIGH);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,HIGH);  CurentButtonActive="back";  onSendWebPage();}voidonLeft(){  digitalWrite(pin_Moror1_front,LOW);  digitalWrite(pin_Moror1_back,HIGH);  digitalWrite(pin_Moror2_front,HIGH);  digitalWrite(pin_Moror2_back,LOW);  CurentButtonActive="left";  onSendWebPage();}voidonRight(){  digitalWrite(pin_Moror1_front,HIGH);  digitalWrite(pin_Moror1_back,LOW);  digitalWrite(pin_Moror2_front,LOW);  digitalWrite(pin_Moror2_back,HIGH);  CurentButtonActive="right";  onSendWebPage();}voidonArmStop(){  charbuff[]="stpn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="stop";  onSendWebPage();}voidonArmRound1(){  charbuff[]="rd1n";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="round1";  onSendWebPage();}voidonArmRound2(){  charbuff[]="rd2n";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="round2";  onSendWebPage();}voidonArmUp(){  charbuff[]="upn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="up";  onSendWebPage();}voidonArmDown(){  charbuff[]="dwnn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="down";  onSendWebPage();}voidonArmFront(){  charbuff[]="frtn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="front";  onSendWebPage();}voidonArmBack(){  charbuff[]="bckn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="back";  onSendWebPage();}voidonArmOpen(){  charbuff[]="opnn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="open";  onSendWebPage();}voidonArmClose(){  charbuff[]="clsn";  for(inti=0;i<sizeofbuff;i )     SPI.transfer(buff[i]);  CurentArmButtonActive="close";  onSendWebPage();}StringcreateWebPage(){  /*Создается html страница, которая будет открываться на установленном сервере*/  StringWebPage="";   // Отображаем страницу HTML   WebPage ="<!DOCTYPE html><html>";   WebPage ="<head><meta name='viewport' content='width=device-width, initial-scale=1'>";              // CSS для стиля кнопок on/off    WebPage ="<style>html { font-family: Helvetica; display: inline-block; margin: 0px auto; text-align: center;}";   WebPage =".button { background-color: #195B6A; border: none; color: white; width: 80px;  padding: 7px 0px;";   WebPage =" text-decoration: none; font-size: 15px; margin: 2px; cursor: pointer;}";   WebPage =".button2 {background-color: #77878A;}</style>";         // Заголовок для страницы   WebPage ="</head><body><div align='center'>";   WebPage ="<table align='center'  valign = 'top'><tr><td>";   WebPage ="<table align='center'  valign = 'top'><tr><td>";   WebPage ="<table align='center'  valign = 'top'><tr><td>";   WebPage ="<a href='/armround1'><button class=";   if(CurentArmButtonActive=="round1")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Round1</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/armround2'><button class=";  if(CurentArmButtonActive=="round2")    WebPage ="'button'";  else    WebPage ="'button button2'";   WebPage =">Round2</button></a>";   WebPage ="</td><tr><td>";   WebPage ="<a href='/armup'><button class=";   if(CurentArmButtonActive=="up")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Up</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/armdwn'><button class=";   if(CurentArmButtonActive=="down")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Down</button></a>";   WebPage ="</td></tr></table>";   WebPage ="</td></tr><tr><td align ='center'>";   WebPage ="<a href='/armstop'><button class=";   if(CurentArmButtonActive=="stop")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Stop</button></a>";   WebPage ="</td></tr><tr><td>";   WebPage ="<table   align='center'  valign = 'top'><tr><td>";      WebPage ="<a href='/armfront'><button class=";   if(CurentArmButtonActive=="front")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Front</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/armback'><button class=";   if(CurentArmButtonActive=="back")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Back</button></a>";   WebPage ="</td><tr><td>";   WebPage ="<a href='/armopn'><button class=";   if(CurentArmButtonActive=="open")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Open</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/armcls'><button class=";   if(CurentArmButtonActive=="close")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Close</button></a>";   WebPage ="</td></tr></table>";   WebPage ="</td></tr></table>";   WebPage ="</td><td><table>";   WebPage ="<tr><td></td><td>";   WebPage ="<a href='/front'><button class=";   if(CurentButtonActive=="front")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Front</button></a>";   WebPage ="</td><td></td></tr><tr><td>";   WebPage ="<a href='/left'><button class=";   if(CurentButtonActive=="left")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Left</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/stop'><button class=";   if(CurentButtonActive=="stop")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Stop</button></a>";   WebPage ="</td><td>";   WebPage ="<a href='/right'><button class=";   if(CurentButtonActive=="right")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Right</button></a>";   WebPage ="</td></tr><tr><td></td><td>";   WebPage ="<a href='/back'><button class=";   if(CurentButtonActive=="back")    WebPage ="'button'";   else    WebPage ="'button button2'";   WebPage =">Back</button></a>";   WebPage ="</td><td></td></tr></table>";   WebPage ="</td></tr></table>";      WebPage ="</div></body></html>";   returnWebPage;}

Я спаяла схему на макетной плате, соединив нужные контакты с обратной стороны.

pic52.jpg

pic53.jpg

Подключаем все по схеме, включаем робота, при этом роборука должна перейти в исходное положение.
Затем берем мобильный телефон, идем в поиск сетей Wifi. Находим сеть «ESP8266Net», подключаемся введя пароль «ESP12345».
Открываем броузер и в строке адреса вводим: «192.168.4.1».
Отобразится html страница:

pic54.jpg

Справа кнопки управляют колесами машины, слева — роборукой.
Робомашинка готова к использованию.

pic55.jpg

Смотрите про коптеры:  Что такое маршрутизатор в роботе пылесосе xiaomi
Оцените статью
Радиокоптер.ру
Добавить комментарий