Arduino console - read user commands

hi everyone,

I am trying to program a simple Arduino console that can get commands using the serial monitor. I based my code on Robin2 ‘serial input basic’ (post B),

Robin2 - serial basic

I used the Robin2 code to get the command from the user as a char array. then I create some keywords stored as constant with values 0-5 for using them as a variable in my switch loop. I hope it’s clear :slight_smile:

the main problem is that: my commands are not getting the values that I set on my keywords constant.
it’s not surprising because I try to convert char array to single int. I used that codes as reference for doing that:

refernce code

and that’s my code, thanks for the help

///run the serial monitor in a ‘new line’ mode

#define TIME 0
#define RFCK 1
#define TEST 2
#define KEYP 3
#define INFO 4
#define MUTE 5

int data;

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {
Serial.begin(9600);
Serial.println("");
}

void loop() {

recvWithEndMarker();
runCommand();

}

void runCommand() {
if (newData == true) {
Serial.println(receivedChars);
int command = atoi(receivedChars);
Serial.println(command);

switch (command)
{
case 0:
{
Serial.print("CMD1 ON ");
break;
}
case 1:
{
Serial.print(“CMD2 ON”);
break;
}
case 2:
{
Serial.print(“CMD3 ON”);
break;
}
case 3:
{
Serial.print(“CMD4 ON”);
break;
}
case 4:
{
Serial.print(“CMD5 ON”);
break;
}
case 5:
{
Serial.print(“CMD6 ON”);
break;
}
}
newData = false;
}
}

void recvWithEndMarker() {
static byte ndx = 0;
char endMarker = ‘\n’;
char rc;

// if (Serial.available() > 0) {
while (Serial.available() > 0 && newData == false) {
rc = Serial.read();

if (rc != endMarker) {
receivedChars[ndx] = rc;
ndx++;
if (ndx >= numChars) {
ndx = numChars - 1;
}
}
else {
receivedChars[ndx] = ‘\0’; // terminate the string
ndx = 0;
newData = true;
}
}
}

void showNewData() {
if (newData == true) {
Serial.print("This just in … ");
Serial.println((char*)receivedChars);
newData = false;
}
}

ANY HELP?

i almost always include some version of pcRead() in all of my code to support single character commands. this version provides general purpose control of pins

// 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
}

then I create some keywords stored as constant with values 0-5 for using them as a variable in my switch loop

What are you expecting the user to enter ?

If it is a single digit then Robin's routine, although excellent, is overkill

More details please

@yinon1984, Please always use the code button </> when posting code and also use the Auto Format tool in the IDE to indent your code for easier reading. Like this …

#define TIME  0
#define RFCK  1
#define TEST  2
#define KEYP  3
#define INFO  4
#define MUTE  5

int data;

const byte numChars = 32;
char receivedChars[numChars]; // an array to store the received data
boolean newData = false;

void setup() {
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

void loop() {

    recvWithEndMarker();
    runCommand();

}

void runCommand() {
    if (newData == true) {
        Serial.println(receivedChars);
        int command = atoi(receivedChars);
        Serial.println(command);


        switch (command)               
        {
            case 0:
                {
                Serial.print("CMD1 ON ");
                break;
                }
            case 1:
                {
                Serial.print("CMD2 ON");
                break;
                }
            case 2:
                {
                Serial.print("CMD3 ON");
                break;
                }
            case 3:
                {
                Serial.print("CMD4 ON");
                break;
                }
            case 4:
                {
                Serial.print("CMD5 ON");
                break;
                }
            case 5:
                {
                Serial.print("CMD6 ON");
                break;
                }
        }
        newData = false;
    }
}


void recvWithEndMarker() {
    static byte ndx = 0;
    char endMarker = '\n';
    char rc;

    // if (Serial.available() > 0) {
    while (Serial.available() > 0 && newData == false) {
        rc = Serial.read();

        if (rc != endMarker) {
            receivedChars[ndx] = rc;
            ndx++;
            if (ndx >= numChars) {
                ndx = numChars - 1;
            }
        }
        else {
            receivedChars[ndx] = '\0'; // terminate the string
            ndx = 0;
            newData = true;
        }
    }
}

void showNewData() {
    if (newData == true) {
        Serial.print("This just in ... ");
        Serial.println((char*)receivedChars);
        newData = false;
    }
}

It is very unreasonable to bump a post with no Reply after less than, say, 48 hours.

the main problem is that: my commands are not getting the values that I set on my keywords constant.

I don’t understand what you mean by that as your code seems to make no attempt to use the “#define” values.

Separately, if this was my project I would use characters rather than numbers for the commands. For example ‘T’ for Time, ‘R’ for RFCK, ‘C’ for CHECK (in place of TEST) etc. I think that would be less confusing for the user and actually easier to program.

…R