/* * Stairs lighting * Copyright 2017 (c) Mark van Renswoude */ #include #include #include #include #include "config.h" #include "protocol.h" #include "components\PCA9685.h" //#include "modes\adc.h" #include "modes\alternate.h" #include "modes\custom.h" #include "modes\slide.h" #include "modes\static.h" #include "stairs.h" PCA9685* pwmDriver; Stairs* stairs; WiFiUDP udpServer; uint8_t currentModeIdentifier; IMode* currentMode; // Forward declarations void checkRequest(); void handleRequest(uint8_t* packet); IMode* createMode(uint8_t identifier); void setCurrentMode(IMode *mode, uint8_t identifier); void handleCurrentMode(); void setup() { pwmDriver = new PCA9685(); pwmDriver->setAddress(PWMDriverAddress, PinSDA, PinSCL); pwmDriver->setPWMFrequency(PWMDriverPWMFrequency); stairs = new Stairs(); stairs->init(pwmDriver); WiFi.hostname(WiFiHostname); WiFi.begin(WiFiSSID, WiFiPassword); // Run a little startup test sequence pwmDriver->setAll(PCA9685::Off); pwmDriver->setPWM(0, PCA9685::On); delay(300); for (int step = 1; step < StepCount; step++) { pwmDriver->setPWM(step - 1, PCA9685::Off); pwmDriver->setPWM(step, PCA9685::On); delay(300); } pwmDriver->setPWM(StepCount - 1, PCA9685::Off); // Pulsate the bottom step while WiFi is connecting uint16_t brightness = 0; uint16_t speed = 16; while (WiFi.status() != WL_CONNECTED) { brightness += speed; if (brightness <= 0 || brightness >= 1024) speed = -speed; pwmDriver->setPWM(0, brightness); delay(16); } setCurrentMode(new StaticMode(), Mode::Static); // Start the UDP server udpServer.begin(UDPPort); } uint32_t currentTime; uint8_t packet[51]; uint8_t* packetRef; void loop() { currentTime = millis(); checkRequest(); handleCurrentMode(); } void checkRequest() { int packetSize = udpServer.parsePacket(); if (packetSize) { int length = udpServer.read(packet, 50); if (length && packet[0]) { packet[length] = 0; packetRef = packet; handleRequest(packetRef); } } } void handleRequest(uint8_t* packet) { // Every request will result in a reply, either containing the // requested data or a copy of the input parameters for verification. // // Apparantly this also makes the ESP8266 more stable, as reports // have been made that UDP communication can stall if no replies are sent. udpServer.beginPacket(udpServer.remoteIP(), udpServer.remotePort()); udpServer.write(Command::Reply); switch (*packet) { case Command::Ping: udpServer.write(Command::Ping); break; case Command::GetMode: udpServer.write(Command::GetMode); udpServer.write(currentModeIdentifier); break; case Command::SetMode: { packet++; uint8_t newIdentifier = *packet; packet++; IMode* newMode = createMode(newIdentifier); if (newMode != NULL) { newMode->read(packet); udpServer.write(Command::SetMode); newMode->write(&udpServer); setCurrentMode(newMode, newIdentifier); } else { udpServer.write(Command::Error); udpServer.write(Command::SetMode); } break; } default: udpServer.write(Command::Error); udpServer.write(*packet); break; } udpServer.endPacket(); } IMode* createMode(uint8_t identifier) { if (identifier == currentModeIdentifier) return currentMode; switch (identifier) { case Mode::Static: return new StaticMode(); //case Mode::Custom: return new CustomMode(); case Mode::Alternate: return new AlternateMode(); //case Mode::Slide: return new SlideMode(); //case Mode::ADC: return new ADCInputMode(); } return NULL; } void setCurrentMode(IMode* mode, uint8_t identifier) { currentModeIdentifier = identifier; currentMode = mode; currentMode->init(stairs, currentTime); } void handleCurrentMode() { currentMode->tick(stairs, currentTime); }