Hi all!
I built an e-scooter a while back (DIY Arduino (FireBeetle) E-Scooter - Hackster.io) and it worked great! But then my motor driver broke, and I had to get a new motor, etc; anyways, it hasn't been working for about a month, and I had ended up changing my code right after I uploaded last time.
My last version works perfectly (https://github.com/Kgray44/DIY_Arduino_E-Scooter/tree/main/diy_e-scooter_cloud_v5) but Im getting an abort error for my code rn! I have never seen an error like it, and can't figure out how to fix it.
My error is:
E (33) gpio: G
abort() was called at PC 0x4008561b on core 1
Backtrace: 0x40084119:0x3ffc5840 0x40088e39:0x3ffc5860 0x4008df75:0x3ffc5880 0x4008561b:0x3ffc5900 0x40085765:0x3ffc5930 0x400e14c8:0x3ffc5950 0x400d892e:0x3ffc5990 0x400d8830:0x3ffc59e0 0x400d3cb1:0x3ffc5a00 0x400dd3a7:0x3ffc5a30
ELF file SHA256: 0f9876c112080128
Rebooting...
Here is my code:
#include "DFRobot_GDL.h"
#include <XPT2046_Touchscreen.h>
#include <SPI.h>
#include "DFRobot_GNSS.h"
#include "DFRobot_BMI160.h"
#include "DFRobot_AHT20.h"
#include "DFRobot_GR10_30.h"
#include <Adafruit_NeoPixel.h>
#include <EEPROM.h>
#include "settings.h"
//Testing
bool testing = false;
//Voltage Conversion for Speed
bool voltconversion = false;
// PWM properties for motor driver
const int freq = 5000;
const int speedChannel = 0;
const int resolution = 8;
//throttle
int throttleoffvalue = 0;
int throttleonvalue = 4095;
int throttleval = 0;
int lastthrottleval = 0;
//Touch coordinates for calibration
#define touchxmin 290
#define touchxmax 3750
#define touchymin 300
#define touchymax 3700
#define backcolor COLOR_RGB565_WHITE
#define erasecolor backcolor//COLOR_RGB565_LGRAY
#define backgroundcolor COLOR_RGB565_CYAN
//gnss / display
long readgnssinc = 1000;//time between GNSS readings
unsigned long lastreadgnss = 0;
long readdisplayinc = 1000;//time between display updates
unsigned long lastdisplay = 0;
sTim_t utc;
sTim_t date;
sLonLat_t latitude;
sLonLat_t longitude;
double altitude;
uint8_t satelites;
double knots;
double course;
//AHT20
float temperature = 0;
float humidity = 0;
float HI = 0;
//WS2812
#define NUMPIXELS 14
float lastcoursereading = 0;
float coursechangetime = 1000;
float lastcoursereadtime = 0;
float courseturnsignalinc = 10; //degrees of turning for turning signal to turn on
float coursechange = 0;
float lastspeedreading = 0;
float speedchangetime = 1000;
float lastspeedreadtime = 0;
float speedbrakeinc = -0.08;//decrease in speed before brake light turns on
int brake[] = {5,6,7,8,9};
int footlight[] = {10,11,12,13};
unsigned long startmillis = 0;
int animationcountleft = 1;
int animationcountright = 1;
bool leftturnsignal = false;
bool rightturnsignal = false;
float speeddiferrence = 0;
bool headlight = false;
int panimationcount = 0;
bool pup = true;
bool ledsoff = false;
//Password
bool locked = false;//true
uint16_t gestures;
int passwordlength = 3;
#define EEPROM_SIZE passwordlength
int passc = 0;//pass count
//battery
float batteryvolts = 0;
int batteryreadings = 10;//number of readings to average, more for a smoother more reliable response
long readbatteryint = 20;//time in milliseconds between battery readings
unsigned long lastbatreading = 0;
long R1 = 15000;//15k ohms
long R2 = 1000;//1.1k ohms
int curbatread = 0;
int batsum = 0;
#define batteryamps 5
#define batteryvoltage 36 //voltage and amp hours of battery, or uncomment "batterywattage" below instead
//#define batterywattage 180
#define motorwattage 350
#define maxcruisespeed 15 //mph //20
//gyro
float lastgyroreading = 0;
float readgyroint = 1;
float curgyroread = 0;
float gyroreadings = 5;
float gyrosum = 0;
float gyroy = 0;
//current sensor
int currentreadings = 10;//number of readings to average, more for a smoother more reliable response
long readcurrentint = 20;//time in milliseconds between battery readings
unsigned long lastcurreading = 0;
int curcurread = 0;
int cursum = 0;
float current = 0; // the average
float watts = 0;
bool lastebrakeon = false;
unsigned long lastebrakechange = 0;
bool ebrakeon = false;
bool lockbtnon = false;
bool lastcruiseon = false;
unsigned long lastcruisechange = 0;
bool cruiseon = false;
float cruisesetspeed = 0;
int motorvalue = 0;
int previousotherx1 = 0;
int previousothery1 = 0;
int previousotherx2 = 0;
int previousothery2 = 0;
bool stole = false;
float speedlimit = 0.00;
bool lastturnstat = false;
XPT2046_Touchscreen ts(TOUCH_CS);
DFRobot_ILI9341_240x320_HW_SPI screen(/*dc=*/TFT_DC,/*cs=*/TFT_CS,/*rst=*/TFT_RST);
DFRobot_GNSS_I2C gnss(&Wire,GNSS_DEVICE_ADDR);
DFRobot_BMI160 bmi160;
const int8_t i2c_addr = 0x69;
DFRobot_AHT20 aht20;
DFRobot_GR10_30 gr10_30(/*addr = */GR10_30_DEVICE_ADDR, /*pWire = */&Wire);
Adafruit_NeoPixel pixels(NUMPIXELS, LEDPIN, NEO_GRB + NEO_KHZ800);
//WiFiMulti wifiMulti;
//BMI160
struct dat{
float x = 0;
float y = 0;
float z = 0;
};
dat accel;
struct data{
float x = 0;
float y = 0;
float z = 0;
};
data gyro;
float baseyangle = 0;
void setup() {
pinMode(speedpin, OUTPUT);
pinMode(27, INPUT_PULLUP);
pinMode(cruisepin, OUTPUT);
digitalWrite(cruisepin, LOW);
if (voltconversion){
digitalWrite(speedpin, HIGH);
}
else {
digitalWrite(speedpin, LOW);
}
Serial.begin(115200);
pixels.begin();
pixels.clear();
pixels.show();
for (int i=0;i<4;i++){
pixels.setPixelColor(footlight[i], pixels.Color(255,255,0));
pixels.show();
}
screen.begin();
screen.setRotation(3);
//pinMode(rpmpin, INPUT);
EEPROM.begin(EEPROM_SIZE);
for (int i=0;i<passwordlength;i++){//read password from EEPROM
password[i] = EEPROM.read(i);
}
pinMode(batterypin, INPUT);
pinMode(throttlepin, INPUT);
pinMode(brakepin, OUTPUT);
//pinMode(rpmpin, INPUT);
//attachInterrupt(rpmpin, interruptRoutine, FALLING);
ledcSetup(speedChannel, freq, resolution);
ledcAttachPin(speedpin, speedChannel);
ledcWrite(speedChannel, 0);
if(!gnss.begin()){
Serial.println("NO GPS device !");
delay(1000);
}
gnss.enablePower();
gnss.setGnss(eGPS_BeiDou_GLONASS);
gnss.setRgbOn();
if (bmi160.softReset() != BMI160_OK){
Serial.println("bmi160 reset false");
//while(1);
}
if (bmi160.I2cInit(i2c_addr) != BMI160_OK){
Serial.println("bmi160 init false");
//while(1);
}
readAccelGyro();
baseyangle = gyro.y;
//baseyangle = 20;
uint8_t status;
if((status = aht20.begin()) != 0){
Serial.print("AHT20 sensor initialization failed. error status : ");
Serial.println(status);
delay(1000);
}
startGestureSensor();
ts.begin();
ts.setRotation(3);
startDisplay();
}
void loop() {
if ((millis() - lastreadgnss) > readgnssinc){
readGNSS();
lastreadgnss = millis();
}
if (!ledsoff){
handleLeds();
}
else {
pixels.clear();
pixels.show();
}
if (locked){
lockedloop();
if (satelites > 8){
if (knots > 2){
//ifttt_counter++;
}
}
return;
}
if (ts.touched()){
TS_Point p = ts.getPoint();
handleTouch(abs(map(p.x,touchxmax,touchxmin,0,320)),abs(map(p.y,touchymax,touchymin,0,240)));
}
readAccelGyro();
readGyro();
readTempHum();
readCurrent();
readBattery();
readThrottle();
if (!rightturnsignal && !leftturnsignal){
if (lastturnstat){
startDisplay();
lastturnstat = false;
}
if (((millis() - lastdisplay) > readdisplayinc) && (satelites != 0)){
handleSlowDisplay();
lastdisplay = millis();
}
handleFastDisplay();
handleDisplayButtons();
float handleAngleLineValue = (baseyangle*100) - (gyroy*100);
handleAngleLine(handleAngleLineValue);
}
else {
if (rightturnsignal){
screen.fillRoundRect(15,38,290,195,12,backgroundcolor);
screen.setTextSize(14);
screen.setCursor(100,75);
screen.setTextColor(COLOR_RGB565_RED);
screen.print(">");
}
else if (leftturnsignal){
screen.fillRoundRect(15,38,290,195,12,backgroundcolor);
screen.setTextSize(14);
screen.setCursor(100,75);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("<");
}
}
handleGestures();
handleMotordriver();
//handleSpeedLimit();
}
/*void onLockChange() {
if (lock == true){
screen.fillRoundRect(15,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(20,70);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("Locked");
screen.fillRoundRect(225,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,70);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("E ON");
ebrakeon = true;
locked = true;
}
if (lock == false){
ebrakeon = false;
locked = false;
}
}*/
/*void onMaxspeedChange() {
speedlimit = maxspeed;
}
void handleSpeedLimit(){
if (knots > speedlimit){
throttleval = throttleval/2;
}
}*/
void handleTouch(int x,int y){
Serial.print("Touch X = " + String(x));
Serial.println(" | Touch Y = " + String(y));
if (x >= 215 && x <= 320){
if (y < 45){
changepassword();
}
else if (y >= 45 && y <= 104){
if ((millis() - lastebrakechange) > 400){//wait 1 second between reading button as pressed
if (knots < 5){
ebrakeon = !ebrakeon;
lastebrakechange = millis();
}
}
}
else if (y >= 105 && y <= 160){
if ((millis() - lastcruisechange) > 400){//wait 1 second between reading button as pressed
cruiseon = !cruiseon;
cruisesetspeed = knots;
lastcruisechange = millis();
}
}
}
else if (x >= 5 && x <= 105){
if (y < 45){
changepassword();
}
else if (y >= 45 && y <= 105){
if (!lockbtnon){
lockbtnon = true;
}
else {
screen.setTextSize(2);
screen.setCursor(15,115);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("Unlock with gestures!");//display unlock warning
delay(3000);
screen.fillRect(14, 114, 290, 20, erasecolor);//erase display unlock warning
}
}
}
}
void handleSlowDisplay(){
//satelites
screen.setTextSize(2);
screen.setCursor(287,15);
screen.fillRect(286, 13, 26, 18, erasecolor);//backcolor
if (satelites <= 5){
screen.setTextColor(COLOR_RGB565_RED);
}
else if (satelites > 5 && satelites <= 8){
screen.setTextColor(COLOR_RGB565_ORANGE);
}
else if (satelites > 8){
screen.setTextColor(COLOR_RGB565_GREEN);
}
screen.print(String(satelites));
//Serial.println(satelites);
//speed (knots)
screen.setTextSize(4);
if (knots >= 10){
screen.setCursor(100,62);//118,62
screen.fillRect(92, 58, 132, 37, erasecolor);//117, 57, 90, 30,
}
else {
screen.setCursor(110,62);//118,62
screen.fillRect(100, 58, 105, 37, erasecolor);//117, 57, 90, 30,
}
if (knots <= 1.00){
screen.setTextColor(COLOR_RGB565_BLUE);
}
else if (knots > 1.00 && knots <= 12.00){
screen.setTextColor(COLOR_RGB565_GREEN);
}
else if (knots > 12.00 && knots <= 19.00){
screen.setTextColor(COLOR_RGB565_ORANGE);
}
else {
screen.setTextColor(COLOR_RGB565_RED);
}
screen.print(knots);
//if (knots >= cruisesetspeed+4.00){//reset cruise if current speed goes above cruisesetspeed + 4
// cruiseon = false;
//}
//temperature
screen.setTextSize(2);
screen.setCursor(12,215);
screen.fillRect(11,214,55,17,erasecolor);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print(temperature,1);//temperature with only one decimal
screen.drawCircle(64,209,2,COLOR_RGB565_GREEN);//degrees symbol
//humidity
screen.setTextSize(2);
screen.setCursor(270,215);
screen.fillRect(269,214,40,17,erasecolor);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print(humidity,0);//humidity with no decimals
screen.print("%");//percentage symbol
//battery
screen.setTextSize(2);
screen.setCursor(140,215);
screen.fillRect(139,214,65,17,erasecolor);
float batpercent = map(batteryvolts*10,300,420,0,100); //map battery voltage to a percentage value of 0 - 100
batpercent = constrain(batpercent,0,100);
if (batpercent > 80.0){
screen.setTextColor(COLOR_RGB565_GREEN);
}
else if (batpercent <= 80.0 && batpercent > 50.0){
screen.setTextColor(COLOR_RGB565_DGREEN);
}
else if (batpercent <= 50.0 && batpercent > 25.0){
screen.setTextColor(COLOR_RGB565_YELLOW);
}
else if (batpercent <= 25.0 && batpercent > 12.0){
screen.setTextColor(COLOR_RGB565_ORANGE);
}
else if (batpercent <= 12.0 && batpercent > 5.0){
screen.setTextColor(COLOR_RGB565_RED);
}
else {
screen.setTextColor(COLOR_RGB565_RED);
batterywarning();
}
screen.print(batpercent,0);//battery percentage with no decimals
screen.print("%");//percentage symbol
//dist to empty; for 36V 5AH (180W) that would be (at 20mph) 8 miles or 0.4 hours
float batwatts = 0;
#ifdef batterywattage
batwatts = batterywattage;
#else
batwatts = batteryvoltage * batteryamps;
#endif
float bathours = batwatts / motorwattage;
float batmiles = maxcruisespeed * bathours;
float batmilesleft = map(batteryvolts*10,300,420,0,batmiles*100);//map function cant map floating values
batmilesleft = batmilesleft / 100;
float bathoursleft = map(batteryvolts*10,300,420,0,bathours*100);//map function cant map floating values
bathoursleft = bathoursleft / 100;
float batminutesleft = map(bathoursleft*100,0,100,0,600);//map function cant map floating values
batminutesleft = batminutesleft / 10;
screen.setTextSize(3);
screen.setCursor(75,187);
screen.fillRect(74,186,198,24,erasecolor);
screen.setTextColor(COLOR_RGB565_BLUE);
screen.print(abs(batmilesleft),1);//miles with no decimals
screen.print("m|");//miles symbol
screen.print(abs(batminutesleft),1);//hours with two decimals
screen.print("m");
Serial.print("Battery: ");
Serial.println(batteryvolts);
Serial.print("Current: ");
Serial.println(current);
}
void handleFastDisplay(){
//Angle
screen.setTextSize(2);
screen.setCursor(140,95);
screen.fillRect(139,94,75,17,erasecolor);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print((baseyangle*100)-(gyroy*100),1);//angle with only one decimal
}
void handleDisplayButtons(){
//e-brake button
if (ebrakeon != lastebrakeon){
if (!ebrakeon){
screen.fillRoundRect(220,45,90,60,12,erasecolor);//erase
screen.drawRoundRect(225,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,70);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("E OFF");
}
else {
screen.fillRoundRect(225,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,70);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("E ON");
}
lastebrakeon = ebrakeon;
}
if (!lockbtnon){
screen.fillRoundRect(12,45,90,60,12,erasecolor);//erase
screen.drawRoundRect(15,50,80,50,12,backgroundcolor);
screen.setTextSize(1);
screen.setCursor(25,70);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("Unlocked");
}
else if (lockbtnon || locked){
screen.fillRoundRect(15,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(20,70);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("Locked");
ebrakeon = true;
locked = true;
}
if (cruiseon != lastcruiseon){
if (!cruiseon){
screen.fillRoundRect(220,105,90,60,12,erasecolor);//erase
screen.drawRoundRect(225,110,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,130);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("C OFF");
}
else {
screen.fillRoundRect(225,110,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,130);
screen.setTextColor(COLOR_RGB565_ORANGE);
screen.print("C ON");
}
lastcruiseon = cruiseon;
}
}
void handleAngleLine(float angle1){
int x=160,y=140; //center point of the two lines
screen.drawLine(x, y, previousotherx1, previousothery1, erasecolor);//line going right
screen.drawLine(x+1, y+1, previousotherx1+1, previousothery1+1, erasecolor);//double thick line
screen.drawLine(x, y, previousotherx2, previousothery2, erasecolor);//line going left
screen.drawLine(x+1, y+1, previousotherx2+1, previousothery2+1, erasecolor);//double thick line
#define DEG2RAD 0.0174532925
float screenangle1 = 135; //value for right line to make it level
float screenangle2 = 315; //value for left line to make it level; appears to be one line instead of two separate ones
float angle2 = angle1;
int w=100,h=100; //length of each line; one going right and one going left
#define linecolor COLOR_RGB565_NAVY
float cosa1 = cos((screenangle1+angle1) * DEG2RAD), sina1 = sin((screenangle1+angle1) * DEG2RAD);
int otherx1 = x - ((w * cosa1 / 2) - (h * sina1 / 2));
int othery1 = y - ((h * cosa1 / 2) + (w * sina1 / 2));
screen.drawLine(x, y, otherx1, othery1, linecolor);//line going right
screen.drawLine(x+1, y+1, otherx1+1, othery1+1, linecolor);//double thick line
float cosa2 = cos((screenangle2+angle2) * DEG2RAD), sina2 = sin((screenangle2+angle2) * DEG2RAD);
int otherx2 = x - ((w * cosa2 / 2) - (h * sina2 / 2));
int othery2 = y - ((h * cosa2 / 2) + (w * sina2 / 2));
screen.drawLine(x, y, otherx2, othery2, linecolor);//line going left
screen.drawLine(x+1, y+1, otherx2+1, othery2+1, linecolor);//double thick line
previousotherx1 = otherx1;
previousothery1 = othery1;
previousotherx2 = otherx2;
previousothery2 = othery2;
}
void batterywarning(){
}
void changepassword(){
screen.fillScreen(backcolor);
screen.fillScreen(COLOR_RGB565_DGRAY);
screen.fillRoundRect(0, 0, 320, 240, 15, backgroundcolor);
screen.fillRoundRect(5, 5, 310, 230, 15, backcolor);
screen.setTextColor(backgroundcolor);
screen.setTextSize(3);
screen.setCursor(30, 11);
screen.print("Change PASS");
screen.drawFastHLine(10, 35, 300, COLOR_RGB565_GREEN);
screen.drawFastHLine(10, 36, 300, COLOR_RGB565_GREEN);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.setTextSize(1);
screen.setCursor(40, 100);
screen.print("Do three gestures to set new password...");
password[0] = 0;
password[1] = 0;
password[2] = 0;
int gesturepasscount = 0;
redo:
if(gr10_30.getDataReady()){
gestures = gr10_30.getGesturesState();
if(gestures&GESTURE_UP){
Serial.println("Up");
password[gesturepasscount] = GESTURE_UP;
}
if(gestures&GESTURE_DOWN){
Serial.println("Down");
password[gesturepasscount] = GESTURE_DOWN;
}
if(gestures&GESTURE_LEFT){
Serial.println("Left");
password[gesturepasscount] = GESTURE_LEFT;
}
if(gestures&GESTURE_RIGHT){
Serial.println("Right");
password[gesturepasscount] = GESTURE_RIGHT;
}
if(gestures&GESTURE_FORWARD){
password[gesturepasscount] = GESTURE_FORWARD;
}
if(gestures&GESTURE_BACKWARD){
password[gesturepasscount] = GESTURE_BACKWARD;
}
if(gestures&GESTURE_CLOCKWISE){
password[gesturepasscount] = GESTURE_CLOCKWISE;
}
if(gestures&GESTURE_COUNTERCLOCKWISE){
password[gesturepasscount] = GESTURE_COUNTERCLOCKWISE;
}
if(gestures&GESTURE_WAVE){
password[gesturepasscount] = GESTURE_WAVE;
}
if(gestures&GESTURE_HOVER){
password[gesturepasscount] = GESTURE_HOVER;
}
if(gestures&GESTURE_CLOCKWISE_C){
password[gesturepasscount] = GESTURE_CLOCKWISE_C;
}
if(gestures&GESTURE_COUNTERCLOCKWISE_C){
password[gesturepasscount] = GESTURE_COUNTERCLOCKWISE_C;
}
EEPROM.write(gesturepasscount,password[gesturepasscount]);
EEPROM.commit();
gesturepasscount++;
Serial.println("gesturepasscount: " + String(gesturepasscount));
}
if (gesturepasscount != passwordlength){
goto redo;
}
Serial.println("Finished!");
gesturepasscount = 0;
startDisplay();
}
void readThrottle(){
throttleval = map(analogRead(throttlepin),throttleoffvalue,throttleonvalue,0,4095);
//Serial.print("Throttle: ");
//Serial.println(throttleval);
//Serial.println("Throttle: " + String(throttleval));
}
void readBattery(){
if ((millis() - lastbatreading) > readbatteryint){
if (curbatread < batteryreadings){
batsum = batsum + analogRead(batterypin);
curbatread++;
}
else{
float batteryread = batsum/batteryreadings;
float batpinvolt = (batteryread*3.3)/4095;//3.3V and 4095 is the max resolution of ESP32
if (testing){
batpinvolt = 2.2;
}
batteryvolts = batpinvolt*16.55;//(1000/(15000+1000)); //(R2/(R1+R2));//VOUT = VIN*R2/R1+R2 ; classic equation for voltage dividers
curbatread = 0;
batsum = 0;
}
lastbatreading = millis();
}
}
void readGyro(){
/*for (curgyroread=0;curgyroread<gyroreadings;curgyroread++){
gyrosum = gyrosum + gyro.y;
delay(readgyroint);
}
gyroy = gyrosum/gyroreadings;
curgyroread = 0;
gyrosum = 0;*/
if ((millis() - lastgyroreading) > readgyroint){
if (curgyroread < gyroreadings){
gyrosum = gyrosum + gyro.y;
curgyroread++;
}
else{
gyroy = gyrosum/gyroreadings;
curgyroread = 0;
gyrosum = 0;
}
lastgyroreading = millis();
}
}
void handleGestures(){
if(gr10_30.getDataReady()){
gestures = gr10_30.getGesturesState();
if(gestures&GESTURE_UP){
Serial.println("Up");
cruiseon = true;
}
if(gestures&GESTURE_DOWN){
Serial.println("Down");
//if (cruiseon){
// ledsoff = !ledsoff;
//}
cruiseon = false;
}
if(gestures&GESTURE_LEFT){
Serial.println("Left");
if (rightturnsignal){
rightturnsignal = false;
pixels.clear();
pixels.show();
}
else {
leftturnsignal = true;
lastturnstat = true;
}
}
if(gestures&GESTURE_RIGHT){
Serial.println("Right");
if (leftturnsignal){
leftturnsignal = false;
pixels.clear();
pixels.show();
}
else {
rightturnsignal = true;
lastturnstat = true;
}
}
if(gestures&GESTURE_FORWARD){
Serial.println("Forward");
ebrakeon = true;
}
if(gestures&GESTURE_BACKWARD){
Serial.println("Backward");
ebrakeon = false;
}
if(gestures&GESTURE_CLOCKWISE){
Serial.println("Clockwise");
}
if(gestures&GESTURE_COUNTERCLOCKWISE){
Serial.println("Contrarotate");
}
if(gestures&GESTURE_WAVE){
Serial.println("Wave");
}
if(gestures&GESTURE_HOVER){
Serial.println("Hover");
}
if(gestures&GESTURE_CLOCKWISE_C){
Serial.println("Continuous clockwise");
headlight = !headlight;
}
if(gestures&GESTURE_COUNTERCLOCKWISE_C){
Serial.println("Continuous counterclockwise");
screen.fillRoundRect(15,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(20,70);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("Locked");
screen.fillRoundRect(225,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,70);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("E ON");
ebrakeon = true;
locked = true;
}
}
}
void lockedloop(){
if(gr10_30.getDataReady()){
gestures = gr10_30.getGesturesState();
Serial.print("Gesture: ");
Serial.println(gestures);
if (gestures&password[passc]){
Serial.println("Correct!");
Serial.println(password[passc]);
passc++;
Serial.println("PASSC: " + String(passc));
}
else {
Serial.println("Wrong");
passc=0;
}
}
if (passc >= passwordlength){
Serial.println("Unlocked!");
passc=0;
locked = false;
//lock = false;
}
}
void readGNSS(){
utc = gnss.getUTC();
date = gnss.getDate();
latitude = gnss.getLat();
longitude = gnss.getLon();
altitude = gnss.getAlt();
satelites = gnss.getNumSatUsed();
knots = gnss.getSog();
course = gnss.getCog();
}
void readAccelGyro(){
int i = 0;
int rslt;
int16_t accelGyro[6]={0};
//get both accel and gyro data from bmi160
//parameter accelGyro is the pointer to store the data
rslt = bmi160.getAccelGyroData(accelGyro);
if(rslt == 0){
for(i=0;i<6;i++){
if (i<3){
//the first three are gyro data
//Serial.print(accelGyro[i]*3.14/180.0);Serial.print("\t");
if (i==0){accel.x = accelGyro[i]*3.14/180.0;}
else if (i==1){accel.y = accelGyro[i]*3.14/180.0;}
else if (i==2){accel.z = accelGyro[i]*3.14/180.0;}
}else{
//the following three data are accel data
//Serial.print(accelGyro[i]/16384.0);Serial.print("\t");
if (i==3){gyro.x = accelGyro[i]/16384.0;}
else if (i==4){gyro.y = accelGyro[i]/16384.0;}
else if (i==5){gyro.z = accelGyro[i]/16384.0;}
}
}
//Serial.println();
}else{
Serial.println("err");
}
}
void readTempHum(){
if(aht20.startMeasurementReady(/* crcEn = */true)){
temperature = aht20.getTemperature_F();
humidity = aht20.getHumidity_RH();
}
HI = 0.5 * (temperature + 61.0 + ((temperature-68.0)*1.2) + (humidity*0.094));
if (HI > 80.0){
HI = -42.379 + 2.04901523*temperature + 10.14333127*humidity - .22475541*temperature*humidity - .00683783*temperature*temperature - .05481717*humidity*humidity + .00122874*temperature*temperature*humidity + .00085282*temperature*humidity*humidity - .00000199*temperature*temperature*humidity*humidity;
if ((temperature > 80.0 && temperature < 112.0) && (humidity < 13.0)){
HI = ((13-humidity)/4)*sqrt((17-abs(temperature-95.0))/17);
}
else if ((temperature > 80.0 && temperature < 87.0) && (humidity > 85.0)){
HI = ((humidity-85)/10) * ((87-temperature)/5);
}
}
temperature = HI;
}
void readCurrent(){
if ((millis() - lastcurreading) > readcurrentint){
if (curcurread < currentreadings){
cursum = cursum + analogRead(currentpin);
curcurread++;
}
else{
float currentread = cursum/currentreadings;
float curpinvolt = (currentread*3.3)/4095;//3.3V and 4095 is the max resolution of ESP32
current = (curpinvolt-1.65)/0.04;
current = constrain(current,0,50);
watts = current*batteryvolts;
watts = constrain(watts,0,500);
curcurread = 0;
cursum = 0;
}
lastcurreading = millis();
}
//Data processing:510-raw data from analogRead when the input is 0;
// 5-5v; the first 0.04-0.04V/A(sensitivity); the second 0.04-offset val;
}
void handleMotordriver(){
//digitalWrite(cruisepin,cruiseon);
digitalWrite(brakepin,ebrakeon);
if (voltconversion){
motorvalue = map(throttleval,3500,0,0,255);
motorvalue = constrain(motorvalue,0,255);
}
else{
motorvalue = map(throttleval,300,4000,0,255);
motorvalue = constrain(motorvalue,0,255);
}
motorvalue = map(motorvalue,255,0,0,255);
if (motorvalue > 245){
digitalWrite(cruisepin, HIGH);
}
else {
digitalWrite(cruisepin, LOW);
}
if (motorvalue >= 200 && motorvalue <= 245){
if (abs(motorvalue - lastthrottleval) <= 5){
motorvalue = lastthrottleval;
}
else {
lastthrottleval = motorvalue;
}
}
else if (motorvalue < 200 && motorvalue > 110){
if (abs(motorvalue - lastthrottleval) <= 15){
motorvalue = lastthrottleval;
}
else {
lastthrottleval = motorvalue;
}
}
else if (motorvalue <= 110 && motorvalue > 5){
motorvalue = map(motorvalue,5,120,32,87);
}
if (motorvalue >= 250){motorvalue = 255;} else if (motorvalue <= 5){motorvalue = 0;}
if ((lastthrottleval - motorvalue) <= -7){
motorvalue = lastthrottleval - 8;
lastthrottleval = motorvalue;
}
motorvalue = abs(motorvalue);
motorvalue = constrain(motorvalue,0,255);
if (throttleval == 0){
motorvalue = 0;
}
Serial.print("Motor val: ");
Serial.print(motorvalue); Serial.print(" | ");
//motorvalue = map(motorvalue,0,255,255,0);
ledcWrite(speedChannel, motorvalue);//pwm signal for speed
}
void handleLeds(){
if ((millis() - lastcoursereadtime) > coursechangetime){//handle turning signal
coursechange = course - lastcoursereading;
lastcoursereading = course;
lastcoursereadtime = millis();
}
if (leftturnsignal == true || rightturnsignal == true){
if (leftturnsignal){
//brakelight(3);
leftblinker();
}
if (rightturnsignal){
//brakelight(3);
rightblinker();
}
}
else if (leftturnsignal == false && rightturnsignal == false){
if (abs(coursechange) > courseturnsignalinc){
if (coursechange < 0){
//brakelight(3);
leftblinker();
}
else {
//brakelight(3);
rightblinker();
}
}
else {
if (speeddiferrence >= speedbrakeinc){
//pixels.clear();
//pixels.show();
brakelight(2);
}
}
}
if ((millis() - lastspeedreadtime) > speedchangetime){//handle brake light
speeddiferrence = knots - lastspeedreading;
if (speeddiferrence < speedbrakeinc){
if (rightturnsignal){
pixels.setPixelColor(5, pixels.Color(255,0,0));
pixels.setPixelColor(6, pixels.Color(255,0,0));
pixels.show();
}
else if (leftturnsignal){
pixels.setPixelColor(9, pixels.Color(255,0,0));
pixels.setPixelColor(8, pixels.Color(255,0,0));
pixels.show();
}
else {
brakelight(1);
}
}
//else {
// brakelight(1);
//}
lastspeedreading = knots;
lastspeedreadtime = millis();
}
if (headlight){
headlights(true);
}
else {
headlights(false);
}
handleFootlight();
}
void leftblinker(){
int turningsignalcolor = pixels.Color(0, 20, 255);
if (animationcountleft == 1){
if ((millis() - startmillis) < 250){
pixels.setPixelColor(7, turningsignalcolor);
pixels.show();
}
else {
animationcountleft++;
startmillis = millis();
}
}
else if (animationcountleft == 2){
if ((millis() - startmillis) < 250){
pixels.setPixelColor(7, pixels.Color(0, 0, 0));
pixels.setPixelColor(6, turningsignalcolor);
pixels.show();
}
else {
animationcountleft++;
startmillis = millis();
}
}
if (animationcountleft == 3){
if ((millis() - startmillis) < 750){
pixels.setPixelColor(6, pixels.Color(0, 0, 0));
pixels.setPixelColor(5, turningsignalcolor);
pixels.show();
}
else {
animationcountleft++;
startmillis = millis();
}
}
if (animationcountleft == 4){
if ((millis() - startmillis) < 400){
pixels.setPixelColor(5, pixels.Color(0, 0, 0));
pixels.show();
}
else {
animationcountleft = 1;
startmillis = millis();
}
}
}
void rightblinker(){
int turningsignalcolor = pixels.Color(0, 20, 255);
if (animationcountright == 1){
if ((millis() - startmillis) < 250){
pixels.setPixelColor(7, turningsignalcolor);
pixels.show();
}
else {
animationcountright++;
startmillis = millis();
}
}
else if (animationcountright == 2){
if ((millis() - startmillis) < 250){
pixels.setPixelColor(7, pixels.Color(0, 0, 0));
pixels.setPixelColor(8, turningsignalcolor);
pixels.show();
}
else {
animationcountright++;
startmillis = millis();
}
}
if (animationcountright == 3){
if ((millis() - startmillis) < 750){
pixels.setPixelColor(8, pixels.Color(0, 0, 0));
pixels.setPixelColor(9, turningsignalcolor);
pixels.show();
}
else {
animationcountright++;
startmillis = millis();
}
}
if (animationcountright == 4){
if ((millis() - startmillis) < 400){
pixels.setPixelColor(9, pixels.Color(0, 0, 0));
pixels.show();
}
else {
animationcountright = 1;
startmillis = millis();
}
}
}
void brakelight(int brakelighton){
if (brakelighton == 1){
for (int i=0;i<5;i++){
pixels.setPixelColor(brake[i], pixels.Color(255, 0, 0));//on brake light
}
pixels.show();
}
else if (brakelighton == 2){
for (int i=0;i<5;i++){
pixels.setPixelColor(brake[i], pixels.Color(60, 0, 0));//on brake light
}
pixels.show();
}
else {
for (int i=0;i<5;i++){
pixels.setPixelColor(brake[i], pixels.Color(0, 0, 0));//on brake light
}
pixels.show();
}
}
void headlights(bool on){
if (on){
pixels.setPixelColor(0, pixels.Color(255, 255, 255));//brake light on
pixels.setPixelColor(1, pixels.Color(255, 255, 255));//brake light on
pixels.setPixelColor(2, pixels.Color(255, 255, 255));//brake light on
pixels.setPixelColor(3, pixels.Color(255, 255, 255));//brake light on
pixels.setPixelColor(4, pixels.Color(255, 255, 255));//brake light on
pixels.show();
}
else {
pixels.setPixelColor(0, pixels.Color(0, 0, 0));//dim brake light
pixels.setPixelColor(1, pixels.Color(0, 0, 0));//dim brake light
pixels.setPixelColor(2, pixels.Color(0, 255, 0));//dim brake light
pixels.setPixelColor(3, pixels.Color(0, 0, 0));//dim brake light
pixels.setPixelColor(4, pixels.Color(0, 0, 0));//dim brake light
pixels.show();
}
}
void handleFootlight(){
if (locked){
if (panimationcount > 235 && pup){
pup = false;
}
else if (panimationcount < 0 && !pup){
pup = true;
}
if (pup){
panimationcount+=8;
}
else {
panimationcount-=8;
}
for (int i=0;i<4;i++){
pixels.setPixelColor(footlight[i], pixels.Color(panimationcount,0,0));
pixels.show();
}
//delayMicroseconds(1);
}
else if (knots < 1){
if (panimationcount > 235 && pup){
pup = false;
}
else if (panimationcount < 25 && !pup){
pup = true;
}
if (pup){
panimationcount+=8;
}
else {
panimationcount-=8;
}
for (int i=0;i<4;i++){
pixels.setPixelColor(footlight[i], pixels.Color(0,panimationcount,0));
pixels.show();
}
//delayMicroseconds(1);
}
else {
for (int i=0;i<4;i++){
pixels.setPixelColor(footlight[i], pixels.Color(0,20,255));
pixels.show();
}
}
}
void startDisplay(){
screen.fillScreen(backcolor);
screen.setTextWrap(false);
screen.fillScreen(COLOR_RGB565_DGRAY);
screen.fillRoundRect(0, 0, 320, 240, 15, backgroundcolor);
screen.fillRoundRect(5, 5, 310, 230, 15, backcolor);
//title
screen.setTextColor(backgroundcolor);
screen.setTextSize(3);
screen.setCursor(30, 11);
screen.print("DIY E-Scooter");
screen.drawFastHLine(10, 35, 300, COLOR_RGB565_GREEN);
screen.drawFastHLine(10, 36, 300, COLOR_RGB565_GREEN);
//speed label
screen.setTextColor(COLOR_RGB565_YELLOW);
screen.setTextSize(2);
screen.setCursor(125,40);
screen.print("Speed");
//dist and time to empty labels
screen.setTextColor(COLOR_RGB565_YELLOW);
screen.setTextSize(2);
screen.setCursor(91,170);
screen.print("Dist Time");
//boost button
screen.drawRoundRect(225,50,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,70);
screen.setTextColor(COLOR_RGB565_RED);
screen.print("E OFF");
//lock button
screen.drawRoundRect(15,50,80,50,12,backgroundcolor);
screen.setTextSize(1);
screen.setCursor(25,70);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("Unlocked");
//cruise button
screen.drawRoundRect(225,110,80,50,12,backgroundcolor);
screen.setTextSize(2);
screen.setCursor(235,130);
screen.setTextColor(COLOR_RGB565_GREEN);
screen.print("C OFF");
}
void startGestureSensor(){
if(gr10_30.begin() != 0){
Serial.println(" Sensor initialize failed!!");
delay(1000);
}
/** Set the gesture to be enabled
* GESTURE_UP
* GESTURE_DOWN
* GESTURE_LEFT
* GESTURE_RIGHT
* GESTURE_FORWARD
* GESTURE_BACKWARD
* GESTURE_CLOCKWISE
* GESTURE_COUNTERCLOCKWISE
* GESTURE_WAVE It is not suggested to enable rotation gesture (CW/CCW) and wave gesture at the same time.
* GESTURE_HOVER Disable other gestures when hover gesture enables.
* GESTURE_UNKNOWN
* GESTURE_CLOCKWISE_C
* GESTURE_COUNTERCLOCKWISE_C
*/
gr10_30.enGestures(GESTURE_UP|GESTURE_DOWN|GESTURE_LEFT|GESTURE_RIGHT|GESTURE_FORWARD|GESTURE_BACKWARD|GESTURE_CLOCKWISE|GESTURE_COUNTERCLOCKWISE|GESTURE_CLOCKWISE_C|GESTURE_COUNTERCLOCKWISE_C);
/**
* Set the detection window you want, only data collected in the range are valid
* The largest window is 31, the configured number represents distance from the center to the top, bottom, left and right
* For example, if the configured distance from top to bottom is 30, then the distance from center to top is 15, and distance from center to bottom is also 15
* udSize Range of distance from top to bottom 0-31
* lrSize Range of distance from left to right 0-31
*/
gr10_30.setUdlrWin(30, 30);//0-31,0-31
/**
* Set moving distance that can be recognized as a gesture
* Distance range 5-25, must be less than distances of the detection window
*/
gr10_30.setLeftRange(10);
gr10_30.setRightRange(10);
gr10_30.setUpRange(10);
gr10_30.setDownRange(10);
//gr10_30.setForwardRange(10);
//gr10_30.setBackwardRange(10);
/**
* Set distance of moving forward and backward that can be recognized as a gesture
* Distance range 1-15
*/
gr10_30.setForwardRange(10);
gr10_30.setBackwardRange(10);
/**
* Set rotation angle that can trigger the gesture
* count Default is 16 range 0-31
* count Rotation angle is 22.5 * count
* count = 16 22.5*count = 360 Rotate 360° to trigger the gesture
*/
gr10_30.setCwsAngle(/*count*/16);
gr10_30.setCcwAngle(/*count*/16);
/**
* Set degrees of continuous rotation that can trigger the gesture
* count Default is 4 range 0-31
* count The degrees of continuous rotation is 22.5 * count
* For example: count = 4 22.5*count = 90
* Trigger the clockwise/counterclockwise rotation gesture first, if keep rotating, then the continuous rotation gesture will be triggered once every 90 degrees
*/
gr10_30.setCwsAngleCount(/*count*/8);
gr10_30.setCcwAngleCount(/*count*/8);
}
/*void interruptRoutine(){
Serial.println("Interrupt...");
}*/
Settings.h:
//Arduino Cloud
const char DEVICE_LOGIN_NAME[] = "*********************************";
const char DEVICE_KEY[] = "***************"; // Secret device password
//WiFi networks
const char SSID1[] = "****************";
const char PASS1[] = "********";
const char SSID2[] = "";
const char PASS2[] = "";
const char SSID3[] = "";
const char PASS3[] = "";
//Motor Driver
#define brakepin 16 //D11
#define cruisepin A4 // actually enable pin, so able to push scooter manually when on
#define speedpin A3
//#define rpmpin A4
//Display
#define TFT_DC 25 //D2
#define TFT_RST 26 //D3
#define TFT_CS 14 //D6
#define TOUCH_CS 4 //D12
#define TFT_BL 12 //D13
//Throttle
#define throttlepin A0 //throttle pin
//LEDs
#define LEDPIN 17//D10
//battery
#define batterypin A2
//current sensor
#define currentpin A1
//Password
int password[] = {GESTURE_UP,GESTURE_DOWN,GESTURE_LEFT};//Adjustable gesture password; can adjust password length (right now it is set to 3 in the "passwordlength" integer)
I would really appreciate some tips!
Thanks in advance!