Hello all. I'm getting a compiler error while using switch-case, and I can't figure out why. Have been experimenting a few hours now... time for help.
Short: I'm running a "Homey", a Dutch home automation hub. They have a neat arduino-library, Homeyduino. With it you can add a network-connected Arduino to your home-automation, to send commands and get states. I have a pool, and I want to control several devices for it with an 8-relay-board controlled by an Arduino with Ethernet Shield V2.
The Homeyduino-library creates 'actions' that are presented to / can be called by your Homey, that correspond to different functions in your Arduino-code. Homey can send arguments along, for example you can have an action "pump", that can be called by Homey with an argument, that makes that function "pump()" in your code will be called, and within that function the argument can be read to know how lung it should pump.
The library is a bit old though, and build for Homey v1. We are a few Homey-iterations further: it onky works now as long as you keep it to one or two actions.
So, as work-around I made one 'action', called Start - and am making use of the argument sent along to let the Arduino know what I want to do.
E.hg. if Homey sends "Start 1", the function "onStart()" is called, and from therein the argument '1' is read into INT "command". That var is then used to run the correct action (in this case: start the pump, "2" is to set the pump to low speed, etc etc).
At first I used IF-statements. This looked messy, and weirdly enough the IF-statement for command==12 would never run (checked with serial monitor to see if something within that IF even would run):
if (command == 1) {
Pump.high();
};
if (command == 2) {
PumpLow.pulse(500);
};
if (command == 3) {
PumpMid.pulse(500);
};
if (command == 4) {
PumpHigh.pulse(500);
};
if (command == 5) {
Pump.low();
};
if (command == 6) {
PoolLight.high();
};
if (command == 7) {
PoolLight.pulse(500);
};
if (command == 8) {
PoolLight.low();
};
if (command == 9) {
Covopen.pulse(500);
};
if (command == 10) {
Covclose.pulse(500);
};
if (command == 11) {
TechLight.high();
};
if (command == 12) {
TechLight.low();
};
if (command == 13) {
for (int thisPin = 0; thisPin < relayCount; thisPin++) { // Set the pins to which the relays for the horns are attached to OUTPUT
digitalWrite(Relays[thisPin], LOW);
}
So then I switched to an array of pointers - but that can't work since some om the functions being called have different arguments (the functions are created by ezOutput, so sometimes I need "pump.high()" to turn on the pump, but for selecting a different pump-speed I just need a pulse, bij calling "pump.low(500)")
So then I switched to SWITCH-CASE. And that, somehow, keeps throwing errors, now matter how I format it...
The error:
Arduino:1.8.19 (Windows Store 1.8.57.0) (Windows 10), Board:"Arduino Uno"
Zwembad_beta3.ino: In function 'void onStart()':
Zwembad_beta3:177:9: error: expected primary-expression before ':' token
case: 8
^
Zwembad_beta3:178:9: error: expected ';' before 'PoolLight'
PoolLight.low();
^~~~~~~~~
Zwembad_beta3:180:9: error: expected primary-expression before ':' token
case: 9
^
Zwembad_beta3:181:9: error: expected ';' before 'Covopen'
Covopen.pulse(500);
^~~~~~~
Zwembad_beta3:183:9: error: expected primary-expression before ':' token
case: 10
^
Zwembad_beta3:184:9: error: expected ';' before 'Covclose'
Covclose.pulse(500);
^~~~~~~~
Zwembad_beta3:186:9: error: expected primary-expression before ':' token
case: 11
^
Zwembad_beta3:187:9: error: expected ';' before 'TechLight'
TechLight.high();
^~~~~~~~~
Zwembad_beta3:189:9: error: expected primary-expression before ':' token
case: 12
^
Zwembad_beta3:190:9: error: expected ';' before 'TechLight'
TechLight.low(); break;
^~~~~~~~~
Zwembad_beta3:191:9: error: expected primary-expression before ':' token
case: 13
^
Zwembad_beta3:193:9: error: expected ';' before 'for'
for (int thisPin = 0; thisPin < relayCount; thisPin++) {
^~~
Zwembad_beta3:193:62: error: expected ';' before ')' token
for (int thisPin = 0; thisPin < relayCount; thisPin++) {
^
exit status 1
expected primary-expression before ':' token
The complete code:
/*
Poolmaster
----------
Control a relayboard from Homey. The Homey-library seems to be buggy - it does not work correctly with more than 2 actions presented to Homey.
This program works around the problem, by only presenting two actions to Homey, while using the parameter that Homey can send through as a specificator
for which action really should be taken.
*/
#include <SPI.h>
#include <Ethernet2.h>
#include <EthernetUdp2.h>
#include <Homey.h>
#include <ezOutput.h> // ezOutput library
byte mac[] = { 0x48, 0x6F, 0x6D, 0x65, 0x79, 0x00 };
const char* name = "Poolmaster";
// Set up the strings containing the command-descriptions to store
const char PROGMEM comm_0[] = "0 - No action";
const char PROGMEM comm_1[] = "1 - Start the pump";
const char PROGMEM comm_2[] = "2 - Set pump to LOW speed";
const char PROGMEM comm_3[] = "3 - Set pump to MID speed";
const char PROGMEM comm_4[] = "4 - Set pump to MAX speed";
const char PROGMEM comm_5[] = "5 - Stop the pump";
const char PROGMEM comm_6[] = "6 - Switch on pool light";
const char PROGMEM comm_7[] = "7 - Switch to next color";
const char PROGMEM comm_8[] = "8 - Switch off pool light";
const char PROGMEM comm_9[] = "9 - Open cover";
const char PROGMEM comm_10[] = "10 - Close cover";
const char PROGMEM comm_11[] = "11 - Switch on Techroom Light";
const char PROGMEM comm_12[] = "12 - Switch off Techroom Light";
const char PROGMEM comm_13[] = "13 - Set all relays to LOW";
// Then set up a table to refer to the strings.
const char *const comm_table[14] PROGMEM = {comm_0, comm_1, comm_2, comm_3, comm_4, comm_5, comm_6, comm_7, comm_8, comm_9, comm_10, comm_11, comm_12, comm_13};
char buffer[30]; // make sure this is large enough for the largest string it must hold
// Setting the relays
int const Relays[] = {13, 2, 3, 5, 6, 7, 8, 9, 14}; // array of pins to which relays are attached. Relays[0] is the builtin led, used for debugging / testing
int const relayCount = 9; // number of relays, inlcuding the builtin led
//Create array-pointers for the different attached systems/devices
int const TestPos = 0; // Testpin position in Relays[]
int const PumpPos = 1; // Pumppin position in Relays[]
int const PumpLowPos = 2; // Set pump to low speed
int const PumpMidPos = 3; // Set pump to mid speed
int const PumpHighPos = 4; // Set pump to high speed
int const PoollightPos = 5; // Relay to trigger the 2 pool-ledlights
int const CoveropenPos = 6; // Relay to send pulse for open-cover signal
int const CoverclosePos = 7; // Relay to send pulse for close-cover signal
int const TechLightPos = 8; // Light in technical room
//Create ezOutput instances for the different relay-pins
ezOutput Pump(Relays[PumpPos]);
ezOutput PumpLow(Relays[PumpLowPos]);
ezOutput PumpMid(Relays[PumpMidPos]);
ezOutput PumpHigh(Relays[PumpHighPos]);
ezOutput PoolLight(Relays[PoollightPos]);
ezOutput Covopen(Relays[CoveropenPos]);
ezOutput Covclose(Relays[CoverclosePos]);
ezOutput TechLight(Relays[TechLightPos]);
//Global variables used for the blink without delay example
unsigned long previousMillis = 0; // Regular use
uint8_t thisPin = 0;
uint8_t command = 0;
uint8_t coveropenTimer = 0;
uint8_t covercloseTimer = 0;
bool pumpStatus = false;
bool coverStatus = false;
//Arduino functions
void setup() {
//Enable serial port
Serial.begin(115200);
//Connect to network
Serial.println("Starting ethernet...");
Ethernet.begin(mac);
//Print IP address
Serial.print("IP address: ");
Serial.println(Ethernet.localIP());
//Start Homey library
Homey.begin(name); // The name of each Arduino on the network needs to be unique
Homey.addAction("Start", onStart);
Homey.addCondition("pomp_aan", onPumpCondition);
Homey.addCondition("cover_open", onCoverCondition);
for (int thisPin = 0; thisPin < relayCount; thisPin++) { // Set the pins to which the relays for the horns are attached to OUTPUT
pinMode(Relays[thisPin], OUTPUT);
digitalWrite(Relays[thisPin], LOW);
}
Serial.println("All pins set.");
Serial.println("Poolmaster Started.");
}
void loop() {
Homey.loop();
Covopen.loop();
Covclose.loop();
PoolLight.loop();
PumpLow.loop();
PumpMid.loop();
PumpHigh.loop();
TechLight.loop();
Pump.loop();
}
void onStart() {
command = Homey.value.toInt(); //Read the argument sent by Homey to 'command' variable
/* COMMANDS AVAILABLE:
1 - Start the pump
2 - Set pump to LOW speed
3 - Set pump to MID speed
4 - Set pump to MAX speed
5 - Stop the pump
6 - Switch on pool light
7 - Switch to next color
8 - Switch off pool light
9 - Open cover
10 - Close cover
11 - Switch on Techroom Light
12 - Switch off Techroom Light
13 - Set all relays to LOW
*/
// Check to see if the command is within valid range
if ( (command < 1) || (command > 13) ) {
return Homey.returnError("Invalid command joh!");
} // End of IF-statement
// Print the received command to serial monitor for debugging purposes
Serial.print("Commando received: ");
strcpy_P(buffer, (char *)pgm_read_word(&(comm_table[command]))); // Necessary casts and dereferencing.
Serial.println(buffer);
switch (command) {
case 1:
Pump.high();
break;
case 2:
PumpLow.pulse(500);
break;
case 3:
PumpMid.pulse(500);
break;
case 4:
PumpHigh.pulse(500);
break;
case 5:
Pump.low();
break;
case 6:
PoolLight.high();
break;
case 7:
PoolLight.pulse(500);
break;
case: 8
PoolLight.low();
break;
case: 9
Covopen.pulse(500);
break;
case: 10
Covclose.pulse(500);
break;
case: 11
TechLight.high();
break;
case: 12
TechLight.low(); break;
case: 13
// Set the pins to which the relays are attached to OUTPUT
for (int thisPin = 0; thisPin < relayCount; thisPin++) {
digitalWrite(Relays[thisPin], LOW);
} // End of FOR-loop
break;
} // End of SWITCH-CASE
} // End of FUNCTION
void onPumpCondition() {
return Homey.returnResult(pumpStatus);
}
void onCoverCondition() {
return Homey.returnResult(coverStatus);
}
void allOff() {
for (int thisPin = 0; thisPin < relayCount; thisPin++) { // Set the pins to which the relays for the horns are attached to OUTPUT
digitalWrite(Relays[thisPin], LOW);
}
}