Автомобиль с видеокамерой. Управление через WiFi. Управление машинкой через WiFi с помощью ESP8266 NodeMCU

Это небольшой рассказ о том, как построить робота в виде игрушечного автомобильчика с видео камерой, которым можно управлять с помощью компьютера или смартфона на ОС Android через WiFi. Устройство не имеет никакой автономности в смысле своего поведения (типа распознавания чего-либо), управление - только от человека, поэтому «робот» - это не совсем подходящее слово в названии.
Началось все с того, что идея управления игрушечными устройствами от первого лица (т.н. FPV) мне показалась чрезвычайно интересной с точки зрения собственно процесса. Ведь мы можем таким образом реализовать свое присутствие, не в виртуальном мире, а в реальном.
Проще и быстрее всего применить эту идею на игрушечных или модельных автомобилях. Текущие технологии должны давать такую возможность промышленности и предложить массу подобных вещей. Однако это предложение оказалось достаточно дорогим по сравнению тем что можно сделать самому.
Так как это мой первый проект, я ни программировать, ни даже паять нормально не умел, и я решил сначала поискать в интернете единомышленников и их варианты решения данной задачи.
Начав изучение вариантов, как можно осуществить эту идею, я нашел очень подробное описание подобного проекта . A его автор с радостью помог мне разобраться в проблемах, возникших при создании робота.
Так я впервые и узнал что такое …duino. Так как это был уже готовый вариант микроконтроллера, где не нужно было паять обвязку к нему, я выбрал именно его. Также очень понравилось присутствие бутлоадера, позволяющего прошивать микроконтроллер без программаторов.

Для реализации данного проекта понадобится:

  • Микроконтроллер Arduino (любой: nano, uno, mega)
  • Аккумулятор 9,6вольт
  • Китайская машинка на радиоуправлении
  • Роутер dir320 (или любой другой поддерживающий OPEN-WRT прошивку)
  • Вебкамера Logitech c310 или любая другая с UVC потоком






Программ пять: на PC, на Android, на роутере (сервер управления и видеопоток), и в микропроцессоре.
Схема работы: соединяем настольный компьютер (ноутбук, далее - PC) с роутером по WiFi. На роутере при его включении автоматически загружаются 2е программы:
1) сервер. Эта программа открывает сокет (соединение) на определенном порту и ждет, когда по этому порту с ней соединится клиент (любая программа, которая обратится в этот порт и также, особым образом скажет серверу, что она готова работать через открытый сокет). Далее, после установки соединения, все что придет от клиента, будет перенаправлено по определенному пути, для нас это COM-порт, на этом порту подключен микропроцессор. И наоборот, все что придет со стороны COM-порта, будет переслано клиенту.
2) программа обработки видео, захватывает его с usb камеры и шлет на определенный порт. Для его просмотра нужно всего лишь иметь соединение с роутером на этом порту.
После того, как между компьютером и роутером установлено WiFi-соединение, запускаем на PC программу для управления роботом (тот самый клиент), эта программа соединяется с программой-сервером на роутере. Эта же или другая программа транслирует видео с WiFi роутера.
Далее, пользователь может управлять автомобильчиком и нажимает, например, кнопку «вперед». Программа на PC, отсылает команду «вперед» прямо на роутер, на его IP, но на определенный порт. На роутере, эта команда поступает в программу-сервер, т.к. выслана она на его порт, и в рамках открытого для этого сокета. Программа-сервер, ничего не делая с этой командой, просто отправляет её в COM-порт. Таким образом, команда «вперед» оказывается в микропроцессоре, который в ответ на нее, дает сигнал «вперед» на один из своих выводов. К таким выводам процессора подсоединена схема управления двигателями, т.к. сам микропроцессор управлять ими не может в силу своей маломощности.
Управлять исполнительным устройством через роутер, без микропроцессора не получится, т.к. микропроцессор может формировать сигналы «1» (напряжение >2,5v) или «0» (меньше обозначенного) на любом из десятка-другого своих выводов. У роутера же выводов нет, есть только порты ввода/вывода, типа USB или COM (serial), в которых по 2-3 провода.
Теперь часть практическая. Заранее скажу, что несмотря на кажущиеся сложности, все на самом деле просто, если речь идет о простом копировании этого проекта – ведь все уже сделано и работает. Нужно просто выполнить в точности эту инструкцию.
Изначально микроконтроллером был freeduino maxserial у которого был com port, который был одним из немногих(как я тогда считал) для подключения к uart роутеру, для этого нужно было паять переходник с uarta на com чтобы соединить его с роутером. Его брать я не очень хотел, так как оригиналом есть все-таки Arduino, да и Freeduino в Украине нет.



Как я выяснил потом, все было это просто излишнее нагромождение схемы. Обойтись можно всего 1 проводком который будет идти от TX роутера(на рисунке) к RX (0 пин) микроконтроллера.
Непонятно почему но на фридуине оказалось для нормального подключения нужно tx на tx. Скорее всего просто неверно нанесено обозначение. (тут 0 пин tx) По этому лучше брать оригинальный .
Машинку я купил хорошую, хоть и китайскую



Машинка оказалась очень мощная, 5 кг на ровной поверхности тянула очень уверено. Также у нее в комплекте шел аккумулятор на 6 вольт. Что касается электроники, то в машинке уже есть готовый драйвер двигателей, на который можно подать управляющие слаботочные выходы с микроконтроллера (если бы с машинкой не повезло - драйвер моторов можно было взять тоже от arduino)
Роутер требует прошивку openwrt и список пакетов указанных на рисунке.



Роутер можно настроить как точку доступа, которой могут подключится любые устройства, имеющие WiFi. И, даже если не будет программного обеспечения для управлении машинкой – использовать ее как беспроводную камеру видеонаблюдения.
Камера с310 просто подключается к порту usb на роутер и не требует пайки, требует небольших настроек в роутере. Проект имеет 2 цепи питания, 1 цепь питается от 9,6 вольт - роутер и микроконтроллер, 2 цепь питается от 6 вольт - привод и рулевое машинки. Можно обойтись всего 1 источником питания в 9,6 вольт, но более емкостным. Роутер потребляет 2А, микроконтроллер потребляет почти незаметно, машинка 4А.
Программа микроконтроллера обрабатывает сообщения, которые приходят с последовательного порта роутера, обработка происходит побайтово через portb arduino, например если пришло в роутер 2, то, переведя в двоичную систему получаем 00000010 – что соответствует 2 пину на portb. Такое решение позволяет управлять одновременно несколькими пинами. Вот что получилось в итоге:




Приложение для андроид:



Приложение для пк:




Данный проект еще не закончен и продолжает совершенствоваться.
В планах использовать arduino mega, роутер mr3020, вебакамеру оставить как есть(возможно добавить сферическую линзу для большего обзора), задействовать шим для плавного и точного управления, использовать сервопривод для поворотов, добавить дальномер. Добавить видео на Android.



- полный каталог плат

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

Обзор проекта

Вы можете реализовать эту систему там, где вам нужно включать нагрузку постоянного тока на определенное время. В этом вам поможет наше Android приложение, не требуя аппаратного интерфейса, клавиатуры и LCD дисплея.

Комплектующие

Сборка макетной платы ESP8266

ESP8266 - недорогой SoC-чип со встроенным микроконтроллером и полным стеком протоколов TCP/IP, что означает, что он может напрямую обращаться к вашей Wi-Fi сети.

Поскольку у этого чипа есть свой микроконтроллер, вы можете поместить в него код своего приложения или можете использовать модуль просто как Wi-Fi приемопередатчик, что мы и собираемся сделать в данном проекте. Более эффективно было бы использовать этот модуль и как приемопередатчик, и как контроллер, но в целях обучения мы будем взаимодействовать с модулем, используя Arduino.

Чип ESP8266 поставляется в разных модулях. Мы будем использовать модуль ESP-01. Конечно, вы можете использовать любой другой модуль.

Во-первых, вы должны знать, что модуль работает с напряжением 3,3 В, и напряжение высокого логического уровня от Arduino должно быть таким же, чтобы не повредить наш модуль. Для этого требуется преобразователь уровня напряжения между платой Arduino (которая работает на 5 В) и модулем. Хорошей новостью является то, что в преобразователе будет нуждаться только вывод для передачи на Arduino, поскольку приемный вывод обычно распознает логические сигналы с напряжением 3,3 В от ESP8266.

Одним из простейших способов выполнения этого преобразования является схема от Sparkfun. Вы можете заказать готовый модуль .

Преобразователь уровня 5В → 3,3В

На рисунке ниже показана распиновка нашего модуля на ESP8266:

Вывод Назначение
UTXD Передача данных через UART
URXD Прием данных через UART. Выход, к которому он подключается, должен быть 3,3 В.
CH_PD Выключение: низкий уровень на входе выключает чип, высокий уровень на входе включает его; для нормальной работы модуля необходимо подтянуть его к линии питания.
GPIO0 При загрузке: должен быть высокий уровень, чтобы входить в нормальный режим загрузки; низкий уровень вводит в специальные режимы загрузки.
GPIO2 При загрузке: низкий уровень заставляет загрузчик войти в режим загрузки флеш-памяти; высокий уровень вызывает нормальный режим загрузки.
RST Сброс; активный уровень - низкий.
GND Земля.
VCC Питание/3,3В.

Я использовал LM317, настраиваемый линейный регулятор напряжения с выходным током до 1,5 А, для обеспечения модуля подходящим источником питания 3,3 В.

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

Я использовал BS170 (вместо BSS138) для преобразователя логических уровней; оба работают хорошо.

Теперь вы можете подключить свой модуль к компьютеру, используя USB-TTL преобразователь, и испытать его.

Сборка макетной платы реле

Для управления реле я использовал биполярный NPN транзистор BC337 с резистором 1 кОм на базе. Для защиты от обратного напряжения катушки я использовал диод 1n4007.

Нормально замкнутый (NC) контакт реле я решил подключить к земле.

Код Arduino

Теперь мы сталкиваемся с проблемой. ESP8266 использует UART в качестве интерфейса для AT-команд, а Arduino Uno (которая использует Atmega328) имеет только один порт UART. Этот порт уже подключен к мосту USB-TTL, а также к выводам 0 и 1.

В качестве решения вы можете использовать эмулятор для UART порта на другом цифровом выводе Arduino с помощью библиотек AltSoftSerial или SoftwareSerial. Это позволит вам по-прежнему иметь аппаратный порт UART для отладки и печати сообщений в консоли, а программный порт - для связи с модулем.

Многие люди (включая меня) сообщают о проблемах с программным последовательным портом при высоких скоростях передачи - как на тех, что мы будем использовать с esp8266, 115200 бит/с. Я могу сказать, что у вас 50% принятых от модуля данных будет повреждено, если вы используете программный UART, а из переданных от Arduino к модулю данных почти 100% будет корректно. Я получил эти результаты после отслеживания сигналов на линиях RX и TX.

В качестве решения я добавил в код несколько директив define , чтобы облегчить вам выбор между аппаратным и программным UART портами. Имейте в виду, что вы не можете использовать один и тот же порт для отладки и общения с модулем, поэтому вам нужно выбирать между ними.

//раскомментируйте Serial.*** , если хотите для связи с ESP использовать аппаратный последовательный порт (выводы 0,1) //раскомментируйте esp8266.*** , если хотите для связи с ESP использовать программный последовательный порт (выводы 2,3) #define esp8266_Available() Serial.available() //esp8266.available() #define esp8266_Find(ARG) Serial.find(ARG) //esp8266.find(ARG) #define esp8266_Read() Serial.read() //esp8266.read() #define esp8266_Write(ARG1,ARG2) Serial.write(ARG1,ARG2) //esp8266.write(ARG1,ARG2) #define esp8266_Print(ARG) Serial.print(ARG) //esp8266.print(ARG)

В исходнике вы найдете часть кода, которая устанавливает модуля с вашим роутером:

SendCommand("AT+RST\r\n", 2000, DEBUG); // перезапустить модуль sendCommand("AT+CWMODE=1\r\n", 1000, DEBUG); // настроить как точку доступа sendCommand("AT+CWJAP=\"tur\",\"341983#tur\"\r\n", 3000, DEBUG); //**** ИЗМЕНИТЬ SSID и ПАРОЛЬ В СООТВЕТСТВИИ С ВАШЕЙ СЕТЬЮ ******// delay(10000); sendCommand("AT+CIFSR\r\n", 1000, DEBUG); // получить ip адрес sendCommand("AT+CIPMUX=1\r\n", 1000, DEBUG); // настроить для нескольких соединений sendCommand("AT+CIPSERVER=1,1337\r\n", 1000, DEBUG); // включить сервер на порту 1337

Цикл скетча ожидает команды, которые должны прийти через Wi-Fi соединение. В настоящее время поддерживаются следующие команды:

  • ‘con’ для получения состояния выводов, высокий или низкий логический уровень;
  • ‘on=’ включить соответствующий вывод;
  • ‘of=’ выключить соответствующий вывод;
  • ‘Tm=n/fS’ установить таймер включения (n) или выключения (f) соответствующего вывода.

Все команды имеют отклик подтверждения.

Примечания:

  • некоторые части скетча основаны на ;
  • если вы используете модули со старым SDK, у вас могут быть такие же ошибки, как и у меня. Единственным решением в этом случае является обновление вашей прошивки до последней версии. Посмотрите , для получения помощи в обновлении прошивки модуля на ESP8266. Я обновил прошивку с версии 1.3 до 1.5.4.

Полный код программы:

#include #define DEBUG 0 // если вы для связи с ESP используете аппаратный последовательный порт, измените значение на 0 #define ESPBaudRate 115200 #define HWSBaudRate 115200 #define OUTPUT1 11 #define OUTPUT2 12 #define OUTPUT3 13 //раскомментируйте Serial.*** , если для связи с ESP хотите использовать аппаратный последовательный порт (выводы 0,1) //раскомментируйте esp8266.*** , если для связи с ESP хотите использовать программный последовательный порт (выводы 2,3) #define esp8266_Available() Serial.available() //esp8266.available() #define esp8266_Find(ARG) Serial.find(ARG) //esp8266.find(ARG) #define esp8266_Read() Serial.read() //esp8266.read() #define esp8266_Write(ARG1,ARG2) Serial.write(ARG1,ARG2) //esp8266.write(ARG1,ARG2) #define esp8266_Print(ARG) Serial.print(ARG) //esp8266.print(ARG) // Делает RX линию Arduino выводом 2, а TX линию Arduino выводом 3. // Это означает, что вам необходимо подключить TX линию от ESP к выводу 2 Arduino, // а RX линию от ESP к выводу 3 Arduino. SoftwareSerial esp8266(2, 3); /*************/ byte OUTPUTstate; byte OUTPUTTMRIsSet ; byte OUTPUTTMRState ; long OUTPUTTimer; /*************/ /***Commands**/ String GETSTATE = "con"; // Строка запроса от мобильного приложения, чтобы узнать состояние каждого выхода String SETON = "on="; // Строка запроса от мобильного приложения, чтобы включить выход String SETOFF = "of="; // Строка запроса от мобильного приложения, чтобы выключить выход String TIMER = "tm="; // Строка запроса от мобильного приложения, чтобы задать таймер для выхода /*************/ void setup() { Serial.begin(HWSBaudRate); // Последовательный порт для отправки сообщений от Arduino на компьютер esp8266.begin(ESPBaudRate); // Программный последовательный порт для отправки сообщений от Arduino на ESP8266 pinMode(OUTPUT1, OUTPUT); digitalWrite(OUTPUT1, LOW); pinMode(OUTPUT2, OUTPUT); digitalWrite(OUTPUT2, LOW); pinMode(OUTPUT3, OUTPUT); digitalWrite(OUTPUT3, LOW); // перезапустить модуль sendCommand("AT+RST\r\n", 2000, DEBUG); // настроить как точку доступа sendCommand("AT+CWMODE=1\r\n", 1000, DEBUG); //**** ИЗМЕНИТЬ SSID и ПАРОЛЬ В СООТВЕТСТВИИ С ВАШЕЙ СЕТЬЮ ******// sendCommand("AT+CWJAP=\"tur\",\"341983#tur\"\r\n", 3000, DEBUG); delay(10000); // получить ip адрес sendCommand("AT+CIFSR\r\n", 1000, DEBUG); // настроить для нескольких соединений sendCommand("AT+CIPMUX=1\r\n", 1000, DEBUG); // включить сервер на порту 1337 sendCommand("AT+CIPSERVER=1,1337\r\n", 1000, DEBUG); if (DEBUG == true) Serial.println("Server Ready"); } void loop() { if (esp8266_Available()) // проверить, послал ли esp сообщение { if (esp8266_Find("+IPD,")) { // ждать, когда последовательный буфер заполнится (прочитаются все последовательные данные) delay(1000); // получить id подключения, чтобы мы могли отключиться int connectionId = esp8266_Read() - 48; // вычитаем 48 потому, что функция read() возвращает // десятичное значение в ASCII, а 0 (первое десятичное число) начинается с 48 String closeCommand = "AT+CIPCLOSE="; // создание команды закрытия подключения closeCommand += connectionId; // добавить id подключения closeCommand += "\r\n"; esp8266_Find("?"); // Этот символ определяет начало команды теле нашего сообщения String InStream; InStream = (char) esp8266_Read(); InStream += (char) esp8266_Read(); InStream += (char) esp8266_Read(); if (DEBUG == true) Serial.println(InStream); if (InStream.equals(GETSTATE)) { // отклик на команду Status=<состояние_выхода_1><состояние_выхода_2><состояние_выхода_3> String response = "Status="; response += OUTPUTstate; response += OUTPUTstate; response += OUTPUTstate; sendHTTPResponse(connectionId, response); sendCommand(closeCommand, 1000, DEBUG); // закрыть подключение } else if (InStream.equals(SETON)) { int pinNumber = (esp8266_Read() - 48); // получить первую цифру, т.е., если вывод 13, то 1-ая цифра равна 1 int secondNumber = (esp8266_Read() - 48); if (secondNumber >= 0 && secondNumber <= 9) { pinNumber *= 10; pinNumber += secondNumber; // получить вторую цифру, т.е., если вывод 13, то 2-ая цифра равна 3, // и добавить ее к первой цифре } if (pinNumber == OUTPUT1) OUTPUTstate = 1; else if (pinNumber == OUTPUT2) OUTPUTstate = 1; else if (pinNumber == OUTPUT3) OUTPUTstate = 1; digitalWrite(pinNumber, 1); String response = "Confg="; // Отклик на команду Confg=<номер_вывода> response += pinNumber; sendHTTPResponse(connectionId, response); sendCommand(closeCommand, 1000, DEBUG); // закрыть подключение } else if (InStream.equals(SETOFF)) { int pinNumber = (esp8266_Read() - 48); // получить первую цифру, т.е., если вывод 13, то 1-ая цифра равна 1 int secondNumber = (esp8266_Read() - 48); if (secondNumber >= 0 && secondNumber <= 9) { pinNumber *= 10; pinNumber += secondNumber; // получить вторую цифру, т.е., если вывод 13, то 2-ая цифра равна 3, // и добавить ее к первой цифре } if (pinNumber == OUTPUT1) OUTPUTstate = 0; else if (pinNumber == OUTPUT2) OUTPUTstate = 0; else if (pinNumber == OUTPUT3) OUTPUTstate = 0; digitalWrite(pinNumber, 0); // изменить состояние вывода String response = "Confg="; // Отклик на команду Confg=<номер_вывода> response += pinNumber; sendHTTPResponse(connectionId, response); sendCommand(closeCommand, 1000, DEBUG); // закрыть подключение } else if (InStream.equals(TIMER)) { int pinNumber = (esp8266_Read() - 48); // получить первую цифру, т.е., если вывод 13, то 1-ая цифра равна 1 int secondNumber = (esp8266_Read() - 48); if (secondNumber >= 0 && secondNumber <= 9) { pinNumber *= 10; pinNumber += secondNumber; // получить вторую цифру, т.е., если вывод 13, то 2-ая цифра равна 3, // и добавить ее к первой цифре } if (esp8266_Read() == "n") { if (DEBUG == true) Serial.println("on"); if (pinNumber == OUTPUT1) OUTPUTTMRState = 1; else if (pinNumber == OUTPUT2) OUTPUTTMRState = 1; else if (pinNumber == OUTPUT3) OUTPUTTMRState = 1; } else { if (DEBUG == true) Serial.println("off"); if (pinNumber == OUTPUT1) OUTPUTTMRState = 0; else if (pinNumber == OUTPUT2) OUTPUTTMRState = 0; else if (pinNumber == OUTPUT3) OUTPUTTMRState = 0; } int j = 0; byte Atime; // Таймер может настроен на максимальное значение в 1 сутки // поэтому программа может принять 5 цифр, так как 1 сутки равны 86400 секундам long Time; // Прочитать секунды, значение имеет переменное количество цифр, поэтому читать, пока не получим "s", // что является символом завершения в теле моего сообщения от мобильного телефона while (1) { Time = esp8266_Read(); if (Time == "s") break; Atime[j] = Time - 48 ; j++; } switch (j) // секунды... { case 1: // одна цифра Time = Atime; break; case 2: // две цифры Time = Atime * 10 + Atime; break; case 3: // три цифры Time = Atime * 100 + Atime * 10 + Atime; break; case 4: // четыре цифры Time = Atime * 1000 + Atime * 100 + Atime * 10 + Atime; break; case 5: // пять цифр Time = Atime * 10000 + Atime * 1000 + Atime * 100 + Atime * 10 + Atime[j]; break; } if (DEBUG == true) { Serial.println("Timer:"); Serial.println(Time); } Time = Time * 1000 + millis(); if (DEBUG == true) { Serial.println("Pin:"); Serial.println(pinNumber); } if (pinNumber == OUTPUT1) { OUTPUTTMRIsSet = 1; OUTPUTTimer = Time; } else if (pinNumber == OUTPUT2) { OUTPUTTMRIsSet = 1; OUTPUTTimer = Time; } else if (pinNumber == OUTPUT3) { OUTPUTTMRIsSet = 1; OUTPUTTimer = Time; } String response = "tConfg="; // Отклик на команду tConfg=<номер_вывода> response += pinNumber; sendHTTPResponse(connectionId, response); sendCommand(closeCommand, 1000, DEBUG); // закрыть подключение } else // принята неподдерживаемая команда { String response = "ERROR"; sendHTTPResponse(connectionId, response); sendCommand(closeCommand, 1000, DEBUG); // закрыть подключение } } } /*****Проверить таймер для каждого выхода******/ if (OUTPUTTMRIsSet != 0 && (OUTPUTTimer < millis())) { digitalWrite(OUTPUT1, OUTPUTTMRState); OUTPUTstate = OUTPUTTMRState; OUTPUTTMRIsSet = 0; } if (OUTPUTTMRIsSet != 0 && (OUTPUTTimer < millis())) { digitalWrite(OUTPUT2, OUTPUTTMRState); OUTPUTstate = OUTPUTTMRState; OUTPUTTMRIsSet = 0; } if (OUTPUTTMRIsSet != 0 && (OUTPUTTimer < millis())) { digitalWrite(OUTPUT3, OUTPUTTMRState); OUTPUTstate = OUTPUTTMRState; OUTPUTTMRIsSet = 0; } /***************************************/ } /* Name: sendData Description: Функция, используемая для отправки данных на ESP8266. Params: command - данные/команда для отправки; timeout - время ожидания отклика; debug - печатать в консоль?(true = да, false = нет) Returns: Отклик от esp8266 (если есть отклик) */ String sendData(String command, const int timeout, boolean debug) { String response = ""; int dataSize = command.length(); char data; command.toCharArray(data, dataSize); esp8266_Write(data, dataSize); // передача символов на esp8266 if (debug) { Serial.println("\r\n====== HTTP Response From Arduino ======"); Serial.write(data, dataSize); Serial.println("\r\n========================================"); } long int time = millis(); while ((time + timeout) > millis()) { while (esp8266_Available()) { // У esp есть данные, поэтому вывести их в консоль char c = esp8266_Read(); // прочитать следующий символ. response += c; } } if (debug) { Serial.print(response); } return response; } /* Name: sendHTTPResponse Description: Функция, которая посылает HTTP 200, HTML UTF-8 отклик */ void sendHTTPResponse(int connectionId, String content) { // создать HTTP отклик String httpResponse; String httpHeader; // HTTP заголовок httpHeader = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\n"; httpHeader += "Content-Length: "; httpHeader += content.length(); httpHeader += "\r\n"; httpHeader += "Connection: close\r\n\r\n"; httpResponse = httpHeader + content + " "; // Здесь в коде баг: последний символ в "content" не посылается, поэтому я добавил дополнительный пробел sendCIPData(connectionId, httpResponse); } /* Name: sendCIPDATA Description: посылает команду CIPSEND=,<данные> */ void sendCIPData(int connectionId, String data) { String cipSend = "AT+CIPSEND="; cipSend += connectionId; cipSend += ","; cipSend += data.length(); cipSend += "\r\n"; sendCommand(cipSend, 1000, DEBUG); sendData(data, 1000, DEBUG); } /* Name: sendCommand Description: Функция, используемая для отправки данных на ESP8266. Params: command - данные/команда для отправки; timeout - время ожидания отклика; debug - печатать в консоль?(true = да, false = нет) Returns: Отклик от esp8266 (если есть отклик) */ String sendCommand(String command, const int timeout, boolean debug) { String response = ""; esp8266_Print(command); // передача символов на esp8266 long int time = millis(); while ((time + timeout) > millis()) { while (esp8266_Available()) { // У esp есть данные, поэтому вывести их в консоль char c = esp8266_Read(); // прочитать следующий символ. response += c; } } if (debug) { Serial.print(response); } return response; }

Android приложение

Чтобы управлять всеми выше перечисленными аппаратными компонентами, мы будем использовать простое приложение для Android. Это приложение позволит нам включать или выключать выход напрямую или через определенный период времени.

Примечание: Приложение требует Android 4.0 (IceCreamSandwich) или выше.

  • Прежде всего, вы должны знать IP адрес своего модуля. Если вы использовали программный последовательный порт, IP адрес будет напечатан в консоли. Если вы использовали аппаратный последовательный порт, то вы должны использовать кабель для отслеживания данных на линиях RX и TX, чтобы увидеть IP адрес. Вам также нужно знать номер порта, который был указан в скетче для Arduino. После этого нажмите "connect", чтобы получить состояние всех трех выходов. Вам нужно убедиться, что ваш Wi-Fi роутер включен, и вы подключены к локальной сети.
  • Теперь нажмите на любой переключатель, который вы хотите включить/выключить. Всякий раз, когда захотите, вы можете нажать "refresh", чтобы обновить состояние всех выходов.
  • На вкладке "Timers" вы можете установить любой из этих трех выходов для включения/выключения через определенный промежуток времени (от 0 до 24 часов).
  • После любого действия вы получите сообщение с подтверждением о том, выполнилась ли команда успешно, или возникла какая-то ошибка.

Демонстрационное видео

Вот и всё! Надеюсь, статья оказалась полезной. Оставляйте комментарии!

Итак будем управлять двумя реверсивными (вращение в обе стороны) двигателями: основным и рулевым. Питать их будем от аккумулятора 3,7 В, но можно и до 12 В в принципе подавать, если согласовать питание контроллера или организовать его отдельным аккумулятором.

В силовой части используем простейший миниатюрный драйвер шагового двигателя l9110s или же можно использовать сборку на L293\8 или любой не менее мощный, который вы найдёте. В общем я всё нарисовал на картинке.

Приобрести комплектующие для проекта можно на алиэкспресс:

WiFi контроллер использован мой любимый NodeMCU 0.9 ESP8266 , но можно использовать и меньший размером WeMos D1 mini.

Аккумулятор можно зарядить через микро-USB, после чего он питает драйвер двигателей напрямую и WiFi-контроллер через повышающий преобразователь до 5 В .

Код программы:

#include
const char* ssid = "имя вашей сети вайфай";
const char* password = "пароль вашей сети";
int up = 2; //номера дискретных выходов
int down = 14;
int left = 4;
int right = 12;
// Create an instance of the server
// specify the port to listen on as an argument
WiFiServer server(80);
void setup() {
Serial.begin(9600);
delay(10);
//подготовка выходов
pinMode(up, OUTPUT);
digitalWrite(up, 0);
pinMode(down, OUTPUT);
digitalWrite(down, 0);
pinMode(left, OUTPUT);
digitalWrite(left, 0);
pinMode(right, OUTPUT);
digitalWrite(right, 0);

// Connect to WiFi network
Serial.println();
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);

WiFi.begin(ssid, password);

While (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");

//Запуск сервера
server.begin();
Serial.println("Server started");
//выводим IP адрес в монитор порта
Serial.println(WiFi.localIP());
}
void loop() {
//проверяем подключился ли клиент
WiFiClient client = server.available();
if (!client) {
return;
}

//Ожидаем пока клиент не пришлет какие-нибудь данные
Serial.println("new client");
while(!client.available()){
delay(1);
}

//Чтение первой строки запроса
String req = client.readStringUntil("\r");
Serial.println(req);
client.flush();

//обработка команды
if (req.indexOf("/gpio/up") != -1){
digitalWrite(up, 1);
digitalWrite(down, 0);
delay(1000);
digitalWrite(up, 0);
digitalWrite(down, 0);
}
else if (req.indexOf("/gpio/down") != -1){
digitalWrite(up, 0);
digitalWrite(down, 1);
delay(1000);
digitalWrite(up, 0);
digitalWrite(down, 0);
}
else if (req.indexOf("/gpio/left") != -1){
digitalWrite(up, 1);
digitalWrite(down, 0);
digitalWrite(left, 1);
digitalWrite(right, 0);
delay(1000);
digitalWrite(up, 0);
digitalWrite(down, 0);
digitalWrite(left, 0);
digitalWrite(right, 0);
}
else if (req.indexOf("/gpio/right") != -1){
digitalWrite(up, 1);
digitalWrite(down, 0);
digitalWrite(left, 0);
digitalWrite(right, 1);
delay(1000);
digitalWrite(up, 0);
digitalWrite(down, 0);
digitalWrite(left, 0);
digitalWrite(right, 0);
}
else {
Serial.println("invalid request");
}

Client.flush();
// подготовка к ответу
String s = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n\r\n\r\n ";

S += "


UP
";
s += "
LEFT     ";
s += "RIGHT
";
s += "
DOWN";
s += "
\n";
// Send the response to the client
client.print(s);
delay(1);
Serial.println("Client disonnected");
} Программа написана в Arduino IDE. Как настроить Arduino IDE для работы с контроллером NodeMCU 0.9 ESP8266 посмотрите по ссылке. После загрузки программы в контроллер, монитором порта можно прочитать IP-адрес, который плата получит после соединения с вашим WiFi-роутером. В браузере компьютера необходимо в адресной строке прописать этот адрес и перейти на страницу, которую сгенерирует программа контроллера. Она будет выглядеть следующим образом:

DOWN

При нажатии на ссылку UP, машинка проедет вперед в течении 1сек и остановится. При нажатии на DOWN, машинка 1 секунду будет ехать назад. LEFT - двигатель поворота повернёт колёса влево и машинка проедет 1 сек влево. То же самое и вправо при нажатии на RIGHT.

Вся эта система будет работать только при настроенной WiFi-точке доступа (WiFi-роутере), но в будущем мне интересно поиграться с контроллером NodeMCU 0.9 ESP8266 , который сам будет организовывать точку доступа и выполнять функцию WEB-сервера, тоесть при заходе на его айпи из браузера, будем видеть web-страничку с элементами управления. Так же интересно организовать передачу данных с одного такого контроллера в другой посредством их автономной WiFi-сети.

В этой статье информация о том как собрать свой танк, оснащенный Web Камерой и управляемый посредством Wifi роутера.

Необходимые материалы:

  1. Web Camera
  2. Роутер TP-Link TL-MR3020
  3. Сервоприводы SG90 - 2шт
  4. Camera Platform Anti-Vibration
  5. Аккумулятор 7.2V 5000mah
  6. Аккумулятор 5V 2000mah
  7. Nano 3.0 Atmel ATmega328
  8. L298N motor driver
  9. Провода, термотрубки, USB хаб, диоды и другое.
  10. Платформа на ваш вкус, я выбрал DD1-1

Сборка нашего монстра
Настройка Роутера MR3020.
Первым делом начнем с роутера. Я долго думал что выбрать OR-WRT или CyberWRT. OR-WRT гибок в настройках, но все редактирование и внесения своих настроек осуществляется через терминал с помощи программы Putty. А так как Я боялся на тот момет работать через терминал, Я выбрал где есть графический интерфейс это CyberWRT, плюс возможно подключение через USB порт.
Для того что бы изменить прошивку нашего роутера, нужно скачать прошивку CyberWrt MR3020.

Как мы скачали, делаем следующее:

1) Включить роутер и подождать загрузки.
2) Зайти и залогиниться на 192.168.0.254 (по умолчанию admin\admin)
3) Найти в меню слева System Tools, там пункт System Upgrade и залить прошивку через веб-форму
4) Дождаться перезагрузки (порядка 4х минут)
Роутер готов к настройке.

Можно выбрать один из режимов: «Точка доступа» и «Клиент Wi-Fi сети». Для настройки режима Клиента:
- выберите режим «Клиент Wi-Fi сети»
- IP адрес Вашего устройства (по этому адресу будет доступно Ваше устройство. Постарайтесь выбрать незанятый IP. Например: 192.168.1.100)
- Маска подсети (255.255.255.0)
- Шлюз (например, IP Вашего домашнего роутера или шлюза - 192.168.1.1)
- Тип шифрования (тип шифрования, используемый в Вашей домашней сети)
- Пароль (пароль, для доступа к Вашей домашней сети)

Если сделали все правильно, то у вас пойдет RSS строка в нижней части экрана.

Когда все заработала, у вас появятся раздел модули, там вы находите модуль "РОБОТ". Устанавливайте. Готово.

Подключение L298N, Arduino Nano, MR3020, Камера и другое

На картинке все наглядно показано, но на всякий случай напишу.

Вывод Arduino DIGITAL 4 - к IN1 пину модуля.
Вывод Arduino DIGITAL 5 - к IN2 пину модуля.
Вывод Arduino DIGITAL 6 - к IN3 пину модуля.
Вывод Arduino DIGITAL 7 - к IN4 пину модуля.
Вывод Arduino GND - к GND клеме модуля.
GND клема модуля - Минус аккумулятора.
7.2V клема модуля - Плюс аккумулятора.
RM клема модуля - Правый моторчик.
LM клема модуля - Левый моторчик.
USB порт Arduino - Подключаем к USB хаб
Web Камера - Подключаем к USB хаб
USB хаб - Подключаем к USB роутера

Питание так скажем логистики, осуществляется вторым аккумулятором. Емкость 2000 mA/h 5v, дабы не спалить роутер. Да и с двумя аккумуляторами робот стабильней работает. Так вот, его мы подключаем просто в разъем микро USB. Через USB хаб который подключен к роутету питанию уже получает и камера и наша ардуинка.

Скетч для Arduino Nano
Вам необходима скачать библиотеку CyberLib , она предназначена только для Atmega 328.

/* Версия 1.5 WIFI Tanka на DD1-1 Реализовано: 1) Движение камеры по X и Y 2) Гудок 3) Фары 4) Звук при включении */ #include // Подключаем библиотеку #include // Подключаем библиотеку сервоприводов Servo myservo1; Servo myservo2; long previousMillis; // Нужно для таймера int LedStep = 0; // Счетчик для LED int i; #define robot_go {D4_High; D5_Low; D6_Low; D7_High;} #define robot_back {D4_Low; D5_High; D6_High; D7_Low;} #define robot_stop {D4_Low; D5_Low; D6_Low; D7_Low;} #define robot_rotation_right {D4_High; D5_Low; D6_High; D7_Low;} #define robot_rotation_left {D4_Low; D5_High; D6_Low; D7_High;} #define LED_ON {D13_High;} #define LED_OFF {D13_Low;} #define Headlamp_ON {D8_Low;} #define Headlamp_OFF {D8_High;} #define Buzzer {tone(11, 494, 500);} #define init {D4_Out; D5_Out; D6_Out; D7_Out; D8_Out; D13_Out;} uint8_t inByte; void setup() { myservo1.attach(9); // Подключение сервоприводов к порту myservo2.attach(10); // Подключение сервоприводов к порту D11_Out; D11_Low; // Динамик Headlamp_OFF; // Фары выкл по умолчанию for(uint8_t i=0; i<12; i++) beep(80, random(100, 2000)); //звуковое оповещение готовности робота init; // Инициализация портов //Buzzer; // Инициализация портов динамика UART_Init(57600);// Инициализация порта для связи с роутером wdt_enable (WDTO_500MS); } void loop() { unsigned long currentMillis = millis(); // Обновление таймера if (LedStep == 0 && currentMillis - previousMillis > 500){ // Задержка 0,5 сек. previousMillis = currentMillis; // обновление таймер LED_ON; // Включить LedStep = 1; // Счетчик шагов } if (LedStep == 1 && currentMillis - previousMillis > 500){ // Задержка 0,5 сек. previousMillis = currentMillis; // обновление таймер LED_OFF; // Выключить LedStep = 2; // Счетчик шагов } if (LedStep == 2 && currentMillis - previousMillis > 500){ // Задержка 0,5 сек. LedStep = 0; // Счетчик шагов } if (UART_ReadByte(inByte)) //Еесли что то пришло { switch (inByte) // Смотрим какая команда пришла { case "x": // Остоновка робота robot_stop; break; case "W": // Движение вперед robot_go; break; case "D": // Повопорт влево robot_rotation_left; break; case "A": // Поворот вправо robot_rotation_right; break; case "S": // Движение назад robot_back; break; case "U": // Серво поднимается myservo1.write(i -= 20); break; case "J": // Серво опускается myservo1.write(i += 20); break; case "H": // Серво поворачивается влево myservo2.write(i += 20); break; case "K": // Серво поворачивается вправо myservo2.write(i -= 20); break; case "Y": // Серво поворачивается 85 myservo1.write(85); myservo2.write(85); break; case "F": // Включить фары Headlamp_ON; break; case "V": // Выключить фары Headlamp_OFF; break; case "I": // Гудок Buzzer; break; } } wdt_reset(); }

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

Канал Science Vetal показал, как сделать машинку на управлении практически от любого андроид смартфона. При этом не будем использовать «Arduino», возьмем микроконтроллер от китайского производителя «Espressive» «esp 8266», штуковина представляет из себя «Arduino» плюс wi-fi модуль.
Все радиодетали и модули в этом китайском магазине .

Вы помните «Arduino uno», оно большое, а здесь маленькая такая штучка, в которой есть wi-fi, возможности «Arduino». К этому микроконтроллеру китайцы разработали такой shield. Он удобный: можно подключить 2 двигателя, или даже 4, при этом можно использовать 11 выводов. Так же возьмем 2 двигателя, 2 стандартных «Arduino» колеса.

Когда на «aliexpress» вводишь «Arduino» в поиск, открываются не только платы, но, сопутствующие товары. Интересные элементы, обязательно что-то интересное найдете, попробуйте.

Возьмём для питания 2 аккумулятора 18650, к ним бокс для 2-х акб, также возьмем 2 уголка, размеры около 5 дюймов, это не столь важно там плюс-минус полдюйма, дюйм. Дело в том, что конструкция может быть ваша, но представленная в ролике авторская удачна, проста.

Берем 2 уголка, при помощи винтов их необходимо соединить, чтобы сюда спокойно помещался shield. Сверлом, диаметр которого 3 мм, делаем 4 отверстия. Берем малюсенькие винты, зажимаем, соединяем эту конструкцию. Такая штуковина получается, прочности данного соединения для такой машинки, как делаем, предостаточно.

Сбоку для вала видео сверлим отверстие диаметром 8 мм, получается конструкция, но необходимо еще сделать 3 отверстия диаметром 3 мм: одно для этого выступа, для этих отверстий крепежных еще 2.

Берем, подставляем таким способом, закручиваем с помощью винтов. Один из идеальных случаев, машинка нравится, сюда нечего добавить, ее незачем переделывать. Делаем отверстия для крепления платы.

Ничего не меняем, кроме как тут, где стоит галочка, выбираем адрес к файлу, который будем заливать, затем выбираем нужный com port, нажимаем кнопочку start. Также под видео есть ссылка на программу, которую нужно установить на ваш любимый android.

Закрепил эту плату, вставляем микроконтроллер. Подключаем провода от двигателей, смотрим, если нижний будет «A-», то с этой стороны «B-» будет верхний. Настало время прикрепить колеса. Делается это легко, так как колёса двигателей – это комплект. В этом месте сверлим отверстие диаметром 4 мм, вставляем винт. Делаем такую нехитрую операцию, регулируем высоту, даже еще ниже можно, что-то получился винт, который сильно торчит. Это лишнее. Это получается, устройство дороже на копеечки, что нам, в общем-то, не нужно, как-то оно выглядит коряво.

Так посмотрим, как получается устройство, которое будет управляться андроидом на расстоянии через wifi. Конечно, получше штука. Отсек для аккумуляторов прикрепим термоклеем, машинка получается.

Вставляем аккумуляторы, необходимо быть внимательным, так как бывает часто так, что все вроде бы правильно собрал, вставил аккумуляторы, а устройство не работает. Оказывается, что эти черные пластиковые боксы. Они не дают акб встать на место.


Программа и скетч http://bbs.smartarduino.com/showthread.php?tid=2013
Приложение для управления https://play.google.com/store/apps/details?id=com.doit.carset

В продолжение темы:
Устройства

можно не только отправлять сообщения и совершать аудиовызовы, но еще и создавать видеоконференции. Для использования этой возможности требуется веб-камера. В ноутбуках она...

Новые статьи
/
Популярные