/* * Stairs lighting * Copyright 2017 (c) Mark van Renswoude * * https://git.x2software.net/pub/Stairs */ #include #include #define SERIAL_COMMANDS_DEBUG #include #include "protocol.h" const uint8_t PinRS485Receive = 2; const uint8_t PinRS485Transmit = 3; const uint8_t PinRS485WriteEnable = 4; const uint32_t RS485BaudRate = 76800; /* * RS485 communication */ SoftwareSerial rs485(PinRS485Receive, PinRS485Transmit); size_t doWrite(const byte what) { return rs485.write (what); } int doAvailable() { return rs485.available (); } int doRead() { return rs485.read (); } RS485 comm(doRead, doAvailable, doWrite, 20); /* * Serial communication (user input) */ SerialCommand cmdPing("ping", handlePingCommand); SerialCommand cmdDisplay("display", handleDisplayCommand); SerialCommand cmdLink("link", handleLinkCommand); SerialCommand cmdLinkAssign("assign", handleLinkAssignCommand); SerialCommand cmdLinkStop("stop", handleLinkStopCommand); SerialCommand cmdSetPWM("setPWM", handlesetPWMCommand); SerialCommand cmdGetSensors("getSensors", handlegetSensorsCommand); char commandBuffer[32]; SerialCommands serialCommands(&Serial, commandBuffer, sizeof(commandBuffer), "\r\n", " "); void cmdUnrecognized(SerialCommands* sender, const char* cmd) { sender->GetSerial()->print("ERROR: Unrecognized command ["); sender->GetSerial()->print(cmd); sender->GetSerial()->println("]"); } bool inLink = false; void showCommands() { Serial.println(""); Serial.println("Available commands:"); Serial.println(" ping [moduleIndex]"); Serial.println(" display"); Serial.println(" link"); Serial.println(" setPWM [moduleIndex] [flags] [value1] [value2]"); Serial.println(" getSensors [moduleIndex]"); Serial.println(""); } void setup() { pinMode(PinRS485WriteEnable, OUTPUT); rs485.begin(RS485BaudRate); comm.begin(); Serial.begin(115200); serialCommands.AddCommand(&cmdPing); serialCommands.AddCommand(&cmdDisplay); serialCommands.AddCommand(&cmdLink); serialCommands.AddCommand(&cmdLinkAssign); serialCommands.AddCommand(&cmdLinkStop); serialCommands.AddCommand(&cmdSetPWM); serialCommands.AddCommand(&cmdGetSensors); serialCommands.SetDefaultHandler(&cmdUnrecognized); Serial.println("Stairs module Mock Master ready"); showCommands(); } void loop () { serialCommands.ReadSerial(); if (comm.update()) handleCommMessage(); } void sendCommMessage(const byte* data, size_t len) { Serial.print("Raw out: "); byte* ptr = data; for (size_t i = 0; i < len; i++, ptr++) { Serial.print(*ptr, HEX); Serial.print(' '); } Serial.println(""); digitalWrite(PinRS485WriteEnable, HIGH); comm.sendMsg(data, len); digitalWrite(PinRS485WriteEnable, LOW); } void handlePingCommand(SerialCommands* sender) { if (inLink) return; int moduleIndex = atoi(sender->Next()); sender->GetSerial()->println("> Ping"); const byte msg[] = { CommandPing, moduleIndex }; sendCommMessage(msg, sizeof(msg)); } void handleDisplayCommand(SerialCommands* sender) { if (inLink) return; sender->GetSerial()->println("> DisplayModuleIndex"); const byte msg[] = { CommandDisplayModuleIndex }; sendCommMessage(msg, sizeof(msg)); } void handleLinkCommand(SerialCommands* sender) { if (inLink) return; sender->GetSerial()->println("> Link"); const byte msg[] = { CommandStartLink }; sendCommMessage(msg, sizeof(msg)); sender->GetSerial()->println(""); sender->GetSerial()->println("Available commands:"); sender->GetSerial()->println(" assign [moduleIndex]"); sender->GetSerial()->println(" stop"); sender->GetSerial()->println(""); inLink = true; } void handleLinkAssignCommand(SerialCommands* sender) { if (!inLink) return; int moduleIndex = atoi(sender->Next()); sender->GetSerial()->println("> LinkRequest response"); const byte msg[] = { ResponseRequestLink, moduleIndex }; sendCommMessage(msg, sizeof(msg)); } void handleLinkStopCommand(SerialCommands* sender) { if (!inLink) return; sender->GetSerial()->println("> StopLink"); const byte msg[] = { CommandStopLink }; sendCommMessage(msg, sizeof(msg)); inLink = false; showCommands(); } void handlesetPWMCommand(SerialCommands* sender) { if (inLink) return; int moduleIndex = atoi(sender->Next()); int flags = atoi(sender->Next()); int value1 = atoi(sender->Next()); int value2 = atoi(sender->Next()); sender->GetSerial()->println("> SetPWM"); const byte msg[] = { CommandSetPWM, moduleIndex, flags, lowByte(value1), highByte(value1), lowByte(value2), highByte(value2) }; sendCommMessage(msg, sizeof(msg)); } void handlegetSensorsCommand(SerialCommands* sender) { if (inLink) return; int moduleIndex = atoi(sender->Next()); sender->GetSerial()->println("> GetSensors"); const byte msg[] = { CommandGetSensors, moduleIndex }; sendCommMessage(msg, sizeof(msg)); } void handleCommMessage() { uint8_t* data = comm.getData(); uint8_t length = comm.getLength(); Serial.print("Raw in: "); byte* ptr = data; for (size_t i = 0; i < length; i++, ptr++) { Serial.print(*ptr, HEX); Serial.print(' '); } Serial.println(""); if (length == 0) return; uint8_t command = *data; data++; length--; switch (command) { case ResponsePing: if (length > 0) Serial.println("< Ping response, module index = " + String(*data)); else Serial.println("< Ping response, module index = "); break; case CommandRequestLink: Serial.println("< Request link"); break; case ResponseSetPWM: Serial.println("< Set PWM response, module index = " + String(*data)); break; case ResponseGetSensors: Serial.println("< Get sensors response, module index = " + String(*data)); data++; length--; if (length >= 2) { Serial.println(" Sensor 1 value: " + String(*reinterpret_cast(data))); data+=2; length-=2; } else Serial.println(" Sensor 1 value: "); if (length >= 2) { Serial.println(" Sensor 2 value: " + String(*reinterpret_cast(data))); data+=2; length-=2; } else Serial.println(" Sensor 2 value: "); break; case ResponseUhmWhat: Serial.println("< Uhm, what? module index = " + String(*data)); break; } }