Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <Wire.h>
- #include <Adafruit_GFX.h>
- #include <Adafruit_SSD1306.h>
- // === OLED ===
- #define SCREEN_WIDTH 128
- #define SCREEN_HEIGHT 64
- #define OLED_RESET -1
- #define OLED_ADDR 0x3C
- Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
- // === Input Pins ===
- const uint8_t INPUT_PINS[4] = {7, 6, 5, 4}; // Inputs 1-4
- const uint8_t ENCODER_PIN_A = 2;
- const uint8_t ENCODER_PIN_B = 3;
- const uint8_t ENCODER_BUTTON = 8;
- // === Analog Inputs ===
- const uint8_t SENSOR_PIN = A1; // Thermistor or Photoresistor
- const uint8_t BATTERY_PIN = A0; // Battery sense
- // === Relay Outputs ===
- const uint8_t RELAY_PINS[4] = {10, 11, 12, 13}; // Relays 1-4
- // === Rotary Encoder State ===
- volatile int encoderPos = 0;
- int lastReportedPos = 0;
- bool encoderButtonPressed = false;
- // === Menu Navigation State ===
- #define MAX_MENU_DEPTH 4
- struct MenuNode {
- const char* label;
- void (*action)(); // Function to call if selected
- MenuNode* parent;
- MenuNode** children;
- uint8_t childCount;
- };
- MenuNode* currentMenu = nullptr;
- uint8_t currentIndex = 0;
- MenuNode* menuStack[MAX_MENU_DEPTH];
- uint8_t indexStack[MAX_MENU_DEPTH];
- uint8_t menuDepth = 0;
- // === Encoder Interrupts ===
- void encoderISR() {
- static uint8_t oldState = 0;
- uint8_t newState = (digitalRead(ENCODER_PIN_A) << 1) | digitalRead(ENCODER_PIN_B);
- if ((oldState == 0b00 && newState == 0b01) || (oldState == 0b01 && newState == 0b11) ||
- (oldState == 0b11 && newState == 0b10) || (oldState == 0b10 && newState == 0b00)) {
- encoderPos++;
- } else {
- encoderPos--;
- }
- oldState = newState;
- }
- void renderMenu() {
- display.clearDisplay();
- display.setTextSize(1);
- display.setCursor(0, 0);
- for (uint8_t i = 0; i < currentMenu->childCount; i++) {
- if (i == currentIndex) display.print("> ");
- else display.print(" ");
- display.println(currentMenu->children[i]->label);
- }
- display.display();
- }
- void handleEncoder() {
- static int lastPos = 0;
- if (encoderPos != lastPos) {
- int delta = encoderPos - lastPos;
- lastPos = encoderPos;
- currentIndex = (currentIndex + delta + currentMenu->childCount) % currentMenu->childCount;
- renderMenu();
- }
- if (digitalRead(ENCODER_BUTTON) == LOW) {
- delay(200); // Debounce
- MenuNode* selected = currentMenu->children[currentIndex];
- if (selected->childCount > 0) {
- if (menuDepth < MAX_MENU_DEPTH - 1) {
- menuStack[menuDepth] = currentMenu;
- indexStack[menuDepth] = currentIndex;
- menuDepth++;
- currentMenu = selected;
- currentIndex = 0;
- renderMenu();
- }
- } else if (selected->action) {
- selected->action();
- renderMenu(); // After action
- }
- }
- }
- void showStatus() {
- // Display sensor/switch/relay status (to be implemented later)
- Serial.println("Status screen");
- }
- void saveSettings() {
- Serial.println("Settings saved (placeholder)");
- }
- MenuNode* inputItems[] = {
- new MenuNode{"Input 1 → Relay Map", nullptr, nullptr, nullptr, 0},
- new MenuNode{"Input 2 → Relay Map", nullptr, nullptr, nullptr, 0},
- new MenuNode{"Input 3 → Relay Map", nullptr, nullptr, nullptr, 0},
- new MenuNode{"Input 4 → Relay Map", nullptr, nullptr, nullptr, 0}
- };
- MenuNode inputConfig = { "Input Config", nullptr, nullptr, inputItems, 4 };
- MenuNode* rootItems[] = {
- new MenuNode{"View Status", showStatus, nullptr, nullptr, 0},
- &inputConfig,
- new MenuNode{"Save Settings", saveSettings, nullptr, nullptr, 0}
- };
- MenuNode root = { "Main Menu", nullptr, nullptr, rootItems, 3 };
- void setup() {
- // === Serial (optional for debug) ===
- Serial.begin(9600);
- // === Inputs ===
- for (uint8_t i = 0; i < 4; i++) {
- pinMode(INPUT_PINS[i], INPUT_PULLUP);
- }
- pinMode(ENCODER_PIN_A, INPUT_PULLUP);
- pinMode(ENCODER_PIN_B, INPUT_PULLUP);
- pinMode(ENCODER_BUTTON, INPUT); // External hardware debounce
- // === Outputs ===
- for (uint8_t i = 0; i < 4; i++) {
- pinMode(RELAY_PINS[i], OUTPUT);
- digitalWrite(RELAY_PINS[i], LOW); // Start relays OFF
- }
- // === OLED Init ===
- if (!display.begin(SSD1306_SWITCHCAPVCC, OLED_ADDR)) {
- Serial.println(F("OLED init failed"));
- while (true); // Loop forever
- }
- display.clearDisplay();
- display.setTextSize(1);
- display.setTextColor(SSD1306_WHITE);
- display.setCursor(0, 0);
- display.println(F("System Booting..."));
- display.display();
- // === Encoder Interrupts ===
- attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), encoderISR, CHANGE);
- attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_B), encoderISR, CHANGE);
- }
- void loop() {
- // Temporary test loop
- display.clearDisplay();
- display.setCursor(0, 0);
- display.print(F("Encoder: "));
- display.println(encoderPos);
- display.print(F("Input States: "));
- for (int i = 0; i < 4; i++) {
- display.print(digitalRead(INPUT_PINS[i]) == LOW ? "1" : "0");
- }
- display.display();
- handleEncoder();
- }
Advertisement
Add Comment
Please, Sign In to add comment