Files
Bachelorarbeit-Rover/src/main.cpp
T
2023-02-21 11:49:25 +01:00

356 lines
11 KiB
C++

/**
* @file main.cpp
* @author Alexander Klein (alex@kleiax.de)
* @brief The main file.
*
* Sets up Network stuff, PS3-Controller, Menu and Lcd
* Handles Controller Input
*
* @version 0.1
* @date 2022-02-15
*
* @copyright Copyright (c) 2022
*
*/
#include <Arduino.h>
#include "config.h"
#include <Ps3Controller.h>
#include <iostream>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP32Ping.h>
#include <BluetoothSerial.h>
#include <esp_bt_main.h>
#include "driveModi/driveManager.h"
#include "OutputBuf/outputBuf.h"
#include "LcdWrapper.h"
#include "moveControl.h"
#include "network.h"
#include "debugMqtt.h"
#include "battery.h"
#include "debugTimes.h"
#include "menu.h"
#include "menuAction.h"
#include "SpecialMenus/driveModi/ManualDrive/menuManualDrive.h"
#include "SpecialMenus/driveModi/CaptureRoute/menuCaptureRoute.h"
#include "SpecialMenus/driveModi/Autopilot/menuAutopilot.h"
#include "SpecialMenus/driveModi/TestMode/menuTestMode.h"
#include "SpecialMenus/Systeminformation/menuSysteminformation.h"
#include "SpecialMenus/PID/menuPidSettings.h"
#include "SpecialMenus/Route/menuRoute.h"
#include "SpecialMenus/GPS/menuGPS.h"
MoveControl moveController;
DriveManager* driveManager;
Menu* main_m;
LiquidCrystal_I2C* lcd;
LcdWrapper* lcdWrapper;
OutputBuf* outputBuf;
DebugMqtt* debugMqtt = nullptr;
Battery* mainBattery;
Ps3Controller* gamepad;
BluetoothSerial SerialBT;
bool wifiIsActive;
bool disconnectPs3 = false;
void configureController(void);
void callbackControllerAction(void);
void callbackControllerConnect(void);
void callbackControllerDisconnect(void);
void i2cScanner(void);
void makeMenu(void);
void restart(void);
void disconnectController(void);
void setup() {
Serial.begin(115200);
// DebugTimes::setConsolOutput(true);
DebugTimes setupTime;
char wifiIndicator = 'X';
mainBattery = new Battery(35, 692000, 218500);
Wire.begin(21, 19);
Wire.setClock(400000);
i2cScanner();
lcd = new LiquidCrystal_I2C(0x3F,16,2);
lcd->init();
lcd->clear();
lcd->noBacklight();
Network::setIps();
Network::setupMQTT();
wifiIsActive = Network::connectWifi();
if (wifiIsActive) {
// const char* remoteHost = "www.google.com";
// std::cout << "Pinging host: " << remoteHost << std::endl;
// if (Ping.ping(remoteHost))
// std::cout << "Ping successful..." << std::endl;
// else
// std::cout << "Ping failed. :/" << std::endl;
if (Network::checkMQTT()) {
DebugMqtt::init(Network::getMqttClient(), Loglevel::debug);
std::cout << "Activate additional output via MQTT..." << std::endl;
debugMqtt = new DebugMqtt("Console");
outputBuf = new OutputBuf(debugMqtt);
} else
outputBuf = new OutputBuf();
wifiIndicator = '-';
} else {
outputBuf = new OutputBuf();
}
std::cout.rdbuf(outputBuf);
std::cout << "Welcome to Kleiax-Rover" << std::endl;
std::cout << "All actions from the main program run on Core -> " << xPortGetCoreID() << std::endl;
gamepad = new Ps3Controller;
driveManager = new DriveManager(&moveController, gamepad, wifiIsActive);
configureController();
outputBuf->activateMqtt(false);
lcd->backlight();
lcd->printf("%c Kleiax-Rover %c", wifiIndicator, wifiIndicator);
lcd->setCursor(0, 1);
lcd->print("Press PS-Button");
lcdWrapper = new LcdWrapper(lcd);
makeMenu();
setupTime.stopConsol("Setup");
}
void loop() {
if (wifiIsActive) {
DebugTimes wifiTime;
Network::checkWiFi();
Network::checkMQTT();
wifiTime.stopConsol("WiFi-Time", 10);
}
driveManager->loop();
lcdWrapper->loop();
mainBattery->loop();
if (mainBattery->isBatteryLow(10)) {
moveController.setDrivingStatus(DrivingStatus::stop);
moveController.setSpeed(0);
moveController.setRotationSpeed(0);
uint16_t voltage = (uint16_t) (mainBattery->getBatteryVoltage() * 100);
lcd->setCursor(0, 0);
lcd->printf("Low Battery: %u", voltage);
lcd->setCursor(0, 1);
lcd->print("Please turn off.");
while (true);
}
if (disconnectPs3) {
DebugTimes disconnectPS3Time;
std::cout << "Disconnect PS3 Controller." << std::endl;
gamepad->end();
esp_bluedroid_disable();
esp_bluedroid_deinit();
configureController();
disconnectPs3 = false;
disconnectPS3Time.stopConsol("Ps3 Disconnect");
}
}
void configureController() {
gamepad->attach(callbackControllerAction);
gamepad->attachOnConnect(callbackControllerConnect);
gamepad->attachOnDisconnect(callbackControllerDisconnect);
std::cout << "\nReady to connect a PS3 Controller... \n";
gamepad->begin(CONTROLLER_MAC);
}
void callbackControllerAction() {
auto isDelayReached = [](bool reset = false) -> bool {
static uint32_t lastMillis = 0;
if (reset)
lastMillis = millis();
static const uint16_t delay = 100;
bool res = false;
if (millis() - lastMillis > delay)
res = true;
return res;
};
// Menu controlling
if (isDelayReached()) {
if (gamepad->data.button.up)
main_m->up();
else if (gamepad->data.button.down)
main_m->down();
else if (gamepad->data.button.left)
main_m->left();
else if (gamepad->data.button.right)
main_m->right();
else if (gamepad->data.button.circle)
main_m->yes();
else if (gamepad->data.button.cross)
main_m->no();
else if (gamepad->data.button.select)
std::cout << "main.cpp callbackControllerAction - Here we are!" << std::endl;
isDelayReached(true);
}
// This have to be stand here because it have to be run on the other Core
main_m->update();
}
void callbackControllerConnect() {
std::cout << "Controller connected to ESP32" << std::endl;
std::cout << "All actions from the Controller run on Core -> " << xPortGetCoreID() << std::endl;
main_m->printMenu();
}
void callbackControllerDisconnect() {
std::cout << "Controller disconnected..." << std::endl;
// gamepad->end();
}
void i2cScanner() {
std::cout << "\nI2C Scanner" << std::endl;
byte error, address;
int nDevices;
std::cout << "Scanning..." << std::endl;
nDevices = 0;
for(address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
error = Wire.endTransmission();
if (error == 0) {
std::cout << "I2C device found at address 0x";
if (address<16)
std::cout << "0";
std::cout << std::hex << (int) address << std::dec << std::endl;
// std::cout << (int) address << std::endl;
nDevices++;
}
else if (error==4) {
std::cout << "Unknow error at address 0x";
if (address<16)
std::cout << "0";
std::cout << std::hex << (int) address << std::dec << std::endl;
}
}
if (nDevices == 0)
std::cout << "No I2C devices found\n" << std::endl;
else
std::cout << "done\n" << std::endl;
}
void makeMenu() {
auto dummy = []() {
std::cout << "Dummy in Action" <<std::endl;
};
// Create Menu
main_m = new Menu();
Menu* mode_m = new Menu();
Menu* pid_m = new Menu();
MenuIntInput* pidl_m = new MenuIntInput(3, new MenuPidSettings(moveController.getPID(0)));
MenuIntInput* pidr_m = new MenuIntInput(3, new MenuPidSettings(moveController.getPID(1)));
MenuManualControl* man_m = new MenuManualControl(driveManager);
MenuCaptureRoute* cap_m = new MenuCaptureRoute(driveManager);
MenuAutopilot* auto_m = new MenuAutopilot(driveManager);
MenuTestMode* testM_m = new MenuTestMode(driveManager);
MenuGPS* gps_m = new MenuGPS(driveManager);
MenuSysteminformation* sys_m = new MenuSysteminformation(mainBattery, gamepad);
MenuRoute* rout_m = new MenuRoute(driveManager->getNavigation()->getRoute());
// Set Menus on LCD
main_m->setLcd(lcdWrapper);
mode_m->setLcd(lcdWrapper);
pid_m->setLcd(lcdWrapper);
pidl_m->setLcd(lcdWrapper);
pidr_m->setLcd(lcdWrapper);
man_m->setLcd(lcdWrapper);
cap_m->setLcd(lcdWrapper);
auto_m->setLcd(lcdWrapper);
testM_m->setLcd(lcdWrapper);
gps_m->setLcd(lcdWrapper);
sys_m->setLcd(lcdWrapper);
rout_m->setLcd(lcdWrapper);
// Entry for the main menu
MenuAction* mode_e = new MenuAction("Mode", mode_m);
MenuAction* gps_e = new MenuAction("GPS", gps_m);
MenuAction* pid_e = new MenuAction("PID", pid_m);
MenuAction* restart_e = new MenuAction("Restart", restart);
MenuAction* contr_e = new MenuAction("Remove PS3", disconnectController);
MenuAction* sys_e = new MenuAction("Systeminfo", sys_m);
MenuAction* rout_e = new MenuAction("Route", rout_m);
main_m->addEntry(mode_e);
main_m->addEntry(gps_e);
main_m->addEntry(rout_e);
main_m->addEntry(pid_e);
main_m->addEntry(sys_e);
main_m->addEntry(contr_e);
main_m->addEntry(restart_e);
// Entry for the mode Menu
MenuAction* autopilot_e = new MenuAction("Autopilot", auto_m);
MenuAction* captureRoute_e = new MenuAction("Capture Route", cap_m);
MenuAction* consolControl_e = new MenuAction("Consol Control", dummy);
MenuAction* manualControl_e = new MenuAction("Manual Control", man_m);
MenuAction* testMode_e = new MenuAction("Test Mode", testM_m);
mode_m->addEntry(autopilot_e);
mode_m->addEntry(captureRoute_e);
mode_m->addEntry(manualControl_e);
mode_m->addEntry(consolControl_e);
mode_m->addEntry(testMode_e);
// Entry for the PID Menu
MenuAction* pidl_e = new MenuAction("Left", pidl_m);
MenuAction* pidr_e = new MenuAction("Right", pidr_m);
pid_m->addEntry(pidl_e);
pid_m->addEntry(pidr_e);
// Other config
pidl_m->setMinMax(0, UINT8_MAX);
pidl_m->setEntry(0, "P-Part", (uint8_t) moveController.getPID(0)->GetKp());
pidl_m->setEntry(1, "I-Part", (uint8_t) moveController.getPID(0)->GetKi());
pidl_m->setEntry(2, "D-Part", (uint8_t) moveController.getPID(0)->GetKd());
pidr_m->setMinMax(0, UINT8_MAX);
pidr_m->setEntry(0, "P-Part", (uint8_t) moveController.getPID(1)->GetKp());
pidr_m->setEntry(1, "I-Part", (uint8_t) moveController.getPID(1)->GetKi());
pidr_m->setEntry(2, "D-Part", (uint8_t) moveController.getPID(1)->GetKd());
}
void restart(void) {
lcdWrapper->clear();
lcdWrapper->setCursor(0, 0);
lcdWrapper->print("Rebooting ...");
ESP.restart();
}
void disconnectController(void) {
disconnectPs3 = true;
lcdWrapper->clear();
lcdWrapper->setCursor(0, 0);
lcdWrapper->print("Controller is");
lcdWrapper->setCursor(0, 1);
lcdWrapper->print("disconnected.");
}