This commit is contained in:
Michal Courson
2025-08-28 21:35:21 -04:00
commit 82dde89d80
23 changed files with 6801 additions and 0 deletions

4
main/CMakeLists.txt Normal file
View File

@ -0,0 +1,4 @@
idf_component_register(
SRCS "main.cpp" "Config.cpp" "kartSender.cpp" "Detector.cpp"
INCLUDE_DIRS ""
)

63
main/Config.cpp Normal file
View File

@ -0,0 +1,63 @@
#include "Config.hpp"
#include <math.h>
#include "FS.h"
#include "SPIFFS.h"
Config config;
void Config::Init() {
SPIFFS.begin(true);
File f = SPIFFS.open("/config.json", FILE_READ);
if (!f) {
SetDefaults();
return;
}
DeserializationError err = deserializeJson(conf_json, f);
if (err == DeserializationError::Ok) {
Load();
} else {
SetDefaults();
}
f.close();
}
void Config::SetDefaults() {
Serial.println("Setting default config");
// Set default MAC address
trackside_mac[0] = 0x34;
trackside_mac[1] = 0x85;
trackside_mac[2] = 0x18;
trackside_mac[3] = 0xa9;
trackside_mac[4] = 0x3d;
trackside_mac[5] = 0xfc;
// Set default kart ID
kart_id = esp_random();
// Save the defaults to SPIFFS
Save();
}
void Config::Save() {
conf_json.to<JsonObject>();
JsonArray arr = conf_json["mac"].to<JsonArray>();
for (int i = 0; i < 6; i++) {
arr.add<int>(trackside_mac[i]);
}
conf_json["kart_id"] = kart_id;
String out;
serializeJson(conf_json, out);
File f = SPIFFS.open("/config.json", FILE_WRITE, true);
f.print(out);
f.close();
Serial.printf("Config saved: %s\n", out.c_str());
}
void Config::Load() {
JsonArray arr = conf_json["mac"];
for (int i = 0; i < 6; i++) {
trackside_mac[i] = arr[i];
}
kart_id = conf_json["kart_id"];
}

22
main/Config.hpp Normal file
View File

@ -0,0 +1,22 @@
#ifndef CONFIG_HPP
#define CONFIG_HPP
#include <Arduino.h>
#include <ArduinoJson.h>
class Config {
public:
void Init();
void Save();
uint8_t trackside_mac[6] = {0x34, 0x85, 0x18, 0xa9, 0x3d, 0xfc};
uint32_t kart_id = -1;
private:
void Load();
void SetDefaults();
JsonDocument conf_json;
};
extern Config config;
#endif

37
main/Detector.cpp Normal file
View File

@ -0,0 +1,37 @@
#include "Detector.hpp"
#include "TimeSync.hpp"
#include "kartSender.hpp"
Detector detector;
#define PIN_BUTTON 0
#define NUM_SAMPLES 100
void Detector::Init() {
pinMode(PIN_BUTTON, INPUT_PULLUP);
}
void Detector::Tasks() {
uint32_t avg = 0;
for (int i = 0; i < NUM_SAMPLES; i++) {
avg += analogRead(1);
}
float detect = avg / (float)NUM_SAMPLES / 4095.0f;
detect -= .37; // idle state
// Serial.printf("Button detect: %.2f\n", detect);
uint16_t button_state = detect < .02f;
if (button_state != last_button_state) {
if (!button_state) {
falling_edge_time = millis();
handled = false;
}
}
last_button_state = button_state;
if (!button_state && millis() - falling_edge_time > 30 && !handled) {
handled = true;
// Serial.printf("Timestamp: %llu\n", TimeSync::GetTime());
kart_sender.Send();
}
}

18
main/Detector.hpp Normal file
View File

@ -0,0 +1,18 @@
#ifndef DETECTOR_HPP
#define DETECTOR_HPP
#include "Arduino.h"
class Detector {
public:
void Init();
void Tasks();
private:
uint32_t falling_edge_time;
bool last_button_state;
bool handled;
};
extern Detector detector;
#endif

37
main/TimeSync.hpp Normal file
View File

@ -0,0 +1,37 @@
#ifndef TIMESYNC_HPP
#define TIMESYNC_HPP
#include <sys/time.h>
#include "Arduino.h"
#include "WiFi.h"
#include "time.h"
class TimeSync {
public:
static void Sync() {
const char* ssid = "ConnectonRefused";
const char* password = "retryconnection";
const char* ntpServer = "pool.ntp.org";
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected.");
configTime(0, 0, ntpServer);
delay(2000);
WiFi.disconnect();
}
static uint64_t GetTime() {
struct timeval tv;
gettimeofday(&tv, NULL); // gets time in seconds and microseconds
uint64_t epochMillis = (uint64_t)tv.tv_sec * 1000 + (tv.tv_usec / 1000);
return epochMillis;
}
};
#endif

19
main/idf_component.yml Normal file
View File

@ -0,0 +1,19 @@
## IDF Component Manager Manifest File
dependencies:
## Required IDF version
idf:
version: '>=4.1.0'
# # Put list of dependencies here
# # For components maintained by Espressif:
# component: "~1.0.0"
# # For 3rd party components:
# username/component: ">=1.0.0,<2.0.0"
# username2/component2:
# version: "~1.0.0"
# # For transient dependencies `public` flag can be set.
# # `public` flag doesn't have an effect dependencies of the `main` component.
# # All dependencies of `main` are public by default.
# public: true
espressif/arduino-esp32: ^3.3.0
bblanchon/arduinojson: ^7.4.2
esp32async/espasyncwebserver: ^3.7.10

10
main/kartMessage.hpp Normal file
View File

@ -0,0 +1,10 @@
#ifndef KART_MESSAGE_HPP
#define KART_MESSAGE_HPP
#include "Arduino.h"
typedef struct {
uint32_t kart_id;
uint32_t transmision;
} kart_msg;
#endif

64
main/kartSender.cpp Normal file
View File

@ -0,0 +1,64 @@
#include "kartSender.hpp"
#include <esp_now.h>
#include <esp_wifi.h>
#include "Arduino.h"
#include "Config.hpp"
#include "WiFi.h"
#include "kartMessage.hpp"
bool tp_state = false;
KartSender kart_sender;
// callback when data is sent
void OnDataSent(const esp_now_send_info_t *tx_info, esp_now_send_status_t status) {
if (status == ESP_NOW_SEND_SUCCESS) {
// esp_now_deinit();
}
// Serial.print("\r\nLast Packet Send Status:\t");
// Serial.println(status == ESP_NOW_SEND_SUCCESS ? "Delivery Success" : "Delivery Fail");
}
esp_now_peer_info_t peerInfo;
void KartSender::Send() {
tp_state = !tp_state;
digitalWrite(21, tp_state);
kart_msg myData;
myData.kart_id = config.kart_id;
myData.transmision = transmission_counter++;
// Send message via ESP-NOW
esp_err_t result = esp_now_send(config.trackside_mac, (uint8_t *)&myData, sizeof(myData));
if (result == ESP_OK) {
Serial.println("Sent with success");
} else {
Serial.println("Error sending the data");
}
}
void KartSender::Init() {
WiFi.mode(WIFI_STA);
// Init ESP-NOW
if (esp_now_init() != ESP_OK) {
Serial.println("Error initializing ESP-NOW");
return;
}
// Once ESPNow is successfully Init, we will register for Send CB to
// get the status of Transmitted packet
esp_now_register_send_cb(OnDataSent);
// Register peer
memcpy(peerInfo.peer_addr, config.trackside_mac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;
// Add peer
if (esp_now_add_peer(&peerInfo) != ESP_OK) {
Serial.println("Failed to add peer");
return;
}
}

17
main/kartSender.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef KART_SENDER_HPP
#define KART_SENDER_HPP
#include "Arduino.h"
class KartSender {
public:
void Init();
void Send();
private:
uint32_t transmission_counter = 0;
};
extern KartSender kart_sender;
#endif

36
main/main.cpp Normal file
View File

@ -0,0 +1,36 @@
#include <esp_now.h>
#include <esp_wifi.h>
#include "Arduino.h"
#include "Config.hpp"
#include "Detector.hpp"
#include "TimeSync.hpp"
#include "WiFi.h"
#include "kartMessage.hpp"
#include "kartSender.hpp"
// Create a struct_message called myData
int trans = 0;
void setup() {
// Init Serial Monitor
Serial.begin(115200);
Serial.setTxBufferSize(255);
Serial.setRxBufferSize(255);
pinMode(21, OUTPUT);
digitalWrite(21, LOW);
// Set device as a Wi-Fi Station
// TimeSync::Sync();
config.Init();
kart_sender.Init();
detector.Init();
}
void loop() {
// Set values to send
// kart_sender.Send();
// delay(5000);
detector.Tasks();
delay(5);
}