Troubleshooting Program that reads Serial Input

Hello,

As per requested previously, I have rewritten my code so that it handles only a single process (reading serial data) to make it easier to debug. I want the serial port to read incoming data from a user. The number that is inputted could be anywhere between 0.001 and 50. I used Robin2's Serial Input Basics (Example 4) and read through his Planning and Implementing an Arduino Program guides and borrowed some of his logic to write this. The following compiles, however when I used the Serial Monitor to test it, nothing was outputted.

// Define Constants

// User Inputs (Changes based on motor and application)
// Set default frequency of motor when there is no user input
const int defaultfreq = 25; // In Hz
// Assign threaded bar measurements to each variable (Inputs here will determine accuracy of actuator movement!)
const int barthreadclearance = 0.1; // Distance between each thread (In cm)
// Define either the number of steps the specified motor takes per revolution or its minimum step angle and comment the other one out (Can find this information on motor's data sheet)
// const int stepsperrev = 400; // Unitless
const float stepangleperrev = 1.8; // In degrees

// Calculate values based on user inputs
const float stepsperrev = 360/stepangleperrev; // Define # of steps per revolution
const float disperstep = (barthreadclearance*stepangleperrev)/360; // Define distance travelled per step

// Other constants
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;
int dataNumber = 0;             // new for this version


void setup() {
  
  // Initialize serial and wait for port to open:
    Serial.begin(9600);
    Serial.println("<Arduino is ready>");
}

// Stepper Motor Program Begins and Loops
void loop() {
  recData();
  displayData();
}

float setspeedfreq = defaultfreq/(1E6); // Sets the freq in to default when no user input

void recData() {
  static byte ndx = 0;
  char endMarker = '\n';
  float posmoveinput;
  if (Serial.available() > 0) { // If there is a serial available, read it
    // read the incoming byte:
    posmoveinput = Serial.parseFloat();
    if (posmoveinput != endMarker) {
      receivedChars[ndx] = posmoveinput;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
    }
    else {
    receivedChars[ndx] = '\0'; // terminate the string
    ndx = 0;
    newData = true;
    }
  }
}

void displayData() {
  if (newData == true) {
    float recerveddec = atof(receivedChars);
    Serial.print("I received: "); // Output numerical input (For testing purposes)
    Serial.println(recerveddec,3);
    float distostep = recerveddec/disperstep;
    if (abs(recerveddec) < 0.001) { // 0.001 cm
      Serial.println("Error!");
    }
    newData = false;
  }
}
posmoveinput = Serial.parseFloat();

What is that doing in Robin2's code? His code reads a character at a time.

    // read the incoming byte:
    posmoveinput = Serial.parseFloat();

What is this all about ?

The idea of Robin's method is to read each character as it is entered and when complete turn the string into a float. Here you are reading a whole float at once. Make up your mind which way you want to do it

Change the code to match the comment and simply read one character

@groundFungus It is not. That is mine. Like I said I borrowed some of the logic so some parts are copied while others are changed/added for my own application. That line you referenced is a part of mine and thank you for pointing that out because you're right, it should be "Serial.read". Nonetheless, changing that line did not fix the issue.

Try this with Newline enabled in the serial monitor (sends a newline after you press send). The code expects a newline ('\n') terminator. If it doesn't get a terminator it is not valid input.

// Define Constants

// User Inputs (Changes based on motor and application)
// Set default frequency of motor when there is no user input
const int defaultfreq = 25; // In Hz
// Assign threaded bar measurements to each variable (Inputs here will determine accuracy of actuator movement!)
const int barthreadclearance = 0.1; // Distance between each thread (In cm)
// Define either the number of steps the specified motor takes per revolution or its minimum step angle and comment the other one out (Can find this information on motor's data sheet)
// const int stepsperrev = 400; // Unitless
const float stepangleperrev = 1.8; // In degrees

// Calculate values based on user inputs
const float stepsperrev = 360 / stepangleperrev; // Define # of steps per revolution
const float disperstep = (barthreadclearance*stepangleperrev) / 360; // Define distance travelled per step

// Other constants
const byte numChars = 32;
char receivedChars[numChars];   // an array to store the received data
boolean newData = false;
int dataNumber = 0;             // new for this version


void setup()
{

   // Initialize serial and wait for port to open:
   Serial.begin(9600);
   Serial.println("<Arduino is ready>");
}

// Stepper Motor Program Begins and Loops
void loop()
{
   recData();
   displayData();
}

float setspeedfreq = defaultfreq / (1E6); // Sets the freq in to default when no user input

void recData()
{
   static byte ndx = 0;
   char endMarker = '\n';
   char c;
   if (Serial.available() > 0)   // If there is a serial available, read it
   {
      // read the incoming byte:
      c = Serial.read();      
      if (c != endMarker)
      {
         receivedChars[ndx] = c;
         ndx++;
         if (ndx >= numChars)
         {
            ndx = numChars - 1;
         }
      }
      else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         Serial.println(receivedChars);
         ndx = 0;
         newData = true;
      }
   }
}

void displayData()
{
   if (newData == true)
   {
      float recerveddec = atof(receivedChars);
      Serial.print("I received: "); // Output numerical input (For testing purposes)
      Serial.println(recerveddec, 3);
      float distostep = recerveddec / disperstep;
      if (abs(recerveddec) < 0.001)   // 0.001 cm
      {
         Serial.println("Error!");
      }
      newData = false;
   }
}

@groundFungus Just tried all that and still does not output anything

On my Uno, with the posted code I get:

5560.55 I received: 5560.550 174.5689 I received: 174.569 66.66 I received: 66.660

Are Newlines enabled? Or Both NL& CR? Do you have the right baud rate?

I tried both "Newlines" and "NL&CR". Baud rates all match (9600). I am using UNO R3. I attached an image of what I see in the monitor.

OP image. How to post images.


Better to copy and paste program output in quote tags.
What are you entering in the send line? I get a response even if I enter text.

some text I received: 0.000 Error! 909090 I received: 909090.000

These are all the ways I formatted the input:

  1. 123
  2. <123>
  3. 123\n
  4. <123>\n

I know it looks silly but I am relatively new to programming in general so I wasn't sure what was the correct format or what dictates that and tried all the ones I know of. The only thing that is outputted is:

Even when I try to type in numbers/letters in any of those formats.

OK. I am officially baffled.

123 I received: 123.000 <123> I received: 0.000 Error! 123\n I received: 123.000 <123>\n I received: 0.000 Error!

Do me the favor of starting from scratch. Close the IDE. Open a new instance of the IDE, select and copy the code from reply #4 and paste it into a blank IDE window. Upload the code and try it again in a new serial monitor window.

If you unplug the Arduino while the serial monitor is open, the serial monitor loses the connection and serial monitor must be restarted (closed and opened again) to restore communication.

@groundfungus That worked! I guess restarting it is what did it. I just have another question that stems from this. In response #6 you quoted the output and in it there are additional numbers that are outputted in a new line under each "I read: ###". What do those numbers represent?

 else
      {
         receivedChars[ndx] = '\0'; // terminate the string
         Serial.println(receivedChars);  //**********************
         ndx = 0;
         newData = true;
      }

I put a Serial print in the code to see exactly what was coming in and forgot to comment it. Serial prints are your primary debugging tool. I sprinkle them around as I code to track the values of variables and program flow. Then delete or comment out later once stuff works.

@groundFungus Awesome, thank for the help!