diff --git a/DinnerRecv/CLAUDE.md b/DinnerRecv/CLAUDE.md new file mode 100644 index 0000000..c6e982f --- /dev/null +++ b/DinnerRecv/CLAUDE.md @@ -0,0 +1,42 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Project Overview + +DinnerRecv is an Arduino project for a FireBeetle 2 ESP32-E microcontroller that controls a WS2812B LED strip. The project creates a sequential white light animation across 8 LEDs. + +## Hardware Configuration + +- **Microcontroller**: FireBeetle 2 ESP32-E +- **LED Strip**: WS2812B (8 pixels) +- **Data Pin**: GPIO 16 +- **Power**: 5V from bottom of the board (under USB connector) +- **Resistor**: 470 Ohm between data line and LED strip + +## Development Environment + +This is an Arduino sketch (.ino file) that should be developed using: +- Arduino IDE +- PlatformIO +- Or other Arduino-compatible development environment + +## Key Dependencies + +- `Adafruit_NeoPixel` library for WS2812B LED control + +## Code Architecture + +The code follows standard Arduino structure: +- `setup()`: Initializes serial communication (115200 baud) and LED strip +- `loop()`: Continuously runs the LED animation sequence + +## Hardware Reference + +Implementation follows the tutorial at: https://esp32io.com/tutorials/esp32-ws2812b-led-strip + +## Configuration Constants + +- `PIN 16`: Data pin for LED strip +- `NUMPIXELS 8`: Number of LEDs in the strip +- `DELAYVAL 50`: Delay in milliseconds between LED updates \ No newline at end of file diff --git a/DinnerRecv/DinnerRecv.ino b/DinnerRecv/DinnerRecv.ino new file mode 100644 index 0000000..299cf3f --- /dev/null +++ b/DinnerRecv/DinnerRecv.ino @@ -0,0 +1,129 @@ +// FireBeetle 2 ESP32-E +// 5v power for the LEDs taken from the +// bottom of the board under the USB connector. +// 470 Ohm resistor between the data line and the LED strip. +// See https://esp32io.com/tutorials/esp32-ws2812b-led-strip +#include +#include +#include + +#define PIN 16 +#define NUMPIXELS 4 + +Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ400); + +// #define DELAYVAL 250 + +#define ESPNOW_WIFI_CHANNEL 6 + +// Dinner alert state +bool dinnerAlert = false; +unsigned long dinnerStartTime = 0; +unsigned long lastBlinkTime = 0; +bool ledState = false; + +uint8_t breath = 0; +uint32_t last_breath_time = 0; + +void onDataReceived(const esp_now_recv_info *mac_addr, + const unsigned char *data, int data_len) { + char message[data_len + 1]; + memcpy(message, data, data_len); + message[data_len] = '\0'; + + Serial.print("Received message: "); + Serial.println(message); + + if (strcmp(message, "dinner") == 0) { + Serial.println("Dinner alert received!"); + dinnerAlert = true; + dinnerStartTime = millis(); + lastBlinkTime = millis(); + ledState = false; + } +} + +void setup() { + Serial.begin(115200); + // while (!Serial){ + // delay(10); + // } + pixels.begin(); + + // Initialize WiFi in station mode + WiFi.mode(WIFI_STA); + WiFi.setChannel(ESPNOW_WIFI_CHANNEL); + while (!WiFi.STA.started()) { + delay(100); + } + + // Initialize ESP-NOW + if (esp_now_init() != ESP_OK) { + Serial.println("Error initializing ESP-NOW"); + return; + } + + // Register callback function + esp_now_register_recv_cb(onDataReceived); + Serial.println("ESP-NOW initialized and ready to receive messages"); + + Serial.println("Dinner RECV"); + Serial.println("Wi-Fi parameters:"); + Serial.println(" Mode: STA"); + Serial.println(" MAC Address: " + WiFi.macAddress()); + Serial.printf(" Channel: %d\n", ESPNOW_WIFI_CHANNEL); + + // Serial.println("setup done"); +} + +void blinkAllLEDs() { + if (millis() - lastBlinkTime >= 2000) { + lastBlinkTime = millis(); + ledState = !ledState; + + if (ledState) { + for (int i = 0; i < NUMPIXELS; i++) { + pixels.setPixelColor(i, pixels.Color(255, 0, 0)); + } + } else { + pixels.clear(); + } + pixels.show(); + } +} + +void breathe() { + uint8_t val = breath > 128 ? 256 - breath : breath; + for (int i = 0; i < NUMPIXELS; i++) { + pixels.setPixelColor(i, pixels.Color(0, 0, val)); + pixels.show(); + } +} + +void dinnerAnimation() { + if (millis() - dinnerStartTime > 15 * 1000) { + dinnerAlert = false; + Serial.println("Dinner alert timeout - returning to normal mode"); + pixels.clear(); + pixels.show(); + } else { + blinkAllLEDs(); + } +} + +void breathAnimation() { + unsigned long time = millis(); + if (time % 25 == 0 && time != last_breath_time) { + breath++; + last_breath_time = time; + breathe(); + } +} + +void loop() { + if (dinnerAlert) { + dinnerAnimation(); + } else { + breathAnimation(); + } +}