sirens/AGENTS.md
Michael Winter 0fbf33b756 Restructure project with OpenSCAD redesign and v1 legacy code
- Move legacy FreeCAD files to v1/
- Add OpenSCAD programmatic CAD designs
- Add README and AGENTS.md documentation
- Add .gitignore
- Update firmware to v2 architecture
2026-03-29 14:24:42 +02:00

5.7 KiB

AGENTS.md - Sirens Project

Project Overview

This is an Arduino/ESP32 embedded systems project for controlling sirens. The codebase consists of multiple Arduino sketches (.ino files) for different hardware components.

Directory Structure

sirens/
├── src/
│   ├── siren_remote_control_esp32_v2/           # Remote control unit
│   │   └── siren_remote_control_esp32_v2.ino
│   ├── siren_controller_esp32_simple_station_v2_multi/  # Station controller
│   │   └── siren_controller_esp32_simple_station_v2_multi.ino
│   └── B_G431B_ESC1_motor_controller/           # SimpleFOC motor controller
│       └── B_G431B_ESC1_motor_controller.ino
├── v1/                                           # Version 1 designs
├── designs/                                      # CAD files (OpenSCAD, STL)
└── AGENTS.md                                     # This file

Build Commands

Current State

  • No command-line build system configured - Uses Arduino IDE
  • Upload via Arduino IDE or PlatformIO (recommended for future)

Future: PlatformIO Migration (TODO)

# Once PlatformIO is configured:
pio run                          # Build all projects
pio run -e <environment>         # Build specific environment
pio run -t upload                # Upload to device
pio device monitor               # Monitor serial output

Running a Single Test

  • No unit tests exist - Embedded projects typically test via hardware
  • For now, manual testing on physical hardware is required

Libraries

The project uses the following Arduino/ESP32 libraries:

Library Purpose
WiFi ESP32 WiFi connectivity
Wire I2C communication
SSD1306Ascii / SSD1306AsciiWire OLED display (128x64)
ArduinoOSCWiFi OSC protocol over WiFi
AiEsp32RotaryEncoder Rotary encoder input
arduino-timer Timer/async operations
Preferences ESP32 NVS storage
SimpleFOC Motor control (B-G431B-ESC1)
SimpleFOCDrivers SimpleFOC driver utilities

Code Style Guidelines

General Conventions

  • Language: C++ (Arduino framework)
  • File extension: .ino (Arduino sketch)
  • Naming: camelCase for variables and functions
  • Constants: UPPER_SNAKE_CASE with const or #define

Arduino Sketch Structure

// 1. Includes
#include "WiFi.h"
#include <Wire.h>
#include <SSD1306Ascii.h>

// 2. Global constants
const int sirenCount = 4;
const char* ssid = "sirening";

// 3. Global variables
int menuSelect = 0;

// 4. Function prototypes (if needed)
void setupEncoderButton(AiEsp32RotaryEncoder& eb, char* val);

// 5. setup() - runs once at boot
void setup() {
  Serial.begin(115200);
  // initialization code...
}

// 6. loop() - runs continuously
void loop() {
  // main logic...
}

Functions

  • Keep functions focused and reasonably sized (<100 lines)
  • Use descriptive names: updateFreq(), killAll(), setupOSC()
  • Group related functions together
  • Use helper functions to reduce duplication in loop()

Types

  • Use explicit types: int, float, bool, unsigned long
  • Prefer const for values that won't change
  • Use float for floating-point values (no double on ESP32)

Error Handling

  • Return early on errors:
    if(!currentSense.init()){
      Serial.println("Current sense init failed.");
      return;
    }
    
  • Use Serial for debugging output with descriptive messages
  • Validate input ranges before use:
    if (input < 500.0 && input >= 0.0) {
      updateFreq(input);
    }
    

Interrupt Service Routines (ISR)

  • Mark ISRs with IRAM_ATTR on ESP32:
    void IRAM_ATTR readFreqEncoderISR() {
      encoderButton1.readEncoder_ISR();
    }
    
  • Keep ISRs minimal - only do essential work

Display/UI Code

  • Use helper functions for display updates:
    void updateDisplayValue(String string) {
      oled.set2X();
      oled.setCursor(12, 5);
      oled.print(string);
      oled.clearToEOL();
    }
    

OSC Communication

  • Use lambda callbacks for OSC subscriptions:
    OscWiFi.subscribe(settings_port, "/freq", [](const OscMessage& m) {
      float input = m.arg<float>(0);
      // handle message...
    });
    

Preferences (NVS)

  • Open with explicit mode:
    prefs.begin("prefs", RO_MODE);  // false = read/write, true = read only
    prefs.putUInt("ports", ports);
    prefs.getUInt("ports");
    prefs.end();
    

Serial Communication

  • Use Serial.begin(115200) for debug output
  • Use HardwareSerial for additional UARTs:
    HardwareSerial freqSerial(1);
    freqSerial.begin(115200, SERIAL_8N1, 18, 19);
    

Comments

  • Use TODO comments for future work:
    //TODO: These should be bound to a publication of the frequency directly from the siren
    
  • Comment out disabled code with explanation
  • Keep comments brief and purposeful

Formatting

  • Use 2-space indentation (Arduino default)
  • Opening brace on same line
  • Space after keywords: if ( not if(

Future Improvements

  1. Add PlatformIO: Create platformio.ini for command-line builds
  2. Add unit tests: Use PlatformIO unit testing for non-hardware logic
  3. Consolidate common code: Extract shared utilities into a common library
  4. Add CI/CD: GitHub Actions for build verification
  5. Document hardware: Add wiring diagrams and pinouts

Hardware Targets

  • ESP32 (WiFi + BLE)
  • B-G431B-ESC1 motor controller (SimpleFOC compatible)
  • OLED Display: SSD1306 128x64 I2C
  • Rotary Encoder: AiEsp32RotaryEncoder

Development Notes

  • Serial monitor uses 115200 baud
  • WiFi AP: sirening / alarm_11735
  • OSC ports: 54000 (settings), 54001 (state)
  • Motor control uses FOC (Field-Oriented Control) via SimpleFOC