2018-04-01 18:06:45 +00:00
|
|
|
// ESPNOWSkate by Lukas Bachschwell this device MASTER =D
|
|
|
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include <esp_now.h>
|
|
|
|
#include <WiFi.h>
|
2018-04-17 09:52:38 +00:00
|
|
|
#include <U8g2lib.h>
|
2018-04-29 12:05:06 +00:00
|
|
|
#include <Preferences.h>
|
2018-04-01 18:06:45 +00:00
|
|
|
|
|
|
|
#include "mac_config.h"
|
2018-04-17 14:46:47 +00:00
|
|
|
#include "graphics.h"
|
2018-04-22 19:46:19 +00:00
|
|
|
#include "accel.h"
|
|
|
|
|
2018-04-28 11:37:51 +00:00
|
|
|
TaskHandle_t clickTaskHandle;
|
2018-04-29 12:05:06 +00:00
|
|
|
Preferences preferences;
|
2018-04-28 11:37:51 +00:00
|
|
|
|
2018-04-24 19:31:32 +00:00
|
|
|
#define B_VOLT 0
|
|
|
|
#define B_VOLT_D 1
|
|
|
|
#define B_TEMP 2
|
|
|
|
#define B_TEMP_D 3
|
|
|
|
#define B_SPEED 4
|
|
|
|
#define B_SPEED_D 5
|
|
|
|
|
|
|
|
uint8_t boardData[6] = {0, 0, 0, 0, 0, 0};
|
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
#define M_NORMAL 0 // Limit is a sub of normal
|
|
|
|
#define M_SELECT 1
|
|
|
|
#define M_SETTINGS 2
|
|
|
|
#define M_CRUISE 3
|
|
|
|
#define M_STEERING 4
|
|
|
|
|
|
|
|
//#define steeringInfluential
|
|
|
|
|
|
|
|
uint8_t currentMode = M_NORMAL;
|
|
|
|
uint8_t selectedIndex = 2;
|
|
|
|
|
|
|
|
bool lightActive = false;
|
|
|
|
bool shouldUpdateSettings = false; // Needed to update limitmode on core 1 instead of 0
|
|
|
|
|
|
|
|
bool crusing = false;
|
|
|
|
uint8_t crusingSpeed = 127;
|
|
|
|
|
|
|
|
#define DEBUG
|
2018-04-29 12:05:06 +00:00
|
|
|
|
|
|
|
#ifdef DEBUG
|
|
|
|
#define DEBUG_PRINTLN(x) Serial.println(x)
|
|
|
|
#define DEBUG_PRINT(x) Serial.print(x)
|
|
|
|
#else
|
|
|
|
#define DEBUG_PRINTLN(x)
|
|
|
|
#define DEBUG_PRINT(x)
|
|
|
|
#endif
|
|
|
|
|
2018-04-24 19:31:32 +00:00
|
|
|
bool connected = false;
|
|
|
|
|
2018-04-28 11:37:51 +00:00
|
|
|
uint8_t clickCounter = 0;
|
|
|
|
bool lastTriggerState = false;
|
|
|
|
long lastClick = 0;
|
|
|
|
#define clickDiff 250
|
|
|
|
|
2018-04-17 09:52:38 +00:00
|
|
|
// Defining variables for OLED display
|
2018-04-24 19:31:32 +00:00
|
|
|
U8G2_SSD1306_128X64_NONAME_F_SW_I2C u8g2 (U8G2_R2, /* clock=*/ 15, /* data=*/ 4, /* reset=*/ 16);
|
2018-04-17 09:52:38 +00:00
|
|
|
char displayBuffer[20];
|
|
|
|
String displayString;
|
|
|
|
short displayData = 0;
|
|
|
|
unsigned long lastSignalBlink;
|
2018-04-24 19:31:32 +00:00
|
|
|
bool signalBlink = false;
|
2018-04-17 09:52:38 +00:00
|
|
|
unsigned long lastDataRotation;
|
|
|
|
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
// Defining variables for Hall Effect throttle.
|
|
|
|
short hallMeasurement;
|
|
|
|
int throttle = 127;
|
2018-04-29 12:05:06 +00:00
|
|
|
uint8_t esc1 = 127;
|
|
|
|
uint8_t esc2 = 127;
|
2018-04-17 09:52:38 +00:00
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
byte hallCenterMargin = 5;
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
const float minVoltage = 3.4;
|
|
|
|
const float maxVoltage = 4.2;
|
2018-04-17 19:57:25 +00:00
|
|
|
const float refVoltage = 3.3;
|
2018-04-24 19:31:32 +00:00
|
|
|
// Resistors in Ohms
|
2018-06-17 20:09:05 +00:00
|
|
|
const float deviderR1 = 22000;
|
|
|
|
const float deviderR2 = 11200;
|
2018-04-17 19:57:25 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
// Global copy of board
|
|
|
|
esp_now_peer_info_t board;
|
|
|
|
#define CHANNEL 1
|
2018-04-01 18:06:45 +00:00
|
|
|
#define PRINTSCANRESULTS 0
|
|
|
|
#define DELETEBEFOREPAIR 0
|
2018-06-17 20:09:05 +00:00
|
|
|
#define HAL_MIN 1390 // defaults
|
|
|
|
#define HAL_MAX 2230 // defaults
|
|
|
|
#define HAL_CENTER 1880 // defaults
|
2018-04-01 18:06:45 +00:00
|
|
|
|
|
|
|
//#define pairingMode
|
|
|
|
#define leverPin 36
|
2018-04-17 19:57:25 +00:00
|
|
|
#define triggerPin 17
|
2018-06-17 20:09:05 +00:00
|
|
|
#define batteryMeasurePin 39
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
bool triggerActive();
|
|
|
|
|
|
|
|
#include "settings.h"
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
void setCrusing(uint8_t speed) {
|
|
|
|
if(speed < 127) { // no backward cruse!
|
|
|
|
crusing = false;
|
|
|
|
crusingSpeed = 127;
|
|
|
|
} else {
|
|
|
|
crusing = true;
|
|
|
|
if(speed > crusingSpeed) crusingSpeed = speed;
|
|
|
|
}
|
|
|
|
}
|
2018-04-01 18:06:45 +00:00
|
|
|
// ESPNOW functions ##############################
|
2018-04-22 19:46:19 +00:00
|
|
|
// Scan for boards in AP mode
|
2018-06-17 20:09:05 +00:00
|
|
|
// 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"));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
#ifdef pairingMode
|
2018-04-24 19:31:32 +00:00
|
|
|
void ScanForBoard() {
|
2018-04-01 18:06:45 +00:00
|
|
|
int8_t scanResults = WiFi.scanNetworks();
|
|
|
|
// reset on each scan
|
2018-04-22 19:46:19 +00:00
|
|
|
bool boardFound = 0;
|
|
|
|
memset(&board, 0, sizeof(board));
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("");
|
2018-04-01 18:06:45 +00:00
|
|
|
if (scanResults == 0) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("No WiFi devices in AP Mode found");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Found "); DEBUG_PRINT(scanResults); DEBUG_PRINTLN(" devices ");
|
2018-04-01 18:06:45 +00:00
|
|
|
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) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT(i + 1);
|
|
|
|
DEBUG_PRINT(": ");
|
|
|
|
DEBUG_PRINT(SSID);
|
|
|
|
DEBUG_PRINT(" (");
|
|
|
|
DEBUG_PRINT(RSSI);
|
|
|
|
DEBUG_PRINT(")");
|
|
|
|
DEBUG_PRINTLN("");
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
2018-04-22 19:46:19 +00:00
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
delay(10);
|
2018-04-22 19:46:19 +00:00
|
|
|
// Check if the current device starts with `board`
|
2018-04-01 18:06:45 +00:00
|
|
|
if (SSID.indexOf("ESK8") == 0) {
|
|
|
|
// SSID of interest
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Found a board.");
|
|
|
|
DEBUG_PRINT(i + 1); DEBUG_PRINT(": "); DEBUG_PRINT(SSID); DEBUG_PRINT(" ["); DEBUG_PRINT(BSSIDstr); DEBUG_PRINT("]"); DEBUG_PRINT(" ("); DEBUG_PRINT(RSSI); DEBUG_PRINT(")"); DEBUG_PRINTLN("");
|
2018-04-22 19:46:19 +00:00
|
|
|
// Get BSSID => Mac Address of the board
|
2018-04-01 18:06:45 +00:00
|
|
|
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 ) {
|
2018-04-22 19:46:19 +00:00
|
|
|
board.peer_addr[ii] = (uint8_t) mac[ii];
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
board.channel = CHANNEL; // pick a channel
|
|
|
|
board.encrypt = 0; // no encryption
|
2018-06-17 20:09:05 +00:00
|
|
|
board.ifidx = ESP_IF_WIFI_STA;
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
boardFound = 1;
|
|
|
|
// we are planning to have only one board in this example;
|
2018-04-01 18:06:45 +00:00
|
|
|
// Hence, break after we find one, to be a bit efficient
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
if (boardFound) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("board Found, processing..");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("board Not Found, trying again.");
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// clean up ram
|
|
|
|
WiFi.scanDelete();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
void deletePeer() {
|
2018-04-22 19:46:19 +00:00
|
|
|
const esp_now_peer_info_t *peer = &board;
|
2018-06-17 20:09:05 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
const uint8_t *peer_addr = board.peer_addr;
|
2018-04-01 18:06:45 +00:00
|
|
|
esp_err_t delStatus = esp_now_del_peer(peer_addr);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("board Delete Status: ");
|
2018-04-01 18:06:45 +00:00
|
|
|
if (delStatus == ESP_OK) {
|
|
|
|
// Delete success
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Success");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (delStatus == ESP_ERR_ESPNOW_NOT_INIT) {
|
|
|
|
// How did we get so far!!
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNOW Not Init");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (delStatus == ESP_ERR_ESPNOW_ARG) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Invalid Argument");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (delStatus == ESP_ERR_ESPNOW_NOT_FOUND) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Peer not found.");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Not sure what happened");
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
// Check if the board is already paired with the master.
|
|
|
|
// If not, pair the board with master
|
|
|
|
bool manageBoard() {
|
|
|
|
if (board.channel == CHANNEL) {
|
2018-04-01 18:06:45 +00:00
|
|
|
if (DELETEBEFOREPAIR) {
|
|
|
|
deletePeer();
|
|
|
|
}
|
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("board Status: ");
|
2018-04-22 19:46:19 +00:00
|
|
|
const esp_now_peer_info_t *peer = &board;
|
|
|
|
const uint8_t *peer_addr = board.peer_addr;
|
2018-04-01 18:06:45 +00:00
|
|
|
// check if the peer exists
|
|
|
|
bool exists = esp_now_is_peer_exist(peer_addr);
|
|
|
|
if ( exists) {
|
2018-04-22 19:46:19 +00:00
|
|
|
// board already paired.
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Already Paired");
|
2018-04-01 18:06:45 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
2018-04-22 19:46:19 +00:00
|
|
|
// board not paired, attempt pair
|
2018-04-01 18:06:45 +00:00
|
|
|
esp_err_t addStatus = esp_now_add_peer(peer);
|
|
|
|
if (addStatus == ESP_OK) {
|
|
|
|
// Pair success
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Pair success");
|
2018-04-01 18:06:45 +00:00
|
|
|
return true;
|
|
|
|
} else if (addStatus == ESP_ERR_ESPNOW_NOT_INIT) {
|
|
|
|
// How did we get so far!!
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNOW Not Init");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
} else if (addStatus == ESP_ERR_ESPNOW_ARG) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Invalid Argument");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
} else if (addStatus == ESP_ERR_ESPNOW_FULL) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Peer list full");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
} else if (addStatus == ESP_ERR_ESPNOW_NO_MEM) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Out of memory");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
} else if (addStatus == ESP_ERR_ESPNOW_EXIST) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Peer Exists");
|
2018-04-01 18:06:45 +00:00
|
|
|
return true;
|
|
|
|
} else {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Not sure what happened");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2018-04-22 19:46:19 +00:00
|
|
|
// No board found to process
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("No board found to process");
|
2018-04-01 18:06:45 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send data
|
|
|
|
void sendData() {
|
2018-05-10 13:57:38 +00:00
|
|
|
const uint8_t data[] = { esc1, esc2, boardOptions };
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
const uint8_t *peer_addr = board.peer_addr;
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Sending: "); DEBUG_PRINTLN(esc1);
|
2018-04-01 18:06:45 +00:00
|
|
|
esp_err_t result = esp_now_send(peer_addr, data, sizeof(data));
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Send Status: ");
|
2018-04-30 18:46:31 +00:00
|
|
|
if(result != ESP_OK) setCrusing(0);
|
2018-04-01 18:06:45 +00:00
|
|
|
if (result == ESP_OK) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Success");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_NOT_INIT) {
|
|
|
|
// How did we get so far!!
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNOW not Init.");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_ARG) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Invalid Argument");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_INTERNAL) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Internal Error");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_NO_MEM) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESP_ERR_ESPNOW_NO_MEM");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_NOT_FOUND) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Peer not found.");
|
2018-06-17 20:09:05 +00:00
|
|
|
} else if (result == ESP_ERR_ESPNOW_IF) {
|
|
|
|
DEBUG_PRINTLN("Interface error.");
|
2018-04-01 18:06:45 +00:00
|
|
|
} else {
|
2018-06-17 20:09:05 +00:00
|
|
|
DEBUG_PRINT("Not sure what happened ");
|
|
|
|
DEBUG_PRINTLN(result);
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
// callback when data is sent from Master to board
|
2018-04-01 18:06:45 +00:00
|
|
|
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]);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Last Packet Sent to: "); DEBUG_PRINTLN(macStr);
|
|
|
|
DEBUG_PRINT("Last Packet Send Status: ");
|
2018-04-24 19:31:32 +00:00
|
|
|
if(status == ESP_NOW_SEND_SUCCESS) {
|
|
|
|
connected = true;
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Delivery Success");
|
2018-04-24 19:31:32 +00:00
|
|
|
} else {
|
|
|
|
connected = false;
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("Delivery Fail");
|
2018-04-30 18:46:31 +00:00
|
|
|
setCrusing(0);
|
2018-04-24 19:31:32 +00:00
|
|
|
}
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
2018-04-22 19:46:19 +00:00
|
|
|
|
|
|
|
// callback when data is recv from board
|
|
|
|
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]);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Last Response Recv from: "); DEBUG_PRINTLN(macStr);
|
2018-04-24 19:31:32 +00:00
|
|
|
memcpy(boardData, data, data_len);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Recieved data! len: ");
|
|
|
|
DEBUG_PRINTLN(data_len);
|
2018-04-22 19:46:19 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 09:52:38 +00:00
|
|
|
//############ End ESP Now
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
//############ Hardware Helpers
|
2018-04-29 12:05:06 +00:00
|
|
|
|
|
|
|
int c_map(int value, int inMin, int inMax, int outMin, int outMax) {
|
|
|
|
return constrain(map(value, inMin, inMax, outMin, outMax), outMin, outMax);
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 09:52:38 +00:00
|
|
|
// Return true if trigger is activated, false otherwice
|
2018-04-17 14:46:47 +00:00
|
|
|
bool triggerActive() {
|
2018-04-28 11:37:51 +00:00
|
|
|
if (digitalRead(triggerPin) == LOW) {
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(0.1));
|
|
|
|
if (digitalRead(triggerPin) == LOW) return true;
|
|
|
|
} else {
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(0.1));
|
|
|
|
if (digitalRead(triggerPin) == HIGH) return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
return false; // biased to false
|
2018-04-17 09:52:38 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
void calculateThrottlePosition() {
|
|
|
|
// Hall sensor reading can be noisy, lets make an average reading.
|
|
|
|
int total = 0;
|
|
|
|
for (int i = 0; i < 10; i++) {
|
|
|
|
total += analogRead(leverPin);
|
|
|
|
}
|
2018-04-29 12:05:06 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
hallMeasurement = total / 10;
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("HAL: ");
|
|
|
|
DEBUG_PRINTLN(hallMeasurement);
|
|
|
|
|
|
|
|
int maxSpeed = 255;
|
2018-04-30 18:46:31 +00:00
|
|
|
if(settings[limitMode] == 1) maxSpeed = 180;
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
if (hallMeasurement >= settings[centerHallValue]) {
|
|
|
|
throttle = c_map(hallMeasurement, settings[centerHallValue], settings[maxHallValue], 127, maxSpeed);
|
2018-04-17 14:46:47 +00:00
|
|
|
} else {
|
2018-06-17 20:09:05 +00:00
|
|
|
throttle = c_map(hallMeasurement, settings[minHallValue], settings[centerHallValue], 0, 127);
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
|
|
|
// removeing center noise
|
|
|
|
if (abs(throttle - 127) < hallCenterMargin) {
|
|
|
|
throttle = 127;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Function to calculate and return the remotes battery voltage.
|
|
|
|
float batteryVoltage() {
|
|
|
|
float batteryVoltage = 0.0;
|
|
|
|
int total = 0;
|
|
|
|
|
2018-04-17 19:57:25 +00:00
|
|
|
for (int i = 0; i < 10; i++) {
|
2018-04-17 14:46:47 +00:00
|
|
|
total += analogRead(batteryMeasurePin);
|
2018-04-17 19:57:25 +00:00
|
|
|
}
|
2018-04-24 19:31:32 +00:00
|
|
|
batteryVoltage = (refVoltage / 4095.0) * ((float)total / 10.0);
|
|
|
|
// Now we have the actual Voltage, lets calculate the value befor the devider
|
|
|
|
batteryVoltage = batteryVoltage / ( deviderR1 / (deviderR1 + deviderR2));
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Batt: ");
|
|
|
|
DEBUG_PRINTLN(batteryVoltage);
|
2018-04-17 19:57:25 +00:00
|
|
|
return batteryVoltage;
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 09:52:38 +00:00
|
|
|
// Function used to indicate the remotes battery level.
|
|
|
|
int batteryLevel() {
|
|
|
|
float voltage = batteryVoltage();
|
|
|
|
|
|
|
|
if (voltage <= minVoltage) {
|
|
|
|
return 0;
|
|
|
|
} else if (voltage >= maxVoltage) {
|
|
|
|
return 100;
|
|
|
|
} else {
|
|
|
|
return (voltage - minVoltage) * 100 / (maxVoltage - minVoltage);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
// Take a number of measurements of the WiFi strength and return the average result.
|
|
|
|
int getStrength(int points){
|
|
|
|
long rssi = 0;
|
|
|
|
long averageRSSI=0;
|
2018-04-24 19:31:32 +00:00
|
|
|
if (points == 1) return WiFi.RSSI();
|
2018-04-17 09:52:38 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
for (int i=0; i < points; i++) {
|
|
|
|
rssi += WiFi.RSSI();
|
|
|
|
delay(20);
|
|
|
|
}
|
2018-04-17 09:52:38 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
averageRSSI=rssi/points;
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("RSSI: ");
|
|
|
|
DEBUG_PRINTLN(averageRSSI);
|
2018-04-17 14:46:47 +00:00
|
|
|
return averageRSSI;
|
|
|
|
}
|
|
|
|
|
2018-04-28 11:37:51 +00:00
|
|
|
void checkClicks(void * parameter) {
|
|
|
|
for (;;) {
|
2018-04-29 12:05:06 +00:00
|
|
|
//DEBUG_PRINT("Trig: "); DEBUG_PRINT(triggerActive()); DEBUG_PRINT(" LAST: "); DEBUG_PRINTLN(lastTriggerState);
|
2018-04-28 11:37:51 +00:00
|
|
|
if(millis()-lastClick > clickDiff && clickCounter!=0) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("reset");
|
2018-05-10 13:57:38 +00:00
|
|
|
//timeout, check amount
|
|
|
|
if(clickCounter == 2) {
|
|
|
|
// cycle page if active
|
|
|
|
DEBUG_PRINTLN("Double, rotate page");
|
|
|
|
if(settings[pageDisplay] != 0) {
|
|
|
|
displayData++;
|
|
|
|
if (displayData > 2) {
|
|
|
|
displayData = 0;
|
|
|
|
}
|
|
|
|
// write and save
|
|
|
|
settings[pageDisplay] = displayData + 1;
|
|
|
|
shouldUpdateSettings = true;
|
|
|
|
}
|
|
|
|
} else if(clickCounter == 3) {
|
|
|
|
DEBUG_PRINTLN("YEAH TRIPPLE");
|
|
|
|
|
|
|
|
if(currentMode == M_NORMAL) {
|
|
|
|
currentMode = M_SELECT;
|
|
|
|
selectedIndex = 2;
|
|
|
|
} else {
|
|
|
|
currentMode = M_NORMAL;
|
|
|
|
}
|
|
|
|
}
|
2018-04-28 11:37:51 +00:00
|
|
|
clickCounter = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(!triggerActive() && lastTriggerState) {
|
2018-05-10 13:57:38 +00:00
|
|
|
DEBUG_PRINTLN("CLICK ##################### ");
|
2018-04-28 11:37:51 +00:00
|
|
|
int timeSinceLastClick = millis()-lastClick;
|
|
|
|
lastClick = millis();
|
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
if(currentMode == M_SELECT) {
|
|
|
|
switch(selectedIndex) {
|
|
|
|
case 0:
|
|
|
|
currentMode = M_SETTINGS;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
if(settings[limitMode] == 0) settings[limitMode] = 1;
|
|
|
|
else settings[limitMode] = 0;
|
|
|
|
shouldUpdateSettings = true;
|
|
|
|
currentMode = M_NORMAL;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
lightActive = !lightActive;
|
2018-05-10 13:57:38 +00:00
|
|
|
updateBoardOptions();
|
2018-04-30 18:46:31 +00:00
|
|
|
currentMode = M_NORMAL;
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
currentMode = M_STEERING;
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
currentMode = M_CRUISE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-10 13:57:38 +00:00
|
|
|
if(timeSinceLastClick < clickDiff) {
|
|
|
|
clickCounter++;
|
|
|
|
} else {
|
|
|
|
clickCounter = 1;
|
2018-04-28 11:37:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
lastClick = millis();
|
|
|
|
lastTriggerState = false;
|
|
|
|
} else if(triggerActive()) {
|
|
|
|
lastTriggerState = true;
|
|
|
|
}
|
|
|
|
vTaskDelay(pdMS_TO_TICKS(20));
|
|
|
|
}
|
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
//############ End Hardware Helpers
|
|
|
|
|
|
|
|
//############ Drawing Functions
|
|
|
|
|
|
|
|
void drawBatteryLevel() {
|
|
|
|
int level = batteryLevel();
|
|
|
|
|
|
|
|
// Position on OLED
|
|
|
|
int x = 108; int y = 4;
|
|
|
|
|
|
|
|
u8g2.drawFrame(x + 2, y, 18, 9);
|
|
|
|
u8g2.drawBox(x, y + 2, 2, 5);
|
|
|
|
|
|
|
|
for (int i = 0; i < 5; i++) {
|
|
|
|
int p = round((100 / 5) * i);
|
2018-04-30 18:46:58 +00:00
|
|
|
if (p <= level) {
|
|
|
|
u8g2.drawBox(x + 4 + (3 * (4-i)), y + 2, 2, 5);
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-17 09:52:38 +00:00
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-17 09:52:38 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
void drawThrottle() {
|
|
|
|
int x = 0;
|
|
|
|
int y = 18;
|
2018-04-30 18:46:31 +00:00
|
|
|
uint8_t displayThrottle = throttle;
|
|
|
|
if(crusing) displayThrottle = crusingSpeed;
|
2018-04-17 14:46:47 +00:00
|
|
|
// Draw throttle
|
|
|
|
u8g2.drawHLine(x, y, 52);
|
|
|
|
u8g2.drawVLine(x, y, 10);
|
|
|
|
u8g2.drawVLine(x + 52, y, 10);
|
|
|
|
u8g2.drawHLine(x, y + 10, 5);
|
|
|
|
u8g2.drawHLine(x + 52 - 4, y + 10, 5);
|
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
if (displayThrottle >= 127) {
|
|
|
|
int width = map(displayThrottle, 127, 255, 0, 49);
|
2018-04-17 14:46:47 +00:00
|
|
|
|
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
u8g2.drawVLine(x + i + 2, y + 2, 7);
|
|
|
|
}
|
|
|
|
} else {
|
2018-04-30 18:46:31 +00:00
|
|
|
int width = map(displayThrottle, 0, 126, 49, 0);
|
2018-04-17 14:46:47 +00:00
|
|
|
for (int i = 0; i < width; i++) {
|
|
|
|
u8g2.drawVLine(x + 50 - i, y + 2, 7);
|
|
|
|
}
|
|
|
|
}
|
2018-04-17 09:52:38 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
void drawSignal() {
|
|
|
|
// Position on OLED
|
|
|
|
int x = 114; int y = 17;
|
2018-04-24 19:31:32 +00:00
|
|
|
if (connected == true) {
|
2018-04-17 14:46:47 +00:00
|
|
|
if (triggerActive()) {
|
|
|
|
u8g2.drawXBM(x, y, 12, 12, signal_transmitting_bits);
|
|
|
|
} else {
|
|
|
|
u8g2.drawXBM(x, y, 12, 12, signal_connected_bits);
|
|
|
|
}
|
2018-04-24 19:31:32 +00:00
|
|
|
} else {
|
2018-04-17 14:46:47 +00:00
|
|
|
if (millis() - lastSignalBlink > 500) {
|
|
|
|
signalBlink = !signalBlink;
|
|
|
|
lastSignalBlink = millis();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (signalBlink == true) {
|
|
|
|
u8g2.drawXBM(x, y, 12, 12, signal_connected_bits);
|
|
|
|
} else {
|
|
|
|
u8g2.drawXBM(x, y, 12, 12, signal_noconnection_bits);
|
|
|
|
}
|
2018-04-24 19:31:32 +00:00
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void drawTitleScreen(String title) {
|
|
|
|
u8g2.firstPage();
|
|
|
|
do {
|
|
|
|
title.toCharArray(displayBuffer, 20);
|
|
|
|
u8g2.setFont(u8g2_font_helvR10_tr );
|
|
|
|
u8g2.drawStr(12, 20, displayBuffer);
|
|
|
|
} while ( u8g2.nextPage() );
|
|
|
|
delay(1500);
|
|
|
|
}
|
|
|
|
|
2018-04-24 19:31:32 +00:00
|
|
|
|
|
|
|
|
|
|
|
void drawPage() {
|
|
|
|
int decimals;
|
|
|
|
String suffix;
|
|
|
|
String prefix;
|
|
|
|
|
|
|
|
int first, last;
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-04-17 19:57:25 +00:00
|
|
|
int x = 0;
|
|
|
|
int y = 16;
|
2018-04-24 19:31:32 +00:00
|
|
|
|
|
|
|
// Rotate the realtime data each 4s.
|
2018-05-10 13:57:38 +00:00
|
|
|
if(settings[pageDisplay] == 0) {
|
|
|
|
if ((millis() - lastDataRotation) >= 4000) {
|
2018-04-24 19:31:32 +00:00
|
|
|
|
2018-05-10 13:57:38 +00:00
|
|
|
lastDataRotation = millis();
|
|
|
|
displayData++;
|
2018-04-24 19:31:32 +00:00
|
|
|
|
2018-05-10 13:57:38 +00:00
|
|
|
if (displayData > 2) {
|
|
|
|
displayData = 0;
|
|
|
|
}
|
2018-04-24 19:31:32 +00:00
|
|
|
}
|
2018-05-10 13:57:38 +00:00
|
|
|
} else {
|
|
|
|
displayData = settings[pageDisplay] - 1;
|
2018-04-24 19:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
switch (displayData) {
|
|
|
|
case 0:
|
|
|
|
first = boardData[B_TEMP];
|
|
|
|
last = boardData[B_TEMP_D];
|
|
|
|
suffix = "C";
|
|
|
|
prefix = "BOX TEMP";
|
|
|
|
decimals = 2;
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
first = boardData[B_SPEED];
|
|
|
|
last = boardData[B_SPEED_D];
|
2018-04-26 15:10:44 +00:00
|
|
|
suffix = "KmH";
|
|
|
|
prefix = "SPEED";
|
2018-04-24 19:31:32 +00:00
|
|
|
decimals = 2;
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
first = boardData[B_VOLT];
|
|
|
|
last = boardData[B_VOLT_D];
|
|
|
|
suffix = "V";
|
|
|
|
prefix = "BATTERY";
|
|
|
|
decimals = 2;
|
|
|
|
break;
|
|
|
|
}
|
2018-04-17 19:57:25 +00:00
|
|
|
|
|
|
|
// Display prefix (title)
|
|
|
|
displayString = prefix;
|
|
|
|
displayString.toCharArray(displayBuffer, 10);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(x, y - 1, displayBuffer);
|
|
|
|
|
|
|
|
// Add leading zero
|
|
|
|
if (first <= 9) {
|
2018-04-24 19:31:32 +00:00
|
|
|
if(connected) displayString = "0" + (String)first;
|
2018-04-26 15:10:44 +00:00
|
|
|
else displayString = "--";
|
2018-04-17 19:57:25 +00:00
|
|
|
} else {
|
2018-04-24 19:31:32 +00:00
|
|
|
if(connected) displayString = (String)first;
|
2018-04-26 15:10:44 +00:00
|
|
|
else displayString = "--";
|
2018-04-17 19:57:25 +00:00
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-04-17 19:57:25 +00:00
|
|
|
// Display numbers
|
2018-04-26 15:10:44 +00:00
|
|
|
displayString.toCharArray(displayBuffer, 4);
|
2018-04-17 19:57:25 +00:00
|
|
|
u8g2.setFont(u8g2_font_logisoso22_tn );
|
|
|
|
u8g2.drawStr(x + 55, y + 13, displayBuffer);
|
|
|
|
|
|
|
|
// Display decimals
|
2018-04-24 19:31:32 +00:00
|
|
|
// Add leading zero
|
|
|
|
if (last <= 9) {
|
|
|
|
if(connected) displayString = ".0" + (String)last;
|
2018-04-26 15:10:44 +00:00
|
|
|
else displayString = ".--";
|
2018-04-24 19:31:32 +00:00
|
|
|
} else {
|
|
|
|
if(connected) displayString = "." + (String)last;
|
2018-04-26 15:10:44 +00:00
|
|
|
else displayString = ".--";
|
2018-04-24 19:31:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Display decimals
|
|
|
|
displayString.toCharArray(displayBuffer, decimals + 2);
|
2018-04-17 19:57:25 +00:00
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(x + 86, y - 1, displayBuffer);
|
|
|
|
|
|
|
|
// Display suffix
|
|
|
|
displayString = suffix;
|
|
|
|
displayString.toCharArray(displayBuffer, 10);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(x + 86 + 2, y + 13, displayBuffer);
|
2018-04-24 19:31:32 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-30 18:46:31 +00:00
|
|
|
|
|
|
|
void controlSelect() {
|
2018-06-17 20:09:05 +00:00
|
|
|
if (hallMeasurement >= (settings[maxHallValue] - 250) && settingsLoopFlag == false) { //settings[maxHallValue]
|
2018-04-30 18:46:31 +00:00
|
|
|
// Up
|
|
|
|
if (selectedIndex != 0) {
|
|
|
|
selectedIndex--;
|
|
|
|
settingsLoopFlag = true;
|
|
|
|
}
|
2018-06-17 20:09:05 +00:00
|
|
|
} else if (hallMeasurement <= (settings[minHallValue] + 250) && settingsLoopFlag == false) {
|
2018-04-30 18:46:31 +00:00
|
|
|
// Down
|
|
|
|
if (selectedIndex < 4) {
|
|
|
|
selectedIndex++;
|
|
|
|
settingsLoopFlag = true;
|
|
|
|
}
|
2018-06-17 20:09:05 +00:00
|
|
|
} else if (inRange(hallMeasurement, settings[centerHallValue] - 50, settings[centerHallValue] + 50)) { // settings[centerHallValue]
|
2018-04-30 18:46:31 +00:00
|
|
|
settingsLoopFlag = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
String selectionTitles[5] = {
|
|
|
|
"Settings","Limit","Light","Steering","Cruise"
|
|
|
|
};
|
|
|
|
|
|
|
|
uint16_t selectionGlyphs[5] = {
|
|
|
|
0x0081, 0x008d, 0x0103, 0x00f6, 0x0088
|
2018-04-30 18:46:31 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
void drawSelectionMenu() {
|
|
|
|
const uint8_t y = 35;
|
|
|
|
const uint8_t xStart = 10;
|
|
|
|
const uint8_t xSpace = 20;
|
|
|
|
|
|
|
|
u8g2.setFontMode(0);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
|
|
|
|
for(int i = 0; i < 5; i++) {
|
|
|
|
if(selectedIndex == i) {
|
2018-06-17 20:09:05 +00:00
|
|
|
String title = selectionTitles[i];
|
|
|
|
title.toCharArray(displayBuffer, 20);
|
|
|
|
u8g2.setFont(u8g2_font_helvR10_tr );
|
|
|
|
u8g2.drawStr(30, 12, displayBuffer);
|
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
u8g2.setFontMode(0);
|
2018-06-17 20:09:05 +00:00
|
|
|
//u8g2.drawBox(xStart-2 + xSpace * i, y-12, 15, 15);
|
|
|
|
u8g2.drawBox(xStart + xSpace * i, y-12, 15, 15);
|
2018-04-30 18:46:31 +00:00
|
|
|
u8g2.setDrawColor(0);
|
|
|
|
}
|
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
//selectionItems[i].toCharArray(displayBuffer, 10);
|
|
|
|
//u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
//u8g2.drawStr(xStart + xSpace * i, y, displayBuffer);
|
|
|
|
|
|
|
|
u8g2.setFont(u8g2_font_open_iconic_all_2x_t);
|
|
|
|
u8g2.drawGlyph(xStart + xSpace * i, y, selectionGlyphs[i]);
|
2018-04-30 18:46:31 +00:00
|
|
|
|
|
|
|
u8g2.setFontMode(0);
|
|
|
|
u8g2.setDrawColor(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawLight() {
|
|
|
|
if(lightActive) {
|
|
|
|
displayString = "Light";
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont10_tr);
|
|
|
|
u8g2.drawStr(100, 38, displayBuffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
void drawMode() {
|
2018-04-30 18:46:31 +00:00
|
|
|
if(currentMode == M_STEERING) {
|
2018-04-29 12:05:06 +00:00
|
|
|
displayString = (String)esc1 + " |S| " + (String)esc2;
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(25, 50, displayBuffer);
|
2018-04-30 18:46:31 +00:00
|
|
|
} else if(currentMode == M_NORMAL && settings[limitMode] == 1) {
|
2018-04-29 12:05:06 +00:00
|
|
|
displayString = "LIM";
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(105, 50, displayBuffer);
|
2018-04-30 18:46:31 +00:00
|
|
|
} else if(currentMode == M_CRUISE) {
|
|
|
|
if(crusing) {
|
|
|
|
displayString = "ACTIVE: " + (String) crusingSpeed;
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(0, 50, displayBuffer);
|
|
|
|
} else {
|
|
|
|
displayString = "Inactive";
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(0, 50, displayBuffer);
|
|
|
|
}
|
|
|
|
|
|
|
|
displayString = "CRU";
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_profont12_tr);
|
|
|
|
u8g2.drawStr(105, 50, displayBuffer);
|
2018-04-29 12:05:06 +00:00
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-17 09:52:38 +00:00
|
|
|
|
|
|
|
void updateMainDisplay() {
|
|
|
|
|
|
|
|
u8g2.firstPage();
|
|
|
|
do {
|
2018-04-30 18:46:31 +00:00
|
|
|
if(currentMode == M_SELECT) {
|
|
|
|
drawSelectionMenu();
|
|
|
|
} else if (currentMode == M_SETTINGS) {
|
2018-04-17 19:57:25 +00:00
|
|
|
drawSettingsMenu();
|
2018-04-17 09:52:38 +00:00
|
|
|
drawSettingNumber();
|
|
|
|
} else {
|
|
|
|
drawThrottle();
|
2018-04-24 19:31:32 +00:00
|
|
|
drawPage();
|
2018-04-17 09:52:38 +00:00
|
|
|
drawBatteryLevel();
|
|
|
|
drawSignal();
|
2018-04-30 18:46:31 +00:00
|
|
|
drawLight();
|
2018-04-29 12:05:06 +00:00
|
|
|
drawMode();
|
2018-04-17 09:52:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
} while ( u8g2.nextPage() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void drawStartScreen() {
|
|
|
|
u8g2.firstPage();
|
|
|
|
do {
|
|
|
|
u8g2.drawXBM( 4, 4, 24, 24, logo_bits);
|
|
|
|
|
|
|
|
displayString = "Esk8 remote";
|
|
|
|
displayString.toCharArray(displayBuffer, 12);
|
|
|
|
u8g2.setFont(u8g2_font_helvR10_tr );
|
|
|
|
u8g2.drawStr(34, 22, displayBuffer);
|
|
|
|
} while ( u8g2.nextPage() );
|
2018-04-24 19:31:32 +00:00
|
|
|
delay(800);
|
2018-04-17 09:52:38 +00:00
|
|
|
}
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
//############ End Drawing Functions
|
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
void setup() {
|
|
|
|
Serial.begin(115200);
|
|
|
|
//Set device in STA mode to begin with
|
2018-06-17 20:09:05 +00:00
|
|
|
//WiFi.mode(WIFI_STA);
|
|
|
|
//Set device in AP mode to begin with
|
|
|
|
WiFi.mode(WIFI_AP_STA);
|
|
|
|
// configure device AP mode
|
|
|
|
configDeviceAP(true);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNowSkate");
|
|
|
|
|
|
|
|
loadSettings();
|
2018-04-01 18:06:45 +00:00
|
|
|
|
|
|
|
// reset the screen
|
|
|
|
pinMode(16, OUTPUT);
|
|
|
|
digitalWrite(16, LOW); // set GPIO16 low to reset OLED
|
|
|
|
delay(50);
|
|
|
|
digitalWrite(16, HIGH);
|
|
|
|
|
2018-04-17 14:46:47 +00:00
|
|
|
// setup other pins
|
|
|
|
pinMode(triggerPin, INPUT_PULLUP);
|
|
|
|
|
2018-04-28 11:37:51 +00:00
|
|
|
xTaskCreatePinnedToCore(
|
|
|
|
checkClicks,
|
|
|
|
"click task",
|
|
|
|
1000,
|
|
|
|
NULL,
|
|
|
|
1,
|
|
|
|
&clickTaskHandle,
|
|
|
|
0);
|
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
initAccel();
|
|
|
|
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNowSkate Sender");
|
2018-04-17 09:52:38 +00:00
|
|
|
u8g2.begin();
|
|
|
|
drawStartScreen();
|
2018-04-17 19:57:25 +00:00
|
|
|
|
|
|
|
if (triggerActive()) {
|
2018-04-30 18:46:31 +00:00
|
|
|
currentMode = M_SETTINGS;
|
2018-04-17 14:46:47 +00:00
|
|
|
drawTitleScreen("Remote Settings");
|
2018-04-17 19:57:25 +00:00
|
|
|
}
|
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
// This is the mac address of the Master in Station Mode
|
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
DEBUG_PRINT("STA MAC: "); DEBUG_PRINTLN(WiFi.macAddress());
|
2018-04-01 18:06:45 +00:00
|
|
|
if (esp_now_init() == ESP_OK) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNow Init Success");
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
else {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN("ESPNow Init Failed");
|
2018-04-01 18:06:45 +00:00
|
|
|
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);
|
2018-04-24 19:31:32 +00:00
|
|
|
//ScanForBoard();
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
// Once ESPNow is successfully Init, we will register for recv CB to
|
|
|
|
// get recv packer info.
|
|
|
|
esp_now_register_recv_cb(OnDataRecv);
|
2018-04-01 18:06:45 +00:00
|
|
|
|
2018-04-22 19:46:19 +00:00
|
|
|
|
|
|
|
// Retrieve board from config:
|
2018-04-01 18:06:45 +00:00
|
|
|
for (int i = 0; i < 6; ++i ) {
|
2018-04-22 19:46:19 +00:00
|
|
|
board.peer_addr[i] = (uint8_t) mac_receiver[i];
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
2018-04-22 19:46:19 +00:00
|
|
|
board.channel = CHANNEL; // pick a channel
|
|
|
|
board.encrypt = 0; // no encryption
|
2018-06-17 20:09:05 +00:00
|
|
|
//board.ifidx = ESP_IF_WIFI_STA;
|
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void loop() {
|
2018-04-17 14:46:47 +00:00
|
|
|
updateMainDisplay();
|
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
//if(currentMode == M_STEERING) readAccel();
|
|
|
|
readAccel();
|
|
|
|
DEBUG_PRINT("Accel Value Left Right (Y): ");
|
|
|
|
DEBUG_PRINT(map(AcY, -15000, 15000, -100, 100));
|
|
|
|
//Serial.print("Help(Y): ");
|
|
|
|
//Serial.println(map(GyY, -15000, 15000, -100, 100));
|
2018-04-29 12:05:06 +00:00
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
DEBUG_PRINT(" (X): ");
|
|
|
|
DEBUG_PRINT(map(AcX, -15000, 15000, -100, 100));
|
2018-04-17 14:46:47 +00:00
|
|
|
|
2018-06-17 20:09:05 +00:00
|
|
|
DEBUG_PRINT(" (Z): ");
|
|
|
|
DEBUG_PRINTLN(map(AcZ, -15000, 15000, -100, 100));
|
|
|
|
|
|
|
|
// left rigt : Z forward Back : Y
|
2018-04-24 19:31:32 +00:00
|
|
|
calculateThrottlePosition();
|
2018-04-30 18:46:31 +00:00
|
|
|
|
|
|
|
if (currentMode == M_SELECT) {
|
|
|
|
controlSelect();
|
|
|
|
esc1 = 127;
|
|
|
|
esc2 = 127;
|
|
|
|
} else if (currentMode == M_SETTINGS) {
|
2018-04-17 14:46:47 +00:00
|
|
|
// Use throttle and trigger to change settings
|
2018-04-29 12:05:06 +00:00
|
|
|
controlSettingsMenu();
|
2018-04-17 14:46:47 +00:00
|
|
|
} else {
|
|
|
|
// Use throttle and trigger to drive motors
|
|
|
|
if (triggerActive()) {
|
2018-04-30 18:46:31 +00:00
|
|
|
if(currentMode == M_STEERING) {
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINT("Value: ");
|
2018-06-17 20:09:05 +00:00
|
|
|
int map = c_map(AcZ, -15000, 15000, -60, 60);
|
2018-04-29 12:05:06 +00:00
|
|
|
DEBUG_PRINTLN(map);
|
|
|
|
|
2018-04-30 18:46:31 +00:00
|
|
|
#ifdef steeringInfluential
|
|
|
|
esc1 = (uint8_t) constrain(throttle - map, 0, 200);
|
|
|
|
esc2 = (uint8_t) constrain(throttle + map, 0, 200);
|
|
|
|
#else
|
|
|
|
esc1 = (uint8_t) constrain(127 - map, 0, 200);
|
|
|
|
esc2 = (uint8_t) constrain(127 + map, 0, 200);
|
|
|
|
if(-10 < map && map < 10) {
|
|
|
|
esc1 = throttle;
|
|
|
|
esc2 = throttle;
|
|
|
|
}
|
2018-06-17 20:09:05 +00:00
|
|
|
|
|
|
|
// ignore reverse
|
|
|
|
if(throttle < 127) {
|
|
|
|
esc1 = throttle;
|
|
|
|
esc2 = throttle;
|
|
|
|
}
|
2018-04-30 18:46:31 +00:00
|
|
|
#endif
|
2018-04-29 12:05:06 +00:00
|
|
|
if(throttle == 127) {
|
|
|
|
esc1 = 127;
|
|
|
|
esc2 = 127;
|
|
|
|
}
|
|
|
|
|
|
|
|
DEBUG_PRINT("SteeringMode: ESC1: "); DEBUG_PRINT(esc1); DEBUG_PRINT(" ESC2: "); DEBUG_PRINTLN(esc2);
|
2018-04-30 18:46:31 +00:00
|
|
|
} else if(currentMode == M_CRUISE) {
|
|
|
|
|
|
|
|
setCrusing(throttle);
|
|
|
|
|
|
|
|
esc1 = (uint8_t) throttle;
|
|
|
|
esc2 = (uint8_t) throttle;
|
|
|
|
|
|
|
|
if(crusing) {
|
|
|
|
esc1 = (uint8_t) crusingSpeed;
|
|
|
|
esc2 = (uint8_t) crusingSpeed;
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
esc1 = (uint8_t) throttle;
|
|
|
|
esc2 = (uint8_t) throttle;
|
2018-04-29 12:05:06 +00:00
|
|
|
}
|
|
|
|
|
2018-04-01 18:06:45 +00:00
|
|
|
} else {
|
2018-04-17 14:46:47 +00:00
|
|
|
// 127 is the middle position - no throttle and no brake/reverse
|
2018-04-29 12:05:06 +00:00
|
|
|
esc1 = 127;
|
|
|
|
esc2 = 127;
|
2018-04-30 18:46:31 +00:00
|
|
|
if(crusing) setCrusing(0);
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-29 12:05:06 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// If board is found, it would be populate in `board` variable
|
|
|
|
// We will check if `board` is defined and then we proceed further
|
|
|
|
if (board.channel == CHANNEL) { // check if board channel is defined
|
|
|
|
// `board` is defined
|
|
|
|
// Add board as peer if it has not been added already
|
|
|
|
bool isPaired = manageBoard();
|
|
|
|
if (isPaired) {
|
|
|
|
sendData();
|
|
|
|
} else {
|
|
|
|
// board pair failed
|
|
|
|
DEBUG_PRINTLN("board not found / paired!");
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|
2018-04-17 14:46:47 +00:00
|
|
|
}
|
2018-04-29 12:05:06 +00:00
|
|
|
else {
|
|
|
|
// No board found to process
|
|
|
|
}
|
2018-04-30 18:46:31 +00:00
|
|
|
|
|
|
|
if(shouldUpdateSettings) {
|
|
|
|
updateSettings();
|
|
|
|
shouldUpdateSettings = false;
|
|
|
|
}
|
2018-04-01 18:06:45 +00:00
|
|
|
}
|