Подключение arduino к телефону. Сборка макетной платы реле. WeMos на базе esp8266

В этой статье информация о том как собрать свой танк, оснащенный 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(); }

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

Как и многие другие самоделкины, я регулярно использую микроконтроллеры AVR для всяких разных любительских поделок. А благодаря концепции «Arduino» эти поделки теперь приобретают еще и элегантный вид. Действительно, за какие-то 300-400 рублей мы получаем миниатюрную многослойную плату с маской, шелкографией и с полностью разведенной на ней периферией для микроконтроллера (причем в SMD исполнении!). Я уже не говорю о всевозможных подключаемых модулях этой же «Arduino» серии: датчиках, контролерах, дисплеях и целых наборов, так нужной нам дополнительной периферии. И опять же всё также недорогих и в прекрасном исполнении. Практически уже нет необходимости, что-то разводить и допаивать на «коленке».­­­­­­­­­

Но все эти разнообразные любительские поделки, требуют естественно, предварительного программирования. Да и в последующем при разных усовершенствованиях, постоянно приходится эти поделки перепрошивать . Понятное дело, что удобнее делать это дистанционно, чем постоянно таскать их к обычному программатору. Вообще, благодаря той же платформе «Arduino», вариантов и здесь много: Bluetooth, ZigBee, радиоканал с вашим личным протоколом, IR, и даже Wi-Fi. Все они позволяют наладить беспроводной контакт с вашим микроконтроллером. Но мы же остановимся на последнем варианте. Основных причин здесь четыре:

1: современно, интернет вещей же!

2: беспроводной роутер есть в каждой квартире, регистрируй в домашней сети свои устройства и вуаля!

3: ваши поделки осуществляют революционный скачок в своём развитии; мало того, что их можно программировать на расстоянии, они теперь ещё и сами могут общаться с окружающим их миром: электронные часы самостоятельно берут точное время с часовых NTP-серверов, исполнительные устройства управляются с другого конца города или страны, регистрирующие девайсы сохраняют накопленные данные в облако и т.д. и т.п.

4: есть замечательная серия микросхем ESP8266 на которой не очень легко всё это реализовать.

Далее, в этой статье на примере механической руки на сервоприводах - будет разобрано и продемонстрировано удаленное программирование и обмен данными с ПК (или чего угодно) с устройствами на базе AVR микроконтроллеров. Сразу же хочу отметить, что все программы приведенные в дальнейшем являются чисто демонстрационными и никакой коммерческой ценности не имеют. Поэтому претензии, типа, почему программатор такой кастрированный и мало функциональный или почему нет дополнительных сервисов, которые есть везде, не принимаются. Поскольку коды открытые, любой желающий может допилить их по своему усмотрению, мне же для работы, пока хватает и таких.

Предполагается, что читатель уже знаком и с «Arduino» модулями (шилдами) и с подключением и прошивкой ESP8266. На самом деле в Сети выложено огромное количество материалов разъясняющих азы работы с этими девайсами и мне не хотелось бы здесь повторяться. Для новичков в конце статьи есть перечень полезных ссылок по этим вопросам, где можно найти кучу информации, почему это всё у вас не работает. По своему опыту бывшего инженера электронщика могу ответственно заявить, что 99 % неполадок сводится к следующему:

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

2. Проблемы с питанием. Не подавайте 5 вольт питания туда, где требуется 3.3. Иногда из ESP8266 от этого идёт дым. Хотя с другой стороны логические сигналы от пятивольтовых устройств она переваривает без проблем.

3. Проблемы с достаточной мощностью питания. ESP8266 имеет подлую натуру и иногда может потреблять чуть ли не триста миллиампер, хотя до этого могла удовлетворяться и тридцатью. Соответственно хилый стабилизатор 3.3 вольт платы «Arduino», к которому вы ничтоже сумняшеся, её подключили, тут же просаживается до микроскопических значений. А вы не можете понять, почему оно, то работает, то нет.

4. Путаница с выводами. Всегда проверяйте, какие сигналы куда идут. Приемник RXD должен соединяться с передатчиком TXD, также как и TXD с RXD, но MOSI должно соединяться с MOSI, а MISO с MISO и так далее.

5. Не рассчитывайте на внутрисхемные подтягивающие резисторы в ESP8266, всегда подтягивайте выводы к нулю или питанию, через 5-10 килоомные внешние резисторы, а не просто перемычкой. Иначе можете в лучшем случае получить невиданный доселе ток потребления, а потом обонять неприятный запах горелого пластика.

6. Косяки программного обеспечения. Поскольку ПО для индивидуальных юзеров пишется таким же энтузиастами, то периодически вылазят глюки самих прошивок и баги при обновлении версий этих же прошивок. Лечится ползанием по соответствующим форумам, иногда даже англоязычным. Некоторые товарищи даже утверждали, что и сама микросхема ESP сырая как погода в Питере, но с другой стороны существует также мнение что с 2014 (года её первого выпуска) ситуация с этим кардинально улучшилась (в отличие от погоды).

7. Загадочные глюки. Это редкое, но нервопотребляющее явление. У меня к примеру, не шилось удалённо одно «Arduino»устройство. Вернее шилось но с ошибками. Но шилось без ошибок, если на нем висел шлейф от программатора (но без самого программатора). «АГА», сказал я себе и припаял конденсатор 15 пФ, между выводом передачи данных и выводом синхронизации. Всё заработало. Но день убил.

Итак, давайте начнем с самого простого. У нас есть механическая конечность MechArm (но не такая какую собрал Говард Воловитс) сделанная в Китае и персональный компьютер с Windows. Задача - удаленная прошивка программы и управление ея с компьютера.


Для управляющего контроллера возьмем симпатичную миниатюрную платку Arduino Nano c камнем ATmega328P. Эта плата прекрасно впихивается внутрь механической руки.


Теперь определимся каким образом мы её будем программировать. Существуют три основных способа наиболее подходящих для удаленной прошивки: через интерфейс SPI, через встроенный загрузчик, через порт JTAG.

Самый простой вариант, это конечно встроенный загрузчик (бутлоадер). Это заранее прописанная во FLASH память, программа, которая по определенному протоколу получает код, (допустим по самому простому UART) и специальными командами записывает его в место расположения загружаемой программы. Так работает, например, сам загрузчик ARDUINO IDE. После сброса или старта, загрузчик ждет какое-то время данные на приём и если не дожидается начинает исполнение программы с нулевого адреса. Если данные приходят, он пишет их в программную секцию. После следующего сброса загруженная программа начинает исполняться. В деталях, возможно, я описал неточно, но суть именно такая. В итоге нам требуется всего три вывода для программирования: приемник RTD, сброс RESET и земля GND. Вообще, используется еще и передатчик TRD, для верификации записанной программы, но для простых демонстрационных приложений (не для атомной электростанции), проверку можно опустить.

Сам загрузчик пишется на языке ассемблера, есть примеры простых загрузчиков в даташитах на AVR. Можно раскопать существующий уже загрузчик, если он в открытом доступе и просто использовать его в готовом виде, если известен протокол по которому он работает. Единственный нюанс, что для этого требуется настроить AVR в специальный режим, путем прошивки специальных фьюз-битов, что делается обычным программатором, а потом им же зашить сам загрузчик в память микроконтроллера (то есть без программатора один раз все равно не обойтись).

Второй вариант, это программирование по последовательному интерфейсу SPI. Тут уж внутреннего загрузчика нет, а программируем мы, посылая специальные команды и затем данные, по вышеупомянутому интерфейсу. Здесь у нас загрузчик уже внешний, но его все равно писать надо. При передаче используются в добавление к RESET и GND уже четыре дополнительных вывода MOSI, MISO - данные, SLK синхронизация, СS - выбор кристалла. Но вообще также можно убрать MISO и СS. Данные будут только приниматься (верификации программы тогда не будет), а кристалл у нас и так всего один.

У каждого подхода есть свои плюсы и минусы (а JTAG я вообще не рассматривал, поскольку жизнь человеческая коротка). Но в итоге я склонился к SPI поскольку на ассемблере писать было лень, а открытых готовых загрузчиков я не нашел (просто хорошо не искал).

Для построения беспроводного канала я, как уже говорилось, выбрал крайне широко известную в настоящее время микросхему ESP8266 - микроконтроллер, а точнее целый SoC (System-on-Chip) китайского производителя Espressif с интерфейсом Wi-Fi. Помимо Wi-Fi он отличается возможностью исполнять программы из внешней флэш-памяти. А конкретно для своего проекта я взял ESP8266-07 с 512 Кб памяти на борту.


Вообще годится любая ESP8266, где есть лишние ноги для реализации SPI. Поэтому самая простая ESP8266-01 нам не подойдет, так как у неё разведено совсем мало ножек для портов ввода-вывода. Но с другой стороны разница в цене на них меньше ста рублей, а доступны они одинаково. Ну и большие отладочные платы с ESP, где для удобства разведена куча периферии, нам тоже не годятся, так как не влазят, туда куда мы их хотим впихнуть, в нашу механическую руку.

Глобальная суть идеи в общем была такова. С компьютера на ESP без проводов по WI-FI (в рамках вашей домашней сети) передается тело загружаемой в микроконтроллер программы. А ESP уже по проводам с использованием интерфейса SPI записывает эту программу непосредственно во FLASH память микроконтроллера. Потом естественно сбрасывает его и дает возможность загруженной программе выполняться. Кроме того в ESP должен быть независимый блок, который заведует еще и обменом данными с микроконтроллером, так как мы хотим не только программировать, ни и еще обмениваться с ним данными. В частности для проекта с MechArm, после записи программы, мы ещё передаем сигналы управления сервоприводами, дабы привесть эту руку в движение. Поэтому на самой ESP нам желательно поднять TCP сервер для передачи программы и UDP сервер для управления MechArm. Соответственно эти серверы присоединяются к домашней сети и внимательно слушают, нет ли там желающих загрузить новый код в MechaArm или помахать кому-нибудь ею.

Так-то, я нашел в Сети, прошивки уже позволяющие производить программирование AVR по воздуху, но там главная проблема в том, что для чего другого эту прошивку использовать уже нельзя. А нам хотелось бы после программирования и общаться с AVR также удаленно.

Какое ПО мы будем использовать:

Для ПК, я писал всё на JAVA, среда IntelliJ IDEA . Но в принципе, можно на чём угодно, нам там главное написать клиент, который будет отправлять программу для прошивки AVR на ESP8266.

Сами программки для AVR я пишу в ATMEL STUDIO , на языке С, редко на ассемблере. Скетчи Arduino не использую принципиально, практически любая нужная библиотека пишется за час другой, причем с полным пониманием её работы. Я пробовал скетчи, но пока у вас нет на AVR операционной системы, скетчи так и будут отбирать у друга периферию и регулярно глючить. Да сама IDE Arduino по сравнению с ATMEL STUDIO, конечно вещь весьма примитивная. Но тут вопрос, конечно, спорный, гуманитариям и школьникам веселее и проще будет, наверное, со скетчами.

Для программирования ESP8266 я использовал прошивку NodeMCU, а программы писал на языке Lua. Нет, я бы с удовольствием писал бы на Java и на С, но их же на ESP нет. Luа язык в применении к нашей задаче не сложный, освоить его пара пустяков. А собственно для загрузки программ и их отладки на ESP, я взял IDE ESPlorer . Отечественный бесплатный продукт (но можете сделать автору donation), который конечно не сравнить со средами упомянутыми выше, но как говорится дарёному коню… Но чтобы пользоваться ESPlorer и писать на LUA, нам сначала необходимо сменить в микросхеме ESP8266 базовую прошивку (поставляемую от производителя) на новую. В этом предприятии нам поможет программа NODE MCU PyFlasher. В смысле, поможет её перепрошить. А саму прошивку мы сами создадим и получим в руки на сайте создателей: NodeMCU .А более подробно об этом процессе вы можете прочесть

Всё очень доступно и понятно. К базовым библиотекам добавляем поддержку SPI и битовые операции (в LUA в нашем случае битовые операции перегружены и от них мало толку). Много в прошивку библиотек пихать не следует, так как из-за наличия всякого разнообразного софта на ESP8266 остается совсем мало памяти, какие-то жалкие 20 кБ.

Конечно, вы можете просто взять готовую прошивку, коих много уже болтается в Интернете, но не рекомендую. Хотя бы потому, что на некоторых нет поддержки битовых операции (а они нам нужны) и нет регулирования скорости передачи данных по SPI.
Соответственно, они передаются по умолчанию со скоростью 40 Мгц делённые на какой-то небольшой коэффициент и поэтому AVR их переваривать не успевает.

Кому лень создавать прошивку можете скачать мою из облака .

Теперь у нас есть прошивка и нам надо загрузить её в ESP8266 вместо базовой. Для этого нам пригодится простейший адаптер USB - UART.


Присоединяем ножки TXD к RXD, а RXD к TXD, делаем общей землю, но не используем, как казалось, удобный вывод питания 3.3 В на адаптере. В большинстве случаев ESP8266 просадит его напрочь. Поэтому запитываем ёё отдельно. Потом переводим ESP в режим программирования (GP0 на землю, если кто забыл) и запускаем NODE MCU PyFlasher .

Главное, не забудьте стереть флэш-память (yes, wipes all data), иначе в зависимости от версии прошивки после программирования в памяти может остаться ненужный мусор, который в свою очередь будет сыпать мусор в консоль при дальнейшей работе. До этого я использовал софт, где не было опции стереть предварительно память, намучался жутко, так как ничего не работало. А ларчик просто открывался, только правда на англоязычном форуме создателей NODE MCU.

Заимев же нужную прошивку мы теперь можем писать и отлаживать программы на языке LUA (там еще MicroPython, но я им не пользовался) используя при этом очень удобные API от NODE MCU. Запускаем уже упомянутый ранее ESPlorer.

Также настраиваем его для работы с ESP8266, устанавливаем параметры последовательного соединения. Всё достаточно просто и многократно изложено в Интернете.

Теперь пишем программульку на LUA, кою потом загрузим в ESP8266:

Загрузчик Lua для AVR, записываемый в ESP8266

function InstrProgrammingEnable () -- instruction for MC "enable programming" p=0 while p<31 do p=p+1 pin=8 gpio.write(pin, gpio.LOW) spi.send(1, 0xAC,0x53) read = spi.recv(1, 8) spi.send(1,0,0) gpio.write(pin, gpio.HIGH) if (string.byte(read)== 83) then print("connection established") p=33 if(p==31) then print("no connection") end end end end function ProgrammingDisable () pin=2--END OF ESET FOR MK gpio.mode(pin, gpio.INPUT) pin=8 gpio.mode(pin, gpio.INPUT) pin=5--CLK MASTER for SPI gpio.mode(pin, gpio.INPUT) pin=6--MISO MASTER for SPI gpio.mode(pin, gpio.INPUT) pin=7--MOSI MASTER for SPI gpio.mode(pin, gpio.INPUT) end function ProgrammingEnable () pin=2-- RESET FOR MK gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.LOW) pin=2--POZITIV FOR 4MSEC RESET FOR MK gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.HIGH) tmr.delay(4) gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.LOW) tmr.delay(25000) end function InstrFlashErase() pin=8 gpio.write(pin, gpio.LOW) spi.send(1,0xAC,0x80,0,0) gpio.write(pin, gpio.HIGH) tmr.delay(15000) pin=2--RESET FOR MK gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.HIGH) tmr.delay(20000) gpio.write(pin, gpio.LOW) print("FLASH is erased") InstrProgrammingEnable () end function InstrStorePAGE(H, address, data) pin=8 gpio.write(pin, gpio.LOW) spi.send(1,H,0,address,data) gpio.write(pin, gpio.HIGH) tmr.delay(500) end function InstrWriteFLASH(page_address_low,page_address_high) pin=8 gpio.write(pin, gpio.LOW) spi.send(1,0x4C,page_address_high,page_address_low,0) gpio.write(pin, gpio.HIGH) tmr.delay(5000)-- иногда не прописываются флэш при малых задержках end function Programming (payload) pin=8--CS MASTER for SPI gpio.mode(pin, gpio.OUTPUT, gpio.PULLUP) pin=4--LED LIGHTS ON LOW gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.LOW) print(string.len(payload)) page_count = 7 -- пишем 1 килобайт for k =0 ,page_count ,1 do--quantity of pages for i=0 , 127, 2 do-- -1 address = i/2 data=payload:byte(i+1+128*k) if data == nil then data = 0xff end InstrStorePAGE(0x40,address,data) -- tmr.delay(100)-- otherwise not in time write data =payload:byte(i+1+1+128*k) if data == nil then data = 0xff end InstrStorePAGE(0x48,address,data) -- tmr.delay(100) end page_address_low=bit.band(k ,3)*64 -- 3 это двоичное 11 page_address_high=k/4+frame1024*2 tmr.delay(1000) InstrWriteFLASH(page_address_low,page_address_high) tmr.wdclr() end pin=4--LED gpio.mode(pin, gpio.OUTPUT) gpio.write(pin, gpio.HIGH) end --MAIN BLOCK wifi.setmode(wifi.STATION) --wifi.sta.config("имя сети","пароль") -- set SSID and password of your access point station_cfg={} tmr.delay(30000) station_cfg.ssid="имя сети" tmr.delay(30000) station_cfg.pwd="пароль" tmr.delay(30000) wifi.sta.config(station_cfg) tmr.delay(30000) wifi.sta.connect() tmr.delay(1000000) print(wifi.sta.status()) print(wifi.sta.getip()) while (wifi.sta.status()~=1) do if(wifi.sta.status()==5) then break end end sv=net.createServer(net.TCP,30) tmr.delay(100) print("SERVER READY") sv:listen(4000,function(c) c:on("receive", function(c, payload) print(payload) if (payload =="program\r\n") then c:send("ready\r\n") print("ready for program\r\n") spi.setup(1, spi.MASTER, spi.CPOL_LOW, spi.CPHA_LOW, spi.DATABITS_8,320,spi.FULLDUPLEX) ProgrammingEnable () tmr.delay(100) InstrProgrammingEnable () tmr.delay(100) InstrFlashErase() tmr.delay(100) frame1024=0--номер переданого фрей мов st=net.createServer(net.TCP,30) st:listen(4001,function(c) c:on("receive", function(c, payload) tmr.wdclr() Programming (payload) frame1024=frame1024+1 end) end) end if (payload =="data\r\n") then c:send("ready\r\n") print("ready for data\r\n") srv=net.createServer(net.UDP) tmr.delay(1000) pin=10 gpio.write(pin, gpio.HIGH) uart.setup(0,9600,8,0,1,0) srv:listen(5000) srv:on("receive", function(srv, pl) pl=pl*1 --print(pl) uart.write(0,pl) tmr.wdclr() end) end if (payload =="stop\r\n") then if(st~=nil) then st:close() frame1024=0 ProgrammingDisable () print("stop program") end if(srv~=nil) then srv:close() print("stop data") end end end) end) end)


Где соответствующие функции выполняют следующие действия:

function InstrProgrammingEnable () – переводит микроконтроллер в режим программирования специальной командой отправляемой по SPI.

function ProgrammingEnable () – просто ресетим AVR на 25 мс перед началом программирования

function ProgrammingDisable () – после окончания программирования, переводим выводы SPI в ESP8266 в неактивное состояние, чтобы они не мешались нам при выполнения кода на микроконтроллере (вдруг они там используются)

function InstrFlashErase() – затираем флэш-память на микроконтроллере перед началом программирования. Зачем это нужно объяснять не нужно.

function InstrStorePAGE(H, address, data) – по этой команде во внутренний буфер микроконтроллера записывается байт программы. Но это ещё не сама флэш запись, так как флэш пишется здесь постранично по 128 байт.

function InstrWriteFLASH(page_address_low,page_address_high) – а вот это уже запись флэш и она требует времени, обратите внимание на временную задержку 5 000 мкс.

function Programming (payload) – самая большая и важная функция использующая и вышеперечисленные функции. Она берет передаваемую программу кусками по 1024 байт, делит их на байтики и формирует для них адреса, а затем отправляет в микроконтроллер во внутренний буфер и через каждый 128 байт инициализирует запись флэш. Потом берет следующий килобайт кода и повторяет операцию, естественно со смещением в адресах, чтобы писать дальше а не затирать записанное. Вначале, я пробовал пересылать программы целиком, но при превышении 6 килобайт в ESP8266 элементарно кончается доступная память и она вылетает. Один килобайт оказался самой удобной единицей, ибо аккуратно делится на части и удобно передается по TCP (нам же надо его с компьютера ещё получить). Больший размер тоже не нужен, TCP, сами знаете, в текущей версии ограничивает передаваемый пакет, в 1500 что ли байт (но у меня передавался почему-то 1440, вроде).

Как бы ничего сложного, но несколько подводных камней пришлось преодолеть.

Регистрируемся в беспроводной сети.

Создаем вначале TCP сервер, который слушает три команды:

1. “program” (будем программировать),

2. “data” (будем меняться данными),

3. ”stop” (всё прекращаем).

Если мы программируем, то сначала инициализируем SPI и создаем еще один TCP сервер, который хапает данные (код прошиваемой программы) покилобайтно и вызывает под них функции программирования микроконтроллера. Я понимаю, что выглядит глупо создавать второй сервер, но это необходимость, ибо местное API поддерживает создание только одного сокета, а нам необходимо разделять команды ”program” и “data” собственно с передаваемыми данными, ибо на глаз они не различаются, там байты и тут байты.

Если же мы хотим не программировать, а обмениваться данными, посылая их в нашем случае в микроконтроллер, то мы сначала отправляем по TCP строку ”data”. В ответ на это будет создан уже UDP сервер (я напомню, что мы управляем динамически механической рукой и нам задержки с формированием TCP пакетов не нужны, да и вообще отправлять один байт целым TCP кадром моветон). А UDP дейтаграммы у нас будут маленькими и формироваться будут быстро.

После инициализируется UART, и каждый принимаемый в беспроводном виде байт, отправляется уже по проводу TXD на микроконтроллер, который обязан, буде там прошита соответствующая программа, его принять. Обмен данными в другом направлении организовать также не сложно, но я пока его не реализовывал.

Ну и по команде ”stop” вышеупомянутые сервера (кроме самого первого) закрывают соединения и самый главный сервер вновь переходит в состояние ожидания команд ”program” и “data”.

Поскольку SPI интерфейс программно эмулируется в ESP8266, то порты ввода-вывода для сигналов CS, CLK, MISO,MOSI, RESET (для AVR), можете использовать любые доступные, а не те, что указаны у меня в загрузчике. Кроме того оказалось, что CS и MISO в принципе тоже можно в данном случае оборвать, будет работать и без них. Ну и один вывод задействуется на встроенный в плату ESP8266 светодиод, чтобы мигал иногда и показывал, что программа ещё живая.

Проверок на ошибки записи не делается (за исключением первого запроса к AVR, но эта информация просто выводится на консоль), EEPROM не программируется, больше 32 Кб не шьется – короче есть ещё над чем поработать. Скорость обмена по SPI примерно 115 Кбит, за несколько секунд всё прошивается, примерно, как у обычного последовательного программатора типа ISP500).

Берите код, вписывайте свои сети и пароли, компилируйте на ESplorer, обзывайте его “init” (чтобы запускался при рестарте) и отправляйте на ESP8266. Должно работать. В смысле работать беспроводным программатором, как минимум.

Мы же теперь займемся управляющей стороной – персональным компьютером.

По сути, нам нужно взять файл формата HEX, в который превращаются ваши программы, написанные в среде ATMEL STUDIO и отправить его по WI-FI на известный нам порт сокета (в данном случае 4000). Маленькая загвоздка в том, что нам нужен двоичный файл BIN для пересылки, а ATMEL STUDIO радует нас только HEXом. Выхода здесь два; или перевести его в формат BIN специальной программой конвертером, типа WinHex или сделать это самим в своей программе. Я пока не сделал, но вроде это не сложно, там надо отрезать заголовок и сделать что-то ещё.

В итоге программу-загрузчик я написал на JAVA (в основном потому, что больше ни на чем не умею), работая в просто прекрасной и бесплатной среде IntelliJ IDEA. В ней создается TCP клиент, который ищет сервер запущенный на ESP8266. Если находит, то связывается с ним и отправляет ему файл расположенный по такому-то адресу. Код ниже.

Загрузчик файлов на JAVA, работающий на стороне ПК

import java.io.*; import java.net.*; import java.util.ArrayList; import java.util.List; public class Net { public static void main(String args) { new Http_client(4000); } } class Http_client extends Thread { int port; String s; String Greetings_from_S; Http_client(int port){ this.port = port; start(); } public void run() { //192.168.1.113 -это адрес ESP8266 в моей сети. Но вообще, узнается из общения с роутером // лучше сделать его статическим, роутеры это умеют try (Socket socket = new Socket("192.168.1.113", port)) { PrintWriter pw = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()),true); pw.println("program");// Greetings with SERVER System.out.println("program"); BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream())); Greetings_from_S = br.readLine(); System.out.println(Greetings_from_S); if(Greetings_from_S.equals("ready")) { try { File file = new File("d:BlinkOUT.bin");// адрес выгружаемого файла BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); byte data = new byte; bis.read(data); byte data_buffer = new byte; int frames = data.length/1024; System.out.println(frames); int residy = data.length%1024; for (int i = 0; i < frames;i++) { for (int k = 0; k< (1024); k++) { data_buffer[k] = data; } sendingChunk(data_buffer); } byte data_buffer2= new byte; for (int i = 0; i < residy;i++) { data_buffer2[i] = data; } sendingChunk(data_buffer2); pw.println("stop");// System.out.println("stop program"); } catch (Exception e) { System.out.println(e); } } } catch (Exception e) { System.out.println(e); } } public void sendingChunk (byte data_buffer){ try (Socket socket = new Socket("192.168.1.113", 4001)){ BufferedOutputStream bos = new BufferedOutputStream((socket.getOutputStream())); bos.write(data_buffer); bos.flush(); System.out.println(data_buffer.length); } catch (Exception e) { System.out.println(e); } } }


Тут конечно накручено лишнего, всякие ready, в принципе не нужны. Если уж TCP соединение установлено, то оно установлено. Единственная проблема была в том, что файл никак не хотел отправляться ровными кусками по 1024 байт, как мне очень требовалось, хотя я и явно указывал размер. Видимо там какой-то финальный буфер недоступный из JAVA, и он отправляет пакеты размером, каким ему хочется, что для приемной стороны совершенно неприёмлемо. Сначала я пробовал сделать задержку, чтобы буфер уставал ждать следующие куски и отправлял как есть. Но задержка стала работать, когда достигла 10 секунд, что мне как-то показалось многовато на один передаваемый килобайт.

Но потом я заметил, что почему-то первый кусок всегда идет ровный, какой был заказан, а уже со второго начинается непредсказуемая вакханалия. Поэтому я сделал так, чтобы клиент открывал соединение, отправлял порцию кода в 1024 байт и закрывал соединение. И так пока не отправится весь файл. Всё успешно заработало.

Единственное, для запуска необходимо поставить на компьютер среду выполнения JAVA. Но я обычно запускаю сразу из IntelliJ IDEA ибо там в консоли всегда видно, что происходит (но и здесь среда JAVA нужна). Хотя, конечно, по-умному надо сделать GUI. То есть окошко, где выпадает путь к файлу, возможность менять там же в окне номера портов и ну и прочие нужные вещи. И все это собрать в виде исполняемого файла.

А таперича, как говаривал Коровьев, вернемся граждане, собственно к механической конечности MechArm, что была упомянута в самом начале. У нас теперь есть возможность удаленно её запрограммировать, а затем ею поуправлять. Перейдём к программе управления на стороне микроконтроллера.

В данном случае нам необходимо контролировать четыре сервопривода. Вот таких.


Такой привод управляется прямоугольными импульсами, периода 20 мс (50Гц) с коэффициентом заполнения от 2 до 4 процентов. То есть 2% это полный поворот в одну сторону, 4% в другую. Задача как раз для встроенного в AVR ШИМ.

Один сервопривод используется для движения вправо-влево; второй на себя – от себя; третий вверх-вниз; четвертый – сама клешня, которая должна сжиматься и разжиматься. Всё написано на С и откомпилировано до HEX файла в ATMEL STUDIO. Немного странный вид программы связан с тем, что изначально рука управлялась с клавиатуры привязанной проводами к микроконтроллеру. Но провода вчерашний день, надо эволюционировать дальше.

Можно конечно использовать скетчи для сервоприводов от ”ARDUINO”, но мне они не понравились. Самому писать интересней. К тому же все четыре сервопривода должны работать одновременно, а не в мультиплексированном режиме, когда ШИМ переключается на каждый сервопривод поочередно. Ибо гравитацию никто не отменял и поднятая вверх конечность, моментально опустится, если на соответствующий сервопривод перестанут поступать управляющие импульсы. Я не уверен, что ”ARDUINO” скетч обеспечивает одновременный режим работы для четырех серво. А вот сами мы вполне можем написать программку отвечающую нужным требованиям. Да и вообще при отсутствии операционной системы, которая отделяет агнцев от козлищ, применение скетчей конкурирующих за периферийные устройства микроконтроллера (а мы даже и не знаем заранее какие) дело слишком багопроизводительное.

Вот сам код, который мы записываем в Arduino Nano посредством ESP8266-07.

Программа для управление MechArm для микроконтроллера AVRmega328P

#define F_CPU 16000000 #include #include // стандартные целые числа #include #include // математика #include //стандартный ввод-вывод #include #include #include //стандартные возможности #define UART_BAUD_RATE 115200 // счетчик Т1 задает временной интервал 20мс #define COUNTER1_OFF TCCR1B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001 без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024 #define COUNTER1_ON TCCR1B=0b00000011 // счетчик Т0 задает ширину управляющего импульса для серво РВ0 и РВ1 #define COUNTER0_OFF TCCR0B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001 без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024 #define COUNTER0_ON TCCR0B=0b00000100 // счетчик Т2 задает ширину управляющего импульса для серво РB2(PD6) и РВ3(PD7) #define COUNTER2_OFF TCCR2B=0b00000000 // CS02 CS01 CS00 - 000 - отключен; 001 без делителя; 010 c делителем 8; 011 -64; 100 -256; 101 -1024 #define COUNTER2_ON TCCR2B=0b00000110 volatile uint16_t period_20ms; volatile uint8_t State_of_keyboard; volatile uint8_t start_position ; volatile int8_t number_servo; ISR(USART_RX_vect)// прерывание для UART { State_of_keyboard=UDR0; return; } ISR(TIMER0_COMPA_vect)// серво РВ0 ширина управляющего импульса { PORTB &=~(1<<0); TIMSK0&=~(1<
Суть программы ясна из текста и комментариев. Мы используем счетчик Т1 для образцового периода 20 мс и счетчики Т0, Т2 для выдачи ШИМ сигналов на четыре линии порта ввода-вывода, благо каждый из этих двух счетчиков, может работать на два устройства.
В программе устанавливаются начальные положения сервоприводов, через загрузку счетных регистров OCR0A, OCR0B, OCR2A,OCR2B. Также вводятся константы ограничители, поскольку нам не всегда нужен размах в 180 градусов. Ну и дальше, по прерыванию от UART, программа ловит число отправленное ESP8266 (от 1 до 8) и переводит его в команду для соответствующего сервопривода. Приводов четыре, каждый работает в двух направлениях, поэтому целых чисел от одного до восьми вполне хватает. Как только число выбрано, содержимое вышеупомянутых регистров счетчиков либо инкрементируется либо декрементируется, соответственно изменяя скважность управляющего импульса и угол поворота выбранного сервопривода. Те приводы, которые мы не выбирали, сохраняют старое значение угла поворота, (поскольку содержимое соответствующих регистров хоть и обновлялось, но не менялось) и продолжают удерживать механическую руку в прежнем положении.

Теперь нам осталось лишь написать управляющую программу, простите за тавталогию, для управления механической рукой уже непосредственно с компьютера по WI-FI.
Код также написан на JAVA, но немного облагорожен. Появился GUI и возможность редактировать номера портов и сетевой адрес ESP8266.

Что там происходит понятно из окошка. Текст программы я здесь не привожу (он доступен на

Добрый день!

Недавно заинтересовался идеей создания «умного дома». Так как из необходимых компонентов в моем распоряжении пока что имеются только arduino и телефон на андроиде, решено было начать с создания пульта управления и связи его с остальной частью системы.

Моё видение системы выглядит так:

Думаю стоит совместить домашний и веб-серверы, прикупив статический айпишник, но на первое время сойдет и так. Начнем с простого – научимся удаленно управлять светодиодом и LCD-дисплеем.

Web-server
На веб-сервере создаем БД с двумя таблицами – leds и texts. Таблица leds содержит 2 поля – id и status. Она содержит одну запись с актуальным состоянием светодиода. Таблица texts содержит 2 поля – id и text. Она также содержит одну запись с текстом, который в данный момент отображается на LCD-дисплее.

Теперь напишем пару скриптов, которые будем вызывать с телефона и передавать информацию для БД. Пишем на php.

Скрипт led.php (управление светодиодом):

Скрипт msg.php (управление LCD-дисплеем):

Я думаю, что из комментариев ясно, как работают эти скрипты. Это все, что находится на веб-сервере. Теперь перейдем к домашнему серверу (или говоря проще, компьютеру, к которому подключен ардуино).

Домашний сервер
На нем будет постоянно работать программка (можно даже назвать ее – демон), посылающая запросы к БД и при изменении находящейся там информации, посылающая на COM-порт с ардуино соответствующую команду. Программку напишем на языке Processing:

Import processing.serial.*; //библиотека для работы с COM-портом import de.bezier.data.sql.*; //библиотека для работы с БД MySQL Serial port; MySQL dbconnection; int prevLEDState = 0; //предыдущее состояние светодиода String prevS = ""; //предыдущий текст, отпаврленный на LCD-дисплей void setup() { port = new Serial(this, "COM4", 9600); //инициализируем COM-порт 4 (на не прицеплена ардуина), скорость обмена - 9600 бод port.bufferUntil("\n"); String user = "имя_пользователя"; String pass = "пароль"; String database = "имя_бд"; dbconnection = new MySQL(this, "ваш_домен.ru", database, user, pass); //соединяемся с БД dbconnection.connect(); } void draw() { //следим за информацией о светодиоде в БД dbconnection.query("SELECT * FROM leds WHERE id = "1""); //делаем запрос к таблице leds while (dbconnection.next()) //обходим выборку из результата запроса { int n = dbconnection.getInt("status"); //получаем значение из поля status if (n != prevLEDState) //если оно изменилось по сравнению с предыдущем "тактом" работы программы, то посылаем команду на COM-порт { prevLEDState = n; port.write("1"); //первый переданный символ будет означать код выполняемой операции: 1 - управление светодиодом, 2 - управление LCD-дисплеем port.write(n); } } //следим за информацией о LCD-дисплее в БД dbconnection.query("SELECT * FROM texts WHERE id = "1""); //делаем запрос к таблице texts while (dbconnection.next())//обходим выборку из результата запроса { String s = dbconnection.getString("text"); //получаем значение из поля text if (s != prevS) { prevS = s; port.write("2"); port.write(s); } } delay(50); //делаем задержку в 50 мс, чтобы не слать запросы непрерывно }
Пояснять этот код я тоже не стану, все и так понятно.
Еще 1 важный момент. Чтобы программа с нашего компьютера могла обращаться к БД, расположенной на удаленном сервере, надо это разрешить. Вводим наш ip в список разрешенных:

Приложение для телефона
Телефон у меня андроиде, для него и пишем. Не буду сильно вдаваться в подробности (очень хорошо как о установке среды программирования, так и о написании первого приложения написано вот в этой статье - ссылка).

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

Приведу только отрывки кода программы под Android. Функция, вызывающая скрипт, управляющий светодиодом:
public void changeLED() { try { URL url1 = new URL("http://ваш_домен.ru/led.php"); HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection(); try { InputStream in = new BufferedInputStream(urlConnection.getInputStream()); } finally { urlConnection.disconnect(); } } catch (Exception e) { } }
Функция, отсылающая текст для отображения на LCD-дисплее:
public void submitMsg() { final EditText tt = (EditText) findViewById(R.id.editText1); try { URL url1 = new URL("http://ваш_домен.ru/msg.php?msg="+tt.getText()); HttpURLConnection urlConnection = (HttpURLConnection) url1.openConnection(); try { InputStream in = new BufferedInputStream(urlConnection.getInputStream()); } finally { urlConnection.disconnect(); } } catch (Exception e) { } }
Ну и главная функция, в которой происходит привязка обработчиков событий к кнопкам:
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); final Button btn1 = (Button) findViewById(R.id.button1); btn1.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) // клик на кнопку { changeLED(); } }); final Button btn2 = (Button) findViewById(R.id.button2); btn2.setOnClickListener(new Button.OnClickListener() { public void onClick(View v) // клик на кнопку { submitMsg(); } }); }
И еще один важный момент – добавить разрешение приложению на выход в интернет. Для этого в файл AndroidManifest.xml (он находится в директории нашего андроид-приложения) надо добавить строчку:

Экспортируем наше приложение в файл APK и устанавливаем на телефон. Пульт управления умным домом готов!

Arduino
Ну и наконец последнее, но не по значению – подключение ардуино и ее прошивка. Схема подключения LCD-экрана и светодиода к Arduino Uno выглядит следующим образом:

Резистор берем на 220 Ом. Более подробно про подключение LCD-экрана можно прочитать здесь - ссылка

А вот как это все выглядит в реальности:

Правда красиво?

Задача ардуино состоит в прослушивании того, что программа-демон на домашнем сервере посылает на COM-порт, к которому и подключена ардуино (хотя фактически подключение идет по USB-кабелю, но компьютер распознает его как последовательный порт). После получения каких-либо данных с компьютера, контроллер по первому символу переданной информации распознает код команды (т.е. чем сейчас предстоит управлять – LCD-дисплеем или светодиодом). Далее в зависимости от кода и следующей за ним информации выполняется либо включение/выключение светодиода, либо вывод на дисплей переданного сообщения. Итак, вот собственно код:

#include //встроенная библиотека для работы с LCD-дисплеем boolean isExecuting = false; //переменная, отражающая, что уже идет выполнение какой-то команды //Cразу поясню, для чего это нужно. За каждый "такт" цикла loop ардуино считывает с COM-порта код одного символа. //Поэтому строка будет передаваться за несколько тактов. При этом перед каждой из двух возможных команд (смена состояния светодиода и передача текста на дисплей) //передается код этой команды (1 и 2 соответственно). Чтобы отделить коды команд от передаваемой далее информации (состояния светодиода или текста для дисплея), //используется эта переменная. LiquidCrystal lcd(4,5,10,11,12,13); //инициализация дисплея int ledPin = 8; //номер пина ардуино, на к которому подсоединен светодиод int prevLEDStatus = 0; //предыдущий статус светодиода (вкл/выкл) int newLEDStatus = 0; //новый статус светодиода int cmd = 0; //код выполняемой команды void setup() { Serial.begin(9600); //инициализация COM-порта (9600 - скорость обмена в бодах) pinMode(ledPin,OUTPUT); //инициализация 8-го пина ардуино как выхода lcd.begin(20,4); //инициализация LCD-дисплея (4 строки по 20 символов) } void loop() { if (Serial.available() > 0) //если на COM-порт пришла какая-то информация { if (isExecuting == false) //если в данный момент не идет выполнение никакой команды { cmd = Serial.read() - "0"; //считываем код выполняемой команды isExecuting = true; //теперь переменная показывает, что началось выполнение команды } if (cmd == 1) //управление светодиодом { newLEDStatus = (int) Serial.read(); //считываем новый статус светодиода if (newLEDStatus != prevLEDStatus) //если он изменился по сравнению с текущим статусом, то меняем текущий статус { digitalWrite(ledPin,newLEDStatus); prevLEDStatus = newLEDStatus; } } else //управление дисплеем { if (isExecuting == false) //если в данный момент не идет выполнение никакой команды { lcd.clear(); //очищаем экран } else { lcd.print((char)Serial.read()); //выводим символ на дисплей } } } else //если на COM-порт не пришла никакая информация { delay(50); //делаем задержку в 50 мс if (Serial.available() <= 0) //если информации по-прежнему нет isExecuting = false; //считаем, что никакая команда не выполняется } }
Я думаю, пояснений он не требует, так как я очень подробно все расписал в комментариях. Единственное, что стоит отметить, так это некоторые ограничения на передаваемые для вывода на дисплей строки. Они не должны содержать пробелов (это ограничение накладывается несовершенством моего алгоритма) и не должны содержать кириллицы (т.к. она поддерживается не всеми дисплеями, а если и поддерживается, то требует передачи кодов символов в своей собственной кодировке, преобразовывать символы в которую нет никакого желания).

Заключение
Ну вот и все. Оказалось, что это довольно просто.
Видео того как все работает:

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

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

Вы можете реализовать эту систему там, где вам нужно включать нагрузку постоянного тока на определенное время. В этом вам поможет наше 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 часов).
  • После любого действия вы получите сообщение с подтверждением о том, выполнилась ли команда успешно, или возникла какая-то ошибка.

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

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

Микросхема ESP8266 – один из самых популярных инструментов для организации беспроводной связи в проектах умного дома. С помощью беспроводного контроллера можно организовывать связь по интерфейсу WiFi, обеспечивая проектам Arduino выход в интернет и возможность дистанционного управления и сбора данных. На основе ESP8266 созданы такие популярные платы как WeMos и NodeMcu, а также огромное количество самодельных проектов. В этой статье, мы узнаем, что из себя представляет ESP82266, какие бывают ее разновидности, как работать с ESP8266 в среде Arduino IDE.

ESP8266 – микроконтроллер с интерфейсом WiFi, который имеет возможность исполнять программы из флеш-памяти. Устройство было выпущено в 2014 году китайской фирмой Espressif и практически сразу же стало популярным.

Контроллер недорогой, обладает небольшим количеством внешних элементов и имеет следующие технические параметры:

  • Поддерживает Wi-Fi протоколы 802.11 b/g/n с WEP, WPA, WPA2;
  • Обладает 14 портами ввода и вывода, SPI, I2C, UART, 10-бит АЦП;
  • Поддерживает внешнюю память до 16 МБ;
  • Необходимое питание от 2,2 до 3,6 В, потребляемый ток до 300 мА в зависимости от выбранного режима.

Важной особенностью является отсутствие пользовательской энергонезависимой памяти на кристалле. Программа выполняется от внешней SPI ПЗУ при помощи динамической загрузки необходимых элементов программы. Доступ к внутренней периферии можно получить не из документации, а из API набора библиотек. Производителем указывается приблизительное количество ОЗУ – 50 кБ.

Особенности платы ESP8266:

  • Удобное подключение к компьютеру – через USB кабель, питание от него же;
  • Наличие встроенного преобразователя напряжения 3,3В;
  • Наличие 4 Мб флеш-памяти;
  • Встроенные кнопки для перезагрузки и перепрошивки;
  • Все порты выведены на плату на две гребенки с шагом 2,5 мм.

Сферы применения модуля ESP8266

  • Автоматизация;
  • Различные системы для умного дома: Беспроводное управление, беспроводные розетки, управление температурой, дополнение к сигнализационным системам;
  • Мобильная электроника;
  • ID метки;
  • Детские игрушки;
  • Mesh-сети.

Распиновка esp8266

Существует огромное количество разновидностей модуля ESP8266. На рисунке представлены некоторые из них. Наиболее популярным вариантом является ESP 01.

Исполнение программы требуется задавать состоянием портов GPIO0, GPIO2 и GPIO15, когда заканчивается подача питания. Можно выделить 2 важных режима – когда код исполняется из UART (GPIO0 = 0, GPIO2 = 1 и GPIO15 = 0) для перепрошивки флеш-карты и когда исполняется из внешней ПЗУ (GPIO0 = 1, GPIO2 = 1 и GPIO15 = 0) в штатном режиме.

Распиновка для ESP01 изображена на картинке.

Описание контактов:

  • 1 – земля, 8 – питание. По документации напряжение подается до 3,6 В – это важно учесть при работе с Ардуино, на которую обычно подают 5 В.
  • 6 – RST, нужна для перезагрузки микроконтроллера при подаче на него низкого логического уровня.
  • 4 – CP_PD, также используется для перевода устройства в энергосберегающий режим.
  • 7 и 0 – RXD0 и TXD0, это аппаратный UART, необходимый для перепрошивки модуля.
  • 2 – TXD0, к этому контакту подключается светодиод, который загорается при низком логическом уровне на GPIO1 и при передаче данных по UART.
  • 5 – GPIO0, порт ввода и вывода, также позволяет перевести устройство в режим программирования (при подключении порта к низкому логическому уровню и подачи напряжения) .
  • 3 – GPIO2, порт ввода и вывода.

Распиновка ESP-12

Основные отличия Ардуино от ESP8266

  • ESP8266 имеет больший объем флеш-памяти, при этом у ESP8266 отсутствует энергонезависимая память;
  • Процессор ESP8266 быстрее, чем у Ардуино;
  • Наличие Wi-Fi у ESP8266;
  • ESP8266 потребляеn больше тока, чем для Ардуино;

Программирование ESP8266 в Arduino IDE

Программный комплект разработчика esp8266 включает в себя:

  • Компилятор из пакета GNU Compiler Collection.
  • Библиотеки, стеки протоколов WiFi, TCP/IP.
  • Средство загрузки информации в программу контроллера.
  • Операционная IDE.

Изначально модули ESP8266 поставляются с прошивкой от фирмы-изготовителя. С ее помощью можно управлять модулем с внешнего микроконтроллера, реализовывать работу с Wi-Fi как с модемом. Также существует множество других готовых прошивок. Некоторые из них позволяют настраивать работу модуля при помощи WEB-интерфейса.

Можно программировать из среды Arduino IDE. При ее помощи можно легко писать скетчи и загружать их в ESP8266, прошивать ESP8266, при этом не требуется сама плата Ардуино. Arduino IDE поддерживает все виды модулей ESP8266.

В настоящий момент для ESP8266 можно реализовать следующие функции:

  • Основные функции языка Wiring. Управлять портами GPIO можно точно так же, как и пинами на плате Ардуино: pinMode, digitalRead, digitalWrite, analogWrite. Команда analogRead(А0) позволяет считать значения АЦП. При помощи команды analogWrite (pin, value) можно подключить ШИМ на нужном выходе GPIO. При value=0 ШИМ отключается, максимальное значение достигает константы, равной 1023.С помощью функций attachInterrupt, detachInterrupt можно выполнять прерывание на любом порте GPIO, кроме 16.
  • Тайминг и delay. Используя команды millis и micros можно вернуть мс и мкс, которые прошли с момента старта. Delay позволяет приостановить исполнение программы на нужное время. Также функция delay(…) позволяет поддерживать нормальную работу Wi-Fi, если в скетче присутствуют большие элементы, которые выполняются более 50 мс. Yield() – аналог функции delay(0).
  • Serial и Serial1 (UART0 и UART1). Работа Serial на ESP8266 аналогична работе на ардуино. Запись и чтение данных блокируют исполнение кода, если FIFO на 128 байт и программный буфер на 256 байт заполнены. Объект Serial пользуется аппаратным UART0, для него можно задать пины GPIO15 (TX) и GPIO13 (RX) вместо GPIO1(TX) и GPIO3(RX). Для этого после функции Serial.begin(); нужно вызвать Serial.swap();. Аналогично Serial1 использует UART1, который работает на передачу. Необходимый пин для этого GPIO2.
  • Макрос PROGMEM. Его работа аналогична работе в Ардуино. Позволяет перемещать данные read only и строковые постоянные во flash-память. При этом в ESP8266 не сохраняются одинаковые константы, что приводит к дополнительной трате флеш-памяти.
  • I2C. Перед началом работы с шиной I2C выбираются шины с помощью функции Wire.pins(int sda, int scl).
  • SPI, OneWire – поддерживаются полностью.

Использование esp8266 для связи Ардуино по WiFi

Перед подключением к Ардуино важно помнить, что у ESP8266 напряжение питания не может быть выше 3,6, в то время как на пате Ардуино напряжение равно 5 В. Соединять 2 микроконтроллера нужно с помощью резистивных делителей. Перед подключением модуля нужно ознакомиться с распиновкой выбранного ESP8266. Схема подключения для ESP8266-01 представлена на рисунке.

3,3 В с Ардуино – на Vcc&CH_PD на модуле ESP8266, Земля с Ардуино – к земле с ESP8266, 0 – TX, 1 – RX.

Для поддержки стабильной работы ESP8266 необходим источник постоянного напряжения на 3,3 В и максимальный ток 250 мА. Если питание происходит от конвертера USB-TTL, могут происходить неполадки и сбои в работе.

Работа с библиотекой Wi-Fi для ESP8266 схожа с библиотекой для обыкновенного шилда. Имеется несколько особенностей:

  • mode(m) – для выбора одного из трех режимов: клиент, точка доступа или оба режима единовременно.
  • softAP(ssid) – нужен для создания открытой точки доступа.
  • softAP(ssid, password) – создает точку доступа с паролем, который должен состоять не менее чем из 8 знаков.
  • WiFi.macAddress(mac) и WiFi.softAPmacAddress(mac)– определяет МАС адрес.
  • WiFi.localIP() и WiFi.softAPIP() – определение IP адреса.
  • printDiag(Serial); – позволят узнать данные о диагностике.
  • WiFiUDP – поддержка передачи и приема multicast пакета в режиме клиента.

Работа выполняется по следующему алгоритму:

  • Подключение USB-TTL к USB и к ESP.
  • Запуск Arduino IDE.
  • Выбрать в меню инструменты нужный порт, плату, частоту и размер flash-памяти.
  • Файл - Примеры - ESP8266WiFi - WiFiWebServer.
  • Записать в скетче SSID и пароль сети Wi-Fi.
  • Начать компиляцию и загрузку кода.
  • Дождаться окончания процесса прошивки, отсоединить GPIO0 от земли.
  • Поставить скорость 115200.
  • Произойдет подключение, будет записан адрес IP.
  • Открыть браузер, ввести в адресной строке номер IP/gpio/1
  • Посмотреть монитор порта, если к выходу GPIO2 подключен светодиод, он должен загореться.

NodeMCU на базе esp8266

NodeMCU – это платформа, основанная на базе модуля esp8266. Используется для управления схемой на расстоянии при помощи интернета через Wi-Fi. Плата малогабаритная, компактная, стоит дешево, на лицевой стороне имеется разъем для USB. Рядом кнопки для отладки и перезагрузки микроконтроллера. Также установлен чип ESP8266. Напряжение питания – от 5 до 12 В, желательно подавать более 10 В.

Большим преимуществом платы является ее малое энергопотребление. Нередко их используют в схемах с автономным питанием. На плате расположены всего 11 портов общего назначения, из них некоторые имеют специальные функции:

  • D1 и D2 – для интерфейса I2C/ TWI;
  • D5-D8- для интерфейса SPI;
  • D9, D10 – для UART;
  • D1-D10 – могут работать как ШИМ.

Платформа имеет современное API для аппаратного ввода и вывода. Это позволяет сократить количество действий во время работы с оборудованием и при его настройке. С помощью прошивки NodeMCU можно задействовать весь рабочий потенциал для быстрой разработки устройства.

WeMos на базе esp8266

WeMos – еще один вид платформы, основанный на базе микроконтроллера esp8266. Соответственно, имеется Wi-Fi модуль, поддерживается Arduino IDE, имеется разъем для внешней антенны. Плата имеет 11 цифровых входов/выходов, которые (кроме D0) поддерживают interrupt/pwm/I2C/one-wire. Максимальное напряжение питания достигает 3,3 В. Также на платформе присутствует USB разъем. Аналоговый вход 1 с максимальным напряжением 3,2В.

Для работы с модулем нужно установить драйвер CH340 и настроить Ардуино IDE под ESP8266. Для этого нужно в меню настройки в строке «дополнительная ссылка для менеджера плат» добавить адрес http://arduino.esp8266.com/stable/package_esp8266com_index.json.

После этого требуется найти пакет esp8266 by ESP8266 и установить его. Затем нужно выбрать в меню инструменты микроконтроллер Wemos D1 R2 и записать нужный скетч.

Выводы по ESP8266

С помощью плат на основе микросхемы ESP8266 вы можете добавить в свои проекты возможности “большого интернета”, сделав их гораздо более интеллектуальными. Дистанционное управление, сбор и анализ данных на сервере, обработка голоса и работа с изображением – все это становится доступным, когда мы подключаем наш проект по WiFi к интернету. В следующих статьях мы подробно рассмотрим то, как можно программировать устройства на базе esp8266, а также уделим внимание таким популярным платам как WeMos и NodeMcu.