Serial Relay control

Hi

I have been playing around with the serial on Arduino.
At the moment , i am controlling 8 relays, they will either be pulsed or latched.
The code below works, but i would like to use a serial string instead of a single character in the switch cases, as an example "relay a pulse" or "relay a on" and "relay a off"

I would like to control a maximum of 16 relays using the MCP23017 I2C chip, all either pulse or latched, but run out of single characters. Also it would keep the code neater using a string.

Any advice would be gratefully received.

[code]
#include <LiquidCrystal.h>

LiquidCrystal lcd(2, 3, 17, 16, 15, 14); // pins for LCD 
void setup(){
    lcd.begin(16,2);             // 16 characters, 2 rows
    lcd.clear();
    
 //Set all the pins we need to output pins
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);
  pinMode(11, OUTPUT);
  pinMode(12, OUTPUT);
  pinMode(13, OUTPUT);
  
  //Begin serial, turn on LCD LED and set welcoming message
  Serial.begin(9600);
  delay(2000);
  digitalWrite(13, HIGH);
  delay(1000);
  lcd.setCursor(0,0);
  lcd.print("Automation");
  delay(1000);
  lcd.setCursor(2,1);
  lcd.print("READY TO RUN");
  Serial.begin(9600);
}

void loop (){
  if (Serial.available()) {
    
    char ser = Serial.read();    //read serial as a character
    
    switch (ser) {
     
      case 'A':
        triggerPin(8);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay A");
        break;
        
        case 'B':
        triggerPin(7);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay B");
        break;
        
        case 'C':
        triggerPin(6);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay C");
        break;
        
      case 'D':
        triggerPin(5);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay D");
        break;
        
        case 'E':
        triggerPin(9);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay E");
        break;
        
        case 'F':
        triggerPin(10);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay F");
        break;
        
      case 'G':
        triggerPin(11);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay G");
        break;
        
        case 'H':
        triggerPin(12);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(2,1);
    lcd.print("Last Relay H");
        break;
        
      case'I':
        digitalWrite(8, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay A ON");
        break;
        
        case 'a':
        digitalWrite(8, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay A OFF");
        break;
        
      case 'J':
        digitalWrite(7, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay B ON");
        break;
        
        case 'b':
        digitalWrite(7, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay B OFF");
        break;
        
         case 'K':
        digitalWrite(6, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay C ON");
        break;
        
        case 'c':
        digitalWrite(6, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay C OFF");
        break;
        
         case 'L':
        digitalWrite(5, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay D ON");
        break;
        
        case 'd':
        digitalWrite(5, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay D OFF");
        break;
        
  case 'M':
        digitalWrite(9, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay E ON");
        break;
        
        case 'e':
        digitalWrite(9, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay E OFF");
        break;
        
         case 'N':
        digitalWrite(10, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay F ON");
        break;
        
        case 'f':
        digitalWrite(10, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay F OFF");
        break;
        
         case 'O':
        digitalWrite(11, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay G ON");
        break;
        
        case 'g':
        digitalWrite(11, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay G OFF");
        break;
        
         case 'P':
        digitalWrite(12, HIGH);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay H ON");
        break;
        
        case 'h':
        digitalWrite(12, LOW);
        lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Automation");
    lcd.setCursor(0,1);
    lcd.print("Last Relay H OFF");
        break;

    } 
  }
}

void triggerPin(int pin){
  digitalWrite(pin, HIGH);
  delay(700);
  digitalWrite(pin, LOW);
  
}

[/code]

You can read the updated Serial Input Basics thread to get ideas.

Don't forget you've upper and lower case letters , so lots of combinations.

It's not hugely efficient but you can use " indexof"'to sort out specific characters within a string to determine what action to take.

arduinosidi:
i would like to use a serial string instead of a single character in the switch cases, as an example "relay a pulse" or "relay a on" and "relay a off"

No can do - the argument of a switch/case must resolve to an integer.

arduinosidi:
I would like to control a maximum of 16 relays using the MCP23017 I2C chip, all either pulse or latched, but run out of single characters.

I don't know how could think you have run out of characters. You could use A for on and a for off and B for on and b for off and easily control 26 relays.

Also it would keep the code neater using a string.

And let me assure you the Arduino code would be very much neater using single characters.

Another way to control 16 (or as many as you like) relays is to send a message like "1111111100000000" in which a 1 signifies that the relay in that position is on and a 0 signifies that it is off. You could update all 16 with a couple of lines of code

for (byte n = 0; n < 16; n++) {
  digitalWrite(relayPin[n], recvdChars[n] - '0');
}

...R

dougp:
No can do - the argument of a switch/case must resolve to an integer.

if the switch case must resolve ti an integer, could i use the IF/ELSE ?

I would like the commands to read logically in the code, if not then single characters it shall be

It's quite easy to do a command in one character.

16 relays = 4 bits. Dedicate 5 for future expansion, you can have up to 32 relays.
Then you have 3 bits left for the commands, and you have three: latched on (so it stays on until told to switch off), pulsed on (I guess you mean it stays on for a predetermined amount of time?), and off.

You have room for total 8 commands in those three bits, so you can have six different "pulse" commands. E.g. take the three high bits of the byte as command, the five low bits as relay number:

byte transmission = Serial.read();
byte command = (transmission >> 5);
byte relay = (transmission & 0x1F);

Thanks for all the input, I will have a play with all combinations.
One thing that has escaped me completely , I can only pulse one relay at a time as I have the delay in the "trigger" is it feasible to modify something like the below to work with serial.
I'm really enjoying learning about Arduino, but the programming is challenging :slight_smile:

[code]
unsigned long elapsedTime;      //set up timers 
unsigned long onTime;
unsigned long elapsedTime1;
unsigned long onTime1;

int time = 5000;              // time of LED activation after button

void setup(){
    
    
 onTime = millis();
 onTime = elapsedTime; 
 pinMode(2, OUTPUT);  //Initialize pin 8 as status LED 
 pinMode(3, INPUT);    // Input button pin 
 onTime1 = millis();
 onTime1 = elapsedTime1; 
 pinMode(1, OUTPUT);  //Initialize pin 9 as status LED 
 pinMode(4, INPUT);    // Input button pin
 
 delay(1000);
 
 }

void loop(){
      
  if (digitalRead(3) == LOW )   // Switch is closed to start LED timer
        {
         digitalWrite(2, HIGH);  // LED comes On  
         onTime = millis(); 
        
         }
     if(onTime > 0 && millis() - onTime > time)  
           {      
           digitalWrite(2, LOW);  // LED goes off
            onTime = 0;
           }
{
 if (digitalRead(4) == LOW)   // Switch is closed to start LED timer
        {
         digitalWrite(1, HIGH);  // LED comes On  
         onTime1 = millis();  
         
         }
     if(onTime1 > 0 && millis() - onTime1 > time)  
           {      
           digitalWrite(1, LOW);  // LED goes off
            onTime1 = 0;
           }
}
}

[/code]

arduinosidi:
I can only pulse one relay at a time as I have the delay in the "trigger"

I don't understand. The only delay() that I can see is in your setup() function.

Maybe you can provide a more extended description of what actually happens.

...R

When i send commands from either the serial monitor or something like putty, if i send say "A" (this should pulse relay A for 700ms). Relay A will pulse for 700ms as it should.

If i send "ABCDEF" relay a, b , c, d, e, f will sequentially pulse for 700ms on after the other.

I know there will be a small delay in individual characters being received, but i would like if possible , if i send two characters to have those relays fire without the 700ms delay

The program in your Reply #8 does not have any code to receive characters. You need to post the code that you are talking about.

In the meantime have a look at the examples in Serial Input Basics - simple reliable ways to receive data.

It is perfectly possible to receive a multi-character message and act on all of the characters at the same time.

...R

cool thankyou

That was just an example of code i had been playing with to get multiple actions .
I was going to try integrating that into my serial code

arduinosidi:
That was just an example of code i had been playing with to get multiple actions .
I was going to try integrating that into my serial code

You need to tell us that sort of stuff when you post code.

...R