From 6f50419e165c18330263ddc8b23fdc39bf5c3c4c Mon Sep 17 00:00:00 2001 From: Rune Harlyk Date: Sun, 14 May 2023 20:38:09 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=8C=8A=20Moves=20all=20logic=20to=20new?= =?UTF-8?q?=20Spot=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/camera.h | 46 ---------- include/config.h | 1 + include/spot.h | 75 +++++++++++++++++ src/main.cpp | 213 +---------------------------------------------- src/spot.cpp | 206 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 286 insertions(+), 255 deletions(-) delete mode 100644 include/camera.h create mode 100644 include/spot.h create mode 100644 src/spot.cpp diff --git a/include/camera.h b/include/camera.h deleted file mode 100644 index b43245b..0000000 --- a/include/camera.h +++ /dev/null @@ -1,46 +0,0 @@ -#include -#include - -#include -#include - -bool setupCamera(){ - camera_config_t camera_config; - camera_config.ledc_channel = LEDC_CHANNEL_0; - camera_config.ledc_timer = LEDC_TIMER_0; - camera_config.pin_d0 = Y2_GPIO_NUM; - camera_config.pin_d1 = Y3_GPIO_NUM; - camera_config.pin_d2 = Y4_GPIO_NUM; - camera_config.pin_d3 = Y5_GPIO_NUM; - camera_config.pin_d4 = Y6_GPIO_NUM; - camera_config.pin_d5 = Y7_GPIO_NUM; - camera_config.pin_d6 = Y8_GPIO_NUM; - camera_config.pin_d7 = Y9_GPIO_NUM; - camera_config.pin_xclk = XCLK_GPIO_NUM; - camera_config.pin_pclk = PCLK_GPIO_NUM; - camera_config.pin_vsync = VSYNC_GPIO_NUM; - camera_config.pin_href = HREF_GPIO_NUM; - camera_config.pin_sscb_sda = SIOD_GPIO_NUM; - camera_config.pin_sscb_scl = SIOC_GPIO_NUM; - camera_config.pin_pwdn = PWDN_GPIO_NUM; - camera_config.pin_reset = RESET_GPIO_NUM; - camera_config.xclk_freq_hz = 20000000; - camera_config.pixel_format = PIXFORMAT_JPEG; - - if(psramFound()){ - camera_config.frame_size = FRAMESIZE_SVGA; - camera_config.jpeg_quality = 10; - camera_config.fb_count = 2; - } else { - camera_config.frame_size = FRAMESIZE_SVGA; - camera_config.jpeg_quality = 12; - camera_config.fb_count = 1; - } - - esp_err_t err = esp_camera_init(&camera_config); - if (err != ESP_OK) { - printf("Camera probe failed with error 0x%x", err); - return 0; - } - return 1; -} \ No newline at end of file diff --git a/include/config.h b/include/config.h index 12e3122..41b90b7 100644 --- a/include/config.h +++ b/include/config.h @@ -12,6 +12,7 @@ #define HTTP_PORT 80 #define WEBSOCKET_PATH "/" #define EVENTSOURCE_PATH "/events" +#define USE_CAPTIVE_PORTAL false /* diff --git a/include/spot.h b/include/spot.h new file mode 100644 index 0000000..841f006 --- /dev/null +++ b/include/spot.h @@ -0,0 +1,75 @@ +#ifndef SPOT_h +#define SPOT_h + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// Server functions +#include +#include + +// Disable brownout problems +#include "soc/rtc_cntl_reg.h" +#include "soc/soc.h" + +// Config +#include +#include + +#ifdef __cplusplus + extern "C" { + #endif + uint8_t temprature_sens_read(); + #ifdef __cplusplus + } +#endif +uint8_t temprature_sens_read(); + +class Spot { + public: + Spot(); + + esp_err_t boot(); + void handle(); + + esp_err_t initialize_wifi(); + + uint8_t cpu_temperature(); + + private: + esp_err_t _initialize_camera(); + esp_err_t _initialize_captive_portal(); + esp_err_t _initialize_arduino_oat(); + esp_err_t _initialize_wifi_connection(); + esp_err_t _initialize_server(); + esp_err_t _initialize_display(); + esp_err_t _initialize_mpu(); + esp_err_t _initialize_pwm_controller(); + esp_err_t _initialize_button(); + + DNSServer _dnsServer; + AsyncEventSource _events; + AsyncWebSocket _ws; + AsyncWebServer _server; + + Adafruit_SSD1306 _display; + Adafruit_PWMServoDriver _pwm; + MPU6050 _mpu; + NewPing _leftUss; + NewPing _rightUss; +}; + +void display_ip_and_ssid(Adafruit_SSD1306* display, String ip, const char* ssid); + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index d8c920f..74fd62f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,216 +1,11 @@ -#include -#include -#include -#include -#include -#include -#include -#include "soc/soc.h" // Disable brownout problems -#include "soc/rtc_cntl_reg.h" // Disable brownout problems +#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -#include -#include - -static const char* TAG = "MAIN"; - -DNSServer dnsServer; -AsyncWebSocket ws(WEBSOCKET_PATH); -AsyncEventSource events(EVENTSOURCE_PATH); -AsyncWebServer server(HTTP_PORT); - -NewPing sonar[2] = { - NewPing(USS_LEFT, USS_LEFT, USS_MAX_DISTANCE), - NewPing(USS_RIGHT, USS_RIGHT, USS_MAX_DISTANCE) -}; - -MPU6050 mpu(Wire); -Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, SCREEN_RESET); - -bool MPU_READY = false; -bool PWM_READY = false; -bool OLED_READY = false; - -const bool USE_CAPTIVE_PORTAL = false; - -int lastState = LOW; -int currentState; - -long timer = 0; - -#ifdef __cplusplus - extern "C" { - #endif - uint8_t temprature_sens_read(); - #ifdef __cplusplus - } -#endif -uint8_t temprature_sens_read(); - -bool setupOLED(){ - if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { - Serial.println(F("SSD1306 allocation failed")); - return 0; - } - - display.display(); - delay(200); - display.clearDisplay(); - return 1; -} - -void setupWiFi(){ - if(USE_CAPTIVE_PORTAL){ - WiFi.softAP(HOSTNAME); - dnsServer.start(53, "*", WiFi.softAPIP()); - } else { - WiFi.begin(SSID, PASS); - while (WiFi.status() != WL_CONNECTED) { - delay(500); - } - if(OLED_READY) { - display.setTextColor(WHITE, BLACK); - display.setTextSize(1); - int16_t x1 = 0; - int16_t y1 = 0; - uint16_t h = 0; - uint16_t w = 0; - display.getTextBounds(WiFi.localIP().toString(), 0, 0, &x1, &y1, &w, &h); - display.setCursor(SCREEN_WIDTH/2 - w/2, SCREEN_HEIGHT/2 - h/2); - display.println(WiFi.localIP()); - display.display(); - } - } - if(MDNS.begin(HOSTNAME)){ - MDNS.addService("http", "tcp", HTTP_PORT); - } -} - -void setupServer(){ - ws.onEvent(onWsEvent); - server.addHandler(&ws); - server.on("/stream", HTTP_GET, streamJpg); - server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html"); - server.begin(); -} - -bool setupMPU(){ - byte status = mpu.begin(); - Serial.print(F("MPU6050 status: ")); - Serial.println(status); - if(status != 0){ return 0; } - Serial.println(F("Calculating offsets, do not move MPU6050")); - delay(1000); - mpu.calcOffsets(true,true); - Serial.println("Done!\n"); - return 1; -} - -void setupOAT(){ - ArduinoOTA.onStart([]() { events.send("Update Start", "ota"); }); - ArduinoOTA.onEnd([]() { events.send("Update End", "ota"); }); - ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { - char p[32]; - sprintf(p, "Progress: %u%%\n", (progress/(total/100))); - events.send(p, "ota"); - }); - ArduinoOTA.onError([](ota_error_t error) { - if(error == OTA_AUTH_ERROR) events.send("Auth Failed", "ota"); - else if(error == OTA_BEGIN_ERROR) events.send("Begin Failed", "ota"); - else if(error == OTA_CONNECT_ERROR) events.send("Connect Failed", "ota"); - else if(error == OTA_RECEIVE_ERROR) events.send("Recieve Failed", "ota"); - else if(error == OTA_END_ERROR) events.send("End Failed", "ota"); - }); - ArduinoOTA.setHostname(HOSTNAME); - ArduinoOTA.begin(); -} +Spot spot; void setup(){ - WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); - Serial.begin(BAUDRATE); - Serial.setDebugOutput(SERIAL_DEBUG_OUTPUT); - - pinMode(BUTTON_LED, OUTPUT); - //pinMode(BUTTON, INPUT); - - Wire.begin(SDA, SCL); - SPIFFS.begin(); - - OLED_READY = setupOLED(); - MPU_READY = setupMPU(); - PWM_READY = setup_pwm_controller(); - - setupCamera(); - setupWiFi(); - setupOAT(); - setupServer(); - - digitalWrite(BUTTON_LED, HIGH); + spot.boot(); } void loop(){ - ArduinoOTA.handle(); - if(USE_CAPTIVE_PORTAL) dnsServer.processNextRequest(); - ws.cleanupClients(); - - currentState = digitalRead(BUTTON); - - if (lastState == HIGH && currentState == LOW) - disable_servos(); - lastState = currentState; - - if(millis() - timer > 50) { - - /*int sketchSize = ESP.getSketchSize(); - int sketchSpace = ESP.getFreeSketchSpace(); - const char* SdkVersion = ESP.getSdkVersion(); - uint32_t mhz = ESP.getCpuFreqMHz(); - uint32_t heapSize = ESP.getHeapSize(); - uint32_t psramSize = ESP.getPsramSize(); - - size_t filesystem_used = SPIFFS.usedBytes(); - size_t filesystem_total = SPIFFS.totalBytes(); - - int64_t sec = esp_timer_get_time() / 1000000; - int64_t upDays = int64_t(floor(sec/86400)); - int upHours = int64_t(floor(sec/3600)) % 24; - int upMin = int64_t(floor(sec/60)) % 60; - int upSec = sec % 60;*/ - - mpu.update(); - size_t numContent = 13; - float content[numContent]; - content[0] = WiFi.RSSI(); - content[1] = mpu.getTemp(); - content[2] = mpu.getAccX(); - content[3] = mpu.getAccY(); - content[4] = mpu.getAccZ(); - content[5] = mpu.getAngleX(); - content[6] = mpu.getAngleY(); - content[7] = mpu.getAngleZ(); - content[8] = (temprature_sens_read() - 32) / 1.8; - content[9] = sonar[0].ping_cm(); - content[10] = sonar[1].ping_cm(); - content[11] = ESP.getFreeHeap(); - content[12] = ESP.getFreePsram(); - - uint8_t* buf = (uint8_t*) &content; - size_t buf_len = sizeof(buf); - - ws.binaryAll(buf, buf_len * numContent); - timer = millis(); - } + spot.handle(); } diff --git a/src/spot.cpp b/src/spot.cpp new file mode 100644 index 0000000..fdf7f7c --- /dev/null +++ b/src/spot.cpp @@ -0,0 +1,206 @@ +#include + +Spot::Spot() + : _events(EVENTSOURCE_PATH) + , _ws(WEBSOCKET_PATH) + , _server(HTTP_PORT) + , _display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, SCREEN_RESET) + , _mpu(Wire) + , _leftUss(USS_LEFT, USS_LEFT, USS_MAX_DISTANCE) + , _rightUss(USS_RIGHT, USS_RIGHT, USS_MAX_DISTANCE) + , _pwm(0x40) +{ } + +esp_err_t Spot::boot(){ + log_i("Booting..."); + WRITE_PERI_REG(RTC_CNTL_BROWN_OUT_REG, 0); + SPIFFS.begin(); + Wire.begin(SDA, SCL); + _initialize_button(); + + _initialize_display(); + _initialize_mpu(); + _initialize_camera(); + + initialize_wifi(); + _initialize_arduino_oat(); + _initialize_server(); + log_i("Done booting"); + return ESP_OK; +} + +void Spot::handle(){ + if(USE_CAPTIVE_PORTAL) _dnsServer.processNextRequest(); + ArduinoOTA.handle(); + _ws.cleanupClients(); +} + +esp_err_t Spot::initialize_wifi(){ + if(USE_CAPTIVE_PORTAL) _initialize_captive_portal(); + else _initialize_wifi_connection(); + if(MDNS.begin(HOSTNAME)){ + MDNS.addService("http", "tcp", HTTP_PORT); + } + + if(USE_CAPTIVE_PORTAL) display_ip_and_ssid(&_display, WiFi.softAPIP().toString(), HOSTNAME); + else display_ip_and_ssid(&_display, WiFi.localIP().toString(), SSID); + return ESP_OK; +} + +uint8_t Spot::cpu_temperature(){ + return (temprature_sens_read() - 32) / 1.8; +} + +esp_err_t Spot::_initialize_camera(){ + camera_config_t camera_config; + camera_config.ledc_channel = LEDC_CHANNEL_0; + camera_config.ledc_timer = LEDC_TIMER_0; + camera_config.pin_d0 = Y2_GPIO_NUM; + camera_config.pin_d1 = Y3_GPIO_NUM; + camera_config.pin_d2 = Y4_GPIO_NUM; + camera_config.pin_d3 = Y5_GPIO_NUM; + camera_config.pin_d4 = Y6_GPIO_NUM; + camera_config.pin_d5 = Y7_GPIO_NUM; + camera_config.pin_d6 = Y8_GPIO_NUM; + camera_config.pin_d7 = Y9_GPIO_NUM; + camera_config.pin_xclk = XCLK_GPIO_NUM; + camera_config.pin_pclk = PCLK_GPIO_NUM; + camera_config.pin_vsync = VSYNC_GPIO_NUM; + camera_config.pin_href = HREF_GPIO_NUM; + camera_config.pin_sscb_sda = SIOD_GPIO_NUM; + camera_config.pin_sscb_scl = SIOC_GPIO_NUM; + camera_config.pin_pwdn = PWDN_GPIO_NUM; + camera_config.pin_reset = RESET_GPIO_NUM; + camera_config.xclk_freq_hz = 20000000; + camera_config.pixel_format = PIXFORMAT_JPEG; + + if(psramFound()){ + camera_config.frame_size = FRAMESIZE_SVGA; + camera_config.jpeg_quality = 10; + camera_config.fb_count = 2; + } else { + camera_config.frame_size = FRAMESIZE_SVGA; + camera_config.jpeg_quality = 12; + camera_config.fb_count = 1; + } + + log_i("Initializing camera"); + esp_err_t err = esp_camera_init(&camera_config); + if (err != ESP_OK) log_i("Camera probe failed with error 0x%x", err); + + return err; +} + +esp_err_t Spot::_initialize_wifi_connection(){ + log_i("Connecting to wifi"); + WiFi.begin(SSID, PASS); + int8_t timeout = 0; + while (WiFi.status() != WL_CONNECTED) { + delay(500); + timeout++; + if(timeout > 15) { + _initialize_captive_portal(); + return ESP_FAIL; + } + } + log_i("Connected successfully"); + return ESP_OK; +} + +esp_err_t Spot::_initialize_arduino_oat(){ + log_i("Starting ArduinoOTA"); + ArduinoOTA.onStart([&]() { _events.send("Update Start", "ota"); }); + ArduinoOTA.onEnd([&]() { _events.send("Update End", "ota"); }); + ArduinoOTA.onProgress([&](unsigned int progress, unsigned int total) { + char p[32]; + sprintf(p, "Progress: %u%%\n", (progress/(total/100))); + _events.send(p, "ota"); + }); + ArduinoOTA.onError([&](ota_error_t error) { + if(error == OTA_AUTH_ERROR) _events.send("Auth Failed", "ota"); + else if(error == OTA_BEGIN_ERROR) _events.send("Begin Failed", "ota"); + else if(error == OTA_CONNECT_ERROR) _events.send("Connect Failed", "ota"); + else if(error == OTA_RECEIVE_ERROR) _events.send("Recieve Failed", "ota"); + else if(error == OTA_END_ERROR) _events.send("End Failed", "ota"); + }); + ArduinoOTA.setHostname(HOSTNAME); + ArduinoOTA.begin(); + return ESP_OK; +} + +esp_err_t Spot::_initialize_captive_portal(){ + log_i("Starting captive portal"); + WiFi.softAP(HOSTNAME); + _dnsServer.start(53, "*", WiFi.softAPIP()); + return ESP_OK; +} + +esp_err_t Spot::_initialize_server(){ + log_i("Starting webserver"); + _ws.onEvent(onWsEvent); + _server.addHandler(&_ws); + _server.on("/stream", HTTP_GET, streamJpg); + _server.serveStatic("/", SPIFFS, "/").setDefaultFile("index.html"); + _server.begin(); + return ESP_OK; +} + +esp_err_t Spot::_initialize_display(){ + log_i("Initializing display"); + if(!_display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) { + log_w("SSD1306 allocation failed"); + return ESP_FAIL; + } + + _display.display(); + delay(200); + _display.clearDisplay(); + return ESP_OK; +} + +esp_err_t Spot::_initialize_mpu(){ + log_i("Initializing MPU"); + byte status = _mpu.begin(); + if(status != 0) { + log_w("MPU initialize failed"); + return ESP_FAIL; + } + log_i("Calculating offsets, do not move MPU6050"); + delay(1000); + log_i("Cone calculating offsets"); + _mpu.calcOffsets(true,true); + return ESP_OK; +} + +esp_err_t Spot::_initialize_pwm_controller(){ + log_i("Initializing PWM controller"); + _pwm.begin(); + _pwm.setOscillatorFrequency(SERVO_OSCILLATOR_FREQUENCY); + _pwm.setPWMFreq(SERVO_FREQ); + return ESP_OK; +} + +esp_err_t Spot::_initialize_button() { + pinMode(BUTTON_LED, OUTPUT); + digitalWrite(BUTTON_LED, HIGH); + //pinMode(BUTTON, INPUT); + return ESP_OK; +} + +void display_ip_and_ssid(Adafruit_SSD1306* display, String ip, const char* ssid) { + display->setTextColor(WHITE, BLACK); + display->setTextSize(1); + int16_t x1 = 0; + int16_t y1 = 0; + uint16_t h = 0; + uint16_t w = 0; + + display->getTextBounds(ssid, 0, 0, &x1, &y1, &w, &h); + display->setCursor(SCREEN_WIDTH/2 - w/2, SCREEN_HEIGHT/2-8 - h/2); + display->println(ssid); + + display->getTextBounds(ip, 0, 0, &x1, &y1, &w, &h); + display->setCursor(SCREEN_WIDTH/2 - w/2, SCREEN_HEIGHT/2+8 - h/2); + display->println(ip); + display->display(); +} \ No newline at end of file