commit 1a1df572fd51dcd491b01da98998505b3436a75b Author: Lukas Bachschwell Date: Sun Apr 1 20:06:45 2018 +0200 Initial working version diff --git a/lib/readme.txt b/lib/readme.txt new file mode 100644 index 0000000..dbadc3d --- /dev/null +++ b/lib/readme.txt @@ -0,0 +1,36 @@ + +This directory is intended for the project specific (private) libraries. +PlatformIO will compile them to static libraries and link to executable file. + +The source code of each library should be placed in separate directory, like +"lib/private_lib/[here are source files]". + +For example, see how can be organized `Foo` and `Bar` libraries: + +|--lib +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| |--Foo +| | |- Foo.c +| | |- Foo.h +| |- readme.txt --> THIS FILE +|- platformio.ini +|--src + |- main.c + +Then in `src/main.c` you should use: + +#include +#include + +// rest H/C/CPP code + +PlatformIO will find your libraries automatically, configure preprocessor's +include paths and build them. + +More information about PlatformIO Library Dependency Finder +- http://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..b7fd470 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,32 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; http://docs.platformio.org/page/projectconf.html + +[env:remote] +platform = espressif32 +board = esp32doit-devkit-v1 +framework = arduino + +src_filter = + + +monitor_baud = 115200 + + +[env:reciever] +platform = espressif32 +board = esp32doit-devkit-v1 +framework = arduino + +src_filter = + + +monitor_baud = 115200 + +lib_deps = + # Using a library name + ServoESP32 diff --git a/src/mac_config.h b/src/mac_config.h new file mode 100644 index 0000000..46ed4b8 --- /dev/null +++ b/src/mac_config.h @@ -0,0 +1,7 @@ +//mac addresses + +// reciever mac: +uint8_t mac_reciever[] = {0x30, 0xae, 0xa4, 0x04, 0x21, 0x2d}; + +// remote macStr +uint8_t mac_remote[] = {0x24, 0x0a, 0xc4, 0x82, 0x51, 0x70}; diff --git a/src/reciever.cpp b/src/reciever.cpp new file mode 100644 index 0000000..ada2d68 --- /dev/null +++ b/src/reciever.cpp @@ -0,0 +1,109 @@ +// ESPNOWSkate Reciever by Lukas Bachschwell this device SLAVE =D +#include +#include "Arduino.h" +#include "SSD1306.h" +#include +#include + +static const int esc1pin = 15; +static const int esc2pin = 13; + +Servo esc1; +Servo esc2; +SSD1306 display(0x3c, 5, 4); + + +//#define pairingMode +#define FAILSAFE 90 +#define CONNECTION_TIMEOUT 200 +#define CHANNEL 1 +long lastPacket = 0; + +bool isConnected = false; + +// ESPNOW Functions ############################ +// +// config AP +void configDeviceAP(bool hidden) { + bool result = WiFi.softAP("ESK8", "ESK8_Password+vD8z2YAvoDBW?Zx", CHANNEL, hidden); + if (!result) { + Serial.println("AP Config failed."); + } else { + Serial.println("AP Config Success. Broadcasting with AP: " + String("ESK8")); + } +} + +void writeServos(uint8_t firstServo, uint8_t secondServo) { + isConnected = true; + esc1.write(firstServo); + esc2.write(secondServo); +} + +// callback when data is recv from Master +void OnDataRecv(const uint8_t *mac_addr, const uint8_t *data, int data_len) { + char macStr[18]; + snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + Serial.print("Last Packet Recv from: "); Serial.println(macStr); + uint8_t recData[2]; + memcpy(recData, data, data_len); + Serial.print("Last Packet Recv Data: "); Serial.println(recData[0]); Serial.print(" "); Serial.print(recData[1]); Serial.print(" len:"); Serial.println(data_len); + + lastPacket = millis(); + isConnected = true; + // Could check mac here for some security + writeServos(recData[0], recData[1]); + + display.clear(); + char buf[25]; + sprintf(buf, "1: %i | 2: %i", recData[0], recData[1]); + display.drawString(2, 0, buf); + display.display(); +} + +// end ESPNOW functions + +void setup() { + Serial.begin(115200); + Serial.println("ESPNowSkate Reciever"); + + display.init(); + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_16); + + esc1.attach(esc1pin); + esc2.attach(esc2pin); + + //Set device in AP mode to begin with + WiFi.mode(WIFI_AP); + // configure device AP mode + #ifdef pairingMode + configDeviceAP(false); + #else + configDeviceAP(true); + #endif + + Serial.print("AP MAC: "); Serial.println(WiFi.softAPmacAddress()); + + // Init ESPNow + if (esp_now_init() == ESP_OK) { + Serial.println("ESPNow Init Success"); + } + else { + Serial.println("ESPNow Init Failed"); + ESP.restart(); + } + // Once ESPNow is successfully Init, we will register for recv CB to + // get recv packer info. + esp_now_register_recv_cb(OnDataRecv); +} + + +void loop() { + if(isConnected) { + if(millis() - lastPacket > CONNECTION_TIMEOUT ) { + isConnected = false; + writeServos(FAILSAFE, FAILSAFE); + } + } +} diff --git a/src/remote.cpp b/src/remote.cpp new file mode 100644 index 0000000..0dea6ac --- /dev/null +++ b/src/remote.cpp @@ -0,0 +1,272 @@ +// ESPNOWSkate by Lukas Bachschwell this device MASTER =D + +#include +#include +#include +#include + +#include "mac_config.h" + +// Global copy of slave +esp_now_peer_info_t slave; +#define CHANNEL 3 +#define PRINTSCANRESULTS 0 +#define DELETEBEFOREPAIR 0 +#define POT_MAX 3900 +#define TRIM_LOW 180 +#define TRIM_HIGH 31 + +//#define pairingMode +#define leverPin 36 +SSD1306 display(0x3c, 4, 15); + +// ESPNOW functions ############################## +// Scan for slaves in AP mode +#ifdef pairingMode +void ScanForSlave() { + int8_t scanResults = WiFi.scanNetworks(); + // reset on each scan + bool slaveFound = 0; + memset(&slave, 0, sizeof(slave)); + + Serial.println(""); + if (scanResults == 0) { + Serial.println("No WiFi devices in AP Mode found"); + } else { + Serial.print("Found "); Serial.print(scanResults); Serial.println(" devices "); + for (int i = 0; i < scanResults; ++i) { + // Print SSID and RSSI for each device found + String SSID = WiFi.SSID(i); + int32_t RSSI = WiFi.RSSI(i); + String BSSIDstr = WiFi.BSSIDstr(i); + + if (PRINTSCANRESULTS) { + Serial.print(i + 1); + Serial.print(": "); + Serial.print(SSID); + Serial.print(" ("); + Serial.print(RSSI); + Serial.print(")"); + Serial.println(""); + } + delay(10); + // Check if the current device starts with `Slave` + if (SSID.indexOf("ESK8") == 0) { + // SSID of interest + Serial.println("Found a Slave."); + Serial.print(i + 1); Serial.print(": "); Serial.print(SSID); Serial.print(" ["); Serial.print(BSSIDstr); Serial.print("]"); Serial.print(" ("); Serial.print(RSSI); Serial.print(")"); Serial.println(""); + // Get BSSID => Mac Address of the Slave + int mac[6]; + if ( 6 == sscanf(BSSIDstr.c_str(), "%x:%x:%x:%x:%x:%x%c", &mac[0], &mac[1], &mac[2], &mac[3], &mac[4], &mac[5] ) ) { + for (int ii = 0; ii < 6; ++ii ) { + slave.peer_addr[ii] = (uint8_t) mac[ii]; + } + } + + slave.channel = CHANNEL; // pick a channel + slave.encrypt = 0; // no encryption + + slaveFound = 1; + // we are planning to have only one slave in this example; + // Hence, break after we find one, to be a bit efficient + break; + } + } + } + + if (slaveFound) { + Serial.println("Slave Found, processing.."); + } else { + Serial.println("Slave Not Found, trying again."); + } + + // clean up ram + WiFi.scanDelete(); +} +#endif + +void deletePeer() { + const esp_now_peer_info_t *peer = &slave; + const uint8_t *peer_addr = slave.peer_addr; + esp_err_t delStatus = esp_now_del_peer(peer_addr); + Serial.print("Slave Delete Status: "); + if (delStatus == ESP_OK) { + // Delete success + Serial.println("Success"); + } else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW Not Init"); + } else if (delStatus == ESP_ERR_ESPNOW_ARG) { + Serial.println("Invalid Argument"); + } else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) { + Serial.println("Peer not found."); + } else { + Serial.println("Not sure what happened"); + } +} + +// Check if the slave is already paired with the master. +// If not, pair the slave with master +bool manageSlave() { + if (slave.channel == CHANNEL) { + if (DELETEBEFOREPAIR) { + deletePeer(); + } + + Serial.print("Slave Status: "); + const esp_now_peer_info_t *peer = &slave; + const uint8_t *peer_addr = slave.peer_addr; + // check if the peer exists + bool exists = esp_now_is_peer_exist(peer_addr); + if ( exists) { + // Slave already paired. + Serial.println("Already Paired"); + return true; + } else { + // Slave not paired, attempt pair + esp_err_t addStatus = esp_now_add_peer(peer); + if (addStatus == ESP_OK) { + // Pair success + Serial.println("Pair success"); + return true; + } else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW Not Init"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_ARG) { + Serial.println("Invalid Argument"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_FULL) { + Serial.println("Peer list full"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) { + Serial.println("Out of memory"); + return false; + } else if (addStatus == ESP_ERR_ESPNOW_EXIST) { + Serial.println("Peer Exists"); + return true; + } else { + Serial.println("Not sure what happened"); + return false; + } + } + } else { + // No slave found to process + Serial.println("No Slave found to process"); + return false; + } +} + +// send data +void sendData() { + uint8_t esc1 = map(analogRead(leverPin), 0, POT_MAX, TRIM_LOW, TRIM_HIGH); + uint8_t esc2 = esc1; + + const uint8_t data[] = { esc1, esc2 }; // no mixture for the normal mode + + const uint8_t *peer_addr = slave.peer_addr; + Serial.print("Sending: "); Serial.println(esc1); + esp_err_t result = esp_now_send(peer_addr, data, sizeof(data)); + Serial.print("Send Status: "); + if (result == ESP_OK) { + Serial.println("Success"); + } else if (result == ESP_ERR_ESPNOW_NOT_INIT) { + // How did we get so far!! + Serial.println("ESPNOW not Init."); + } else if (result == ESP_ERR_ESPNOW_ARG) { + Serial.println("Invalid Argument"); + } else if (result == ESP_ERR_ESPNOW_INTERNAL) { + Serial.println("Internal Error"); + } else if (result == ESP_ERR_ESPNOW_NO_MEM) { + Serial.println("ESP_ERR_ESPNOW_NO_MEM"); + } else if (result == ESP_ERR_ESPNOW_NOT_FOUND) { + Serial.println("Peer not found."); + } else { + Serial.println("Not sure what happened"); + } +} + +// callback when data is sent from Master to Slave +void OnDataSent(const uint8_t *mac_addr, esp_now_send_status_t status) { + char macStr[18]; + snprintf(macStr, sizeof(macStr), "%02x:%02x:%02x:%02x:%02x:%02x", + mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); + Serial.print("Last Packet Sent to: "); Serial.println(macStr); + Serial.print("Last Packet Send Status: "); Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail"); +} + +void setup() { + Serial.begin(115200); + //Set device in STA mode to begin with + WiFi.mode(WIFI_STA); + Serial.println("ESPNowSkate"); + + // reset the screen + pinMode(16, OUTPUT); + digitalWrite(16, LOW); // set GPIO16 low to reset OLED + delay(50); + digitalWrite(16, HIGH); + Serial.println("ESPNowSkate Sender"); + + display.init(); + display.flipScreenVertically(); + display.setFont(ArialMT_Plain_10); + display.setTextAlignment(TEXT_ALIGN_LEFT); + display.drawString(5, 5, "ESPNOW Test"); + display.display(); + + // This is the mac address of the Master in Station Mode + Serial.print("STA MAC: "); Serial.println(WiFi.macAddress()); + + if (esp_now_init() == ESP_OK) { + Serial.println("ESPNow Init Success"); + } + else { + Serial.println("ESPNow Init Failed"); + ESP.restart(); + } + + // Once ESPNow is successfully Init, we will register for Send CB to + // get the status of Trasnmitted packet + esp_now_register_send_cb(OnDataSent); + //ScanForSlave(); + + + // Retrieve Slave from config: + for (int i = 0; i < 6; ++i ) { + slave.peer_addr[i] = (uint8_t) mac_reciever[i]; + } + slave.channel = CHANNEL; // pick a channel + slave.encrypt = 0; // no encryption +} + +void loop() { + char buf[10]; + sprintf(buf, "%i", map(analogRead(leverPin), 0, POT_MAX, TRIM_LOW, TRIM_HIGH)); + //Serial.println(analogRead(leverPin)); + display.clear(); + display.drawString(3, 0, buf); + display.display(); + + // If Slave is found, it would be populate in `slave` variable + // We will check if `slave` is defined and then we proceed further + if (slave.channel == CHANNEL) { // check if slave channel is defined + // `slave` is defined + // Add slave as peer if it has not been added already + bool isPaired = manageSlave(); + if (isPaired) { + // pair success or already paired + // Send data to device + sendData(); + } else { + // slave pair failed + + Serial.println("Slave not found / paired!"); + } + } + else { + // No slave found to process + } + + delay(20); +}