User defined motor PWM setting / speed not working

Hello.

(Totally new in the Arduino world and forum so if there is something wrong with the post, I will try to correct it ASAP).

I am making a laboratory equipment where user can set the speeds of peristaltic pumps using L298N Dual Bridge H-motor controller (idea is set up the transfer pumps with user controlled speeds).

When trying to give the PWM speed by the user for the test sketch when controlling only one pump:

#include <Wire.h>

// Dosing pump pins
int dir1PinA = 7;
int dir2PinA = 8;
// Transfer pump 1 pins
int dir3PinA = 3;
int dir4PinA = 4;
int speedPinA = 9; // Needs to be a PWM pin to be able to control motor speed
// Transfer pump 2 pins
int dir5PinA = 5;
int dir6PinA = 6;
int speedPinB = 10; // Needs to be a PWM pin to be able to control motor speed

//select one by uncommenting
byte ValueS1;
//int ValueS1;

//byte ByteS2;
//int ValueS2;



void setup() {
  Serial.begin(9600);
  // Motor output
  pinMode(dir1PinA, OUTPUT);
  pinMode(dir2PinA, OUTPUT);
  pinMode(dir3PinA, OUTPUT);
  pinMode(dir4PinA, OUTPUT);
  pinMode(dir5PinA, OUTPUT);
  pinMode(dir6PinA, OUTPUT);
  pinMode(speedPinA, OUTPUT);
  pinMode(speedPinB, OUTPUT);



  Serial.begin(9600);                 //initialize serial communication


  Serial.println ("Give speed to transfer pump 1");


  while (Serial.available() <= 0)     //if <= 0, there is no input
  {
       // read the value sent from keyboard, wait until there is incoming serial data
  }
   ValueS1 = Serial.read();

 


}

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

//  ValueS1 = map(ValueS1, 0, 1023, 0, 255);
  analogWrite(speedPinA, ValueS1);//Sets speed variable via PWM
  digitalWrite(dir3PinA, HIGH);
  digitalWrite(dir4PinA, LOW);
  Serial.println("Transfer pump on, speed"); // Text to screen
  Serial.println(byte(ValueS1));
  Serial.println(ValueS1);
  Serial.println(int(ValueS1));
  Serial.println("   "); // Empty line

}

by inputting value 255 from the serial monitor, the response is:

"Transfer pump on, speed
50
50
50"

and for the input value 100 the PWM is 49, input value 0 the PWM is 48, etc. and motor is not getting the correct PWM value (motor is turning slowly but not pumping)

So far I have tried:

  • When changing
  analogWrite(speedPinA, ValueS1);//Sets speed variable via PWM

ValueS1 to 255 the pump works fine at full speed, but even still PWM input 1 gives the output of 49.

  • Tested between int and byte for the ValueS1, no change in function
  • Tested if the problem was with analog read/write (1023 to 255 value), no change
  • Tested with input methods, no change. Checked that serial input 255 is read as 255.
  • Checked the connections (ruled out when replacing user defined value with 255 pump works, not the output)

Thanks, any help is appreciated!

Please, try the following sketch (your one with slight modification). Select Newline option in the Line ending tab of Serial Monitor (Fig-1).

int dir1PinA = 7;
int dir2PinA = 8;
// Transfer pump 1 pins
int dir3PinA = 3;
int dir4PinA = 4;
int speedPinA = 9; // Needs to be a PWM pin to be able to control motor speed
// Transfer pump 2 pins
int dir5PinA = 5;
int dir6PinA = 6;
int speedPinB = 10; // Needs to be a PWM pin to be able to control motor speed
byte ValueS1;
char myData[10];

void setup()
{
  Serial.begin(9600);
  pinMode(dir1PinA, OUTPUT);
  pinMode(dir2PinA, OUTPUT);
  pinMode(dir3PinA, OUTPUT);
  pinMode(dir4PinA, OUTPUT);
  pinMode(dir5PinA, OUTPUT);
  pinMode(dir6PinA, OUTPUT);
  pinMode(speedPinA, OUTPUT);
  pinMode(speedPinB, OUTPUT);

  Serial.begin(9600);                 //initialize serial communication
  Serial.println ("Give speed to transfer pump 1");
}

void loop()
{
  if (Serial.available() != 0)     //if <= 0, there is no input
  {
    byte m = Serial.readBytesUntil('\n', myData, 10);
    myData[m] = '\0';
    ValueS1 = atoi(myData);  //Input: 0 -255; output: 0 -255

    analogWrite(speedPinA, ValueS1);//Sets speed variable via PWM
    digitalWrite(dir3PinA, HIGH);
    digitalWrite(dir4PinA, LOW);
    Serial.println("Transfer pump on, speed"); // Text to screen
    Serial.println(byte(ValueS1));
    Serial.println(ValueS1);
    Serial.println(int(ValueS1));
    Serial.println("   "); // Empty line
  }
}


Figure-1:

Thank You!

Seems to work now with any given value.

I will try to implement this for the second transfer pump as well!

(Updating the project as it goes if any further issues rise..)

Thank you and have joy!

ValueS1 = Serial.read();

That doesn't work for you for several reasons.

  1. Serial.read() will only read one character. So, entering 1, 100, or 111111 will get you the same value each time. "1"
  2. Serial.read() is returning a single byte character. Computers absolutely do not understand numbers (such as "123") nor characters (such as "ABC"). Keep in mind that if you enter "100", the Serial.read() will fetch the 1 out, but leave the "00" in the buffer. If you make a second entry, for example 255 and do another Serial.read(), it will fetch "0" (from the 100, the next character after the 1 previously fetched). The 255 you just entered is simply added into the Serial buffer and would eventually be read out, just not when one might expect it.

Computers only understand, on an Arduino, 8 bit bytes as numerical values. The interpretation is done, on an Arduino at least, by an international standard called ASCII. In that standard, the CHARACTER "1" has a numerical value of 49 which is why you are getting 49 as a value from Serial.read().
If you are trying to scan in integer numbers, you should use Serial.parstInt(). If you entered 123 in the Serial monitor (which only understands the three characters 1/49, 2/50, 3/51) then Serial.parseInt() will give you the numerical value of 123 into whatever variable you read it into.
Does that explanation help any at all?

Arduino Reference says that the read() method returns "first byte (8-bit) of incoming serial data available" and recommends to use int as a data type, which accommodates 8-bit very well.

Now, the concern is -- OP has sent a character (say: 1) from the Serial Monitor which has arrived to UNO as 0011 0001 (0x31 in hex base) about which OP may not aware. Therefore, OP would be expecting to see 1 instead of 49 (the decimal equivalent of 0x31) in the Serial Monitor. In such case, OP should have included the following codes in his sketch:

byte ValueS1;
Valus1 = Serial.read();
Serial.println((char)ValueS1);   //shows: 1

Why has OP seen 49 on Serial Monitor?
He has executed the following code:

byte ValueS1;
ValueS1 = Serial.read();  //ValueS1 holds 0x31
Serial.println(ValueS1);   //has shown 49 in base-10 ox 0x31