• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь связать 2 ESP8266-01 для управления серво.

AndreyFly

New member
Абсолютно верно, если бы знал, то давно бы сделал. Но к сожалению в интернет протоколах и все, что связано с Web протоколами я не разбираюсь от слова совсем. Я до сих пор не понимаю принципов общения модулем, но думаю за пару недель поборю.

Код:
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

const char *ssid = "Paraplan";
const char *password = "Throttle";

const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int average = 0;                // the average

int inputPin = A0;
int val;



ESP8266WebServer server(80);

void handleRoot() {
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(inputPin);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
     readIndex = 0;}
  average = total / numReadings;
 
  server.send(200, "text/html", String(average));
}

void setup() {
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;}
   
  delay(1000);
  WiFi.softAP(ssid, password);
  IPAddress myIP = WiFi.softAPIP();
  server.on("/", handleRoot);
  server.begin();
}

void loop() {
  server.handleClient();
}
Если я все правильно понял, то по запросу с клиента, будет вызываться процедура [inline]void handleRoot() {[/inline]. В таком случае я опрашиваю АЦП именно при ее вызове, высчитываю среднее по 10 последним измерениям и шлю на клиента. Все ли верно я понял?
 

AndreyFly

New member
Я не могу пробовать все примеры подряд. К половине примеров нету обьяснений, приходится смотреть для каждой непонятной инструкции еще кучу роликов, с них еще есть непонятности. Поэтому все движется небыстро. В СИ я могу разобраться, но проблема не в СИ, а именно в отсутствии понимания, как оба модуля друг с другом общаются. Что, куда отправляется, что запрашивается, на все это надо время. За 1 вечер я не разберусь, так что не требуйте строго.
 

nikolz

Well-known member
Я не могу пробовать все примеры подряд. К половине примеров нету обьяснений, приходится смотреть для каждой непонятной инструкции еще кучу роликов, с них еще есть непонятности. Поэтому все движется небыстро. В СИ я могу разобраться, но проблема не в СИ, а именно в отсутствии понимания, как оба модуля друг с другом общаются. Что, куда отправляется, что запрашивается, на все это надо время. За 1 вечер я не разберусь, так что не требуйте строго.
Перед вами есть три варианта формата общения ESP
TCP
UDP
ESP-NOW
сейчас вам вкручивают TCP
но это самый громоздкий протокол возможности которого вам не нужны
следующий по простоте это UDP
и самый простой ESP-now
начните с него
посмотрите ролики которые я указал
там все наглядно показано на экране монитора и рассказано правда на англ
в ссылках лежат готовые тесты
возьмите их и соберите для понимания что и как
потом выкиньте то что не надо и получится статуя аполлона.
 

CodeNameHawk

Moderator
Команда форума
Если я все правильно понял, то по запросу с клиента, будет вызываться процедура void handleRoot()
Правильно поняли.
В таком случае я опрашиваю АЦП именно при ее вызове, высчитываю среднее по 10 последним измерениям и шлю на клиента.
Идея такая, в основном цикле (loop) рассчитывайте среднее значение АЦП постоянно (опрос АЦП, усреднение, обработка запроса клиента, если поступил) и когда поступит запрос, отдадите среднее значение АЦП.
Не будет задержки на десять считываний АЦП, но возможно есп быстрый и это не кому не помешает.

nikolz, я не против UDP, ни ESP-NOW, но если есть желание помочь, набросайте примерный скетч из своих разработок.
(Некоторые примеры ESP-NOW загоняют есп в сон, есп01 проснется?)
 

AndreyFly

New member
Набросал код приемника, в верном ли я направлении иду, или опять взял за основу неправильный пример?

Код:
#include <Arduino.h>

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClient.h>
#include <Servo.h>
Servo myservo;

ESP8266WiFiMulti WiFiMulti;
int val=0;
void setup() {

  delay(1000);
  myservo.attach(2,1100,2200);
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("Paraplan", "Throttle");

}

void loop() {
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
    http.begin("http://192.168.4.1/");
     int httpCode = http.GET();
     http.setTimeout(100);
      if (httpCode > 0) {
        if (httpCode == HTTP_CODE_OK) {
          String RX = http.getString();
          int average = RX.toInt();
          if (average <= 550) { average = 550;}
          if (average >= 990)  {average = 990;}
          val = map(average, 550, 990, 1100, 2200);
          myservo.writeMicroseconds(val);
        }
      }
      http.end();
    }
 

  delay(5000);
}
 

AndreyFly

New member
Не нужно переживать за пилота. Параплан - это не самолет и не вертолет. При остановке моторов ничего не меняется в полете, просто пилот не сможет набирать высоту с помощью моторов. Но если есть восходящие потоки, то набор высоты без моторов - это обычное дело. Точнее сказать, что моторы на парапланах - это от лени пешком ходить в горы. Обычно полеты идут без моторов. Либо с горы, либо затягивание лебедкой. Горы есть не везде, иногда и дорог нет на горы, с которых возможен полет. Для лебедки нужен еще и оператор лебедки, что тоже не всегда доступно. Остановка моторов ничего плохого не сделает. Парапланы с помощью восходящих потоков без всяких моторов с легкостью преодолевают до 500+ км пути за 1 полет.
 

nikolz

Well-known member
Правильно поняли.

Идея такая, в основном цикле (loop) рассчитывайте среднее значение АЦП постоянно (опрос АЦП, усреднение, обработка запроса клиента, если поступил) и когда поступит запрос, отдадите среднее значение АЦП.
Не будет задержки на десять считываний АЦП, но возможно есп быстрый и это не кому не помешает.

nikolz, я не против UDP, ни ESP-NOW, но если есть желание помочь, набросайте примерный скетч из своих разработок.
(Некоторые примеры ESP-NOW загоняют есп в сон, есп01 проснется?)
покажите где загоняют в сон, исправим.
я же дал ссылку на кучу скетчей
выбирайте по вкусу.
 

nikolz

Well-known member
набросал два скрипта ESP-NOW
клиент и сервер
в клиент читаем с ацп и отправляем используем таймер для ожидания подтверждения
в сервере принимаем и пользуем данные от клиента
скрипты сырые, так как дурину не использую.
 

Вложения

AndreyFly

New member
Всем добрый вечер. У нас уже 23:30, а я только с работы пришел... Исходники еще не смотрел, чуть позже гляну.
Почитал философию в этом топике. Все по своему правы. Халява портит человека, все должно достигаться только трудом и усердием. К сожалению я из-за лени тоже часто делаю копи-паст, правлю некоторые моменты и пользуюсь. Это во первых из-за природной лени, во вторых из-за катастрофической нехватки свободного времени. Но и разработку с нуля самостоятельно тоже люблю. Обычно я не повторяю сборку одного и того же. Что-то выкладываю, что-то только направление даю, все зависит от собеседника. Например я в этом году собрал 4 ЧПУ 3д фрезера на марлине. И около помог по телефону и ватсапу еще где-то десятерым. Начиная от 3д моделей для 3д пеачти, и кончая тонкостями настройки марлина. При этом при всем, я не ждал благодарности в ответ, просто это мое хобби, и если у человека такое же хобби, то почему бы и не помочь.
 

enjoynering

Well-known member
немного офтопа. как боретесь с пропуском шагов на микростепинге?
 

Сергей_Ф

Moderator
Команда форума
[off]Думаю, что чистка темы от оффтопа никого не обидела. В следующий раз инициатор оффтопа станет читателем на неделю. [/off]
 

AndreyFly

New member
немного офтопа. как боретесь с пропуском шагов на микростепинге?
Если вопрос ко мне, и про ЧПУ, то попытаюсь ответить. Прошивка Марлин для ардуино мега спокойно работает с 1\32 микрошага. В самой прошивке есть файл с настройками, где указывается скорость разгона и максимальная скорость шаговых двигателей. Для станков стараюсь, чтобы моторы не раскручивались более 600 об\мин, так как далее идет сильное уменьшение момента на валу двигателя. Стартовую скорость принимаю за 1\2 от максимальных оборотов. Остальное прошивка делает сама, и плавный разгон и плавное торможение. Никогда пропусков шагов еще небыло.
 

AndreyFly

New member
Код:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
uint8_t remoteMac[] = {0x1A, 0xFE, 0x34, 0xD5, 0xFA, 0x39}; // это мак адресс второго ESP
#define CHANNEL 1
long data;
 void recv_cb(u8 *macaddr, u8 *data, u8 len)
{ 
    esp_now_send(macaddr,1,1 );  //отправляем подтверждение 
 //data содержит принятые данные   работаем с ними
}; //колбек приема 

void onTimer(){ flag=1; }

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);   WiFi.disconnect();
  if (esp_now_init() == 0){ 
    esp_now_register_send_cb(send_cb);
    esp_now_register_send_cb(recv_cb);
    esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
    esp_now_add_peer(remoteMac, ESP_NOW_COMBO, CHANNEL, NULL, 0);
 } else Serial.println("init error")
 }

void loop() {
 }
Насколько я понял, в примере есть недостающие строки. void onTimer(){ flag=1; } не будет вызвано никогда? Или запуск происходит из библиотеки?
void recv_cb(u8 *macaddr, u8 *data, u8 len) нужно вызывать с определенной периодичностью? Или Эта функция срабатывает автоматически, когда есть данные от клиента?
 

nikolz

Well-known member
Код:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
uint8_t remoteMac[] = {0x1A, 0xFE, 0x34, 0xD5, 0xFA, 0x39}; // это мак адресс второго ESP
#define CHANNEL 1
long data;
 void recv_cb(u8 *macaddr, u8 *data, u8 len)
{
    esp_now_send(macaddr,1,1 );  //отправляем подтверждение
 //data содержит принятые данные   работаем с ними
}; //колбек приема

void onTimer(){ flag=1; }

void setup() {
  Serial.begin(115200);
  WiFi.mode(WIFI_STA);   WiFi.disconnect();
  if (esp_now_init() == 0){
    esp_now_register_send_cb(send_cb);
    esp_now_register_send_cb(recv_cb);
    esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
    esp_now_add_peer(remoteMac, ESP_NOW_COMBO, CHANNEL, NULL, 0);
 } else Serial.println("init error")
 }

void loop() {
 }
Насколько я понял, в примере есть недостающие строки. void onTimer(){ flag=1; } не будет вызвано никогда? Или запуск происходит из библиотеки?
void recv_cb(u8 *macaddr, u8 *data, u8 len) нужно вызывать с определенной периодичностью? Или Эта функция срабатывает автоматически, когда есть данные от клиента?
так как этот скрипт делал из скрипта клиента , то
void onTimer(){ flag=1; } - осталось случайно.
удалить (но не мешает)
==============================
поясню логику алгоритм работы данных скриптов и протокола ESP-NOW
----------------
ESP-NOW это простейший протокол обмена данными без установления соединения но с подтверждением
Проще говоря имеем два комплекта приемо-передающей аппаратуры
желающий передать излучает пакет данных в котором указан адрес получателя длина и данные
второй приемник получает пакет
сверяет свой адрес с адресом получателя в пакете и если это его то принимает данные
в качестве адресов выступает мас адрес
т е это фактически беспроводной ethernet ну или LORA или bluetooth
Т е это асинхронный режим передачи данных точка-точка.
максимальный объем данных 250 байт
------------------------
Чтобы использовать этот протокол надо
включить приемо-передатчик у ESP установив какой нибудь режим WiFi я использую режим станции
потом выполнить инициализацию параметров esp_now
потом задать колбек функции для передачи и приема
потом определить тип устройcтва (set_self_role)
и сформировать список устройств с которыми надо поддерживать связь (add_peer)
ну и все настройки
-----------------
условно я назвал сервером - ESP управления двигателем
и клиентом - ESP с потенциометром
-------------------
алгоритм такой
клиент измеряет напряжение на потенциометре и передает его серверу
и ждет подтверждение от него
Можно и не делать специальное подтверждение так как ESP-NOW автоматом его посылает в ответ на сообщение
----------------
кроме того в клиенте есть таймер
который отслеживает интервал ожидания ответа
поправьте программу
таймер надо поставить в одноразовый режим
у меня он в автоматическом
-------------------------------
повторю еще раз это эскиз
-----------------------------------------
я не раздаю рыбу, а учу ее ловить.
 

AndreyFly

New member
потом задать колбек функции для передачи и приема
Код:
  if (esp_now_init() == 0){
    esp_now_register_send_cb(send_cb);
    esp_now_register_send_cb(recv_cb);
    esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
здесь надо полагать опечатка? esp_now_register_send_cb(recv_cb); Должно быть esp_now_register_recv_cb(recv_cb); ? Эта инструкция как я понял задает имя процедуры, которая вызывается при получении информации, с клиента, верно ли я понял?
 

AndreyFly

New member
не получается привести типы данных к требуемым. Бьюсь уже не один час

Код:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
uint8_t remoteMac[] = {0x84, 0xF3, 0xEB, 0x66, 0x16, 0xE5}; // это мак адресс второго ESP
#define CHANNEL 1

void send_cb( uint8_t *mac, uint8_t sendStatus); //колбек отправки данных
void recv_cb(u8 *macaddr, u8 *data, u8 len); //колбек подтверждения


void setup() {
  system("chcp 1251");
  system("cls");
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
  readings[thisReading] = 0;
  } 
  WiFi.mode(WIFI_STA);   WiFi.disconnect();
  if (esp_now_init() == 0){
  esp_now_register_send_cb(send_cb);
  esp_now_register_recv_cb(recv_cb);
  esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
  esp_now_add_peer(remoteMac, ESP_NOW_ROLE_CONTROLLER, CHANNEL, NULL, 0);
}
}

void loop() {

long data = system_adc_read();
esp_now_send(remoteMac, &data, sizeof(data)); //  передаем данные
delay(50);
}
выводит ошибку

Код:
NK_ESP_NOW_clirnt:43:45: error: cannot convert 'long int*' to 'u8* {aka unsigned char*}' for argument '2' to 'int esp_now_send(u8*, u8*, int)'

  esp_now_send(remoteMac, &data, sizeof(data)); //  передаем данные

                                             ^

exit status 1
cannot convert 'long int*' to 'u8* {aka unsigned char*}' for argument '2' to 'int esp_now_send(u8*, u8*, int)'
Я в ступоре.
 

nikolz

Well-known member
esp_now_register_send_cb(send_cb);
esp_now_register_recv_cb(recv_cb);
-------------------------------------
esp_now_send(remoteMac, (unsigned char*)data, sizeof(data)); // передаем данные
 

AndreyFly

New member
Код:
#include <ESP8266WiFi.h>
extern "C" {
#include <espnow.h>
}
uint8_t remoteMac[] = {0x84, 0xF3, 0xEB, 0x66, 0x16, 0xE5}; // это мак адрес второго ESP
#define CHANNEL 1

void send_cb( uint8_t *mac, uint8_t sendStatus); //колбек отправки данных
void recv_cb(u8 *macaddr, u8 *data, u8 len); //колбек подтверждения

void setup() {
  system("chcp 1251");
  system("cls");
  Serial.begin(115200);
  // initialize all the readings to 0:
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
  readings[thisReading] = 0;
  } 
  WiFi.mode(WIFI_STA);   WiFi.disconnect();
  if (esp_now_init() == 0){
  esp_now_register_send_cb(send_cb);
  esp_now_register_recv_cb(recv_cb);
  esp_now_set_self_role(ESP_NOW_ROLE_COMBO);
  esp_now_add_peer(remoteMac, ESP_NOW_ROLE_CONTROLLER, CHANNEL, NULL, 0);
}
}

void loop() {

long  data = system_adc_read();
esp_now_send(remoteMac, (unsigned char*)data, sizeof(data)); //  передаем данные
delay(50);
}
мне с этим не справиться. Сегодня на обеде сделал правки, ошибка исчезла, но появилась новая.


Код:
c:/users/user/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\NK_ESP_NOW_clirnt.ino.cpp.o:(.text.setup+0x18): undefined reference to `send_cb(unsigned char*, unsigned char)'

c:/users/user/appdata/local/arduino15/packages/esp8266/tools/xtensa-lx106-elf-gcc/2.5.0-3-20ed2b9/bin/../lib/gcc/xtensa-lx106-elf/4.8.2/../../../../xtensa-lx106-elf/bin/ld.exe: sketch\NK_ESP_NOW_clirnt.ino.cpp.o:(.text.setup+0x1c): undefined reference to `recv_cb(unsigned char*, unsigned char*, unsigned char)'

collect2.exe: error: ld returned 1 exit status

exit status 1
Ошибка компиляции для платы Generic ESP8266 Module.
Намекните, что еще нужно этому компилятору? Я до вчерашнего дня в принципе на ардуино не пользовался указателями на переменные... Может я не все библиотеки подключил?
 
Сверху Снизу