arduino serial input switch between automated and manual control of actuators

Hello ,

I am new to Arduino
An i want to build a system with 2 sensors , 2 relays and one servo .
the system needs to have
1 automatic control , in which the relays and servo are controlled by the sensors input
2 manual control by the user using serial monitor inputs.
the automatic and manual control needs to be toggled via the serial monitor .
I managed to make the control control selection via serial input and the automated control , but when choosing manual control none of the serial imputes work (only the switching between auto and manual mode ).
for clarity i attached the code

auto_manual control of microgarden.ino (3.24 KB)

More members will see your code if you post your code as described in the forum guidelines.

in general, as we all did at one time, i think you're overthinking this.

in your entire code, there should only be on place you check for serial input, "if (available())", read it and process it. there's no need to delay and then check for available() again

in looped, your serial input can either enable or disable automatic/manual processing. that state may decide how you processed serial input, or ignore some commands. It likely also determined if you perform automatic processing in loop, in addition to checking for serial input

pseudo code wise

loop ()
{
    getTemp();
    getHumidity ();

    if (Serial.available ()) {
        char c = Serial.read ();

        processSerial (c);
    }

    if (auto) {
        doAuto ();
    }
}

consider the following which i use in some form in all my code to help drive, test, debug

// pcRead - debugging using serial monitor

const char version [] = "PcRead 200416a";

int debug = 0;

// ---------------------------------------------------------
// toggle output bit
void
pinToggle (
    int pin)
{
    static int  bits = 0;
    int     bit = 1 << pin;

    if (debug)  {
        Serial.print ("pinToggle: ");
        Serial.println (pin);
    }

    if (bits & bit)  {
        digitalWrite (pin, LOW);
        bits &= ~bit;
    }
    else {
        digitalWrite (pin, HIGH);
        bits |= bit;
    }
}

// ---------------------------------------------------------
// toggle output bit
int
readString (
    char *s,
    int   maxChar )
{
    int  n = 0;

    Serial.print ("> ");
    do {
        if (Serial.available()) {
            int c    = Serial.read ();

            if ('\n' == c)
                break;

            s [n++] = c;
            if (maxChar == n)
                break;
        }
    } while (true);

    return n;
}

// -----------------------------------------------------------------------------
// process single character commands from the PC
#define MAX_CHAR  10
char s [MAX_CHAR] = {};

int  analogPin = 0;

void
pcRead (void)
{

    static int  val = 13;

    if (Serial.available()) {
        int c = Serial.read ();

        switch (c)  {
        case '0':
        case '1':
        case '2':
        case '3':
        case '4':
        case '5':
        case '6':
        case '7':
        case '8':
        case '9':
            val = c - '0' + (10 * val);
            break;

        case 'A':
            analogPin = val;
            Serial.print   ("analogPin = ");
            Serial.println (val);
            val = 0;
            break;

        case 'D':
            debug ^= 1;
            break;

        case 'I':
            pinMode (val, INPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT");
            val = 0;
            break;

        case 'O':
            pinMode (val, OUTPUT);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" OUTPUT");
            val = 0;
            break;

        case 'P':
            pinMode (val, INPUT_PULLUP);
            Serial.print   ("pinMode ");
            Serial.print   (val);
            Serial.println (" INPUT_PULLUP");
            val = 0;
            break;


        case 'a':
            Serial.print   ("analogRead: ");
            Serial.println (analogRead (val));
            val = 0;
            break;

        case 'c':
            digitalWrite (val, LOW);
            Serial.print   ("digitalWrite: LOW  ");
            Serial.println (val);
            val = 0;
            break;

        case 'p':
#if !defined(ARDUINO_ARCH_ESP32)
            analogWrite (analogPin, val);
            Serial.print   ("analogWrite: pin ");
            Serial.print   (analogPin);
            Serial.print   (", ");
            Serial.println (val);
            val = 0;
#endif
            break;

        case 'r':
            Serial.print   ("digitalRead: pin ");
            Serial.print   (val);
            Serial.print   (", ");
            Serial.println (digitalRead (val));
            val = 0;
            break;

        case 's':
            digitalWrite (val, HIGH);
            Serial.print   ("digitalWrite: HIGH ");
            Serial.println (val);
            val = 0;
            break;

        case 't':
            Serial.print   ("pinToggle ");
            Serial.println (val);
            pinToggle (val);
            val = 0;
            break;

        case 'v':
            Serial.print ("\nversion: ");
            Serial.println (version);
            break;

        case '\n':          // ignore
            break;

        case '"':
            while ('\n' != Serial.read ())     // discard linefeed
                ;

            readString (s, MAX_CHAR-1);
            Serial.println (s);
            break;

        case '?':
            Serial.println ("\npcRead:\n");
            Serial.println ("    [0-9] append to #");
            Serial.println ("    A # - set analog pin #");
            Serial.println ("    D # - set debug to #");
            Serial.println ("    I # - set pin # to INPUT");
            Serial.println ("    O # - set pin # to OUTPUT");
            Serial.println ("    P # - set pin # to INPUT_PULLUP");
            Serial.println ("    a # - analogRead (pin #)");
            Serial.println ("    c # - digitalWrite (pin #, LOW)");
            Serial.println ("    p # -- analogWrite (analogPin, #)");
            Serial.println ("    r # - digitalRead (pin #)");
            Serial.println ("    s   - digitalWrite (pin #, HIGH)");
            Serial.println ("    t   -- toggle pin # output");
            Serial.println ("    v   - print version");
            Serial.println ("    \"   - read string");
            Serial.println ("    ?   - list of commands");
            break;

        default:
            Serial.print ("unknown char ");
            Serial.println (c,HEX);
            break;
        }
    }
}

// -----------------------------------------------------------------------------
void
loop (void)
{
    pcRead ();
}

// -----------------------------------------------------------------------------
void
setup (void)
{
    Serial.begin(115200);

    Serial.println (version);
#if defined(ARDUINO_ARCH_ESP32)
    Serial.println ("esp32");
#endif
}

and select "</>" to post your code

Hi , thank you for the quick response.
I tried to use a switch table as follow :

void loop
(value) serial read:
switch = value

{

case 1 = 'a' - this one is for auto
case 2 = 'b' - togle relay 1 on
case 3 = 'c' -togle relay 1 off
case 4 = 'b' - togle relay 2 on
case 5 = 'c' -togle relay 2 off
case 6 = 'b' - servo open
case 7 = 'c' -servo closed

}

But i can't get case 1 to run in a loop .
i am just starting to code so my code is made from what i found here and there also at the end there are some cases missing

code :

#include "Servo.h"
char value;
int sensorH_pin = A1;
int Humidity ;
int sensor_pin = 8;
int ThermistorPin = A0;
int Vo;
float R1 = 4580;
float logR2, R2, T, Tc;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

Servo servo1; //creat servo obj

#include "Servo.h"
char value;
int sensorH_pin = A1;
int Humidity ;
int sensor_pin = 8;
int ThermistorPin = A0;
int Vo;
float R1 = 4580;
float logR2, R2, T, Tc;
float c1 = 1.009249522e-03, c2 = 2.378405444e-04, c3 = 2.019202697e-07;

Servo servo1; //creat servo obj

void setup()
{
// put your setup code here, to run once:
Serial.begin(9600);

pinMode(sensor_pin, INPUT);
servo1.attach(6);
servo1.write(20);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);

digitalWrite(3, HIGH);
digitalWrite(5, HIGH);

}

int getTemp ()
{

Vo = analogRead(ThermistorPin);
R2 = R1 * (1023.0 / (float)Vo - 1.0);
logR2 = log(R2);
T = (1.0 / (c1 + c2 * logR2 + c3 * logR2 * logR2 * logR2));
Tc = T - 273.15;
return Tc;
// Serial.print("Temperature: ");
// Serial.print(Tc);
// Serial.println(" C");
}

int getHumidity ()
{
Humidity = analogRead(sensorH_pin);
Humidity = map(Humidity, 550, 0, 0, 100);
return Humidity;
}
void loop()
{

getTemp();
getHumidity ();
Serial.print("Temperature: ");
Serial.print(Tc);
Serial.println(" C");
Serial.print("Umiditate: ");
Serial.print(Humidity);
Serial.println(" %");
delay (1000);

if (Serial.available())
value = Serial.read ();
switch (value)
{
case 'a':

Serial.println("a");
if (Tc >= 30)
{
digitalWrite ( 3 , LOW); //fan condition turnon if temp>30 C
servo1.write(90);

}
else
{

digitalWrite ( 3 , HIGH); //fan condition turnon if temp<30 C
servo1.write(20);//window

}

case 'b':

digitalWrite ( 3 , HIGH); //fan off
break;

case 'c':

digitalWrite ( 3 , LOW); //fan off
break;

}
}

post your code inside the code tags, select the "</>" icon top left

in your loop() you process value regardless of when you just received it. the switch should be conditionally executed along with the read()

if (Serial.available())  {
    value = Serial.read ();
    switch (value)

you also don't have a "break" for the 'a' case

well the brake stops it , i want a conditional break .
I tried experimenting with while , but i can't get it to stop .
is there a code for wile to stop on input from serial monitor ?
i checked some posts but no luck
anyway here is my evolution with case a (it should only break when a key is pressed in this case m but it does not) :

incomingByte and m are declared as variables at the start of the program (in the header )

< switch (value)
{
case 'a':
delay (100);

while (true)
{

Serial.println("aaaaaaa");
getTemp();
getHumidity ();
Serial.print("Temperature: ");
Serial.print(Tc);
Serial.println(" C");
Serial.print("Umiditate: ");
Serial.print(Humidity);
Serial.println(" %");
delay (1000);

if (Tc >= 30)
{
digitalWrite ( 3 , LOW); //fan condition turnon if temp>30 C
servo1.write(90);

}
else
{

digitalWrite ( 3 , HIGH); //fan condition turnon if temp<30 C
servo1.write(20);//window
value = Serial.read ();
}
if (Serial.available() > 0)
incomingByte = Serial.read ();
if ( incomingByte == 'm')
{
m++;
}

@gcjr also i corrected the code as you suggested (the bracket )

@gcjr also i corrected the code as you suggested (the bracket )

But you didn't insert the code tags.

I managed to solve it . :slight_smile:
Now the switch behaves as i want . It may not be the best solution ,but it works and i am happy .
Thank you all for the help.
Also if you have any tips for a beginner i will post the full code meanwhile the part that i fixed:

<
case 'a':
{
delay (100);
int incomingByte = 0;
int m = (0);
while (true)
{

incomingByte = Serial.read ();
if ( incomingByte == 'm')
{
m++;
break;
}

Serial.println("aaaaaaa");
getTemp();
getHumidity ();
Serial.print("Temperature: ");
Serial.print(Tc);
Serial.println(" C");
Serial.print("Umiditate: ");
Serial.print(Humidity);
Serial.println(" %");
delay (1000);

if (Tc >= 30)
{
digitalWrite ( 3 , LOW); //fan condition turnon if temp>30 C
servo1.write(90);

}
else
{

digitalWrite ( 3 , HIGH); //fan condition turnon if temp<30 C
servo1.write(20);//window

}
}
break;
}

1 Like