Read decimal number from Serial.read

I'm working on a code that outputs PWM values in the range 0 to 255 based on the values of a depth sensor.

The 'setpoint' in the code is the depth at which i want the pwm output to be exactly zero.
The float pwm is the pwm output, i've made a formula to map the depth values to the pwm values.

The problem is that when I plug in a value for the setpoint manually, i.e., in the program, like 0.3 or 0.4 whatever, the motor runs fine. It stops at the setpoint value and increases/decreases speed according to the depth.

But when I include the char setpoint = Serial.read(); and replace the setpoint values with the variable setpoint which i'm reading from the serial monitor, the motor is not functioning according to the code at all.

I think the problem is with the setpoint = Serial.read() line. Does arduino not read the exact number i input in the serial monitor?

Like if i enter 0.3, will it read something else or 0.3 only?

#include <Wire.h>
#include "MS5837.h"
MS5837 sensor;
#define motor_pin1 5
#define motor_pin2 6

void setup() {
  Serial.begin(9600);
  Wire.begin();
  //MOTOR
pinMode (motor_pin1, OUTPUT);
pinMode (motor_pin2, OUTPUT);
analogWrite (motor_pin1, LOW);
analogWrite (motor_pin2, LOW);

  // Initialize pressure sensor
  // Returns true if initialization was successful
  while (!sensor.init()) {
    Serial.println("Init failed!");
    Serial.println("Are SDA/SCL connected correctly?");
    Serial.println("Blue Robotics Bar30: White=SDA, Green=SCL");
    Serial.println("\n\n\n");
    delay(1000);
  }
  sensor.setModel(MS5837::MS5837_30BA);
  sensor.setFluidDensity(997); // kg/m^3 (freshwater, 1029 for seawater)
}

void loop() {
 
  sensor.read();
  float depth = sensor.depth();
  Serial.print(depth); 
  Serial.println(" m"); 
  
 // if (Serial.available() > 0) {
    float setpoint = Serial.read();
    
     if (depth > setpoint) {
    //mapping of below setpoint
    float pwm = 255 + (-255)*((depth-0.5)/(setpoint-0.5));
    analogWrite (motor_pin2, pwm);
    analogWrite (motor_pin1, 0); 
    Serial.print("right  ");
    Serial.println(pwm);  
  }

  else {
    //mapping of above setpoint
    int pwm = (255)*((depth-setpoint)/(-setpoint));
    analogWrite (motor_pin2, 0);
    analogWrite (motor_pin1, pwm);
    Serial.print("left ");
    Serial.println(pwm);
  }
  
 //   }

  delay(1000);
}

assuming there is a byte to read, when you do

char setpoint = Serial.read();

you get that byte. if you type the character '7' you get the ASCII code for that character inside setpoint.
the ASCII code for '7' is 55 in decimal, so that's the value you'll have for setpoint.

if you want to go back to '7' then subtract the ascii code for '0'

char setpoint = Serial.read() - '0';

ideally you would do some range checking before doing so

if (Serial.available()) {
  char received = Serial.read();
  if ((received >= '0') && (received <= '9')) {
    setpoint = received - '0';
    ... // do some stuff here
  } else {
    // wrong input
  }
}

now if you typed 235 in the Serial monitor, then Serial.read(); is not what you want to do to get the number 235

I would suggest to study Serial Input Basics to handle this although there are (with some caveats) builtin blocking with timeout functions such as Serial.parseInt() functions that could be put to good use.

and what if i want to input a decimal number like 0.5?

From the reference - you might try first, if you want to get to the answers quickly

Returns

The first byte of incoming serial data available (or -1 if no data is available). Data type: **int**.

Please do some reading in Reference, particularly
Serial.parseFloat()

if you want to accept int and float, then use Serial.parseFloat() indeed

just be aware of the timeout and blocking nature of the function but as long as you use the Arduino terminal set for sending LF or CRLF at the end of a command, you should be good to go

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.