0

I am struggling to get my head around why this just won't work. In my simple mind this simple sketch should do as it's told. But I am obviously missing something fundamental.

If anyone could shed some light on what I am doing wrong that would be very good!

The sketch is just to control a relay by typing on or off into the serial monitor. However although it uploads, all I get is the Serial.println repeating and no action on the physical relay.

I can manage to control things over serial by using the switch, case statements but I wanted to try it using full words rather than single chars and also using IF statements etc.

Thanks in advance!

EDIT I just changed the string inputs to a char input and serial.readstring to just serial.read and it works with just entering a 1 or a 2 for example. So to re-ask my question - how can I get it to respond the same but using words? Thanks!

int relay=8;
String serialInput;

void setup() {
  Serial.begin(9600);
  pinMode(relay, OUTPUT);
}

void loop() {
  Serial.println("To toggle relay enter on or off");
  while (Serial.available()==0) {}
  serialInput = Serial.readString();
  if(serialInput=="on") {
    digitalWrite(relay, HIGH);
  }
  if(serialInput=="off") {
    digitalWrite(relay, LOW);
  }
}
3

You are assuming that Serial.readString() will magically know how long a string you meant to send, and wait until it's all there. It doesn't guarantee that.

If your PC uses Linux or Mac, you can use Serial.readStringUntil('\n'), which will read until a line end, and send on<ENTER> as your command.

If you use Windows, the line endings are \r\n so it's a bit more awkward. Build up your string piece by piece, perhaps

int relay=8;
String serialInput;

void setup() {
  Serial.begin(9600);
  pinMode(relay, OUTPUT);
}

void loop() {
  if (Serial.available()) {
    char c = Serial.read();   // get one byte from serial buffer
    if ('\r'==c || '\n'==c) {
      // End of line - process the string
      if(serialInput=="on") {
        digitalWrite(relay, HIGH);
      } else if (serialInput=="off") {
        digitalWrite(relay, LOW);
      }
      serialInput = "";
    } else {
      serialInput += c;     // add it to readString
    }
  }
}

Brief description of how it works:

The string SerialInput starts empty. We do the following repeatedly:

  • If there is a character available on the serial port, read it.
  • If it is not an end-of-line character, add it to the end of our string
  • If it IS an end-of-line character, we know we've got to the end of the line, so...
    • check whether it matches one of our "target" strings, and act on it if so
    • clear it back to an empty string
  • Many thanks for you reply! Not fully understanding your code, but i'll research it some more. I tried to run you code, but it won't compile. I think 1 error was with a missing ' after ('\r'==c so I added that but it still wont run. the error mentions serialInput not declared in this scope. I tried entering that also as a variable in the loop but still didn't work. any ideas? Thanks again for your time! – Michael Sinclair Jan 5 '17 at 21:01
  • Very welcome. Whoops, typos fixed, and also added the first part of the code (which is an exact copy of yours). Also added an explanation of the code, which I hope helps. – Mark Smith Jan 5 '17 at 21:30
  • Mark, thank you again!!! I really appreciate you taking your time here to help me understand. And I think it's starting to click! Your code works a treat now. Lastly if you don't mind to check that it has clicked with me... the C variable is just a random letter? it could be anything I liked? and the \r is simply waiting until i press enter\return on the serial monitor before checking then against the arguments set. And the \n is that like a double check for a return or specifically a newline? So it might work without that if you so desired? Honestly thanks again for your help!! – Michael Sinclair Jan 6 '17 at 13:33
  • Glad it's helpful! Yes, char c could have been char theNewCharacter or anything you like. \r is a carriage return, \n is a new line. Windows puts both on the end of a line, Unix-like OSs put only \n. Rather than worrying about whether we'll get one or both, we just say "whenever we get a character which is part of a line-end, we know we have the whole line, so process it". On Windows you'll get both so you'll process the "real" line, then immediately try to process an empty string, which won't match "on" or "off", so nothing will happen - no harm done. – Mark Smith Jan 6 '17 at 13:41
  • 1
    Fantastic explanation Mark! I GET IT!!! WOOO!!! I don't suppose you do private paid tutoring on Skype etc? I have a lots questions I have struggled with in programming for years and can never seem to get passed the basics. My end goal is to have DIY IOT capability with anything in the house I want, with a nice custom web interface to control or view these things. 3D printed parts and arduino's hooked into everything! But when I struggle so much with the basics it does seem like that goal is unreachable at times. Thanks again! – Michael Sinclair Jan 6 '17 at 14:00

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.