Changing Variables via Serial monitor

Good evening everyone.

I am not sure if what I am trying to do is even possible.
I have only been messing around with my arduino for just over a week.

I am trying to change the value of a variable (String) via the serial monitor to see how the program works.

I am aware of the recommendation of using the “char” functions, but since I didnt completely understand how that works, I was sticking to using the string since it serves my purpose at the moment.

So I have a string variable in my code (below) called “doorfunction”, and I wanted to change its value via the serial monitor.

I was expecting to be able to write in the serial monitor something like: doorfunction = “open”
Maybe also be able to read the value of the variable with another command?

#include <Servo.h>
Servo doorlatch;  // create servo object to control the latch
int pos = doorlatch.read ();    // variable to store the servo position.
String doorpos = "none"; // variable to declare the position of the door - starts as none
String doorfunction = "none"; // variable to call the function open/close door - starts as none

void setup() {
  doorlatch.attach(2);  // attaches the servo on pin 2 to the servo object
  Serial.begin(9600); // refresh rate
  Serial.println(doorfunction); 
  Serial.println(doorpos); 
}

void opendoor() { 
if ((doorpos == "DoorClosed") & (pos == 20) & (doorfunction == "Open"));
  doorlatch.write(-20);
  delay(200);
  doorfunction = "none";
  doorpos = "DoorOpen";
}

void closedoor() { 
if ((doorpos == "DoorOpen") & (pos == -20) & (doorfunction == "Close"));
  doorlatch.write(20);
  delay(200);
  doorfunction = "none";
  doorpos = "DoorClosed";
}

void loop() {

if ((pos != 20) & (pos != -20)) {
  Serial.println("Unknown latch position");
}

if (doorfunction == "Open"){
  opendoor();
}

if (doorfunction == "Close"){
  closedoor();
}
}

Ps: Please dont kill me for my poor coding skills, I am just trying to learn :slight_smile:

Welcome to the forum. +1 karma for actually posting using code tags.

If you want to communicate with the Serial monitor, your arduino sketch needs to read characters for Serial and then process them. Start with Robin2's excellent tutorial on how to do that here

Tks @blh64

I had read that post already.

I guess I am too used to my other programming language (KRL) having an interface to change variables and view their status, I was hoping arduino could do the same.

The same way I also can check in Python and send commands, I was hoping for a similar solution for arduino.

My main loop checks for serial data, adds any it finds to the buffer, and then handles the buffer if either full or sufficient time has passed for timeout.

The first char of the buffer is a command, and the rest arguments.

You could, for example, have “t” mean “tell” and “s” mean “set”, and then a table of possible variables, probably numbered (you’re not going to be specifying any old variable by name in a compiled language!)

So “t1” could mean, “tell me the name of the first variable on the list”, and “s1” could set the value of variable 1 to blah, and so forth.

I find it more useful to report the status of concepts than specific variables.

That said, part of what you’re seeing here seems to be the difference between compilers and interpreters.

Thanks.

That was actually pretty enlightning.

So I can do what I want for debugging reasons, but I will need to type extra code in, as you said.

Thank you both.

I just need to figure out to correct code to be able to set my variables.

A few comments on that code if I may:

You may think that this line:

int pos = doorlatch.read ();

… actually detects where the servo is? It doesn’t: it returns the last position to which the servo was commanded.

From the reference:

Description

Read the current angle of the servo (the value passed to the last call to write()).

The servo may not actually have got there. In any case, you haven’t explicity commanded it at that stage in your code so I suspect it will use the default of 90, which is where a subsequent attach will command it.

These if() statements wont be doing anything due to the ; on the end. The lines immediately following will always happen.

if ((doorpos == "DoorClosed") & (pos == 20) & (doorfunction == "Open"));
if ((doorpos == "DoorOpen") & (pos == -20) & (doorfunction == "Close"));

I’m not sure what the effect of this -20 will actually be,

doorlatch.write(-20);

… but from the servo reference page:

Syntax

servo.write(angle)
Parameters

servo: a variable of type Servo

angle: the value to write to the servo, from 0 to 180

Try the following sketch (your one with slight modifications) with the following command(s) format to be entered from the InputBox of Serial Monitor (Fig-1, Step-3) with Line ending tab at Newline option.

1. To open/close door, enter the following strings in the InputBox of Serial Monitor and click on the Send button.

doorfunction = <open
doorfunction = <DoorClosed

2. Try this sketch (untested)

#include <Servo.h>
Servo doorlatch;  // create servo object to control the latch
int pos;// = doorlatch.read ();    // variable to store the servo position.
char doorpos[50] = "none"; // variable to declare the position of the door - starts as none
char doorfunction[50] = "none"; // variable to call the function open/close door - starts as none
char temp[50];
int i = 0;
int j = 0;
char y;

void setup()
{
  doorlatch.attach(2);  // attaches the servo on pin 2 to the servo object
  Serial.begin(9600); // refresh rate
  Serial.println(doorfunction);
  Serial.println(doorpos);
}

void loop()
{
  byte n = Serial.available();
  {
    if (n != 0)
    {
      byte m = Serial.readBytesUntil(0x0A, doorfunction, 50);
      doorfunction[m] = 0x0A;
      do
      {
        y = doorfunction[i];
        i++;
      }
      while (y != '<');
      do
      {
        y = doorfunction[i];
        temp[j] = y;
        i++;
        j++;
      }
      while (y != 0x0A);  //temp[] holds value: open or DoorClosed
      memset(doorfunction, 0, 50);
      strcpy(doorfunction, temp);
      strcpy(doorpos, temp);

      if ((pos != 20) && (pos != -20))
      {
        Serial.println("Unknown latch position");
      }

      if (doorfunction == "Open")
      {
        opendoor();
      }

      if (doorfunction == "Close")
      {
        closedoor();
      }
    }
  }
}


void opendoor()
{
  if ((doorpos == "DoorClosed") && (pos == 20) && (doorfunction == "Open"));
  doorlatch.write(-20);
  delay(200);
  char doorfunction[50] = "none";
  char doorpos[50] = "DoorOpen";
}

void closedoor() {
  if ((doorpos == "DoorOpen") && (pos == -20) && (doorfunction == "Close"));
  doorlatch.write(20);
  delay(200);
  char doorfunction[50] = "none";
  char doorpos[50] = "DoorClosed";
}

3. The Serial Monitor
SerialMonitor.png
Figure-1:

SerialMonitor.png

GolamMostafa:
3. The Serial Monitor

Time to update that pic to show the timestamp box next to autoscroll...

timestamp.PNG

timestamp.PNG

blomcrestlight:
Time to update that pic to show the timestamp box next to autoscroll...

Updated Layout of Serial Monitor. Any suggestion to improve?

Joe84:
I was expecting to be able to write in the serial monitor something like: doorfunction = “open”

There is no intrinsic logical link between the Serial Monitor and whatever program is on the Arduino. The Serial Monitor knows nothing about the Arduino program.

You can use the Serial Monitor to send text to the Arduino program but how that text is interpreted is entirely down to the code in your Arduino program.

You should also be aware that there are no variable names (such as doorfunction) in the code that gets uploaded to an Arduino, The compiler converts the variable names in your code to the address in memory where the value will reside.

Using the parse example in Serial Input Basics as a basis for an example you could use the Serial Monitor to send text like <doorfunction, open> and have the two values saved into two cstring variables - let’s call then commandName and commandAction. Then you could have code something like this (not tested)

if (strcmp(commandName, "doorfunction") == 0) {
   strcpy(doorfunction, commandAction);
}

I suspect you will quickly see that sending an abbreviated message such as <D,O> would make things a lot simpler as you can test individual characters with ==. For example (Note that the < and > will not be in receivedChars

if (receivedChars[0] == 'D') {
   doorfuntion = receivedChars[2];
}

…R

doorfuntion = receivedChars[2];

or

receivedChars[1]

:wink:

blomcrestlight:

doorfuntion = receivedChars[2];

or

receivedChars[1]

:wink:

So the 'funtion' is now ',' ? Strange...

Whandall:
So the 'funtion' is now ',' ? Strange...

Good spot, and apologies to Robin2.

I was thinking his example 3 used a delimiter, but that's example 5 :wink:

So yes if it's de-coded ala example 3, the comma is the 2nd element, receivedChars[1], not a delimiter.

blomcrestlight:
So yes if it's de-coded ala example 3, the comma is the 2nd element, receivedChars[1], not a delimiter.

It's always a difficult choice between writing several paragraphs of explanation or just being simple - I tend towards the latter.

...R

(The last time I used code from your tut (just the other day here, on soft serial for BT) I used example 5's technique to parse 4 integers, so I was thinking "example 5" not "example 3" here. Really good material, thank you.)

Robin2:
I suspect you will quickly see that sending an abbreviated message such as <D,O> would make things a lot simpler as you can test individual characters with ==. For example (Note that the < and > will not be in receivedChars

if (receivedChars[0] == 'D') {

doorfuntion = receivedChars[2];
}

In Post#9 due to @Rabin2 (part of which is quoted above), the door-opening command coming from Serial Monitor is this: D, O after discarding the start/stop (< and >) marks. As a result, the contents of receivedChars array are:

receivedChars[0] = 'D'
receivedChars[1] = ','
receivedChars[2] = 'O'

If the content of location receivedChars[0] is D, then the character O (the content of location receivedChars[2]) will enter into variable doorfunction. This is to say that:

doorfunction = receivedChars[2];

A simple comment //receivedChars[1] will hold separating character ',' in the above quote would remove all confusions and mistakes of a group of readers?

Robin2:
It's always a difficult choice between writing several paragraphs of explanation or just being simple - I tend towards the latter.

simple.png

In Post#9, the simplicity has created a confusion/difficulty for not putting an explanatory comment or for not putting the charcaters D and O into two consecutive locations of the array?

simple.png

What an awesome community

Thank you all for your answers, they are extremely helpful, and are helping me very much
Im going to sit down and carefully read all your suggestions.

@blomcrestlight tks for your comments they are very helpful.

int pos = doorlatch.read ();

Yes I did think it would read the actual position of the servo.
I would like to be able to read the actual position in case it loses power.

Lets say the board loses power while the latch was moving, then can i just move to 90? or i need to know where I am first?

These if() statements wont be doing anything due to the ; on the end. The lines immediately following will always happen.

Thanks, I missed that, now I can see the mistake there, it should be "{" :

void opendoor() { 
if ((doorpos == "DoorClosed") & (pos == 20) & (doorfunction == "Open")){
  doorlatch.write(-20);
  delay(200);
  doorfunction = "none";
  doorpos = "DoorOpen";
}
}

As for :

I'm not sure what the effect of this -20 will actually be,

I just want the servo to move to -20 or +20 if the doorfunction open/closed is called (Im not using a bigger number because the servo I recieved seems to be damaged, but it will work, once the code is running I can get a new servo).

@GolamMostafa

Thanks for taking the time to write that scetch, at first view I dont really understand everything happening there.
So I am definetly going to study it and learn line by line what is happening there.

I really appreciate it very much :slight_smile:

@Robin2

You should also be aware that there are no variable names (such as doorfunction) in the code that gets uploaded to an Arduino, The compiler converts the variable names in your code to the address in memory where the value will reside.

I fully understand it know, thank you very much.

I will definetly try your suggestions until I can achieve what I want :slight_smile:

Again I can´t say how grateful i am to everyone.
Thank you all so much!

Joe84:
@GolamMostafa

Thanks for taking the time to write that scetch, at first view I dont really understand everything happening there.
So I am definetly going to study it and learn line by line what is happening there.

Thank you; your all kinds of questions/queries would be honored to the best of ability.

Lets say the board loses power while the latch was moving, then can i just move to 90? or i need to know where I am first?

The servo knows where it actually is; it keeps that a secret though. So if it's en-route from say 180 to 90 and the power goes off while it's at 150, when it powers up and you tell it to go to 90 it's happy with that, even though you the mere human, didn't know where it was.

I just want the servo to move to **-**20

But there is no such place: the servo reference says it's a value from 0 to 180. That's what I meant when I said I don't know what it will make of a -ve position. The position you feed the servo is an absolute position, where 0 is say on the left, 90 in the middle, 180 at the right.

If by -20 you meant 20 to the left say, relative to where it is now, well you would have to do that calculation so if you wanted 20 to the left of 60, you would need to tell it to go to 40, not move -20.

So I have tried to learn about all your comments

At the moment I have tried the sketch from @GolamMostafa

I have commented all the lines with what I believe is happening, but I havent been fully able to understand everything

#include <Servo.h>
Servo doorlatch;  // create servo object to control a servo
int pos = doorlatch.read ();    // variable to store the servo position.
char doorpos[50] = "none"; // variable to declare the position of the door - starts as none
char doorfunction[50] = "none"; // variable to call the function open/close door - starts as none
char temp[50]; // Temporal array
int i = 0; //Integer set to zero
int j = 0; //Integer set to zero
char y; // Variable "y" declared

void setup() {
  doorlatch.attach(2);  // attaches the servo on pin 2 to the servo object
  Serial.begin(9600); // refresh rate
  Serial.println(doorfunction); // Print actual function, result should be none
  Serial.println(doorpos); // Print actual door pos, result should be none (until further development)
}

// Open door function, will open the latch if the conditions are all ok
void opendoor() { 
if ((doorpos == "DoorClosed") & (pos == 110) & (doorfunction == "Open")){
  doorlatch.write(70); // send to 70 degrees
  delay(100); // wait for servo to reach position
  char doorfunction[50] = "none"; // function finished, reset to none
  char doorpos[50] = "DoorOpen"; // position door open reached
}
}

// Close door function, will close the latch if the conditions are all ok
void closedoor() { 
if ((doorpos == "DoorOpen") & (pos == 70) & (doorfunction == "Close")){
  doorlatch.write(110); // send to 110 degrees
  delay(100); // wait for servo to reach position
  char doorfunction[50] = "none"; // function finished, reset to none
  char doorpos[50] = "DoorClosed"; // position door closed reached
}
}

void loop() {

{
  byte n = Serial.available(); // set byte n = value of serial data
  {
    if (n != 0) // if n (serial data available) has been recieved
    {
      byte m = Serial.readBytesUntil(0x0A, doorfunction, 50);  // searches in the buffer for 0x0A (new line or \n) and stores in doorfunction array ¿why searching for newline? new line of input in serial monitor?
      doorfunction[m] = 0x0A; // doorfunction array "m" = 0x0A (new line)
      
      do // loop until variable "y" is not equal to "<"
      {
        y = doorfunction[i]; // Variable "y" = ???
        i++; // ????
      }
      while (y != '<'); // exit loop when variable "y" is not equal to "<"   - (Why would y be = "<" ??? )
      
      do // loop until variable y is not equal to new line (0x0A) 
      {
        y = doorfunction[i]; // Variable "y" = ???
        temp[j] = y; // Temp array "j" = Variable "y" ????
        i++; // Increment variable i +1 ???
        j++; // Increment variable j +1 ???
      }
      while (y != 0x0A);  //temp[] holds value: Open or Close
      
      memset(doorfunction, 0, 50); // Resets the array ???
      strcpy(doorfunction, temp); // Copies the value of temp in to doorfunction ???
      strcpy(doorpos, temp); // Copies the value of temp in to doorpos ???

      if ((pos != 110) && (pos != 70)) // If position is not open or closed
      {
        Serial.println("Unknown latch position"); // Further devolepment needed
      }

      if (doorfunction == "Open") // If variable doorfuntion is set to Open, run opendoor function
      {
        opendoor(); // Calls the function to Open the latch
      }

      if (doorfunction == "Close") // If variable doorfuntion is set to Close, run closedoor function
      {
        closedoor(); // Calls the function to Close the latch
      }
    }
  }
}
}

I did try very hard but didnt understand everything.
I left question marks where I didn´t understand what was happening.

I do however see a problem with this solution (returning to the main topic of the post)
I want to be able to change a variable for debugging purposes, and in this sketch I believe the function “do…while” will generate a loop that will not exit unless input is inserted via serial monitor.

I am really aiming to have my loop running and then be affected by a variable change, not waiting for a variable.

However I am still going to hope tu fully understand the code above, before moving on to try @Robin2 suggestion.

Tks once again :slight_smile: