Делаем бюджетный чудо корабль с управлением по WiFi на базе ESP8266.


Подробное руководство о том как взять ESP8266, добавить немножко клея и пенопласта и подарить детям (и взрослым) массу удовольствий.

Руководство состоит из следующих частей:
Описание платы
Предыстория
Используемые материалы
Изготовление корабля
Программирование
Плавание

Описание платы.

Мозгом корабля является купленная на Алиэкспресс плата. Данная отладочная плата является удобным средством для начала работы с WiFi модулем ESP8266-12.
На плате распаян сам модуль, а на штыревые разъёмы выведены все выводы модуля. К 6-ти выводам через токоограничительные резисторы припаяны красные светодиоды. Ещё к трём выводам припаян RGB светодиод.
Также присутствует стабилизатор 3,3 В, распаяны резисторы обвязки модуля, на входе ADC висит фоторезистор, присутствует джампер для перевода модуля в режим программирования.
Отдельно выведены выходы USART, причём маркировка Rx и Tx перепутаны местами.
Ко входу питания модуля припаян батарейный отсек на 3 батарейки. А в модуль уже загружена тестовая прошивка под управлением которой, насколько я помню, создаётся новая точка доступа. Подключившись к этой точке доступа можно управлять свечением светодиодов на плате. Если как для первого раза — то это прям волшебство какое то.

Предыстория постройки кораблика.

В процессе вялотекущего самообразования в сторону построения умного дома, год назад был закуплена эта плата (магазин в котором была сделана покупка сейчас закрыт). Вместе с ней взял ещё два голых модуля ESP8266-12 и с помощью сайта запустил на них два термометра/измерителя влажности, которые до сих пор успешно работают.

Далее попытался состыковать их с MajorDoMo — открытой и бесплатной системой управления Умным Домом. Но как то не пошло это дело,- забросил до поры.
В середине лета я наткнулся на статью. Оказывается esp8266 можно программировать как любую ардуину!!! И ардуиновских библиотек под esp8266 портировано уже на все случаю жизни.
Для меня настал качественно новый этап освоения esp8266…
Вдоволь поигрался с библиотечными примерами и захотелось мне сделать нечто с практическим применением.
Решил собрать детям для дачного водоёма самоходный кораблик, да не простой, а такой чтоб управлять им можно было с любого смартфона!
В начало

Используемые материалы

На строительный материал корпуса были выбраны пылящиеся в кладовке куски пенопласта.

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

Гребные винты — из куска жести.
На гребные валы замечательно подошли вязальные спицы (экспроприированные у супруги).

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

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

Также пригодились клей Dragon и клеевой термопистолет.

Для управления двигателями в загашнике нашлись два полевых транзистора выпаянных со старой материнской платы.
Источником питания послужили купленные в оффлайне аккумуляторы 18650.
Ещё понадобился маленький тумблер для подачи питания, несколько резисторов и макетная платка для соединения всего электричества между собой.

В начало

Изготовление корабля

Для резки пенопласта на скорую руку был собран ТермоЭлектроРезак состоящий из палки, двух длинных шурупов и куска тонкой проволоки. Проволоку лучше взять нихромовую, но у меня таковой не нашлось (а советский проволочный резистор ломать на это дело не хотелось) — поставил тоненькую стальную.
Запитал этот импровизированный станок от «народного блока питания» через DC-DC преобразователь. И тот и другой были куплены благодаря здешним обзорам.
Всего на этой фотографии пытливый взгляд может найти аж 10 товаров ранее обозреваемых на Муське.

Регулируя напряжение на выходе DC-DC преобразователя, опытным путём необходимо установить такой нагрев проволоки ТермоЭлектроРезака, при котором пенопласт разрезается легко и непринуждённо.
В итоге получаем более — менее ровные куски пенопласта удобные для последующей сборки.
На корпус кораблика пошли два самых больших куска, склееные между собой клеем Дракон.

Гребные винты изготавливаются в несколько операций:

— нарезать из жести квадратную заготовку (у меня 20*20 мм)
— соединив рисками диагональные углы найти центр

— просверлить по центру отверстие (диаметр 3,5 мм)
— затянуть подходящим винтом с гайкой (М 3*20)
— зажав винт в патрон дрели, на малых оборотах подходящим острым предметом начертить(нацарапать) окружность
— вырезать ровный круг

— надрезать по имеющимся диагональным рискам круг на 2/3 радиуса и изогнуть под углом (30-45 градусов)


Затем берём спицу. Отрезаем 25-30 мм кусок термоусадочной трубки диаметром чуть больше чем у спицы. Вращаем спицу с термоусадкой над маленьким пламенем газовой конфорки (или электрической) пока трубка не прогреется и плотно охватит спицу.
Далее отрезаем кусок трубки ещё большего диаметра,… и т.д. пока очередную трубку можно будет одеть на шестерню двигателя. Т.К. шестерня посажена на вал двигателя достаточно плотно, то она будет хорошо передавать крутящий момент гребному валу.
Берём последний кусок термоусадки и одеваем его одновременно на гребной вал и на двигатель.
После прогрева термоусадки получаем хорошее соединение.


Пора устанавливать двигатели в корпус.
Дрелью высверливаем в корпусе два отверстия под гребные валы. Со стороны днища вставляем подшипники скольжения.

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


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


Соединяем и спаиваем всё согласно схеме.

Питание с аккумуляторов подаётся через тумблер и дальше идёт на двигатели и на линейный стабилизатор 3,3 В. Второй вывод каждого двигателя подключен через полевой транзистор к минусу питания. Подавая с выхода ESP8266 за затвор полевого транзистора ШИМ сигнал различной скважности импульсов мы будем регулировать скорость вращения двигателя.
Напряжение питания также подаётся через резистивный делитель на вход ADC модуля ESP8266 для контроля состояния батареи.
Силовые транзисторы с резисторами обвязки, выключатель питания, стабилизатор, резистивный делитель для измерения напряжения батареи — всё размещено на макетной плате. К ней же припаяны плата с модулем ESP8266, выводы аккумулятора и двигателей.
К модулю подключен переходник USB-TTL.

Итак, всё готово для того чтобы вдохнуть в практически готовый кораблик искру жизни…
В начало

Программирование

О том как установить Arduino IDE и обеспечить в ней поддержку ESP8266 достаточно хорошо расписано в вышеупомянутой статье.

Для управления корабликом мы будем создавать на ESP8266 точку доступа и поднимать вэб сервер. Подключившись смартфоном к точке доступа и набрав в браузере адрес сервера (192.168.4.1) увидим страницу с элементами управления и телеметрией с борта нашего судна.

Дабы снизить нагрузку на ESP8266, уменьшить время отклика управляющих воздействий и повысить интерактивность я решил использовать технику AJAX запросов.
Выдержка из Википедии:
AJAX, Ajax (ˈeɪdʒæks, от англ. Asynchronous Javascript and XML — «асинхронный JavaScript и XML») — подход к построению интерактивных пользовательских интерфейсов веб-приложений, заключающийся в «фоновом» обмене данными браузера с веб-сервером. В результате, при обновлении данных веб-страница не перезагружается полностью, и веб-приложения становятся быстрее и удобнее.

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

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

Помучав некоторое время Гугл в поисках подходящей реализации моих хотелок, я набрёл на форум
в котором позаимствовал подходящий код
Первоначальный код

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
ESP8266WebServer server(80);
const char* ssid="yourSSID";
const char* password="yourPASSWORD";
String webSite,javaScript,XML;
unsigned long wait000=0UL,wait001=1000UL;
int LED=16;const int sliderMAX=10;                         // This sets the number of sliders you wantint sliderVal[sliderMAX]={60},ESPval[sliderMAX];
void buildWebsite(){
  buildJavascript();
  webSite="<!DOCTYPE HTML>\n";
  webSite+="<META name='viewport' content='width=device-width, initial-scale=1'>\n";
  webSite+=javaScript;
  webSite+="<BODY onload='process()'>\n";
  webSite+="
This is the ESP website ...
\n";
  webSite+="Runtime = <A ID='runtime'></A>

\n";
     webSite+="Сила сигнала a= \n";
     webSite+= Sila ;// Сила сигнала WiFi
     webSite+="

\n";
  webSite+="<TABLE BORDER=1 style='text-align:center;border-collapse:collapse'>\n";
  for(int i=0;i<sliderMAX;i++){
    webSite+="<TR>\n";
    webSite+="<TD>
<INPUT ID='slider"+(String)i+"' TYPE='range' ONCHANGE='Slider("+(String)i+")'></TD>\n";  //in Firefox, Chrome and Edge use ONINPUT     
    webSite+="<TD>Slidervalue"+(String)i+" = <A ID='Sliderval"+(String)i+"'></A>
\n";
    webSite+="ESPval"+(String)i+" = <A ID='ESPval"+(String)i+"'></A> milliseconds</TD>\n";
    webSite+="</TR>\n";
  }
  webSite+="</TABLE>\n";
  webSite+="</BODY>\n";
  webSite+="</HTML>\n";
}

void buildJavascript(){
  javaScript="<SCRIPT>\n";
  javaScript+="xmlHttp=createXmlHttpObject();\n";
  
  javaScript+="function createXmlHttpObject(){\n";
  javaScript+="  if(window.XMLHttpRequest){\n";
  javaScript+="    xmlHttp=new XMLHttpRequest();\n";
  javaScript+="  }else{\n";
  javaScript+="    xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');\n";
  javaScript+="  }\n";
  javaScript+="  return xmlHttp;\n";
  javaScript+="}\n";
  
  javaScript+="function process(){\n";
  javaScript+="  if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n";
  javaScript+="    xmlHttp.onreadystatechange=function(){\n";
  javaScript+="      if(xmlHttp.readyState==4&&xmlHttp.status==200){\n";
  javaScript+="        xmlDoc=xmlHttp.responseXML;\n";
  javaScript+="        xmlmsg=xmlDoc.getElementsByTagName('millistime')[0].firstChild.nodeValue;\n";
  javaScript+="        document.getElementById('runtime').innerHTML=xmlmsg;\n";
  javaScript+="        for(i=0;i<"+(String)sliderMAX+";i++){\n";
  javaScript+="          xmlmsg=xmlDoc.getElementsByTagName('sliderval'+i)[0].firstChild.nodeValue;\n";
  javaScript+="          document.getElementById('slider'+i).value=xmlmsg;\n";
  javaScript+="          document.getElementById('Sliderval'+i).innerHTML=xmlmsg;\n";
  javaScript+="          xmlmsg=xmlDoc.getElementsByTagName('ESPval'+i)[0].firstChild.nodeValue;\n";
  javaScript+="          document.getElementById('ESPval'+i).innerHTML=xmlmsg;\n";
  javaScript+="        }\n";
  javaScript+="      }\n";
  javaScript+="    }\n";
  javaScript+="    xmlHttp.open('PUT','xml',true);\n";
  javaScript+="    xmlHttp.send(null);\n";
  javaScript+="  }\n";
  javaScript+="  setTimeout('process()',1000);\n";
  javaScript+="}\n";
  
  javaScript+="function Slider(cnt){\n";
  javaScript+="  sliderVal=document.getElementById('slider'+cnt).value;\n";
  javaScript+="  document.getElementById('Sliderval'+cnt).innerHTML=sliderVal;\n";
  javaScript+="  document.getElementById('ESPval'+cnt).innerHTML=9*(100-sliderVal)+100;\n";
  javaScript+="  if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n";
  javaScript+="    xmlHttp.open('PUT','setESPval?cnt='+cnt+'&val='+sliderVal,true);\n";
  javaScript+="    xmlHttp.send(null);\n";
  javaScript+="  }\n";
  javaScript+="}\n";
  
  javaScript+="</SCRIPT>\n";
}

void buildXML(){
  Sila = WiFi.RSSI();  // Сила сигнала
  XML="<?xml version='1.0'?>";
  XML+="<xml>";
  XML+="<millistime>";
  XML+=millis2time();
  XML+="</millistime>";
  for(int i=0;i<sliderMAX;i++){
    XML+="<sliderval"+(String)i+">";
    XML+=String(sliderVal[i]);
    XML+="</sliderval"+(String)i+">";
    XML+="<ESPval"+(String)i+">";
    ESPval[i]=9*(100-sliderVal[i])+100;
    XML+=String(ESPval[i]);
    XML+="</ESPval"+(String)i+">";
  }
  XML+="</xml>";
}
String millis2time(){
  String Time="";
  unsigned long ss;
  byte mm,hh;
  ss=millis()/1000;
  hh=ss/3600;
  mm=(ss-hh*3600)/60;
  ss=(ss-hh*3600)-mm*60;
  if(hh<10)Time+="0";
  Time+=(String)hh+":";
  if(mm<10)Time+="0";
  Time+=(String)mm+":";
  if(ss<10)Time+="0";
  Time+=(String)ss;
  return Time;
}

void handleWebsite(){
  buildWebsite();
  server.send(200,"text/html",webSite);
}

void handleXML(){
  buildXML();
  server.send(200,"text/xml",XML);
}

void handleESPval(){
  int sliderCNT=server.arg("cnt").toInt();
  sliderVal[sliderCNT]=server.arg("val").toInt();
  buildXML();
  server.send(200,"text/xml",XML);
}

void setup() {
  Serial.begin(115200);
  pinMode(LED13,OUTPUT);
  pinMode(LED14,OUTPUT);
  pinMode(LED15,OUTPUT);
  WiFi.begin(ssid,password);
  while(WiFi.status()!=WL_CONNECTED)delay(500);
  WiFi.mode(WIFI_STA);

  Sila = WiFi.RSSI();
  Serial.println("\n\nBOOTING ESP8266 ...");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("Station IP address: ");
  Serial.println(WiFi.localIP());
  server.on("/",handleWebsite);
  server.on("/xml",handleXML);
  server.on("/setESPval",handleESPval);
  server.begin();
//  HTTP_begin();
}

void loop() {
  server.handleClient();
  if(millis()>wait000){
    buildXML();
    wait000=millis()+1000UL;
  }
  if(millis()>wait001){
    digitalWrite(LED13,!digitalRead(LED13));
    wait001=millis()+ESPval[0];
    Serial.print("   Sl3 ");
    Serial.print(ESPval[0]);
    analogWrite(LED13, ESPval[0]);
    Serial.print("   Sl4 ");
    Serial.print(ESPval[1]);
    analogWrite(LED14, ESPval[1]);
    Serial.print("   Sl5 ");
    Serial.println(ESPval[2]);
    analogWrite(LED15, ESPval[2]);
    Serial.print(WiFi.RSSI());  // Сила сигнала


 //   WiFi.printDiag(Serial);
  }
} 

Путём последовательных приближений код был доведён до нужного мне рабочего варианта.
окончательный код

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);
const char* ssid="ABPOPA"; //название точки доступа
const char* password=""; // пароль не будем писать
//const char* ssid="HomeIoT"; // здесь пишем название домашней точки доступа
//const char* password="DDV987654321"; // и пароль

String webSite,javaScript,XML;
unsigned long wait000=0UL,wait001=1000UL;
int OUT1=14, OUT2=12, BAT=17;//Назначение выводов 
int Sila, SilaLow = -43;   // Контроль силы сигнала WiFi
int Batareya, BatLow = 400; //Контроль напряжения батареи
float Povorot = 0.8, Trimer;    // Переменные для значений поворота и тримера двигателя
String Bat, SilaW;
const int sliderMAX=3;     // This sets the number of sliders you want
int sliderVal[3]={100, 50, 50};  //Начальные значения 1 слайдера - скорость, 2-го - поворот, 3- тример
int ESPval[sliderMAX];

void Batare(){
  Batareya = analogRead(BAT);         // Меряем напряжение батареи
  if (Batareya < BatLow){            // Если напряжение батареи меньше порогового значения
    Bat = "          Батарея села, ПОРА на ЗАРЯДКУ"; // Пишем предупреждение
  }
  else{                              // Если норма
    Bat = "";                       // Ничего не пишем
  }
}
void SilaWifi(){
  Sila = WiFi.RSSI();  // Меряем силу сигнала WiFi
  if (Sila < SilaLow){
    SilaW = "          Сигнал слабый, РАЗВОРАЧИВАЙ";
  }
  else{
    SilaW = "";
  }
}

void buildJavascript(){
  javaScript="<SCRIPT>\n";
  javaScript+="xmlHttp=createXmlHttpObject();\n";
  
  javaScript+="function createXmlHttpObject(){\n";
  javaScript+="  if(window.XMLHttpRequest){\n";
  javaScript+="    xmlHttp=new XMLHttpRequest();\n";
  javaScript+="  }else{\n";
  javaScript+="    xmlHttp=new ActiveXObject('Microsoft.XMLHTTP');\n";
  javaScript+="  }\n";
  javaScript+="  return xmlHttp;\n";
  javaScript+="}\n";
  
  javaScript+="function process(){\n";
  javaScript+="  if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n";
  javaScript+="    xmlHttp.onreadystatechange=function(){\n";
  javaScript+="      if(xmlHttp.readyState==4&&xmlHttp.status==200){\n";
  javaScript+="        xmlDoc=xmlHttp.responseXML;\n";
  javaScript+="        xmlmsg=xmlDoc.getElementsByTagName('millistime')[0].firstChild.nodeValue;\n";
  javaScript+="        document.getElementById('runtime').innerHTML=xmlmsg;\n";               // Добавляем наши данные
  javaScript+="        xmlmsg=xmlDoc.getElementsByTagName('Sila')[0].firstChild.nodeValue;\n";// Сила сигнала WiFi
  javaScript+="        document.getElementById('Sila').innerHTML=xmlmsg;\n";                  // Сила сигнала WiFi
  javaScript+="        xmlmsg=xmlDoc.getElementsByTagName('Batareya')[0].firstChild.nodeValue;\n";// Напряжение батареи
  javaScript+="        document.getElementById('Batareya').innerHTML=xmlmsg;\n";                  // Напряжение батареи
  javaScript+="        for(i=0;i<"+(String)sliderMAX+";i++){\n";
  javaScript+="          xmlmsg=xmlDoc.getElementsByTagName('sliderval'+i)[0].firstChild.nodeValue;\n";
  javaScript+="          document.getElementById('slider'+i).value=xmlmsg;\n";
  javaScript+="          document.getElementById('Sliderval'+i).innerHTML=xmlmsg;\n";
  javaScript+="          xmlmsg=xmlDoc.getElementsByTagName('ESPval'+i)[0].firstChild.nodeValue;\n";
  javaScript+="          document.getElementById('ESPval'+i).innerHTML=xmlmsg;\n";
  javaScript+="        }\n";
  javaScript+="      }\n";
  javaScript+="    }\n";
  javaScript+="    xmlHttp.open('PUT','xml',true);\n";
  javaScript+="    xmlHttp.send(null);\n";
  javaScript+="  }\n";
  javaScript+="  setTimeout('process()',1000);\n";
  javaScript+="}\n";
  
  javaScript+="function Slider(cnt){\n";
  javaScript+="  sliderVal=document.getElementById('slider'+cnt).value;\n";
  javaScript+="  document.getElementById('Sliderval'+cnt).innerHTML=sliderVal;\n";
  javaScript+="  document.getElementById('ESPval'+cnt).innerHTML=9*(100-sliderVal)+100;\n";
  javaScript+="  if(xmlHttp.readyState==0||xmlHttp.readyState==4){\n";
  javaScript+="    xmlHttp.open('PUT','setESPval?cnt='+cnt+'&val='+sliderVal,true);\n";
  javaScript+="    xmlHttp.send(null);\n";
  javaScript+="  }\n";
  javaScript+="}\n";
  
  javaScript+="</SCRIPT>\n";
}
void buildWebsite(){    // Создаём страницу с элементами управления
  buildJavascript();
  webSite="<!DOCTYPE HTML>\n";
  webSite+="<META name='viewport' content='width=device-width, initial-scale=1', charset=\"utf-8\">\n";
  webSite+=javaScript;
  webSite+="<BODY onload='process()'>\n"; 
  webSite+="
Кораблик
\n";
  webSite+="Время работы = <A ID='runtime'></A>
\n";
  webSite+="Сила сигнала <A ID='Sila'></A>
\n";              // Сила сигнала WiFi
  webSite+="Напряжение батареи <A ID='Batareya'></A>

\n"; // Напряжение батареи
  webSite+="<TABLE BORDER=1 width='700' height='200' style='text-align:center;border-collapse:collapse'>\n";
  //  webSite+="<INPUT ' TYPE='range' width='600'> \n";  // это пример слайдера
  webSite+="<TR>\n";        // 1 слайдер
  webSite+="<TD>
<INPUT ID='slider"+(String)0+"' TYPE='range' ONCHANGE='Slider("+(String)0+")'></TD>\n";
  webSite+="<TD>Обороты = <A ID='Sliderval"+(String)0+"'></A>
\n";
  webSite+="Моторов = <A ID='ESPval"+(String)0+"'></A> * </TD>\n";
  webSite+="</TR>\n";

  webSite+="<TR>\n";        // 2 слайдер
  webSite+="<TD>
<INPUT ID='slider"+(String)1+"' TYPE='range' ONCHANGE='Slider("+(String)1+")'></TD>\n";
  webSite+="<TD>Направление = <A ID='Sliderval"+(String)1+"'></A>
\n";
  webSite+="Движения = <A ID='ESPval"+(String)1+"'></A></TD>\n";
  webSite+="</TR>\n";
  
  webSite+="<TR>\n";        // 3 слайдер
  webSite+="<TD>
<INPUT ID='slider"+(String)2+"' TYPE='range' ONCHANGE='Slider("+(String)2+")'></TD>\n";
  webSite+="<TD>Корекция = <A ID='Sliderval"+(String)2+"'></A>
\n";
  webSite+="Моторов = <A ID='ESPval"+(String)2+"'></A></TD>\n";
  webSite+="</TR>\n";

  webSite+="</TABLE>\n";
  webSite+="</BODY>\n";
  webSite+="</HTML>\n";
}

String millis2time(){ // преобразование милисекунд в вид ч/м/с
  String Time="";
  unsigned long ss;
  byte mm,hh;
  ss=millis()/1000;
  hh=ss/3600;
  mm=(ss-hh*3600)/60;
  ss=(ss-hh*3600)-mm*60;
  if(hh<10)Time+="0";
  Time+=(String)hh+":";
  if(mm<10)Time+="0";
  Time+=(String)mm+":";
  if(ss<10)Time+="0";
  Time+=(String)ss;
  return Time;
}

void buildXML(){
  XML="<?xml version='1.0'?>";
  XML+="<xml>";
  XML+="<millistime>";
  XML+=millis2time();
  XML+="</millistime>";   // Добавляем наши данные
  SilaWifi();             // Здесь измеряем силу сигнала
  XML+="<Sila>";          // Сила сигнала WiFi
  XML+=String(Sila)+SilaW;// Сила сигнала WiFi
  XML+="</Sila>";         // Сила сигнала WiFi
  Batare();                 // Здесь измеряем напряжение батареи
  XML+="<Batareya>";        // Напряжение батареи
  XML+=String(Batareya)+Bat;// Напряжение батареи
  XML+="</Batareya>";       // Напряжение батареи
  for(int i=0;i<sliderMAX;i++){
    XML+="<sliderval"+(String)i+">";
    XML+=String(sliderVal[i]);
    XML+="</sliderval"+(String)i+">";
    XML+="<ESPval"+(String)i+">";
    ESPval[i]=9*(100-sliderVal[i])+100;
    XML+=String(ESPval[i]);
    XML+="</ESPval"+(String)i+">";
  }
  XML+="</xml>";
}

void handleWebsite(){
  buildWebsite();
  server.send(200,"text/html",webSite);
}

void handleXML(){
  buildXML();
  server.send(200,"text/xml",XML);
}

void handleESPval(){
  int sliderCNT=server.arg("cnt").toInt();
  sliderVal[sliderCNT]=server.arg("val").toInt();
  buildXML();
  server.send(200,"text/xml",XML);
}

void setup() {
  Serial.begin(115200);
  pinMode(OUT1,OUTPUT);
  pinMode(OUT2,OUTPUT);
  pinMode(BAT,INPUT);
  WiFi.softAP(ssid, password); // Создаём точку доступа
//  WiFi.begin(ssid,password);  //Это вариант для подключения к существующей точке
//  while(WiFi.status()!=WL_CONNECTED)delay(500);
//  WiFi.mode(WIFI_STA);
  
  Serial.println("\n\nBOOTING ESP8266 ...");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("Station IP address: ");
  Serial.println(WiFi.localIP());     // Вывод в монитор порта присвоенный IP
  server.on("/",handleWebsite);
  server.on("/xml",handleXML);
  server.on("/setESPval",handleESPval);
  server.begin();
}

void loop() {
  server.handleClient();
  if(millis()>wait000){
    buildXML();
    wait000=millis()+1000UL;
  }
  if(millis()>wait001){
    wait001=millis()+300;           //Обновляем значения раз в 300 милисекунд
    Trimer = (ESPval[2]*.0015); 
    Serial.print("   Skorost] ");
    Serial.print(ESPval[0]); 
    Serial.print("   Povorot ");
    Serial.print(ESPval[1]);
    Serial.print("   Trimer ");   
    Serial.print(ESPval[2]);
    Serial.print(Trimer);

   if (ESPval[0] > 200){               // Если слайдер скорости  > 200
        if ( ESPval[1] > 600) {        //  Если слайдер поворота > 600 то поворачиваем на лево 
            analogWrite(OUT1, ESPval[0]);
            analogWrite(OUT2, int(ESPval[0] * Povorot*Trimer));
            Serial.print(" Le  ");
            Serial.print(ESPval[0] * Povorot*Trimer);
           }
       else if (400 > ESPval[1] ){     //  Если слайдер поворота < 400 то поворачиваем на право
           analogWrite(OUT1, int(ESPval[0] * Povorot));
           analogWrite(OUT2, int(ESPval[0]*Trimer));
           Serial.print("   Pr ");
           Serial.print(int(ESPval[0] * Povorot));
           }
       else {                          //  Если слайдер поворота > 400 и < 600то едем прямо
           analogWrite(OUT1, ESPval[0]);
           analogWrite(OUT2, int(ESPval[0]*Trimer));
           Serial.print("   OK ");
           }
      }
   else {                          //  Если слайдер скорости  < 200 - выключить моторы
       analogWrite(OUT1, 0);
       analogWrite(OUT2, 0);
       Serial.print("   Stop ");
       }    
    Serial.print("   Batareya ");
    Serial.println(Batareya);
 }
} 

В коде довольно много пояснений, надеюсь всё будет понятно.
Двигатели кораблика управляются путём изменения положения ползунков трёх слайдеров на странице.
— Первый слайдер отвечает за скорость вращения моторов (и скорость движения кораблика соответственно). Если изменять положение ползунка этого слайдера от 20 до 100%, то будет меняться значение связанной со слайдером переменной ESPval[0]. Значение переменной записывается в порты OUT1 и OUT2 ESP8266 (выводы которых идут на управляющие затворы полевых транзисторов) и обороты двигателей будут нарастать от 0 до максимума.
В диапазоне положений этого ползунка от 0 до 20% в порты записываются 0 и двигатели стоят.
— Второй слайдер отвечает за повороты (переменная ESPval[1]). Если его ползунок находится в правом или левом положении, то значение скорости соответствующего двигателя будет снижаться на коэффициент 0,8 (константа Povorot). Двигатель будет притормаживаться, а кораблик поворачивать в нужную сторону.
— Третий слайдер (переменные ESPval[2] и Trimer) нужен для нивелирования разности характеристик двигателей. В зависимости от положения слайдера можно притормаживать или ускорять один из двигателей.

К сожалению функционал измерения напряжения батареи довести до конца не удалось. В процессе наладки был сожжён вход ADC модуля (надо думать замкнул его на + батареи)…
Измерение мощности сигнала WiFi работает, но требуется более точная калибровка.

Для отладки использовалось подключение к домашней WiFi сети и вывод информации в последовательный порт.

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

Скетч компилировался в IDE версии 1.6.12.

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

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

В начало


Плавание

Сначала были пробные запуски в акватории ванной, по результатам которых были сделаны следующие доработки:
— 4 батарейки АА в источнике питания были безоговорочно заменены на 2 аккумулятора 18650
— к регулировкам скорости и поворота было добавлено триммирование одного из двигателей
— был увеличен шаг гребных винтов

Затем в ближайший выезд на дачу судно было было торжественно отправлено в плавание на большой воде.

Полевые испытания показали что в следующей версии необходимо:
— усилить мощность сигнала WiFi модуля путём добавления внешней антенны
— увеличить диаметр гребных винтов (или заказать винты на Алиэкспресс )
— увеличить притормаживание двигателей при поворотах с 20% до 40-50%
— доработать корпус для улучшения обтекания
— заменить двигатели на бесколлекторные
— сделать руль с приводом от сервомашинки
— прикрутить FPV
— добавить светодиодной иллюминации для ночных заплывов
— установить на палубу фейерверк и запускать его на середине пруда
— всё что душа пожелает…

Но эти доработки возможно воплотятся уже в новом сезоне.

В начало

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

Без существенной переделки программы таким же нехитрым образом можно слепить управляемую машинку (или несколько машинок) для весёлых заездов по квартире долгими зимними вечерами.

Буду рад если этот опус вдохновит кого либо для занятий творчеством.
Планирую купить +91 Добавить в избранное +131 +257
+
avatar
+18
Шикарно) не готовый набор собирать, а практически новая жизнь мусора на китайских соплях)
Сразу почему-то вспомнились кружки моделистов в доме пионеров, там тоже стояли корпуса из пенопласта и гребные валы из банки нескафе)
+
avatar
  • dmit9
  • 01 октября 2016, 07:56
+8
В далёком советском пионерском детстве я тоже посещал авиамодельный кружок.
+
avatar
  • shaman
  • 01 октября 2016, 08:34
+7
Спасибо матери с отцом! :)
+
avatar
  • dmit9
  • 01 октября 2016, 10:32
+9
Это да, журналы Моделист конструктор, Техника молодёжи, Юный техник…
+
avatar
  • bignab
  • 01 октября 2016, 13:54
+1
Автор безусловно молодец, но у меня пара вопросов — ЗАЧЕМ КОТЭ так подстриг?
И система видео наблюдения как устроена на компе или отдельной железякой?
+
avatar
  • dmit9
  • 01 октября 2016, 14:31
0
Котэ постриг чтоб красиво и нежарко было скотинке.
Видео наблюдение строил на отдельном 16 канальном регистраторе.
+
avatar
  • wwest
  • 03 ноября 2016, 00:46
+1
Из пенопласта??? Это демократические выбрики конца перестройки.
Из куска дерева-прямоугольный брусок с острым носом.Резиномотор и такие же гребные винты из гнутой жести.А возвратом по ЖПиС служил изогнутый жестяной руль, который и заворачивал лодку на середине фонтана обратно.
+
avatar
  • Boriz
  • 01 октября 2016, 07:53
+4
Спасибо, интересная затея.
Цепочку таких плавающих по Волге точек доступа штук 20 и интернет по WiFi до дачи доберётся. :)
+
avatar
  • Siroc-co
  • 01 октября 2016, 08:23
+4
Ага. На якорь их, а винты пусть генерируют питалово для точек доступа\ретрансляторов от течения.
+
avatar
  • Boriz
  • 01 октября 2016, 08:30
+21
Или поставлю на гаситель, а то он уже лет 30 как пылится )))
+
avatar
  • grom-761
  • 01 октября 2016, 08:57
+6
Крутая игрушка для тех времён. Помню в советское время нормальную жратву, шмотки и хорошие игрушки можно было купить только в Москве, в нашей дыре только оловянные солдатики продавались. Мне типа такого, с Москвы привозили, работал от батареек, пульты управления тогда ещё не придумали, как хочешь, так и лови, если уплывёт)))
+
avatar
  • Boriz
  • 01 октября 2016, 09:23
+1
До этого много всяких лодочек на моторчиках делал из чего попало. А вот как эту подарили так и отшептало ). Позже радиоуправление пробовал к ней приделать. Однако с батарейками был дефицит ( А343. если кто помнит). Так и оставил в покое до «лучших времён» ). Покупалось, как ни странно, в универмаге. Цена 25 рублей
+
avatar
  • grom-761
  • 01 октября 2016, 09:42
+7
25 рублей по тем деньгам солидная сумма, мопед Рига-13, если не ошибаюсь 130 рублей стоил. В те времена вещи ценились, так как был дефицит, сейчас купил телевизор и никакой радости:)
+
avatar
  • demonbig
  • 01 октября 2016, 15:15
+2
ООО, да знаменитый дырчик, при мне 145 рублей стоил в 89 году
+
avatar
  • grom-761
  • 01 октября 2016, 16:07
0
145 рублей стоил в 89 году
Как раз в 89 его мне и купили, хотя мечта была Карпаты или Дельта.
+
avatar
  • dmit9
  • 01 октября 2016, 17:44
0
Хех, а у меня была Верховина
+
avatar
  • grom-761
  • 01 октября 2016, 18:04
0
Да, были такие)) а ещё помню были ЗИФ и Мокик, последний редко продавали. У вас в Украине видел ещё чешские (может и не чешский) трёх скоростные, у нас таких вообще не было, марку не помню.
+
avatar
  • Pomisov
  • 04 октября 2016, 20:06
+1
ява 50-ка бабетта
выставка только что закрылась в Киеве, была там мопедка.
+
avatar
  • wwest
  • 03 ноября 2016, 00:50
+2
В те времена вещи ценились, так как был дефицит,---
Дифсита в СССР НЕ было.Идёшь к знакомому еврею из торговли(главбух, завсклад, завмаг, старший продавец), переплачиваешь сверху и имеешь что хочешь.
Был дефицит денег-все хорошие ВЕЩИ в СССР стоили ОЧЕНЬ дорого.
А дифсит делали искусственно заинтересованные лица определённой национальности сидящие в торговле и министерствах.
В 70, начале 80 телевизорами были забиты ВСЕ магазины.
Вот только стоили они 8-10 зарплат.Оооочень дорого.
В конце 80 дефицит ЦТВ был СДЕЛАН искусственно.
Лично видел склады забитые ЦТВ на десятки метров вверх и на километры в длину.Когда на полках было пусто.
В 90г -91г Львовский завод произвёл более 3 миллионов ЦТВ ни один из них не поступил в продажу, людям не заплатили за работу.
Зато как только объявили незалежность все полки оказались забиты товарами, НО за новую валюту-купоны.
Продажная торговля многие годы готовилась к перевороту и свержению народной власти.Создавали озлобленность быдла пустыми полками.
+
avatar
+2
Идёшь к знакомому еврею из торговли
У нас легче было снежного человека встретить, чем еврея. В нашем уральском 80-и тысячном городишке штук пять бы набралось и то хорошо и среди местных немцев терялись, так как фамилии на немецкие походили:))
Ещё помню партийные бонзы жировали, во дворе у парня папа был шишкой в местном горкоме КПСС и мама тоже заведовала одним большим объектом в городе, помню эту мразь толстую, его папу, как он жигули новой модели как перчатки менял, когда как простому работяге надо было лет 5-10 на неё горбатиться и как он ящики с заморским провиантом постоянно с багажника вытаскивал, где-то по блату затаривался, в то время когда в магазине было шаром покати, время прошло, те же партийные крысы у власти, только название страны поменялось.
+
avatar
0
Не только название страны. Теперь черта с два ты «партийного бонзу» увидишь во дворе. Теперь у них свои коттеджы, и не жигули, а мерседесы, и не один. Разрыв между простым людом и боссами вырос на порядок.
+
avatar
  • sea
  • 01 октября 2016, 10:32
+4
Да, очень хорошо помню этот пожарный катер. Он стоял в нашем небольшом городе в «Детском мире» в 80-х годах в стеклянной витрине именно за 25 рублей — нереально большие деньги!
Это была моя несбыточная мечта, и я, идя со школы домой, частенько заходил полюбоваться на него. Просить родителей купить даже не было мысли за такие деньги.
Он же был изначально на р/у? Это было большой редкостью для советских игрушек.
+
avatar
  • bahek29
  • 01 октября 2016, 11:14
+1
помнится мне досталась от старшего двоюродного брата здоровенная машинка на р/у, синяя такая, типа формулы)))
хорошо запомнилось что в выходных каскадах еще стояли германиевые транзисторы
работала она на адском количестве батареек и пульт был в виде рулевого колеса
+
avatar
  • Boriz
  • 02 октября 2016, 06:55
0
В нём предусмотрена установка Р/У, только в комплекте конструктора его не было. Цена не маленькая — это я сейчас понимаю :). Но семья строителя-монтажника 6-го разряда была финансово благополучной по тем временам.
+
avatar
  • Bober
  • 03 ноября 2016, 18:14
+1
Такой был, покупали в Чугуеве. Пять рублей был, или около того. Отдел игрушек там был маленький, но интересный, даже лучше, чем в Харькове, в Доме Торговли.
+
avatar
  • she
  • 01 октября 2016, 13:50
+1
ААА у меня тоже такой есть!!! Еще есть у меня парусник 2 выпуск.
+
avatar
  • Siroc-co
  • 01 октября 2016, 08:20
+8
Идеально! Спасибо за идею, не знал чем занять крестника приехавшего погостить. Ща оттопырю коленку, соберём за час, думаю. Тем более что все есть в наличии в кладовке, код у вас возьму, пруд неподалёку, и бабье лето дало немного тепла.
Спасибо! Мы пошли…
+
avatar
  • dmit9
  • 01 октября 2016, 08:45
+1
Там в коде для лучшего маневрирования константу Povorot = 0.8 измените на 0.4 или 0.6
+
avatar
  • shaman
  • 01 октября 2016, 08:24
+1
Плюсую за Ваше рукожопстводелие! Делал тоже по детству кораблик. Советский мотор-винт был в наличии. Мотор-винт-выключатель-батарейка на 4,5 Вольта, и немного криво вклееный винт в пенопласт — чтобы кораблик гонял по кругу, и его можно было изловить. Ардуин тогда не было, как и сотовых аппаратов. Ну и при приклейке палубы к корпусу пенопласт сожрало — тогда клей «Момент» был на толуоле. Как и при покраске днища ацетоно-содержащим лаком. Но лётал кораблик шустро! Хрен поймаешь с первого раза.
И Вам бы использовать лучше что-то типа Пеноплекса-утеплителя. Он не такой пористый.
+
avatar
  • dmit9
  • 01 октября 2016, 08:28
0
Там нижнем слоем пенопласт от упаковки. Он имеет плотную структуру, хорошо режется простым ножом и не крошится.
+
avatar
  • DMA
  • 02 октября 2016, 14:30
0
Серый лист XPS в Леруа ~70 р/шт. — можно целую флотилию ножом нарезать)
+
avatar
  • Setjet
  • 01 октября 2016, 08:42
+2
Интересно что-то подобное на газонокосилку примастырить
+
avatar
  • DDimann
  • 01 октября 2016, 08:49
+4
Блин, тоже детство вспомнилось…
Только тогда просто брали и делали, не глядя на внешний вид, главное — что бы работало.
Плюсую.
+
avatar
  • CasmSar
  • 01 октября 2016, 19:10
0
Только тогда просто брали и делали, не глядя на внешний вид, главное — что бы работало.
Вот-вот так и, став взрослыми, продолжаем. Жигули клепаем почти 50 лет — корыто-корытом, но ведь же «работают». Да вся промышленность, практически, работает по принципу «лишь бы работало», об эстетической составляющей — дизайне никогда и речи не было. Все инженеры, технологи — безрукие и полубезмозглые. Одна военка еще, слава Богу, шевелится.
+
avatar
  • DDimann
  • 01 октября 2016, 19:53
+4
Ну зачем так обобщать? Не все же так и не продвинулись дальше уроков первого класса…
Вот сделали быстро такую страшную на вид, о работающую штуку — и для детей много это интересней, чем если бы их папа пару месяцев вылизывал корпус, как на выставку.
А дальше, после первого результата, и именно быстро полученного — можно это дело окультурить — но именно когда интерес появился.
Или следующую задумку делать — только уже можно подольше, не макет, а именно модель…
Ну, а можно и жигули клепать, это уж кому что дано…
+
avatar
  • CasmSar
  • 01 октября 2016, 20:23
0
В основном вы не правы, товарисч. Как раз наступил момент, когда уже с самого раннего детства нужно приучать детей к прекрасному, а не «лишь бы работало». Уже скоро сто лет бывшие сссровские страны живут по этому принципу. Неужели самим не противно брать в руки «совдеповские» товары, и прошлого века и нынешнего? За редким исключением, по пальцам пересчитать, были такие товары, на которые можно было приятно посмотреть. И если бы папа лишний часик посидел бы за изготовлением модели и хотя бы чуть-чуть ее привел в эстетический вид, то корона МОДЕЛИСТА с него бы не слетела.
+
avatar
  • DDimann
  • 01 октября 2016, 21:41
+4
Может, и не прав…
Помню, как собирал мультивибратор на проводах, усилитель — на картонке.
С тех пор у меня несколько изменился подход к разработке и исполнению.

… а еще у меня в первом классе была пятерка по рисованию.
Рисую я сейчас точно так же — но пятерки мне за это почему то не ставят…
+
avatar
  • Dimon_
  • 01 октября 2016, 09:08
+1
Спасибо, обзор понравился.
Хотя лично мне, вдобавок к «фринзингу» явно и остро не хватает принципиальной схемы. Вы уж хоть от руки нарисуйте, а?

Всего на этой фотографии пытливый взгляд может найти аж 10 товаров ранее обозреваемых на Муське.
Неужели был обзор кота??? :)
+
avatar
  • dmit9
  • 01 октября 2016, 10:23
0
вечером список 10 товаров оглашу
P/S. это кошка
+
avatar
  • dmit9
  • 01 октября 2016, 21:58
+1
mySKU.me/blog/china-stores/33703.html Деревянная головоломка «54T tetris»
mySKU.me/blog/china-stores/37597.html Обучаемый пульт Chunghop
mySKU.me/blog/aliexpress/40354.html 4портовый usb3.0 hub с выключателями портов
mySKU.me/blog/aliexpress/35492.html Набор для сборки паяльной станции на жалах Hakko T12.
mySKU.me/blog/china-stores/33286.html 24 Вольта 100 Ватт блок питания с неплохим результатом
mySKU.me/blog/china-stores/33405.html DC-DC преобразователь, как это иногда бывает.
mySKU.me/blog/china-stores/40662.html Миниатюрный многофункциональный измеритель для всяких поделок
mySKU.me/blog/aliexpress/24145.html Недорогой и удобный DC-DC преобразователь.
mySKU.me/blog/aliexpress/41082.html Мобильный роутер NEXX WT3020H
ещё так и не смог найти, скроллинг у мышки устал, одноканальный RF димер/выключатель подсветки 12 В
+
avatar
  • mVlad77
  • 01 октября 2016, 09:27
+10
На любом рынке есть простые лодки рублей за 100 (для корпуса вместо этого ужасного куска пенопласта), я в свое время ребенку для ванной по 45 руб вот две такие купил в Fix Price.
+
avatar
  • dmit9
  • 01 октября 2016, 10:44
+2
Это ж надо было идти, искать… Если бы такой корпус валялся под рукой — то да.
+
avatar
  • serg_mur
  • 01 октября 2016, 09:37
+5
Автор — Вы молодец! Огромный плюс. Ваше применение ESP ляжет в основу идеи прикормки для рыбы. Добавить на плавучую платформу чашу с прикормом, которая будет опрокидываться по команде в нужном месте — обязательно сделаю к следующему рыбацкому сезону. Спасибо большое за подсказку.
Кстати, у меня тоже проблема сопряжения ESP с Majordomo — по отдельности всё работает.
+
avatar
  • bOBZILLA
  • 01 октября 2016, 10:44
0
Для Ваших целей вместо (или в дополнение) гребных винтов можно попробовать использовать «водометы» в виде маленьких аквариумных помп. Должны создавать меньше вибрации в воде.
+
avatar
  • serg_mur
  • 01 октября 2016, 11:57
0
Спасибо за идею! Надо попробовать.
+
avatar
  • DMA
  • 01 октября 2016, 12:24
+3
Можно вместо воды воздух молотить, сделав аэролодку.
+
avatar
0
Все рыбаки будут признательны Вам.
+
avatar
  • serg_mur
  • 01 октября 2016, 12:12
0
Да не жалко. Пусть пользуются. )))
+
avatar
  • SEM
  • 01 октября 2016, 12:16
+2
С GPS, указанием маршрута, точек сброса и с возвратом на «базу»…

P.S. WiFi — это до 100 метров, рогатка или двухметровая «ложка» не проще ли будут?
+
avatar
  • dmit9
  • 01 октября 2016, 14:36
+1
Кстати да, радиус уверенной работы этого модуля со штатной антеннкой не более 30 м. Для дальних заплывов надо модуль с внешней антенной. Также важно чтоб смартфон/планшет «чуствительный был».
+
avatar
  • Bober
  • 03 ноября 2016, 18:16
0
Китайцы уже подсуетились. Для прикорма лодочки с радиусом действия до 200м — в районе 30-40 мертвых енотов.
+
avatar
  • peetbull
  • 01 октября 2016, 09:41
0
Далее попытался состыковать их с MajorDoMo — открытой и бесплатной системой управления Умным Домом. Но как то не пошло это дело,- забросил до поры.
вот это интересно тоже) как освоите напишите обзор
+
avatar
  • Baton72
  • 02 октября 2016, 07:12
0
Я не автор, но… Как это ни парадоксально, но собранные по схеме и с прошивкой с wifi-iot девайсы линкуются с Мажордомой с полпинка. Нужно только в прошивке прописать адрес Мажордомы и скопипастить код, который на их форуме приведен.
+
avatar
  • AlekseyM
  • 01 октября 2016, 09:42
+1
А я на ней температурные станции, датчики собираю, а тут вон оно что можно!
+
avatar
  • dmit9
  • 01 октября 2016, 10:22
0
Главное в подобных вопросах — нужно только себе разрешить это сделать. Не отмазываться для самого себя типа: у меня не получится, это слишком сложно(легко и неинтересно) для меня, образование не то, зачем мне на это время тратить и т.д.
+
avatar
  • maxibons
  • 06 октября 2016, 21:46
0
Поговорку слышали такую — «Что бы Вы ни делали на базе ESP8266 — все равно получится метеостанция»?
+
avatar
  • vp7
  • 01 октября 2016, 10:34
0
А как добились герметизации? Ведь вода должна протекать между корпусом ручки и валами.
+
avatar
  • dmit9
  • 01 октября 2016, 10:41
0
никакой герметизации, от верха палубы до воды больше 2- см. Вода вверх не поднимается, капиллярный эффект между корпусом ручки и валом не наблюдал)
+
avatar
  • pc_boy
  • 01 октября 2016, 10:56
+7
А мы сделали вот такой катер.
youtu.be/HsG7ND4z6IU
Аппаратура радиоуправления куплена в Китае за ~30$. А вот поворотом ракетной установки и выстрелами управляет ардуинка.
+
avatar
  • dmit9
  • 01 октября 2016, 11:24
0
Клас! А что в качестве ракет, петарды?
+
avatar
  • SEM
  • 01 октября 2016, 12:20
+2
Кораблик или не кораблик, а вот взять эту схему с кодом и после лёгкой переделки сделать управление светом, вентилятором или розетками мне кажется несложным. «Умные» розетки стоят 15-20$, а тут 3$, больше возможностей плюс удовольствие от того что сделал сам.
+
avatar
  • DMA
  • 01 октября 2016, 12:28
+1
Для этих вещей есть sonoff — суть та-же esp, только с питанием от 220, реле и в корпусе.
+
avatar
  • SEM
  • 01 октября 2016, 12:42
0
И сколько там цена набегает?
+
avatar
  • SEM
  • 01 октября 2016, 13:27
+2
Как одиночный «вкл/выкл» оно хорошо, всё готовое и дешевле чем покупать элементы отдельно.
Но по вышеприведённой схеме и коду можно сделать более сложное управление, под конкретную задачу, будь то управление группами ламп, или три скорости вентилятора.
+
avatar
  • spectral
  • 01 октября 2016, 14:08
+2
Все зависит от целей. ТС просто мог купить готовый корабль. И тогда обзор был бы одним из тысяч «зацените че купил!».
По функционалу выбор очень большой, диву даешься, что «все уже придумано до нас». Опять же, самоделка все-равно упираеся в сбор из готового (можно купить отладку ESP8266-12, а можно развести, вытравить и спаять; терморезак можно купить, а клеевый пистолет сделать).
Но сделанное руками всегда интереснее, необычнее и веселее. :)
+
avatar
  • SolarW
  • 09 октября 2016, 23:59
0
www.electrodragon.com/product/wifi-iot-relay-board-based-esp8266/ — вроде от электродраконов коробочка поинтересней будет чем Sonoff…
И два канала реле, и гребенка где можно остальные пины ESP8266 взять, и готовая разводка/место под пайку DHT22…
Только что-то она подорожала после апгрейда релюшек…
Раньше, когда релюшки Songle стояли (такие как на фотках) вроде 6$ за штуку было.
+
avatar
0
И щас она $6 стоит с сетевым питанием, с DC питанием еще дешевле.
+
avatar
  • KnDmPetr
  • 01 октября 2016, 13:16
+2
А видео можно было еще в меньшем квадратике сделать? (Сарказм)
+
avatar
  • dmit9
  • 01 октября 2016, 14:40
0
Жутко извиняюсь, первый опыт работы с Сони Movie Studio и первое видео выложенное в сеть.
В следующий раз исправлюсь.)
+
avatar
0
В ютьюб редакторе нет обрезки?
+
avatar
  • bazis13
  • 01 октября 2016, 15:36
0
Когда-нибудь в этом десятилетии я сниму свое первое видео, которое НЕ выложу в сеть )
+
avatar
  • DMA
  • 02 октября 2016, 03:58
0
Для простой вырезки сегмента из видео перед заливкой на ютуб используйте простой и топорный AviDemux в режиме копирования видео и аудио потоков. И не забывайте в ютубе отключать их долбанную стабилизацию, которую они пихают по дефолту.
+
avatar
  • SEM
  • 02 октября 2016, 13:24
0
OFF. Случайно не подскажете простую программу для обрезки MKV, без избыточного функционала, «регистраций и SMS»? Типа как VDub для AVI.
Скаченные с торрентов серии часто имеют в начале 30-40 сек. рекламы от спонсора релизера, хочется перед заливкой на флешку для телевизора весь этот мусор обрезать…
+
avatar
  • bird
  • 02 октября 2016, 14:02
+2
Типа как VDub для AVI
AviDemux оно самое. Режет без перекодировки, быстро. Я здесь беру в zip архиве www.avidemux.org/nightly/
+
avatar
  • DMA
  • 02 октября 2016, 14:33
+1
Подтверждаю. В том числе AviDemux отлично режет mov и mp4 с видеорегистраторов и смартфонов. При необходимости легко активировать перекодирование в нужный кодек и упаковку в нужный контейнер. Включить ресайз, обрезку и прочее. Короче, эдакий швейцарский нож, выполненный в шкодовском simply clever стиле. Если же вам нужно обрезать 30-40 сек перед заливкой на флешку у целого сезона — это вам лучше всего разобраться с командной строкой ffmpeg и делать всё через него в пакетном режиме.
+
avatar
  • Corvair
  • 01 октября 2016, 15:50
+2
Классная самоделка. Еще вместо винтов можно применить гребные колеса, тогда при работе враздрай кораблик сможет разворачиваться на месте. В детстве делал кораблик с двумя моторчиками и бортовыми колесами, без какой-либо системы управления, кроме выключателя.
+
avatar
  • trekker
  • 01 октября 2016, 17:04
0
Для резки пенопласта хороша спираль от электроплитки. В продаже видел недавно.
+
avatar
  • aspok
  • 01 октября 2016, 18:08
+1
Класс! Люблю такие обзоры. Идея для использования отличная.
+
avatar
  • pxzlodes
  • 02 октября 2016, 12:52
0
Заказал ESP8266, не поглядел, что там было без всей обвязки. В Интернете не нашёл нормальной схемы, у Вас не будет такой, случаем?
+
avatar
  • Johnny
  • 02 октября 2016, 13:11
+1

Это обвязка нужная для стабильной работы голого esp.
При том, что в ней ни usb<>uart конвертера, ни стабилизатора на требуемые 3.3v.

Для освоения и разработки в разы удобней использовать вот такой модуль:
aliexpress.com/item/New-Wireless-module-CH340-NodeMcu-V3-Lua-WIFI-Internet-of-Things-development-board-based-ESP8266-We/32565317233.html
+
avatar
  • pxzlodes
  • 02 октября 2016, 13:46
0
Спасибо, добрый человек!
usb<>uart у меня есть, на нём же есть 3.3v, только для боевых условий надо бы преобразователь на 5v > 3.3v
+
avatar
  • Johnny
  • 02 октября 2016, 13:56
+2
Пожалуйста! Часто пишут что ESP работает нестабильно когда запитана от подобного девайса, т.к. в них как правило стоят слаботочные стабилизаторы. Попробовать, конечно, стоит. Читайте esp8266.ru, например esp8266.ru/esp8266-podkluchenie-obnovlenie-proshivki/#esp8266-connect
+
avatar
  • DMA
  • 02 октября 2016, 14:36
0
Кстати, на подобном девайсе уровни TTL 5v? Есть ли возможность переключения на 3.3v и обратно на 5v?
+
avatar
  • dmit9
  • 02 октября 2016, 18:40
0
По минимуму достаточно двух резисторов по 10 кОм и 10 вывод на минус подключать при программировании. Причём резисторы можно прямо на выводы модуля припаять. И всё, подпаять питание, залить прошивку — и в перёд.
+
avatar
  • lohness
  • 03 октября 2016, 13:36
0
теперь я знаю что мне делать с валяющимся катером на радиоуправлении без управления и с поломанными винтами

и как я не додумался (а вроде рукастый) сделать винты из жести наверное остатки пластиковых винтов сузили кругозор :(
+
avatar
  • dmit9
  • 04 октября 2016, 12:34
0
Вообще я сначала думал искать/покупать какую либо лодку-игрушку с винтами, но потом лень пересилила и решил попробовать жестянки…
+
avatar
  • Rzzz
  • 04 октября 2016, 15:51
0
Жестянки на клею будут довольно хреново держаться. Припаять лучше.
+
avatar
  • dmit9
  • 04 октября 2016, 19:54
0
Там спицы алюминиевые. Пошкуренные винты и спица — держит неплохо.
+
avatar
0
вопрос новичка по ардуине.

а как можно на базе этой платы реализовать управление сервой, чтобы угол поворота головки сервы соответствовал углу поворота потенциометра от 0 до 270?
(тобишь управлять обычным потенциометром и передавать координаты его «открытия» )

или для этого можно и без ардуины обойтись?
+
avatar
  • dmit9
  • 04 октября 2016, 20:01
+1
В примерах Arduino IDE есть Servo ESP8266, полагаю это то что надо.
На вход ADC подавать напряжение с потенциометра и в соответствии с ним крутить серву.
Гугл на запрос «esp8266 сервопривод» 3-й сторокой выдаёт ролик Ютуб — Cервопривод SG90 управление с ESP 8266 по WI-FI, c помощью…
+
avatar
  • edgi
  • 09 октября 2016, 13:10
0
еще идея: солнечную панельку и вместо аккумуляторов ионистор.
+
avatar
  • dmit9
  • 09 октября 2016, 16:25
0
Не потянет. До аккумуляторов я пробовал на 4-х АА батарейках так всё время обрывы связи были. Модуль довольно прожорлив.
+
avatar
  • edgi
  • 10 октября 2016, 08:59
0
400F возможно хватит минут 5 катания, да беда чем больше фарада тем уже тяжелее. Не пойдет для сверх легкого кораблика но все же интересно по экспериментировать.
+
avatar
  • avater
  • 02 ноября 2016, 07:45
0
Автор, Ты чудо!))) Я загорелся желанием сделать аналогичную посудину.

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

как предложение для доработки — добавить задний ход, и может быть сделать в ПО(только что в голову пришло пока писал) включение заднего хода, если сигнал пропал в процессе плаванья, например: далеко уплыл кораблик.
+
avatar
  • dmit9
  • 03 ноября 2016, 00:25
0
Автоматическое включение заднего хода — плохая идея т.к. неизвестно в какую сторону будет ориентирован корпус в этот момент и может ещё дальше уплыть.
Вот если GPS на борту будет и будет известна точка старта… Но это уже несколько другой уровень погружения в корабликостроительство. )))
+
avatar
  • avater
  • 03 ноября 2016, 05:44
0
Всё может быть
Да, GPS это отдельная песня…
+
avatar
  • Mkone
  • 01 марта 2017, 23:32
0
Код программы не рабочий
+
avatar
0
Скорее всего версия ардуиноиде более новая, вот и не компилится. А вообще писать надо сразу что за ошибки выдает.
+
avatar
  • Mkone
  • 07 марта 2017, 15:17
0
Какая версия ардуино нужна?
+
avatar
  • dmit9
  • 07 марта 2017, 18:00
0
В обзоре указано «Скетч компилировался в IDE версии 1.6.12»
+
avatar
+2
Просто сайт сломал строки, поэтому когда копируешь код из обзора выдает штук 10 ошибок.
Просто надо перенос строки убрать.
Скомпилировал на ардуино 1.8.1 Библиотеки обновлены.
+
avatar
  • Mkone
  • 09 марта 2017, 02:32
0
Можете прокампилировать и скинуть сохраненный файл после кампиляции?
+
avatar
+1
сделал архив с исправленным скетчем. dropmefiles.com/vnnBl
+
avatar
  • Mkone
  • 09 марта 2017, 19:15
0
+
avatar
  • dmit9
  • 09 марта 2017, 19:58
0
У меня скетч от KarlikNos скомпилировался без вопросов
+
avatar
  • malanik
  • 15 апреля 2017, 19:13
0
RSSI в режиме, когда esp8266 — точка доступа, не работает.
+
avatar
0
У меня такая ошибка
+
avatar
0
Сделай в одну строку, там просто перенеслось на следующую. И вообще базовый синтаксис C изучи.
+
avatar
  • bampr
  • 14 декабря 2018, 14:52
0
а IP камеру сюда добавить можно, ну чтобы 1 приложение?
+
avatar
0
Исправленный код (в части оформления)

Дополнительная информация
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);
const char* ssid=«WiFI_ROBO»; //название точки доступа
const char* password=«12345678»; // пароль не будем писать
//const char* ssid=«autoCAR»; // здесь пишем название домашней точки доступа
//const char* password=«12345678»; // и пароль

String webSite,javaScript,XML;
unsigned long wait000=0UL,wait001=1000UL;
int OUT1=14, OUT2=12, BAT=17;//Назначение выводов
int Sila, SilaLow = -43; // Контроль силы сигнала WiFi
int Batareya, BatLow = 400; //Контроль напряжения батареи
float Povorot = 0.8, Trimer; // Переменные для значений поворота и тримера двигателя
String Bat, SilaW;
const int sliderMAX=3; // This sets the number of sliders you want
int sliderVal[3]={100, 50, 50}; //Начальные значения 1 слайдера — скорость, 2-го — поворот, 3- тример
int ESPval[sliderMAX];

void Batare(){
Batareya = analogRead(BAT); // Меряем напряжение батареи
if (Batareya < BatLow){ // Если напряжение батареи меньше порогового значения
Bat = "Батарея села, ПОРА на ЗАРЯДКУ\n"; // Пишем предупреждение
}
else{ // Если норма
Bat = ""; // Ничего не пишем
}
}
void SilaWifi(){
Sila = WiFi.RSSI(); // Меряем силу сигнала WiFi
if (Sila < SilaLow){
SilaW = " Сигнал слабый, РАЗВОРАЧИВАЙ";
}
else{
SilaW = "";
}
}

void buildJavascript(){
javaScript="\n";
}
void buildWebsite(){ // Создаём страницу с элементами управления
buildJavascript();
webSite="<!DOCTYPE HTML>\n";
webSite+="<META name='viewport' content='width=device-width, initial-scale=1', charset=\«utf-8\»>\n";
webSite+=javaScript;
webSite+="\n";
webSite+="Панель управления роботом\n";

webSite+="Время работы = \n";
webSite+="Сила сигнала \n"; // Сила сигнала WiFi
webSite+="Напряжение батареи \n";

// Напряжение батареи
webSite+="
\n"// webSite+="<INPUT ' TYPE='range' width='600'> \n"// это пример слайдера
webSite+="\n"// 1 слайдер
webSite+="\n"webSite+="Обороты = \n"webSite+=«Моторов = * \n»;
webSite+="\n"webSite+="\n"// 2 слайдер
webSite+="\n"webSite+="Направление = \n"webSite+=«Движения = \n»;
webSite+="\n"webSite+="\n"// 3 слайдер
webSite+="\n"webSite+="Корекция = \n"webSite+=«Моторов = \n»;
webSite+="\n"webSite+="\n"webSite+="\n"webSite+="\n"}
String millis2time(){ // преобразование милисекунд в вид ч/м/с
String Time=""unsigned long ss;
byte mm,hh;
ss=millis()/1000;
hh=ss/3600;
mm=(ss-hh*3600)/60;
ss=(ss-hh*3600)-mm*60;
if(hh<10)Time+=«0»;
Time+=(String)hh+":"if(mm<10)Time+=«0»;
Time+=(String)mm+":"if(ss<10)Time+=«0»;
Time+=(String)ss;
return Time;
}
void buildXML(){
XML="<?xml version='1.0'?>"XML+=""XML+=""XML+=millis2time();
XML+=""// Добавляем наши данные
SilaWifi(); // Здесь измеряем силу сигнала
XML+=""// Сила сигнала WiFi
XML+=String(Sila)+SilaW;// Сила сигнала WiFi
XML+=""// Сила сигнала WiFi
Batare(); // Здесь измеряем напряжение батареи
XML+=""// Напряжение батареи
XML+=String(Batareya)+Bat;// Напряжение батареи
XML+=""// Напряжение батареи
for(int i=0;i<sliderMAX;i++){
XML+="<sliderval"+(String)i+">"XML+=String(sliderVal[i]);
XML+="</sliderval"+(String)i+">"XML+="<ESPval"+(String)i+">"ESPval[i]=9*(100-sliderVal[i])+100;
XML+=String(ESPval[i]);
XML+="</ESPval"+(String)i+">"}
XML+=""}
void handleWebsite(){
buildWebsite();
server.send(200,«text/html»,webSite);
}
void handleXML(){
buildXML();
server.send(200,«text/xml»,XML);
}
void handleESPval(){
int sliderCNT=server.arg(«cnt»).toInt();
sliderVal[sliderCNT]=server.arg(«val»).toInt();
buildXML();
server.send(200,«text/xml»,XML);
}
void setup() {
Serial.begin(115200);
pinMode(OUT1,OUTPUT);
pinMode(OUT2,OUTPUT);
pinMode(BAT,INPUT);
WiFi.softAP(ssid, password); // Создаём точку доступа
// WiFi.begin(ssid,password); //Это вариант для подключения к существующей точке
// while(WiFi.status()!=WL_CONNECTED)delay(500);
// WiFi.mode(WIFI_STA);
Serial.println("\n\nBOOTING ESP8266 ...");
Serial.print(«Connected to „);
Serial.println(ssid);
Serial.print(“Station IP address: „);
Serial.println(WiFi.localIP()); // Вывод в монитор порта присвоенный IP
server.on(“/»,handleWebsite);
server.on("/xml",handleXML);
server.on("/setESPval",handleESPval);
server.begin();
}
void loop() {
server.handleClient();
if(millis()>wait000){
buildXML();
wait000=millis()+1000UL;
}
if(millis()>wait001){
wait001=millis()+300; //Обновляем значения раз в 300 милисекунд
Trimer = (ESPval[2]*.0015);
Serial.print(" Skorost] ");
Serial.print(ESPval[0]);
Serial.print(" Povorot ");
Serial.print(ESPval[1]);
Serial.print(" Trimer ");
Serial.print(ESPval[2]);
Serial.print(Trimer);
if (ESPval[0] > 200){ // Если слайдер скорости > 200
if ( ESPval[1] > 600) { // Если слайдер поворота > 600 то поворачиваем на лево
analogWrite(OUT1, ESPval[0]);
analogWrite(OUT2, int(ESPval[0] * Povorot*Trimer));
Serial.print(" Le ");
Serial.print(ESPval[0] * Povorot*Trimer);
}
else if (400 > ESPval[1] ){ // Если слайдер поворота < 400 то поворачиваем на право
analogWrite(OUT1, int(ESPval[0] * Povorot));
analogWrite(OUT2, int(ESPval[0]*Trimer));
Serial.print(" Pr ");
Serial.print(int(ESPval[0] * Povorot));
}
else { // Если слайдер поворота > 400 и < 600то едем прямо
analogWrite(OUT1, ESPval[0]);
analogWrite(OUT2, int(ESPval[0]*Trimer));
Serial.print(" OK ");
}
}
else { // Если слайдер скорости < 200 — выключить моторы
analogWrite(OUT1, 0);
analogWrite(OUT2, 0);
Serial.print(" Stop ");
}
Serial.print(" Batareya ");
Serial.println(Batareya);
}
}