1

I'm having a weird issue with my Uno trying to power on a PWM fan using a MOSFET.

I'm setting a simple power on/off code using commands sent over the Serial Monitor, and although this code worked before, after I tried to add some code to control the speed of the PWM fan, my if statements do not work anymore, even with the simple power on/off code:

    String command;           //Define the string variable "command"

void setup() {
  // put your setup code here, to run once:

  pinMode(5, OUTPUT);     //Set pin 5 as MOSFET Gate signal pin
  pinMode(13, OUTPUT);    //Set pin 13 to use onboard LED as a waiting for command status LED
  digitalWrite(5, LOW);   //Start with MOSFET off
  digitalWrite(13, LOW);  //Star with status LED off
  Serial.begin(9600);     //Start Serial comm for sending commands

}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println("What's your command?"); //Ask for a command in the Serial Monitor

  while (Serial.available()==0) {        //Wait for user input stopping the code
    digitalWrite(13, HIGH);               //Blink the onboard LED indicating that the code is waiting for user input
    delay(100);
    digitalWrite(13, LOW);
    delay(100);
  }

  command=Serial.readString();          //Save the Serial Monitor String command to the "command" variable as a String
  Serial.println("data read");          //Confirm Serial Monitor input
  Serial.println(command);              //Print the command sent over the Serial Monitor to confirm the data received

  if (command=="On") {                  //Turn the MOSFET on
    digitalWrite(5, HIGH);
  } else if (command=="Off") {                  //Turn the MOSFET off
    digitalWrite(5, LOW);
  }
  else {                                 //Provide feedback for a wrong command
    Serial.println("Wrong command!");
  }
}

This is my Serial Monitor output after sending "On":

What's your command?
data read
On

Wrong command!
What's your command?

To check if the pin works, I tested a simple code that worked fine:

void setup() {
  // put your setup code here, to run once:

  pinMode(5, OUTPUT);     //Set pin 5 as MOSFET Gate signal pin
  digitalWrite(5, LOW);   //Start with MOSFET off
  Serial.begin(9600);     //Start Serial comm for sending commands

}

void loop() {
  // put your main code here, to run repeatedly:

    digitalWrite(5, HIGH);
    delay(2000);
    digitalWrite(5, LOW);
    delay(2000);

}

Does anyone have any idea why the if statements are not working anymore?

Thank you in advance!

AC

EDIT: After trying to use the "else" statement as recommended by per1234, the issue continues to happen, but changing the variable type to an integer works, although the Serial output is rather messy:

int command;           //Define the int variable "command"

void setup() {
  // put your setup code here, to run once:

  pinMode(5, OUTPUT);     //Set pin 5 as MOSFET Gate signal pin
  pinMode(13, OUTPUT);    //Set pin 13 to use onboard LED as a waiting for command status LED
  digitalWrite(5, LOW);   //Start with MOSFET off
  digitalWrite(13, LOW);  //Star with status LED off
  Serial.begin(9600);     //Start Serial comm for sending commands

}

void loop() {
  // put your main code here, to run repeatedly:

  Serial.println("What's your command?"); //Ask for a command in the Serial Monitor

  while (Serial.available()==0) {        //Wait for user input stopping the code
    digitalWrite(13, HIGH);               //Blink the onboard LED indicating that the code is waiting for user input
    delay(100);
    digitalWrite(13, LOW);
    delay(100);
  }

  command=Serial.parseInt();          //Save the Serial Monitor imput command to the "command" variable as an int

  Serial.println("data read");          //Confirm Serial Monitor input
  Serial.println(command);              //Print the command sent over the Serial Monitor to confirm the data received

  if (command==1) {                  //Turn the MOSFET on
    digitalWrite(5, HIGH);
  } 
  if (command==2) {                  //Turn the MOSFET off
    digitalWrite(5, LOW);
  }
  else {                                 //Provide feedback for a wrong command
    Serial.println("Wrong command!");
  }
}

And the Serial Monitor output:

What's your command?
data read
1
What's your command?
data read
0
Wrong command!
What's your command?
data read
2
What's your command?
data read
0
Wrong command!
What's your command?

Does anyone experience this issue? I even tried rolling back my IDE to 1.8.3, which I used to write the code the first time, then after a library update, and also getting version 1.8.5, it stopped working.

Also, anyone knows how to avoid the multiple Serial Monitor outputs?

I tested this with "String" variables to be able to get this fixed.

Also, a side question regarding the post size, should I remove the original code when editing, or should I move it to another answer?

Thank you.

1

The problem with the original code is evidenced in the following:

What's your command?
data read
On

Wrong command!

See that blank line? Nowhere in your sketch do you specifically print a blank line, rather it is being printed because the command string contains a carriage return and/or newline character captured with the input, which is causing a comparison of exact equality to fail.

To fix this, you could either trim these non-printing characters off the end, or use a different comparison, for example command.startsWith("On"). But if you do use a start-of-string comparison, beware if you have any command verbs that extend other shorter ones.

You also have a bug in your block if-else statements, in that instead of

if ...
if ...
else ...

you should have

if ...
else if ...
else ....

So that the "none of the above" clause only runs when none of the conditions are satisfied, rather than running whenever the penultimate condition is not satisfied.

In terms of the numeric version producing an un-entered value of 0, this is the documented return value of the parseInt() methods if they time out without finding a valid integer.

It would be more traditional to use an end-of-line condition rather than a timeout to detect the end of user input. Many traditional "until end of line" read mechanisms trim the line ending characters off the resulting string for you, eliminate the comparison problem, too.

  • Thank you Chris, the if-else statements have changed on my second revision of the code, since the serial output doesn't have the blank line anymore. Do you think deleting everything from my Arduino folder under the Windows user folder would help? The newline or carriage return can be causing the 0 character to show up automatically on the serial output on my integer code. – avc Jan 4 '18 at 18:03
  • No, don't wipe your install, rather see the documentation for parseInt and what it says it does if input times out with no number entered. – Chris Stratton Jan 4 '18 at 18:31
4

Let's look at what this code does when you send "On":

  if (command=="On") {                  //Turn the MOSFET on
    digitalWrite(5, HIGH);
  }

This will evaluate true so pin 5 is set to HIGH.

  if (command=="Off") {                  //Turn the MOSFET off
    digitalWrite(5, LOW);
  }

This will evaluate false so the else clause is executed:

  else {                                 //Provide feedback for a wrong command
    Serial.println("Wrong command!");
  }

So the output you are seeing is correct for your code. The problem is that your code doesn't match your intent. For that you need to change this line:

  if (command=="Off") {                  //Turn the MOSFET off

to:

  else if (command=="Off") {                  //Turn the MOSFET off

Then the else clause will only run if the command doesn't match "On" or "Off".

For more information see: https://www.arduino.cc/reference/en/language/structure/control-structure/else/

  • Thank you per1234. I'll test this and provide feedback later in the day. – avc Jan 4 '18 at 7:01
  • Hi per1234. Unfortunately, this did not fix my issue, but changing the variable type did. Can you please check the code in my edit? – avc Jan 4 '18 at 17:34
0

Thank you for your help.

I have been able to find the root cause of my original problem.

After reading this post on https://forum.arduino.cc/index.php?topic=73372.0, more specifically an answer regarding filtering for \n and \r characters and the Arduino IDE Serial Monitor line ending option.

My problem was caused by having the "Newline" option selected in the Serial Monitor. After selecting "No line ending", my original code runs as expected, and I know now how to use String variable and Serial.readString() in a more efficient way, and the if-else statements.

Also, the blank line mentioned by Chris Stratton is gone, and my search to fix that led me to the solution of the main problem, and the code also works 100% with the formatting help provided by per1234.

Thank you both again for the help.

  • You probably do not want to disable the line ending transmission; rather you likely want to read until a line ending (and then exclude it) rather than until a timeout. The Arduino serial monitor is a bit odd as a client in encouraging you to tap an on-screen button to send, more typically it's pressing return than triggers transmission, or else if characters are sent as typed, makes the recipient act on them. – Chris Stratton Jan 4 '18 at 22:37
  • Thank you for that info Chris. I will look into that. For now, I'm going to use the serial monitor to simulate the input and effects on my code, since my final goal is to setup the Arduino to read external analog signals, but since I'm quite new to this type of programming, I'm trying to understand what I can or can't do. I've been using Arduino for some years, but mostly with pre-assembled sensor boards and copy pasting code. – avc Jan 5 '18 at 7:41

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.