Latest Version with all features enabled
This commit is contained in:
parent
51ad765581
commit
d113c1b1f7
13 changed files with 1206 additions and 75 deletions
33
vscode/Unendlichkeitsmaschine/.vscode/settings.json
vendored
Normal file
33
vscode/Unendlichkeitsmaschine/.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{
|
||||||
|
"svn.ignoreMissingSvnWarning": true,
|
||||||
|
"files.associations": {
|
||||||
|
"typeinfo": "cpp",
|
||||||
|
"*.tcc": "cpp",
|
||||||
|
"chrono": "cpp",
|
||||||
|
"ctime": "cpp",
|
||||||
|
"iomanip": "cpp",
|
||||||
|
"limits": "cpp",
|
||||||
|
"numeric": "cpp",
|
||||||
|
"ratio": "cpp",
|
||||||
|
"streambuf": "cpp",
|
||||||
|
"tuple": "cpp",
|
||||||
|
"type_traits": "cpp",
|
||||||
|
"utility": "cpp",
|
||||||
|
"array": "cpp",
|
||||||
|
"string": "cpp",
|
||||||
|
"unordered_map": "cpp",
|
||||||
|
"algorithm": "cpp",
|
||||||
|
"functional": "cpp",
|
||||||
|
"memory": "cpp",
|
||||||
|
"memory_resource": "cpp",
|
||||||
|
"optional": "cpp",
|
||||||
|
"random": "cpp",
|
||||||
|
"system_error": "cpp",
|
||||||
|
"cmath": "cpp",
|
||||||
|
"fstream": "cpp",
|
||||||
|
"istream": "cpp",
|
||||||
|
"ostream": "cpp",
|
||||||
|
"thread": "cpp",
|
||||||
|
"regex": "cpp"
|
||||||
|
}
|
||||||
|
}
|
27
vscode/Unendlichkeitsmaschine/include/capportal.hpp
Normal file
27
vscode/Unendlichkeitsmaschine/include/capportal.hpp
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef CAPPORTAL_HPP
|
||||||
|
#define CAPPORTAL_HPP
|
||||||
|
|
||||||
|
#include <WiFi.h> // Replace with WiFi.h for ESP32
|
||||||
|
#include <WebServer.h> // Replace with WebServer.h for ESP32
|
||||||
|
#include <AutoConnect.h>
|
||||||
|
#include "time.h"
|
||||||
|
extern String html_content;
|
||||||
|
|
||||||
|
class Cap{
|
||||||
|
private:
|
||||||
|
const char* ntpServer = "pool.ntp.org";
|
||||||
|
const long gmtOffset_sec = 3600;
|
||||||
|
const int daylightOffset_sec = 3600;
|
||||||
|
AutoConnect *Portal;
|
||||||
|
AutoConnectConfig *Config;
|
||||||
|
public:
|
||||||
|
void begin();
|
||||||
|
void handle();
|
||||||
|
unsigned long epochTime();
|
||||||
|
String localTime();
|
||||||
|
String localTime(time_t epochtime);
|
||||||
|
String localIP();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //CAPPORTAL_HPP
|
55
vscode/Unendlichkeitsmaschine/include/eeprom.hpp
Normal file
55
vscode/Unendlichkeitsmaschine/include/eeprom.hpp
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
#ifndef __eeprom_H__
|
||||||
|
#define __eeprom_H__
|
||||||
|
#include <TridentTD_ESP32NVS.h>
|
||||||
|
|
||||||
|
class Eeprom
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
Eeprom();
|
||||||
|
~Eeprom();
|
||||||
|
void set_int(String name , uint64_t val );
|
||||||
|
void set_int_period(String name , uint64_t val , time_t period_ms);
|
||||||
|
uint64_t get_int(String name );
|
||||||
|
void begin();
|
||||||
|
};
|
||||||
|
|
||||||
|
Eeprom::Eeprom()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Eeprom::~Eeprom()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void Eeprom::begin()
|
||||||
|
{
|
||||||
|
Serial.println("Init EEPROM ...");
|
||||||
|
NVS.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Eeprom::set_int_period(String name , uint64_t val , time_t period_ms)
|
||||||
|
{
|
||||||
|
static time_t last_stored_ms = 0;
|
||||||
|
if((last_stored_ms == 0) || ((millis() - last_stored_ms) > period_ms))
|
||||||
|
{
|
||||||
|
last_stored_ms = millis();
|
||||||
|
set_int(name , val );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Eeprom::set_int(String name , uint64_t val )
|
||||||
|
{
|
||||||
|
if(NVS.getInt(name) != val)
|
||||||
|
{
|
||||||
|
NVS.setInt(name, val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t Eeprom::get_int(String name )
|
||||||
|
{
|
||||||
|
return NVS.getInt(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
29
vscode/Unendlichkeitsmaschine/include/json.hpp
Normal file
29
vscode/Unendlichkeitsmaschine/include/json.hpp
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef JSON_HPP
|
||||||
|
#define JSON_HPP
|
||||||
|
|
||||||
|
#include <ArduinoJson.h>
|
||||||
|
#include <map>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char * name;
|
||||||
|
unsigned long ticks;
|
||||||
|
unsigned long period_ticks;
|
||||||
|
const char * unit;
|
||||||
|
double value;
|
||||||
|
float unit_factor;
|
||||||
|
unsigned long last_update_ms;
|
||||||
|
unsigned long timestamp;
|
||||||
|
} DataStruct;
|
||||||
|
|
||||||
|
const uint8_t NR_JSON_SECTION_OBJECTS = 8;
|
||||||
|
|
||||||
|
class Myjson{
|
||||||
|
|
||||||
|
private:
|
||||||
|
public:
|
||||||
|
String create_json_string(volatile DataStruct *data_struct, size_t nr_dataobjects, time_t runtime_s);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //JSON_HPP
|
106
vscode/Unendlichkeitsmaschine/include/main.hpp
Normal file
106
vscode/Unendlichkeitsmaschine/include/main.hpp
Normal file
|
@ -0,0 +1,106 @@
|
||||||
|
#ifndef MAIN_HPP
|
||||||
|
#define MAIN_HPP
|
||||||
|
|
||||||
|
#define MACHINE_RESTART
|
||||||
|
//#define DUMMY_DATA
|
||||||
|
|
||||||
|
#define EEPROM_NAME_TICK "hall_tick"
|
||||||
|
#define EEPROM_NAME_TIMESTAMP "timestamp"
|
||||||
|
#define EEPROM_NAME_RUN_TIME "runtime"
|
||||||
|
#define EEPROM_NAME_START_EPOCHTIME "starttime"
|
||||||
|
#define EEPROM_STORE_RUNTIME_ALL_MS 1000 * 60 //* 5
|
||||||
|
|
||||||
|
#include <NTPClient.h>
|
||||||
|
#include <ESP32Servo.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
||||||
|
#include "eeprom.hpp"
|
||||||
|
#include "oled.hpp"
|
||||||
|
#include "capportal.hpp"
|
||||||
|
|
||||||
|
#define HAS_MQTT
|
||||||
|
#ifdef HAS_MQTT
|
||||||
|
#include "mqtt.hpp"
|
||||||
|
#include "json.hpp"
|
||||||
|
Mymqtt mqtt;
|
||||||
|
Myjson json;
|
||||||
|
|
||||||
|
|
||||||
|
/*makerlab*/
|
||||||
|
const char* mqttServer = "mqtt.makerlab-murnau.de";
|
||||||
|
const int mqttPort = 8883;
|
||||||
|
const char* mqttUser = "";
|
||||||
|
const char* mqttPassword = "";
|
||||||
|
|
||||||
|
/*hivemq*/
|
||||||
|
/*
|
||||||
|
const char* mqttServer = "ccb0edef424149d4b3d2ee2ee503b87d.s1.eu.hivemq.cloud";
|
||||||
|
const int mqttPort = 8883;
|
||||||
|
const char* mqttUser = "infinity";
|
||||||
|
const char* mqttPassword = "12345678";
|
||||||
|
*/
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WiFiUDP ntpUDP;
|
||||||
|
//NTPClient timeClient(ntpUDP);
|
||||||
|
NTPClient timeClient( ntpUDP,"pool.ntp.org", 3600);
|
||||||
|
|
||||||
|
// Variables to save date and time
|
||||||
|
String timeStamp;
|
||||||
|
|
||||||
|
Eeprom Store;
|
||||||
|
Cap capportal;
|
||||||
|
Servo ESC; // Der ESC-Controller (Electronic Speed Controller bzw. elektronischer Fahrtregler) wird als Objekt mit dem Namen "ESC" festgelegt.
|
||||||
|
Oled display;
|
||||||
|
|
||||||
|
const unsigned long UPDATE_TURN_VALUES_EVERY_MS = 1000;
|
||||||
|
|
||||||
|
const uint8_t HALL_SENSORS_COUNT = 8; // input, sec, min, hour, day, week, month, year
|
||||||
|
const uint8_t ALL_DATA_COUNT = HALL_SENSORS_COUNT;
|
||||||
|
|
||||||
|
const uint8_t HALL_TICKS_PER_TURN = 4;
|
||||||
|
const uint8_t HALL_MIN_PULSE_MS = 50;
|
||||||
|
|
||||||
|
volatile DataStruct AllData[ALL_DATA_COUNT];
|
||||||
|
volatile DataStruct *HallData = AllData;
|
||||||
|
|
||||||
|
const char *Data_names[ALL_DATA_COUNT] =
|
||||||
|
{
|
||||||
|
// Hall sensors
|
||||||
|
"cascade_input", "cascade_sec", "cascade_min", "cascade_hour", "cascade_day", "cascade_week", "cascade_month", "cascade_year",
|
||||||
|
};
|
||||||
|
const char *Data_units[ALL_DATA_COUNT] =
|
||||||
|
{
|
||||||
|
// Hall sensors
|
||||||
|
"U/min", "sec", "min", "hour", "day", "week", "month", "year",
|
||||||
|
};
|
||||||
|
const float Data_units_factor[ALL_DATA_COUNT] =
|
||||||
|
{
|
||||||
|
//Hall sensors
|
||||||
|
(60000.0/UPDATE_TURN_VALUES_EVERY_MS)/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN, 1.0/HALL_TICKS_PER_TURN
|
||||||
|
};
|
||||||
|
|
||||||
|
const char ** Hall_names = Data_names;
|
||||||
|
const char ** Hall_units = Data_units;
|
||||||
|
const float * Hall_units_factor = Data_units_factor;
|
||||||
|
|
||||||
|
const uint8_t LED_BUILTIN = 2;
|
||||||
|
const uint8_t POTI_PIN = 36; // never use ADC2 (GPIO0, 2, 4, 12, 13, 14, 15, 25, 26 and 27) if Wifi is active ... use ADC1 instead (GPIO32-GPIO39)
|
||||||
|
const uint8_t ESC_PIN = 16;
|
||||||
|
|
||||||
|
|
||||||
|
const uint8_t HALL1_PIN = 34;
|
||||||
|
const uint8_t HALL2_PIN = 35;
|
||||||
|
const uint8_t HALL3_PIN = 32;
|
||||||
|
const uint8_t HALL4_PIN = 33;
|
||||||
|
const uint8_t HALL5_PIN = 25;
|
||||||
|
const uint8_t HALL6_PIN = 26;
|
||||||
|
const uint8_t HALL7_PIN = 27;
|
||||||
|
const uint8_t HALL8_PIN = 14;
|
||||||
|
|
||||||
|
const uint8_t MAX_ESC_SPEED = 60;
|
||||||
|
const uint8_t MIN_ESC_SPEED = 35;
|
||||||
|
const uint16_t MAX_POTI_VALUE = 4095;
|
||||||
|
const uint16_t JITTER_POTI_PERCENT = 10;
|
||||||
|
|
||||||
|
#endif //MAIN_HPP
|
75
vscode/Unendlichkeitsmaschine/include/mqtt.hpp
Normal file
75
vscode/Unendlichkeitsmaschine/include/mqtt.hpp
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#ifndef MQTT_HPP
|
||||||
|
#define MQTT_HPP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#include <WiFi.h> // Replace with WiFi.h for ESP32
|
||||||
|
//#include <WiFiClient.h>
|
||||||
|
#include <WiFiClientSecure.h>
|
||||||
|
#include <PubSubClient.h>
|
||||||
|
|
||||||
|
static const char *root_ca PROGMEM = R"EOF(
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
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
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
)EOF";
|
||||||
|
|
||||||
|
|
||||||
|
#define MQTT_TRY_TO_CONNECT_MS 2000
|
||||||
|
#define MQTT_CHANNEL "infinitymachine"
|
||||||
|
#define MQTT_BUFFER_SIZE 1024
|
||||||
|
#define SEND_MQTT_EVERY_MS 1000
|
||||||
|
|
||||||
|
class Mymqtt
|
||||||
|
{
|
||||||
|
|
||||||
|
private:
|
||||||
|
WiFiClientSecure *espClient;
|
||||||
|
PubSubClient *client;
|
||||||
|
String _server = "";
|
||||||
|
uint16_t _port = 0;
|
||||||
|
String _mqttUser = "";
|
||||||
|
String _mqttPassword = "";
|
||||||
|
String _data_sent = "";
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void begin(const char * server, uint16_t mqttPort, const char* mqttUser, const char* mqttPassword);
|
||||||
|
bool connect();
|
||||||
|
bool is_connected();
|
||||||
|
bool publish(String topic,String data);
|
||||||
|
bool send_and_loop(String topic,String data);
|
||||||
|
bool loop();
|
||||||
|
//void callback(char* topic, byte* payload, unsigned int length);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //MQTT_HPP
|
43
vscode/Unendlichkeitsmaschine/include/oled.hpp
Normal file
43
vscode/Unendlichkeitsmaschine/include/oled.hpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#ifndef OLED_HPP
|
||||||
|
#define OLED_HPP
|
||||||
|
|
||||||
|
#include "SSD1306Wire.h" // legacy: #include "SSD1306.h"
|
||||||
|
#include "json.hpp"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
|
||||||
|
class Oled
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
const unsigned long PAGE_VIEW_TIME_MS = 10000;
|
||||||
|
const uint8_t HALLS_PER_PAGE = 4;
|
||||||
|
const uint8_t MAX_PAGE_NR = HALL2;
|
||||||
|
const uint8_t MIN_PAGE_NR = SPEED;
|
||||||
|
|
||||||
|
enum pages {SPEED, HALL1, HALL2};
|
||||||
|
|
||||||
|
//SSD1306Wire display(0x3c, SDA, SCL);
|
||||||
|
SSD1306Wire *display;
|
||||||
|
|
||||||
|
uint8_t xpos = 0;
|
||||||
|
uint8_t ypos = 0;
|
||||||
|
|
||||||
|
pages page = SPEED;
|
||||||
|
uint8_t page_nr = MIN_PAGE_NR;
|
||||||
|
|
||||||
|
void next_page(bool speedchange);
|
||||||
|
void show_page_header( String ipaddr, pages page);
|
||||||
|
void show_speed(int speed, int min_speed, int max_speed, double u_min, unsigned long runtime, pages page);
|
||||||
|
void show_halls(volatile DataStruct *HallData, uint8_t hall_sensor_count, pages page);
|
||||||
|
void show_page_footer(pages page);
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
void begin();
|
||||||
|
void progressBar(uint8_t i);
|
||||||
|
void show_values(int speed, int min_speed, int max_speed, volatile DataStruct *HallData, uint8_t hall_sensors_count, unsigned long runtime, String ipaddr);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif //OLED_HPP
|
|
@ -9,9 +9,16 @@
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
|
||||||
[env:esp32]
|
[env:esp32]
|
||||||
|
monitor_speed = 115200
|
||||||
platform = espressif32
|
platform = espressif32
|
||||||
board = esp32dev
|
board = esp32dev
|
||||||
framework = arduino
|
framework = arduino
|
||||||
lib_deps =
|
lib_deps =
|
||||||
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.2.1
|
thingpulse/ESP8266 and ESP32 OLED driver for SSD1306 displays@^4.2.1
|
||||||
madhephaestus/ESP32Servo@^0.11.0
|
madhephaestus/ESP32Servo@^0.11.0
|
||||||
|
tridenttd/TridentTD_ESP32NVS@^1.0
|
||||||
|
hieromon/AutoConnect@^1.4.0
|
||||||
|
knolleary/PubSubClient@^2.8
|
||||||
|
bblanchon/ArduinoJson@^6.19.4
|
||||||
|
arduino-libraries/NTPClient@^3.2.1
|
||||||
|
paulstoffregen/Time@^1.6.1
|
||||||
|
|
85
vscode/Unendlichkeitsmaschine/src/capportal.cpp
Normal file
85
vscode/Unendlichkeitsmaschine/src/capportal.cpp
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
#include "capportal.hpp"
|
||||||
|
#include <TimeLib.h>
|
||||||
|
|
||||||
|
WebServer CapServer;
|
||||||
|
String html_content = "";
|
||||||
|
|
||||||
|
static void rootPage() {
|
||||||
|
CapServer.send(302, "text/html", html_content);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cap::begin() {
|
||||||
|
|
||||||
|
Portal = new AutoConnect(CapServer);
|
||||||
|
Config = new AutoConnectConfig();
|
||||||
|
|
||||||
|
Config->autoReset = false; // Not reset the module even by intentional disconnection using AutoConnect menu.
|
||||||
|
Config->portalTimeout = 1000; // Do not block the sketch and exit after 1000ms
|
||||||
|
//Config->immediateStart = true;
|
||||||
|
Config->autoReconnect = true; // Reconnect to known access points.
|
||||||
|
Config->reconnectInterval = 6; // Reconnection attempting interval is 3[min].
|
||||||
|
Config->retainPortal = true; // Keep the captive portal open.
|
||||||
|
Config->apid = "Unendlichkeit_AP";
|
||||||
|
Config->menuItems = Config->menuItems | AC_MENUITEM_UPDATE;
|
||||||
|
Config->hostName = "Unendlichkeit";
|
||||||
|
Config->ota = AC_OTA_BUILTIN;
|
||||||
|
Portal->config(*Config);
|
||||||
|
|
||||||
|
configTime(gmtOffset_sec, daylightOffset_sec, ntpServer);
|
||||||
|
|
||||||
|
//content = "<!DOCTYPE html><html><head><meta http-equiv=\"refresh\" content=\"0; url='/_ac'\" /></head><body></body></html>";
|
||||||
|
CapServer.on("/", rootPage);
|
||||||
|
if (Portal->begin()) {
|
||||||
|
Serial.println("WiFi connected: " + WiFi.localIP().toString());
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
Serial.println("No configured Wifi connection. Connect to '" + Config->apid + "' and configure network connections.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String Cap::localIP()
|
||||||
|
{
|
||||||
|
return WiFi.localIP().toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cap::handle(){
|
||||||
|
Portal->handleClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function that gets current epoch time
|
||||||
|
unsigned long Cap::epochTime() {
|
||||||
|
time_t now;
|
||||||
|
struct tm timeinfo;
|
||||||
|
if ( !getLocalTime(&timeinfo)) {
|
||||||
|
//Serial.println("Failed to obtain time");
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
time(&now);
|
||||||
|
//Serial.printf("Epochtime: %lu\n", now);
|
||||||
|
return now;
|
||||||
|
}
|
||||||
|
|
||||||
|
String Cap::localTime(){
|
||||||
|
String dateTime = "";
|
||||||
|
struct tm timeinfo;
|
||||||
|
if(!getLocalTime(&timeinfo)){
|
||||||
|
//Serial.println("Failed to obtain time");
|
||||||
|
return(dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S");
|
||||||
|
dateTime = String(timeinfo.tm_year + 1900) + "-" + String(timeinfo.tm_mon + 1) + "-" + String(timeinfo.tm_mday) + "+" + String(timeinfo.tm_hour) + ":" + String(timeinfo.tm_min) + ":" + String(timeinfo.tm_sec);
|
||||||
|
//Serial.printf("%s\n", dateTime.c_str());
|
||||||
|
|
||||||
|
return(dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
String Cap::localTime(time_t epochtime){
|
||||||
|
String dateTime = "";
|
||||||
|
dateTime = String(year(epochtime)) + "-" + String(month(epochtime)) + "-" + String(day(epochtime)) + "+" + String(hour(epochtime)) + ":" + String(minute(epochtime)) + ":" + String(second(epochtime));
|
||||||
|
Serial.printf("%s\n", dateTime.c_str());
|
||||||
|
|
||||||
|
return(dateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
28
vscode/Unendlichkeitsmaschine/src/json.cpp
Normal file
28
vscode/Unendlichkeitsmaschine/src/json.cpp
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
#include "json.hpp"
|
||||||
|
|
||||||
|
String Myjson::create_json_string(volatile DataStruct *data_struct, size_t nr_dataobjects, time_t runtime_sec)
|
||||||
|
{
|
||||||
|
static unsigned long last_send_ms = 0;
|
||||||
|
unsigned int _sections = nr_dataobjects; //number of different values
|
||||||
|
const unsigned int _sec_objects = NR_JSON_SECTION_OBJECTS; //number of objects per value
|
||||||
|
const unsigned int _obj_members = 5; //number of members per object
|
||||||
|
String json_str = "";
|
||||||
|
|
||||||
|
int _capacity = JSON_ARRAY_SIZE(_sections) + _sec_objects*JSON_OBJECT_SIZE(_obj_members);
|
||||||
|
DynamicJsonDocument _doc(_capacity + 100);
|
||||||
|
_doc["runtime_s"] = runtime_sec;
|
||||||
|
JsonObject _doc_object[_sections];
|
||||||
|
for(unsigned int section_nr = 0; section_nr < _sections; section_nr++)
|
||||||
|
{
|
||||||
|
_doc_object[section_nr] = _doc.createNestedObject(data_struct[section_nr].name);
|
||||||
|
_doc_object[section_nr]["ticks"] = data_struct[section_nr].ticks;
|
||||||
|
_doc_object[section_nr]["value"] = data_struct[section_nr].value;
|
||||||
|
_doc_object[section_nr]["unit"] = data_struct[section_nr].unit;
|
||||||
|
_doc_object[section_nr]["timestamp"] = data_struct[section_nr].timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nr_bytes = serializeJson(_doc, json_str);
|
||||||
|
|
||||||
|
return(json_str);
|
||||||
|
|
||||||
|
}
|
|
@ -1,115 +1,390 @@
|
||||||
#include <ESP32Servo.h>
|
#include "main.hpp"
|
||||||
#include <Arduino.h>
|
|
||||||
#include <Wire.h> // Only needed for Arduino 1.6.5 and earlier
|
|
||||||
#include "SSD1306Wire.h" // legacy: #include "SSD1306.h"
|
|
||||||
|
|
||||||
SSD1306Wire display(0x3c, SDA, SCL);
|
|
||||||
Servo ESC; // Der ESC-Controller (Electronic Speed Controller bzw. elektronischer Fahrtregler) wird als Objekt mit dem Namen "ESC" festgelegt.
|
|
||||||
int Drehregler; // Ausgabewert des Drehreglers
|
int Drehregler; // Ausgabewert des Drehreglers
|
||||||
int speed, last_speed; // Das Wort "Geschwindigkeit" steht als Variable für den Ansteuerungswert am ESC.
|
int speed; // Das Wort "Geschwindigkeit" steht als Variable für den Ansteuerungswert am ESC.
|
||||||
unsigned long turn = 0;
|
int last_speed;
|
||||||
unsigned long speedturns = 0;
|
|
||||||
unsigned long speedchanged_ms = 0;
|
|
||||||
unsigned long speed_u_per_min = 0;
|
|
||||||
|
|
||||||
const uint8_t LED_BUILTIN = 2;
|
time_t run_time = 0;
|
||||||
const uint8_t POTI_PIN = 4;
|
time_t start_time = 0;
|
||||||
const uint8_t ESC_PIN = 16;
|
|
||||||
const uint8_t LS1_PIN = 14;
|
|
||||||
|
|
||||||
const uint8_t MAX_ESC_SPEED = 60;
|
void ISR_HALL1();
|
||||||
const uint8_t MIN_ESC_SPEED = 35;
|
void ISR_HALL2();
|
||||||
const uint16_t MAX_POTI_VALUE = 4095;
|
void ISR_HALL3();
|
||||||
|
void ISR_HALL4();
|
||||||
|
void ISR_HALL5();
|
||||||
|
void ISR_HALL6();
|
||||||
|
void ISR_HALL7();
|
||||||
|
void ISR_HALL8();
|
||||||
|
|
||||||
void show_values();
|
void data_generate();
|
||||||
void ISR();
|
void data_store();
|
||||||
|
void data_check();
|
||||||
|
void data_init();
|
||||||
|
void speed_set();
|
||||||
|
void count_secs(time_t* run_time);
|
||||||
|
|
||||||
|
#ifdef HAS_MQTT
|
||||||
|
void json_init();
|
||||||
|
#endif
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
Serial.begin(9600);
|
delay(1000);
|
||||||
// Initialising the UI will init the display too.
|
Serial.begin(115200);
|
||||||
display.init();
|
Serial.println("Init capture portal ...");
|
||||||
display.clear();
|
|
||||||
display.flipScreenVertically();
|
randomSeed(micros());
|
||||||
//display.setFont(ArialMT_Plain_10);
|
|
||||||
display.setTextAlignment(TEXT_ALIGN_CENTER);
|
display.begin();
|
||||||
display.setFont(ArialMT_Plain_24);
|
capportal.begin();
|
||||||
display.setFont(ArialMT_Plain_16);
|
html_content = "<!DOCTYPE html><html><head><meta http-equiv=\"refresh\" content=\"0; url='/_ac'\" /></head><body></body></html>";
|
||||||
display.drawString(64, 2, "Init controller");
|
|
||||||
display.setFont(ArialMT_Plain_10);
|
#ifdef HAS_MQTT
|
||||||
display.drawString(64, 40, "You may hear some beeps.");
|
mqtt.begin(mqttServer, mqttPort, mqttUser, mqttPassword);
|
||||||
display.drawString(64, 52, "That's OK! ;-)");
|
#endif
|
||||||
display.display();
|
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
Store.begin();
|
||||||
display.setFont(ArialMT_Plain_16);
|
data_init();
|
||||||
|
|
||||||
|
Serial.println("Init ETC ...");
|
||||||
ESC.attach(ESC_PIN,1000,2000);
|
ESC.attach(ESC_PIN,1000,2000);
|
||||||
|
|
||||||
for(uint8_t i=0;i<=100;i=i+10)
|
for(uint8_t i=0;i<=100;i=i+10)
|
||||||
{
|
{
|
||||||
display.drawProgressBar(6, 28, 116, 6, i);
|
display.progressBar(i);
|
||||||
delay(500);
|
delay(500);
|
||||||
ESC.write(0);
|
ESC.write(0);
|
||||||
display.display();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
attachInterrupt(LS1_PIN, ISR, RISING);
|
pinMode(39, INPUT_PULLDOWN);
|
||||||
|
pinMode(HALL1_PIN, INPUT);
|
||||||
|
pinMode(HALL2_PIN, INPUT);
|
||||||
|
pinMode(HALL3_PIN, INPUT);
|
||||||
|
pinMode(HALL4_PIN, INPUT);
|
||||||
|
pinMode(HALL5_PIN, INPUT);
|
||||||
|
pinMode(HALL6_PIN, INPUT);
|
||||||
|
pinMode(HALL7_PIN, INPUT);
|
||||||
|
pinMode(HALL8_PIN, INPUT);
|
||||||
|
|
||||||
last_speed = 0;
|
|
||||||
speed = 0;
|
|
||||||
|
|
||||||
|
//Serial.println("Init light sensor interrupt ...");
|
||||||
|
//attachInterrupt(LS1_PIN, ISR_LS1, RISING);
|
||||||
|
|
||||||
|
Serial.println("Init hall sensor interrupts ...");
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL1_PIN), ISR_HALL1, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL2_PIN), ISR_HALL2, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL3_PIN), ISR_HALL3, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL4_PIN), ISR_HALL4, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL5_PIN), ISR_HALL5, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL6_PIN), ISR_HALL6, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL7_PIN), ISR_HALL7, FALLING);
|
||||||
|
attachInterrupt(digitalPinToInterrupt(HALL8_PIN), ISR_HALL8, FALLING);
|
||||||
|
|
||||||
|
Serial.println(" Auf gehts ... ");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop()
|
void loop()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
capportal.handle();
|
||||||
|
|
||||||
|
data_generate();
|
||||||
|
|
||||||
|
count_secs(&run_time);
|
||||||
|
speed_set();
|
||||||
|
data_check();
|
||||||
|
data_store();
|
||||||
|
|
||||||
|
#ifdef HAS_MQTT
|
||||||
|
mqtt.send_and_loop("infinity/data", json.create_json_string(AllData, ALL_DATA_COUNT, run_time));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
display.show_values(speed, MIN_ESC_SPEED, MAX_ESC_SPEED, HallData, HALL_SENSORS_COUNT, run_time, capportal.localIP());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void count_secs(time_t* run_time)
|
||||||
|
{
|
||||||
|
static time_t last_update_ms = 0;
|
||||||
|
if(last_update_ms == 0)
|
||||||
|
{
|
||||||
|
last_update_ms = millis();
|
||||||
|
}
|
||||||
|
if(millis() - last_update_ms >= 1000)
|
||||||
|
{
|
||||||
|
last_update_ms = millis();
|
||||||
|
*run_time = *run_time + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void speed_set()
|
||||||
|
{
|
||||||
|
static uint8_t _count_meas = 0;
|
||||||
|
static int _Drehregler = 0;
|
||||||
|
static unsigned long _last_read_ms = 0;
|
||||||
|
|
||||||
|
if( millis() - _last_read_ms > 25)
|
||||||
|
{
|
||||||
|
_last_read_ms = millis();
|
||||||
|
int maxDrehregler = 0;
|
||||||
|
int minDrehregler = 0;
|
||||||
|
int sumDrehregler = 0;
|
||||||
|
for(uint8_t i = 0; i<6;i++)
|
||||||
|
{
|
||||||
Drehregler = analogRead(POTI_PIN); // Dieser Befehl liest den Wert des Potentiometers am analogen Pin A0 aus und speichert ihn unter der Variablen "Drehregler". Der Wert liegt zwischen 0 und 1023.
|
Drehregler = analogRead(POTI_PIN); // Dieser Befehl liest den Wert des Potentiometers am analogen Pin A0 aus und speichert ihn unter der Variablen "Drehregler". Der Wert liegt zwischen 0 und 1023.
|
||||||
|
if(i==0)
|
||||||
|
{
|
||||||
|
maxDrehregler = Drehregler;
|
||||||
|
minDrehregler = Drehregler;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(Drehregler < minDrehregler)
|
||||||
|
{
|
||||||
|
minDrehregler = Drehregler;
|
||||||
|
}
|
||||||
|
if(Drehregler > maxDrehregler)
|
||||||
|
{
|
||||||
|
maxDrehregler = Drehregler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sumDrehregler = sumDrehregler + Drehregler;
|
||||||
|
}
|
||||||
|
sumDrehregler = sumDrehregler - maxDrehregler - minDrehregler;
|
||||||
|
sumDrehregler = sumDrehregler/4;
|
||||||
|
speed = map(sumDrehregler, 0, MAX_POTI_VALUE, MIN_ESC_SPEED, MAX_ESC_SPEED); // Der "MAP-" Befehl wandelt den Messwert aus der Variablen "Drehregler" um, damit er am ESC verarbeitet werden kann. Der Zahlenbereich 0 bis 1023 wird dabei in einen Zahlenwert zwischen 0 und 180 umgewandelt.
|
||||||
|
/*
|
||||||
|
if(abs(Drehregler - _Drehregler) < ((_Drehregler * JITTER_POTI_PERCENT)/100) )
|
||||||
|
{
|
||||||
|
_count_meas++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_count_meas = 0;
|
||||||
|
}
|
||||||
|
_Drehregler = Drehregler;
|
||||||
|
|
||||||
|
if(_count_meas >= 4)
|
||||||
|
{
|
||||||
|
_count_meas >= 0;
|
||||||
speed = map(Drehregler, 0, MAX_POTI_VALUE, MIN_ESC_SPEED, MAX_ESC_SPEED); // Der "MAP-" Befehl wandelt den Messwert aus der Variablen "Drehregler" um, damit er am ESC verarbeitet werden kann. Der Zahlenbereich 0 bis 1023 wird dabei in einen Zahlenwert zwischen 0 und 180 umgewandelt.
|
speed = map(Drehregler, 0, MAX_POTI_VALUE, MIN_ESC_SPEED, MAX_ESC_SPEED); // Der "MAP-" Befehl wandelt den Messwert aus der Variablen "Drehregler" um, damit er am ESC verarbeitet werden kann. Der Zahlenbereich 0 bis 1023 wird dabei in einen Zahlenwert zwischen 0 und 180 umgewandelt.
|
||||||
if(speed != last_speed)
|
}
|
||||||
{
|
*/
|
||||||
last_speed = speed;
|
|
||||||
speedchanged_ms = millis();
|
|
||||||
speedturns = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(millis() - speedchanged_ms > 10000)
|
|
||||||
{
|
|
||||||
speed_u_per_min = (speedturns*6);
|
|
||||||
speedturns = 0;
|
|
||||||
speedchanged_ms = millis();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Serial.print("Drehregler:"); Serial.print(Drehregler); Serial.print(", Speed:");Serial.println(speed);
|
|
||||||
if(MIN_ESC_SPEED < speed)
|
if(MIN_ESC_SPEED < speed)
|
||||||
ESC.write(speed); // Der endgültige Wert für den ESC wird an den ESC gesendet. Der ESC nimmt das Signal an dieser Stelle auf und steuert den Motor entsprechend der gesendeten Werte an.
|
ESC.write(speed); // Der endgültige Wert für den ESC wird an den ESC gesendet. Der ESC nimmt das Signal an dieser Stelle auf und steuert den Motor entsprechend der gesendeten Werte an.
|
||||||
else
|
else
|
||||||
ESC.write(0);
|
ESC.write(0);
|
||||||
|
|
||||||
show_values();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_values()
|
void data_init()
|
||||||
{
|
{
|
||||||
display.clear();
|
Serial.println("Init internal data ...");
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
#ifdef MACHINE_RESTART
|
||||||
display.setFont(ArialMT_Plain_10);
|
run_time = 0;
|
||||||
display.drawString(1, 1, "Speed:");
|
start_time = capportal.epochTime();
|
||||||
display.drawProgressBar(40, 4, 80, 6, map(speed, MIN_ESC_SPEED,MAX_ESC_SPEED,0,100));
|
Store.set_int(EEPROM_NAME_RUN_TIME , run_time );
|
||||||
display.setFont(ArialMT_Plain_10);
|
Store.set_int(EEPROM_NAME_START_EPOCHTIME, start_time );
|
||||||
display.drawString(1, 15, "Turns:");
|
Serial.printf("Machine restarted. Set runtime to 0. Stored this value and the epoch start time %lu to EEPROM.\n", start_time);
|
||||||
display.drawString(35, 15, String(turn));
|
#else
|
||||||
display.setFont(ArialMT_Plain_24);
|
run_time = Store.get_int(EEPROM_NAME_RUN_TIME );
|
||||||
display.setTextAlignment(TEXT_ALIGN_RIGHT);
|
start_time = Store.get_int(EEPROM_NAME_START_EPOCHTIME );
|
||||||
display.drawString(64, 37, String(speed_u_per_min));
|
Serial.printf("Machine runtime loaded from EPPROM: %lu seconds. Machine was started %s\n", run_time, capportal.localTime(start_time));
|
||||||
display.setTextAlignment(TEXT_ALIGN_LEFT);
|
#endif
|
||||||
display.drawString(68,37, "U/min");
|
last_speed = 0;
|
||||||
display.display();
|
speed = 0;
|
||||||
}
|
for (uint8_t i = 0; i < ALL_DATA_COUNT; i ++)
|
||||||
|
|
||||||
void IRAM_ATTR ISR()
|
|
||||||
{
|
{
|
||||||
turn++;
|
AllData[i].name = Data_names[i];
|
||||||
speedturns++;
|
AllData[i].unit = Data_units[i];
|
||||||
|
AllData[i].value = 0;
|
||||||
|
AllData[i].unit_factor = Data_units_factor[i];
|
||||||
|
AllData[i].period_ticks = 0;
|
||||||
|
#ifdef MACHINE_RESTART
|
||||||
|
AllData[i].ticks = 0;
|
||||||
|
#else
|
||||||
|
AllData[i].ticks = Store.get_int(EEPROM_NAME_TICK+String(i));
|
||||||
|
AllData[i].timestamp = Store.get_int(EEPROM_NAME_TIMESTAMP+String(i));
|
||||||
|
#endif
|
||||||
|
AllData[i].last_update_ms = 0;
|
||||||
|
AllData[i].timestamp = 0;
|
||||||
|
}
|
||||||
|
delay(500);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void data_check()
|
||||||
|
{
|
||||||
|
static unsigned long speedchanged_ms ;
|
||||||
|
unsigned long current_millis = millis();
|
||||||
|
|
||||||
|
Serial.printf("H1(pin %d): %d, H2(pin %d): %d, H3(pin %d): %d, H4(pin %d): %d, H5(pin %d) : %d, H6(pin %d) : %d, H7(pin %d) : %d, H8(pin %d) : %d.\n",
|
||||||
|
HALL1_PIN, digitalRead(HALL1_PIN),
|
||||||
|
HALL2_PIN, digitalRead(HALL2_PIN),
|
||||||
|
HALL3_PIN, digitalRead(HALL3_PIN),
|
||||||
|
HALL4_PIN, digitalRead(HALL4_PIN),
|
||||||
|
HALL5_PIN, digitalRead(HALL5_PIN),
|
||||||
|
HALL6_PIN, digitalRead(HALL6_PIN),
|
||||||
|
HALL7_PIN, digitalRead(HALL7_PIN),
|
||||||
|
HALL8_PIN, digitalRead(HALL8_PIN)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
if(speed != last_speed)
|
||||||
|
{
|
||||||
|
last_speed = speed;
|
||||||
|
speedchanged_ms = current_millis;
|
||||||
|
HallData[0].period_ticks = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(current_millis - speedchanged_ms > UPDATE_TURN_VALUES_EVERY_MS)
|
||||||
|
{
|
||||||
|
speedchanged_ms = current_millis;
|
||||||
|
HallData[0].value = (HallData[0].period_ticks * HallData[0].unit_factor);
|
||||||
|
HallData[0].period_ticks = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(uint8_t nr = 1; nr < HALL_SENSORS_COUNT; nr++)
|
||||||
|
{
|
||||||
|
HallData[nr].value = (HallData[nr].ticks * HallData[nr].unit_factor);
|
||||||
|
HallData[nr].period_ticks = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void data_store()
|
||||||
|
{
|
||||||
|
static unsigned long _last_stored_ms = 0;
|
||||||
|
if(_last_stored_ms == 0)
|
||||||
|
{
|
||||||
|
_last_stored_ms = millis();
|
||||||
|
}
|
||||||
|
if(millis() - _last_stored_ms >= EEPROM_STORE_RUNTIME_ALL_MS)
|
||||||
|
{
|
||||||
|
_last_stored_ms = millis();
|
||||||
|
Store.set_int(EEPROM_NAME_RUN_TIME, run_time);
|
||||||
|
for(uint8_t nr = 0; nr < HALL_SENSORS_COUNT; nr++)
|
||||||
|
{
|
||||||
|
Store.set_int(EEPROM_NAME_TICK+String(nr), HallData[nr].ticks);
|
||||||
|
Store.set_int(EEPROM_NAME_TIMESTAMP+String(nr), HallData[nr].timestamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL1()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 0;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL2()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 1;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL3()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 2;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL4()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 3;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL5()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 4;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL6()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 5;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL7()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 6;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRAM_ATTR ISR_HALL8()
|
||||||
|
{
|
||||||
|
const uint8_t hallnr = 7;
|
||||||
|
HallData[hallnr].ticks++;
|
||||||
|
HallData[hallnr].period_ticks++;
|
||||||
|
HallData[hallnr].timestamp = run_time;
|
||||||
|
HallData[hallnr].last_update_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
//this code is just for generating dummy data - in normal use not needed
|
||||||
|
void data_generate()
|
||||||
|
{
|
||||||
|
#ifdef DUMMY_DATA
|
||||||
|
|
||||||
|
static unsigned long _last_updated_ms = 0;
|
||||||
|
unsigned long _wait_ms = map(speed, MIN_ESC_SPEED, MAX_ESC_SPEED, 60000/500/4, 60000/1500/4);
|
||||||
|
//Serial.printf("Speed is : %lu and _wait_ms is %lu\n", speed, _wait_ms);
|
||||||
|
|
||||||
|
if(_last_updated_ms == 0)
|
||||||
|
{
|
||||||
|
_last_updated_ms = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(millis() - _last_updated_ms >= _wait_ms )
|
||||||
|
{
|
||||||
|
_last_updated_ms = millis();
|
||||||
|
|
||||||
|
for(uint8_t i = 0; i < HALL_SENSORS_COUNT; i++)
|
||||||
|
{
|
||||||
|
if(i == 0)
|
||||||
|
{
|
||||||
|
HallData[i].ticks++;
|
||||||
|
HallData[i].period_ticks++;
|
||||||
|
HallData[i].last_update_ms = millis();
|
||||||
|
HallData[i].timestamp = run_time;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Serial.printf("i=%d HallData[i-1].ticks=%lu %4 = %d\n" , i, HallData[i-1].ticks , HallData[i-1].ticks % 4);
|
||||||
|
if (HallData[i].last_update_ms != HallData[i-1].last_update_ms && HallData[i-1].ticks % 4 == 0)
|
||||||
|
{
|
||||||
|
HallData[i].ticks++;
|
||||||
|
HallData[i].period_ticks++;
|
||||||
|
HallData[i].last_update_ms = HallData[i-1].last_update_ms;
|
||||||
|
HallData[i].timestamp = run_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
131
vscode/Unendlichkeitsmaschine/src/mqtt.cpp
Normal file
131
vscode/Unendlichkeitsmaschine/src/mqtt.cpp
Normal file
|
@ -0,0 +1,131 @@
|
||||||
|
#include "mqtt.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
void Mymqtt::begin(const char * server, uint16_t mqttPort, const char* mqttUser, const char* mqttPassword)
|
||||||
|
{
|
||||||
|
_server = server;
|
||||||
|
_port = mqttPort;
|
||||||
|
_mqttPassword = mqttPassword;
|
||||||
|
_mqttUser = mqttUser;
|
||||||
|
espClient = new WiFiClientSecure();//new WiFiClient();
|
||||||
|
client = new PubSubClient(*espClient);
|
||||||
|
client->setBufferSize(MQTT_BUFFER_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void callback(char* topic, byte* payload, unsigned int length) {
|
||||||
|
String incommingMessage = "";
|
||||||
|
for (int i = 0; i < length; i++) incommingMessage+=(char)payload[i];
|
||||||
|
Serial.println("Message arrived ["+String(topic)+"]"+incommingMessage);
|
||||||
|
// check for other commands
|
||||||
|
/* else if( strcmp(topic,command2_topic) == 0){
|
||||||
|
if (incommingMessage.equals(“1”)) { } // do something else
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mymqtt::connect()
|
||||||
|
{
|
||||||
|
static unsigned long last_connection_try_ms = 0;
|
||||||
|
unsigned long start_ms = 0;
|
||||||
|
if(true == is_connected())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if((last_connection_try_ms == 0) || (millis() - last_connection_try_ms > MQTT_TRY_TO_CONNECT_MS))
|
||||||
|
{
|
||||||
|
last_connection_try_ms = millis();
|
||||||
|
if (WiFi.status() == WL_CONNECTED)
|
||||||
|
{
|
||||||
|
Serial.printf("(Re)connecting to MQTT ... server '%s' port: %d \n", _server.c_str(), _port);
|
||||||
|
espClient->setCACert(root_ca);
|
||||||
|
client->setServer(_server.c_str(), _port);
|
||||||
|
client->setCallback(callback);
|
||||||
|
start_ms = millis();
|
||||||
|
String clientId = MQTT_CHANNEL "-"; // Create a random client ID
|
||||||
|
clientId += String(random(0xffff), HEX);
|
||||||
|
if (client->connect(MQTT_CHANNEL, _mqttUser.c_str(), _mqttPassword.c_str()))
|
||||||
|
{
|
||||||
|
Serial.println(" -> MQTT connected");
|
||||||
|
String connect_msg = "Connected from Infinitymachine of MakerLab Murnau e.V at " + String(millis());
|
||||||
|
if(client->publish("infinity/connected", connect_msg.c_str()))
|
||||||
|
{
|
||||||
|
Serial.println("Connection and initial publish passed.");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("Connection and initial publish FAILED.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.print(" -> MQTT connection failed with state ");
|
||||||
|
Serial.println(client->state());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Serial.println("Not connected to the WiFi network");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(is_connected());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mymqtt::is_connected()
|
||||||
|
{
|
||||||
|
return(client->connected());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mymqtt::publish(String topic,String data)
|
||||||
|
{
|
||||||
|
if(true == connect())
|
||||||
|
{
|
||||||
|
client->publish(topic.c_str(), data.c_str(), true);
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mymqtt::loop()
|
||||||
|
{
|
||||||
|
if(true == connect())
|
||||||
|
{
|
||||||
|
client->loop();
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Mymqtt::send_and_loop(String topic,String data)
|
||||||
|
{
|
||||||
|
static unsigned long _last_sent_ms = 0;
|
||||||
|
if(millis() - _last_sent_ms >= SEND_MQTT_EVERY_MS)
|
||||||
|
{
|
||||||
|
_last_sent_ms = millis();
|
||||||
|
if(true == connect())
|
||||||
|
{
|
||||||
|
client->loop();
|
||||||
|
if(data != _data_sent)
|
||||||
|
{
|
||||||
|
if((MQTT_BUFFER_SIZE - 20) > data.length())
|
||||||
|
{
|
||||||
|
if( client->publish(topic.c_str(), data.c_str() , data.length()) )
|
||||||
|
{
|
||||||
|
_data_sent = data;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Serial.printf("Sending data (topic: %s): FAILED!!!\n -> '%s'\n", topic.c_str(), data.c_str());
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Serial.printf("Data length (%d) is larger than MQTT buffer(%d + 20bytes header)\n", data.length(), MQTT_BUFFER_SIZE);
|
||||||
|
return(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return(false);
|
||||||
|
}
|
237
vscode/Unendlichkeitsmaschine/src/oled.cpp
Normal file
237
vscode/Unendlichkeitsmaschine/src/oled.cpp
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
#include "oled.hpp"
|
||||||
|
//#include "main.hpp"
|
||||||
|
|
||||||
|
void Oled::begin()
|
||||||
|
{
|
||||||
|
display = new SSD1306Wire(0x3c, SDA, SCL);
|
||||||
|
Serial.println("Init OLED display ...");
|
||||||
|
display->init();
|
||||||
|
display->clear();
|
||||||
|
display->flipScreenVertically();
|
||||||
|
//display->setFont(ArialMT_Plain_10);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->setFont(ArialMT_Plain_24);
|
||||||
|
display->setFont(ArialMT_Plain_16);
|
||||||
|
display->drawString(64, 2, "Init controller");
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
display->drawString(64, 40, "You may hear some beeps.");
|
||||||
|
display->drawString(64, 52, "That's OK! ;-)");
|
||||||
|
display->display();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(ArialMT_Plain_16);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::progressBar(uint8_t i)
|
||||||
|
{
|
||||||
|
display->drawProgressBar(6, 28, 116, 6, i);
|
||||||
|
display->display();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::next_page(bool speedchange)
|
||||||
|
{
|
||||||
|
static unsigned long last_switch_page_ms = 0;
|
||||||
|
|
||||||
|
if(last_switch_page_ms == 0)
|
||||||
|
{
|
||||||
|
page_nr = MIN_PAGE_NR;
|
||||||
|
last_switch_page_ms = millis();
|
||||||
|
}
|
||||||
|
if(speedchange == true)
|
||||||
|
{
|
||||||
|
last_switch_page_ms = millis();
|
||||||
|
page_nr = SPEED;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if(millis() - last_switch_page_ms > PAGE_VIEW_TIME_MS)
|
||||||
|
{
|
||||||
|
last_switch_page_ms = millis();
|
||||||
|
if(page_nr >= MAX_PAGE_NR)
|
||||||
|
{
|
||||||
|
page_nr = MIN_PAGE_NR;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
page_nr++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
page = (pages)page_nr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::show_values(int speed, int min_speed, int max_speed, volatile DataStruct *HallData, uint8_t hall_sensors_count, unsigned long runtime, String ipaddr)
|
||||||
|
{
|
||||||
|
const uint8_t local_hall_count = 8;
|
||||||
|
static int _speed = 0;
|
||||||
|
static double _hall[local_hall_count] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
static unsigned long _runtime = 0;
|
||||||
|
static String _ipaddr = "-";
|
||||||
|
|
||||||
|
bool hall_has_changed = false;
|
||||||
|
for(uint8_t i = 0; i < min(local_hall_count,hall_sensors_count); i++)
|
||||||
|
{
|
||||||
|
if(_hall[i] != HallData[i].value)
|
||||||
|
{
|
||||||
|
hall_has_changed = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( _speed != speed || hall_has_changed == true || _runtime != runtime || _ipaddr != ipaddr)
|
||||||
|
{
|
||||||
|
|
||||||
|
next_page(_speed != speed);
|
||||||
|
|
||||||
|
_speed = speed;
|
||||||
|
for(uint8_t i = 0; i < min(local_hall_count,hall_sensors_count); i++)
|
||||||
|
{
|
||||||
|
_hall[i] = HallData[i].value;
|
||||||
|
}
|
||||||
|
_runtime = runtime; //runtime comes in in secs
|
||||||
|
_ipaddr = ipaddr;
|
||||||
|
|
||||||
|
show_page_header(ipaddr, page);
|
||||||
|
show_speed(speed, min_speed, max_speed, _hall[0], _runtime, page );
|
||||||
|
show_halls(HallData, min(local_hall_count,hall_sensors_count), page);
|
||||||
|
show_page_footer(page);
|
||||||
|
display->display();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::show_page_footer(pages page)
|
||||||
|
{
|
||||||
|
const int16_t distance = 1;
|
||||||
|
int16_t _xpos = 0;
|
||||||
|
uint8_t nr_pages = 1+(MAX_PAGE_NR - MIN_PAGE_NR);
|
||||||
|
const int16_t radius = 3;
|
||||||
|
const int16_t _ypos = 66 - radius;
|
||||||
|
uint8_t space_all_circles = nr_pages*(2*radius) + (nr_pages-1)*distance;
|
||||||
|
uint8_t start_xpos = (128-space_all_circles)/2;
|
||||||
|
for(uint8_t i = 0; i < nr_pages; i++)
|
||||||
|
{
|
||||||
|
_xpos = start_xpos + i*(radius*2+distance);
|
||||||
|
if((pages)i == page)
|
||||||
|
{
|
||||||
|
display->fillCircle(_xpos, _ypos, radius);
|
||||||
|
|
||||||
|
}
|
||||||
|
display->drawCircle(_xpos, _ypos, radius);
|
||||||
|
}
|
||||||
|
display->drawHorizontalLine(0,63,start_xpos-3);
|
||||||
|
display->drawHorizontalLine(_xpos+radius*2-2,63,128 - (_xpos+radius*2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::show_page_header(String ipaddr, pages page)
|
||||||
|
{
|
||||||
|
xpos = 0;
|
||||||
|
ypos = 0;
|
||||||
|
display->clear();
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
switch(page)
|
||||||
|
{
|
||||||
|
case HALL1:
|
||||||
|
case HALL2:
|
||||||
|
display->drawString(0, ypos, "Measured numbers:");
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
break;
|
||||||
|
case SPEED:
|
||||||
|
default:
|
||||||
|
if(ipaddr == "0.0.0.0")
|
||||||
|
{
|
||||||
|
display->drawString(0, ypos, "No WiFi.");
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display->drawString(128,ypos, "x");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
display->drawString(0, ypos, "IP:" + ipaddr);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display->drawString(128,ypos, "Y");
|
||||||
|
display->drawString(124,ypos-2, "--");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
display->drawHorizontalLine(0,ypos+12, 128);
|
||||||
|
ypos = ypos + 13;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::show_speed(int speed, int min_speed, int max_speed, double u_min, unsigned long runtime, pages page)
|
||||||
|
{
|
||||||
|
if(page == SPEED)
|
||||||
|
{
|
||||||
|
static char _runtime_str[26];
|
||||||
|
static unsigned long _runtime = 0;
|
||||||
|
if( _runtime != runtime || _runtime == 0)
|
||||||
|
{
|
||||||
|
_runtime = runtime;
|
||||||
|
uint8_t _runtime_years = _runtime / (365*24*3600 + 6*3600); // this includes the leap year as an offset of 6hours each year -> all for years this is a full day
|
||||||
|
_runtime = _runtime - _runtime_years * (365*24*3600 + 6*3600);
|
||||||
|
uint8_t _runtime_month = _runtime / (30*24*3600); //assumes a month has 30 days ...
|
||||||
|
_runtime = _runtime - _runtime_month * (30*24*3600);
|
||||||
|
uint8_t _runtime_week = _runtime / (7*24*3600);
|
||||||
|
_runtime = _runtime - _runtime_week * (7*24*3600);
|
||||||
|
uint8_t _runtime_days = _runtime / (24*3600); // time in days
|
||||||
|
_runtime = _runtime - _runtime_days * (24*3600);
|
||||||
|
uint8_t _runtime_hour = _runtime / 3600 ;
|
||||||
|
_runtime = _runtime - _runtime_hour * 3600;
|
||||||
|
uint8_t _runtime_min = _runtime / 60;
|
||||||
|
_runtime = _runtime - _runtime_min * 60;
|
||||||
|
uint8_t _runtime_sec = _runtime;
|
||||||
|
sprintf(_runtime_str, "%01dy %02dm %01dw %01dd %02dh %02dm %02ds", _runtime_years, _runtime_month, _runtime_week, _runtime_days, _runtime_hour, _runtime_min, _runtime_sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t _ypos = ypos;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
display->drawString(1, _ypos, "Speed:");
|
||||||
|
display->drawProgressBar(38, _ypos+4, 87, 5 , map(speed, min_speed, max_speed,0,100));
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
_ypos=_ypos+9;
|
||||||
|
display->setFont(ArialMT_Plain_24);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display->drawString(83, _ypos, String(u_min));
|
||||||
|
display->setFont(ArialMT_Plain_16);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->drawString(85,_ypos+8, "U/min");
|
||||||
|
_ypos=_ypos+24;
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_CENTER);
|
||||||
|
display->drawString(64, _ypos, _runtime_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Oled::show_halls(volatile DataStruct *HallData, uint8_t hall_sensor_count, pages page)
|
||||||
|
{
|
||||||
|
if(page == HALL1 || page == HALL2)
|
||||||
|
{
|
||||||
|
uint8_t hall_start = (page_nr-HALL1)*HALLS_PER_PAGE;
|
||||||
|
uint8_t hall_count = min(HALLS_PER_PAGE, (uint8_t)(hall_sensor_count-hall_start));
|
||||||
|
uint8_t _ypos = ypos;
|
||||||
|
uint8_t _xpos = 1;
|
||||||
|
display->setFont(ArialMT_Plain_10);
|
||||||
|
_ypos = _ypos + 1;
|
||||||
|
_xpos = _xpos + 1;
|
||||||
|
for(uint8_t i=hall_start; i<(hall_count+hall_start);i++)
|
||||||
|
{
|
||||||
|
String text = "H" + String(i+1) + " [" + String(HallData[i].unit) + "] ";
|
||||||
|
String value = String(HallData[i].value);
|
||||||
|
String point = ".";
|
||||||
|
uint16_t width_text = display->getStringWidth(text);
|
||||||
|
uint16_t width_value = display->getStringWidth(value);
|
||||||
|
uint16_t width_point = display->getStringWidth(point);
|
||||||
|
uint8_t nr_points = (128-_xpos-width_text-width_value)/width_point;
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_LEFT);
|
||||||
|
display->drawString(_xpos, _ypos, text);
|
||||||
|
for(uint8_t i=0;i<nr_points-1;i++)
|
||||||
|
{
|
||||||
|
display->drawString(_xpos+width_text+i*width_point, _ypos, point);
|
||||||
|
}
|
||||||
|
display->setTextAlignment(TEXT_ALIGN_RIGHT);
|
||||||
|
display->drawString(128,_ypos, value);
|
||||||
|
_ypos = _ypos + 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue