// Enumerate command types
enum CommandType {
CMD_LED,
CMD_MOTOR,
CMD_UNKNOWN
};
// Define a type for command handler functions
typedef void (*CommandHandler)(char *param);
// Define a structure for command entries
struct CommandEntry {
const char *commandName;
CommandType commandType;
CommandHandler handler;
};
// Function prototypes
void handleLEDCommand(char *param);
void handleMotorCommand(char *param);
void showPrompt();
void toLowerCase(char *str);
long parseParameter(char *param);
// List of supported commands with function pointers
CommandEntry commandTable[] = {
{"led", CMD_LED, handleLEDCommand},
{"motor", CMD_MOTOR, handleMotorCommand},
};
// Number of commands in the table
const int numCommands = sizeof(commandTable) / sizeof(CommandEntry);
const int bufferSize = 50; // Adjust the buffer size as needed
char inputBuffer[bufferSize];
int bufferIndex = 0;
void setup() {
Serial.begin(9600); // Start serial communication at 9600 baud rate
pinMode(LED_BUILTIN, OUTPUT); // Initialize built-in LED pin
pinMode(9, OUTPUT); // Initialize motor pin (assumed on pin 9)
showPrompt();
}
void loop() {
if (Serial.available() > 0) {
char incomingChar = Serial.read();
// Check for end of command
if (incomingChar == '\n' || incomingChar == '\r') {
inputBuffer[bufferIndex] = '\0'; // Null-terminate the string
parseCommand(inputBuffer);
bufferIndex = 0; // Reset buffer index for the next command
showPrompt(); // Show the prompt again after processing
} else {
// Add character to buffer if space permits
if (bufferIndex < bufferSize - 1) {
inputBuffer[bufferIndex++] = incomingChar;
}
}
}
}
void parseCommand(char *command) {
// Convert the command to lowercase for case-insensitive comparison
toLowerCase(command);
char *commandName = strtok(command, ":");
char *commandParam = strtok(NULL, ":"); // If no parameter, this will be NULL
CommandType cmdType = getCommandType(commandName);
for (int i = 0; i < numCommands; i++) {
if (commandTable[i].commandType == cmdType) {
commandTable[i].handler(commandParam); // Call the handler with the parameter (if any)
return;
}
}
Serial.println("Unknown command");
}
CommandType getCommandType(const char *commandName) {
for (int i = 0; i < numCommands; i++) {
if (strcmp(commandName, commandTable[i].commandName) == 0) {
return commandTable[i].commandType;
}
}
return CMD_UNKNOWN;
}
void handleLEDCommand(char *param) {
if (param == NULL) {
// Handle parameterless input
int state = digitalRead(LED_BUILTIN);
Serial.print("LED is currently ");
Serial.println(state == HIGH ? "ON" : "OFF");
} else {
long ledState = parseParameter(param);
if (ledState == 1) {
digitalWrite(LED_BUILTIN, HIGH); // Turn on LED
Serial.println("LED ON");
} else if (ledState == 0) {
digitalWrite(LED_BUILTIN, LOW); // Turn off LED
Serial.println("LED OFF");
} else {
Serial.println("Invalid LED parameter");
}
}
}
void handleMotorCommand(char *param) {
if (param == NULL) {
// Handle parameterless input
Serial.println("Motor speed control requires a parameter (0-255)");
} else {
long motorSpeed = parseParameter(param);
if (motorSpeed >= 0 && motorSpeed <= 255) {
analogWrite(9, motorSpeed); // Assume motor is connected to pin 9 (PWM)
Serial.print("Motor speed set to ");
Serial.println(motorSpeed);
} else {
Serial.print("Invalid motor speed parameter - ");
Serial.println(motorSpeed,HEX);
}
}
}
// Function to show the command prompt
void showPrompt() {
Serial.print("CMD> ");
}
// Convert a string to lowercase
void toLowerCase(char *str) {
while (*str) {
*str = tolower(*str);
str++;
}
}
// Function to parse a parameter, supporting both hex ("0x") and decimal formats
long parseParameter(char *param) {
if (param == NULL) return -1;
if (strlen(param) > 2 && param[0] == '0' && param[1] == 'x') {
return strtol(param, NULL, 16); // Convert hex string to long
} else {
return strtol(param, NULL, 10); // Convert decimal string to long
}
}