mirror of
https://github.com/okalachev/flix.git
synced 2026-06-28 05:56:44 +00:00
Implement ESP-NOW support
This commit is contained in:
+6
-2
@@ -10,6 +10,7 @@
|
|||||||
|
|
||||||
extern const int MOTOR_REAR_LEFT, MOTOR_REAR_RIGHT, MOTOR_FRONT_RIGHT, MOTOR_FRONT_LEFT;
|
extern const int MOTOR_REAR_LEFT, MOTOR_REAR_RIGHT, MOTOR_FRONT_RIGHT, MOTOR_FRONT_LEFT;
|
||||||
extern const int RAW, ACRO, STAB, AUTO;
|
extern const int RAW, ACRO, STAB, AUTO;
|
||||||
|
extern const int W_AP, W_STA, W_ESPNOW;
|
||||||
extern float t, dt, loopRate;
|
extern float t, dt, loopRate;
|
||||||
extern uint16_t channels[16];
|
extern uint16_t channels[16];
|
||||||
extern float controlTime;
|
extern float controlTime;
|
||||||
@@ -45,6 +46,7 @@ const char* motd =
|
|||||||
"wifi - show Wi-Fi info\n"
|
"wifi - show Wi-Fi info\n"
|
||||||
"ap <ssid> <password> - setup Wi-Fi access point\n"
|
"ap <ssid> <password> - setup Wi-Fi access point\n"
|
||||||
"sta <ssid> <password> - setup Wi-Fi client mode\n"
|
"sta <ssid> <password> - setup Wi-Fi client mode\n"
|
||||||
|
"espnow <mac> - setup ESP-NOW peer\n"
|
||||||
"mot - show motor output\n"
|
"mot - show motor output\n"
|
||||||
"log [dump] - print log header [and data]\n"
|
"log [dump] - print log header [and data]\n"
|
||||||
"cr - calibrate RC\n"
|
"cr - calibrate RC\n"
|
||||||
@@ -143,9 +145,11 @@ void doCommand(String str, bool echo = false) {
|
|||||||
} else if (command == "wifi") {
|
} else if (command == "wifi") {
|
||||||
printWiFiInfo();
|
printWiFiInfo();
|
||||||
} else if (command == "ap") {
|
} else if (command == "ap") {
|
||||||
configWiFi(true, arg0.c_str(), arg1.c_str());
|
configWiFi(W_AP, arg0.c_str(), arg1.c_str());
|
||||||
} else if (command == "sta") {
|
} else if (command == "sta") {
|
||||||
configWiFi(false, arg0.c_str(), arg1.c_str());
|
configWiFi(W_STA, arg0.c_str(), arg1.c_str());
|
||||||
|
} else if (command == "espnow") {
|
||||||
|
configWiFi(W_ESPNOW, arg0.c_str(), arg1.c_str());
|
||||||
} else if (command == "mot") {
|
} else if (command == "mot") {
|
||||||
print("front-right %g front-left %g rear-right %g rear-left %g\n",
|
print("front-right %g front-left %g rear-right %g rear-left %g\n",
|
||||||
motors[MOTOR_FRONT_RIGHT], motors[MOTOR_FRONT_LEFT], motors[MOTOR_REAR_RIGHT], motors[MOTOR_REAR_LEFT]);
|
motors[MOTOR_FRONT_RIGHT], motors[MOTOR_FRONT_LEFT], motors[MOTOR_REAR_RIGHT], motors[MOTOR_REAR_LEFT]);
|
||||||
|
|||||||
+4
-1
@@ -10,7 +10,7 @@ extern int channelZero[16];
|
|||||||
extern int channelMax[16];
|
extern int channelMax[16];
|
||||||
extern int rollChannel, pitchChannel, throttleChannel, yawChannel, armedChannel, modeChannel;
|
extern int rollChannel, pitchChannel, throttleChannel, yawChannel, armedChannel, modeChannel;
|
||||||
extern int rcRxPin;
|
extern int rcRxPin;
|
||||||
extern int wifiMode, udpLocalPort, udpRemotePort;
|
extern int wifiMode, wifiLongRange, udpLocalPort, udpRemotePort, espnowChannel;
|
||||||
extern float rcLossTimeout, descendTime;
|
extern float rcLossTimeout, descendTime;
|
||||||
extern int voltagePin;
|
extern int voltagePin;
|
||||||
extern float voltageScale;
|
extern float voltageScale;
|
||||||
@@ -112,6 +112,9 @@ Parameter parameters[] = {
|
|||||||
{"WIFI_MODE", &wifiMode},
|
{"WIFI_MODE", &wifiMode},
|
||||||
{"WIFI_PORT_LOC", &udpLocalPort},
|
{"WIFI_PORT_LOC", &udpLocalPort},
|
||||||
{"WIFI_PORT_REM", &udpRemotePort},
|
{"WIFI_PORT_REM", &udpRemotePort},
|
||||||
|
{"WIFI_LONG_RANGE", &wifiLongRange},
|
||||||
|
// espnow
|
||||||
|
{"ESPNOW_CHANNEL", &espnowChannel},
|
||||||
// mavlink
|
// mavlink
|
||||||
{"MAV_SYS_ID", &mavlinkSysId},
|
{"MAV_SYS_ID", &mavlinkSysId},
|
||||||
{"MAV_RATE_SLOW", &telemetrySlow.rate},
|
{"MAV_RATE_SLOW", &telemetrySlow.rate},
|
||||||
|
|||||||
+51
-17
@@ -1,82 +1,116 @@
|
|||||||
// Copyright (c) 2023 Oleg Kalachev <okalachev@gmail.com>
|
// Copyright (c) 2023 Oleg Kalachev <okalachev@gmail.com>
|
||||||
// Repository: https://github.com/okalachev/flix
|
// Repository: https://github.com/okalachev/flix
|
||||||
|
|
||||||
// Wi-Fi communication
|
// Wi-Fi and ESP-NOW communication
|
||||||
|
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
#include <WiFiAP.h>
|
#include <WiFiAP.h>
|
||||||
#include <WiFiUdp.h>
|
#include <WiFiUdp.h>
|
||||||
|
#include <MacAddress.h>
|
||||||
|
#include <ESP32_NOW_Serial.h>
|
||||||
#include "Preferences.h"
|
#include "Preferences.h"
|
||||||
|
|
||||||
extern Preferences storage; // use the main preferences storage
|
extern Preferences storage; // use the main preferences storage
|
||||||
|
|
||||||
const int W_DISABLED = 0, W_AP = 1, W_STA = 2;
|
const int W_DISABLED = 0, W_AP = 1, W_STA = 2, W_ESPNOW = 3;
|
||||||
int wifiMode = W_AP;
|
int wifiMode = W_AP;
|
||||||
|
int wifiLongRange = 0;
|
||||||
int udpLocalPort = 14550;
|
int udpLocalPort = 14550;
|
||||||
int udpRemotePort = 14550;
|
int udpRemotePort = 14550;
|
||||||
|
int espnowChannel = 6;
|
||||||
IPAddress udpRemoteIP = "255.255.255.255";
|
IPAddress udpRemoteIP = "255.255.255.255";
|
||||||
|
|
||||||
WiFiUDP udp;
|
WiFiUDP udp;
|
||||||
|
ESP_NOW_Serial_Class espnow(NULL, 0, WIFI_IF_AP);
|
||||||
|
|
||||||
void setupWiFi() {
|
void setupWiFi() {
|
||||||
print("Setup Wi-Fi\n");
|
print("Setup Wi-Fi\n");
|
||||||
|
WiFi.enableLongRange(wifiLongRange);
|
||||||
|
|
||||||
if (wifiMode == W_AP) {
|
if (wifiMode == W_AP) {
|
||||||
WiFi.softAP(storage.getString("WIFI_AP_SSID", "flix").c_str(), storage.getString("WIFI_AP_PASS", "flixwifi").c_str());
|
WiFi.softAP(storage.getString("WIFI_AP_SSID", "flix").c_str(), storage.getString("WIFI_AP_PASS", "flixwifi").c_str());
|
||||||
|
udp.begin(udpLocalPort);
|
||||||
} else if (wifiMode == W_STA) {
|
} else if (wifiMode == W_STA) {
|
||||||
WiFi.begin(storage.getString("WIFI_STA_SSID", "").c_str(), storage.getString("WIFI_STA_PASS", "").c_str());
|
WiFi.begin(storage.getString("WIFI_STA_SSID", "").c_str(), storage.getString("WIFI_STA_PASS", "").c_str());
|
||||||
} else {
|
udp.begin(udpLocalPort);
|
||||||
return;
|
} else if (wifiMode == W_ESPNOW) {
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.setChannel(espnowChannel);
|
||||||
|
espnow.setChannel(espnowChannel);
|
||||||
|
espnow.addr(MacAddress(storage.getString("ESPNOW_PEER_MAC", "").c_str()));
|
||||||
|
espnow.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
WiFi.setSleep(false); // disable power save
|
WiFi.setSleep(false); // disable power save
|
||||||
udp.begin(udpLocalPort);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void sendWiFi(const uint8_t *buf, int len) {
|
void sendWiFi(const uint8_t *buf, int len) {
|
||||||
|
if (espnow) {
|
||||||
|
espnow.write(buf, len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (WiFi.softAPgetStationNum() == 0 && !WiFi.isConnected()) return;
|
if (WiFi.softAPgetStationNum() == 0 && !WiFi.isConnected()) return;
|
||||||
|
|
||||||
udp.beginPacket(udpRemoteIP, udpRemotePort);
|
udp.beginPacket(udpRemoteIP, udpRemotePort);
|
||||||
udp.write(buf, len);
|
udp.write(buf, len);
|
||||||
udp.endPacket();
|
udp.endPacket();
|
||||||
}
|
}
|
||||||
|
|
||||||
int receiveWiFi(uint8_t *buf, int len) {
|
int receiveWiFi(uint8_t *buf, int len) {
|
||||||
|
if (espnow) {
|
||||||
|
return espnow.read(buf, len);
|
||||||
|
}
|
||||||
|
|
||||||
if (WiFi.softAPgetStationNum() == 0 && !WiFi.isConnected()) return 0;
|
if (WiFi.softAPgetStationNum() == 0 && !WiFi.isConnected()) return 0;
|
||||||
|
|
||||||
udp.parsePacket();
|
udp.parsePacket();
|
||||||
if (udp.remoteIP()) udpRemoteIP = udp.remoteIP();
|
if (udp.remoteIP()) udpRemoteIP = udp.remoteIP();
|
||||||
return udp.read(buf, len);
|
return udp.read(buf, len);
|
||||||
}
|
}
|
||||||
|
|
||||||
void printWiFiInfo() {
|
void printWiFiInfo() {
|
||||||
if (WiFi.getMode() == WIFI_MODE_AP) {
|
if (espnow) {
|
||||||
|
print("Mode: ESP-NOW\n");
|
||||||
|
print("ESP-NOW version: %d\n", ESP_NOW.getVersion());
|
||||||
|
print("Max packet size: %d\n", ESP_NOW.getMaxDataLen());
|
||||||
|
print("MAC: %s\n", WiFi.softAPmacAddress().c_str());
|
||||||
|
print("Peer MAC: %s\n", MacAddress(espnow.addr()).toString().c_str());
|
||||||
|
print("Channel: %d\n", espnow.getChannel());
|
||||||
|
} else if (WiFi.getMode() == WIFI_MODE_AP) {
|
||||||
print("Mode: Access Point (AP)\n");
|
print("Mode: Access Point (AP)\n");
|
||||||
print("MAC: %s\n", WiFi.softAPmacAddress().c_str());
|
print("MAC: %s\n", WiFi.softAPmacAddress().c_str());
|
||||||
print("SSID: %s\n", WiFi.softAPSSID().c_str());
|
print("SSID: %s\n", WiFi.softAPSSID().c_str());
|
||||||
print("Password: ***\n");
|
print("Password: ***\n");
|
||||||
|
print("Channel: %d\n", WiFi.channel());
|
||||||
print("Clients: %d\n", WiFi.softAPgetStationNum());
|
print("Clients: %d\n", WiFi.softAPgetStationNum());
|
||||||
print("IP: %s\n", WiFi.softAPIP().toString().c_str());
|
print("IP: %s\n", WiFi.softAPIP().toString().c_str());
|
||||||
|
print("Remote IP: %s\n", udpRemoteIP.toString().c_str());
|
||||||
} else if (WiFi.getMode() == WIFI_MODE_STA) {
|
} else if (WiFi.getMode() == WIFI_MODE_STA) {
|
||||||
print("Mode: Client (STA)\n");
|
print("Mode: Client (STA)\n");
|
||||||
print("Connected: %d\n", WiFi.isConnected());
|
print("Connected: %d\n", WiFi.isConnected());
|
||||||
print("MAC: %s\n", WiFi.macAddress().c_str());
|
print("MAC: %s\n", WiFi.macAddress().c_str());
|
||||||
print("SSID: %s\n", WiFi.SSID().c_str());
|
print("SSID: %s\n", WiFi.SSID().c_str());
|
||||||
print("Password: ***\n");
|
print("Password: ***\n");
|
||||||
print("IP: %s\n", WiFi.localIP().toString().c_str());
|
print("Channel: %d\n", WiFi.channel());
|
||||||
print("RSSI: %d dBm\n", WiFi.RSSI());
|
print("RSSI: %d dBm\n", WiFi.RSSI());
|
||||||
|
print("IP: %s\n", WiFi.localIP().toString().c_str());
|
||||||
|
print("Remote IP: %s\n", udpRemoteIP.toString().c_str());
|
||||||
} else {
|
} else {
|
||||||
print("Mode: Disabled\n");
|
print("Mode: Disabled\n");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
print("Channel: %d\n", WiFi.channel());
|
|
||||||
print("Remote IP: %s\n", udpRemoteIP.toString().c_str());
|
|
||||||
print("MAVLink connected: %d\n", mavlinkConnected);
|
print("MAVLink connected: %d\n", mavlinkConnected);
|
||||||
}
|
}
|
||||||
|
|
||||||
void configWiFi(bool ap, const char *ssid, const char *password) {
|
void configWiFi(int mode, const char *first, const char *second) {
|
||||||
if (ap) {
|
if (mode == W_AP) {
|
||||||
storage.putString("WIFI_AP_SSID", ssid);
|
storage.putString("WIFI_AP_SSID", first);
|
||||||
storage.putString("WIFI_AP_PASS", password);
|
storage.putString("WIFI_AP_PASS", second);
|
||||||
} else {
|
} else if (mode == W_STA) {
|
||||||
storage.putString("WIFI_STA_SSID", ssid);
|
storage.putString("WIFI_STA_SSID", first);
|
||||||
storage.putString("WIFI_STA_PASS", password);
|
storage.putString("WIFI_STA_PASS", second);
|
||||||
|
} else if (mode == W_ESPNOW) {
|
||||||
|
storage.putString("ESPNOW_PEER_MAC", first);
|
||||||
}
|
}
|
||||||
print("✓ Reboot to apply new settings\n");
|
print("✓ Reboot to apply new settings\n");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
# ESPNOW-proxy
|
||||||
|
|
||||||
|
Proxy sketch for using ESP-NOW MAVLink connection with Flix drone.
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
// Copyright (c) 2026 Oleg Kalachev <okalachev@gmail.com>
|
||||||
|
// Repository: https://github.com/okalachev/flix
|
||||||
|
|
||||||
|
// Proxy for ESP-NOW connection
|
||||||
|
|
||||||
|
#include <WiFi.h>
|
||||||
|
#include <ESP32_NOW_Serial.h>
|
||||||
|
#include <MacAddress.h>
|
||||||
|
#include <MAVLink.h>
|
||||||
|
|
||||||
|
const int CHANNEL = 6;
|
||||||
|
|
||||||
|
ESP_NOW_Serial_Class espnow(NULL, CHANNEL, WIFI_IF_AP);
|
||||||
|
MacAddress peerMac;
|
||||||
|
volatile bool peerFound = false;
|
||||||
|
|
||||||
|
void onNewPeer(const esp_now_recv_info_t *info, const uint8_t *data, int len, void *arg) {
|
||||||
|
peerMac = info->src_addr;
|
||||||
|
peerFound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
WiFi.mode(WIFI_AP);
|
||||||
|
WiFi.setSleep(false);
|
||||||
|
WiFi.setChannel(CHANNEL);
|
||||||
|
|
||||||
|
// while (!WiFi.AP.started()) {
|
||||||
|
// delay(100);
|
||||||
|
// }
|
||||||
|
|
||||||
|
ESP_NOW.onNewPeer(onNewPeer, NULL);
|
||||||
|
ESP_NOW.begin();
|
||||||
|
|
||||||
|
while (!peerFound) {
|
||||||
|
Serial.printf("MAC: %s, waiting for peer...\n", WiFi.softAPmacAddress().c_str());
|
||||||
|
delay(1000);
|
||||||
|
}
|
||||||
|
Serial.printf("Peer found: %s\n", peerMac.toString().c_str());
|
||||||
|
|
||||||
|
espnow.addr(peerMac);
|
||||||
|
espnow.setChannel(CHANNEL);
|
||||||
|
espnow.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
uint8_t buf[5000];
|
||||||
|
|
||||||
|
// Send from serial to ESP-NOW
|
||||||
|
while (Serial.available() > 0) {
|
||||||
|
int b = Serial.read();
|
||||||
|
if (b < 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mavlink_message_t msg;
|
||||||
|
mavlink_status_t status;
|
||||||
|
if (mavlink_parse_char(MAVLINK_COMM_0, (uint8_t)b, &msg, &status)) {
|
||||||
|
int len = mavlink_msg_to_send_buffer(buf, &msg);
|
||||||
|
// ESP_NOW.write(buf, len);
|
||||||
|
espnow.write(buf, len);
|
||||||
|
// espnow.send(buf, len);
|
||||||
|
// esp_now_send(peerMac, buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send from ESP-NOW to serial
|
||||||
|
int len = espnow.read(buf, sizeof(buf));
|
||||||
|
if (len > 0) {
|
||||||
|
Serial.write(buf, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user