Re-implementing serial monitor (serial read) C++

Hello,

I've been struggling to read the serial buffer from my program written in C++ for a while now.

I have set my arduino to repetively print a string which I'm trying to recieve in my C++ program and then print to console.

I'm just using the standard example from arduino examples to print a sensor value and number as a string as follows:

/*
  Analog input, analog output, serial output
 
 Reads an analog input pin, maps the result to a range from 0 to 255
 and uses the result to set the pulsewidth modulation (PWM) of an output pin.
 Also prints the results to the serial monitor.
 
 The circuit:
 * potentiometer connected to analog pin 0.
   Center pin of the potentiometer goes to the analog pin.
   side pins of the potentiometer go to +5V and ground
 * LED connected from digital pin 9 to ground
 
 created 29 Dec. 2008
 by Tom Igoe
 
 This example code is in the public domain.
 
 */

// These constants won't change.  They're used to give names
// to the pins used:
const int analogInPin = 0;  // Analog input pin that the potentiometer is attached to
const int analogOutPin = 9; // Analog output pin that the LED is attached to

int sensorValue = 0;        // value read from the pot
int outputValue = 0;        // value output to the PWM (analog out)

void setup() {
  // initialize serial communications at 9600 bps:
  Serial.begin(9600); 
}

void loop() {
  // read the analog in value:
  sensorValue = analogRead(analogInPin);            
  // map it to the range of the analog out:
  outputValue = map(sensorValue, 0, 1023, 0, 255);  
  // change the analog out value:
  analogWrite(analogOutPin, outputValue);           

  // print the results to the serial monitor:
  Serial.print("sensor = " );                       
  Serial.print(sensorValue);      
  Serial.print("\t output = ");      
  Serial.println(outputValue);   

  // wait 1000 milliseconds before the next loop
  // for the analog-to-digital converter to settle
  // after the last reading:
  delay(1000);                     
}

My C code is as follows:

#include <cstdlib>
#include <iostream>
#include "stdio.h"
#include <windows.h>

using namespace std;

void PrintError( LPCSTR str)
{
LPVOID lpMessageBuffer;
int error = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), //The user default language
(LPTSTR) &lpMessageBuffer,
0,
NULL
);
printf("%s: (%d) %s\n\n",str,error,lpMessageBuffer);
LocalFree( lpMessageBuffer );
}


const char* ReadSerialLine(){

// open port for I/O
string myString;
HANDLE h = CreateFile("com3",
GENERIC_READ|GENERIC_WRITE,
0,NULL,
OPEN_EXISTING,0,NULL); // my adruino on com4 but this value can be read from argv

if(h == INVALID_HANDLE_VALUE) {
PrintError("E012_Failed to open port");
} else {
// set timeouts
//COMMTIMEOUTS cto = { 1, 100, 1000, 0, 0 };
DCB dcb;
//if(!SetCommTimeouts(h,&cto))
//PrintError("E013_SetCommTimeouts failed");

// set DCB
memset(&dcb,0,sizeof(dcb));
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = 9600;
dcb.fBinary = 1;
dcb.fOutxCtsFlow = 1;
dcb.fRtsControl = DTR_CONTROL_HANDSHAKE;
dcb.fDtrControl = DTR_CONTROL_DISABLE; // avoid reset of arduino board
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
dcb.ByteSize = 8;

if(!SetCommState(h,&dcb))
PrintError("E014_SetCommState failed");

char buf[50];
buf[19] = '\0';
DWORD read = 0;

ReadFile(h,buf,sizeof(buf)-1,&read,NULL); // read is updated with the number of bytes read


myString = buf;

CloseHandle(h);

}
return myString.c_str();
}


int main(int argc, char** argv) {

    for (int x=0;x<1000;x++){
    printf(ReadSerialLine());
    }

return 0;
}

My problem is that the returned string is always only half there and when the buffer is empty it returns some wierd characters.

I really need someway of checking if the buffer is full and only then attempting to read it. Similar to the available function in arduino processing.

I don't know how to implement this in C++ and I've been searching for it for months now... yes MONTHS!

help would be really appreciated.

Doesn't ReadFile tell you how many bytes it read? Isn't that what the read variable is for? Shouldn't you then be putting a NULL in buf at that position?

I really need someway of checking if the buffer is full and only then attempting to read it. Similar to the available function in arduino processing.

The available() function in Processing and on the Arduino tells how many bytes are in the buffer to read. It doesn't prevent you from reading until the buffer is full.

On the Arduino, waiting to read until the buffer is full (or in your program) isn't a good idea. What happens if the buffer never gets full?

const char* ReadSerialLine(){
// open port for I/O
string myString;
[glow]// From this point...[/glow]

// [snip]

[glow]// ...until this point, myString exists.  PAST THIS POINT IT DOES NOT.  You are returning a pointer to a buffer that will be freed before...[/glow]
return myString.c_str();
}

int main(int argc, char** argv) {
    for (int x=0;x<1000;x++){
[glow]//...it can be used in the call to printf.  The pointer returned from ReadSerialLine is no longer valid; it points to a buffer that is essential corrupt.[/glow]
    printf(ReadSerialLine());
    }
return 0;
}

Totally missed that. It's a good thing when more than one set of eyes is looking at the problem.

Thanks, but how do I resolve that ?

Make it global.
or
Pass it in as a parameter.
or
Allocate a new one.
or...

You really don't want to close the file and reopen it every time you read a line, do you? You will undoubtedly miss some of the Arduino output.

Here's a simple C program that uses your Windows Handle functions (but without the windows error message stuff) that might be a starting reference point.

Make a "readline" function if you want. Pass the handle and a buffer pointer if you want. Or, maybe, change it back to C++ and use strings and just have your readline function return a string. Stuff like that.

#include <stdio.h>
#include <stdlib.h>
#include <windows.h>

int main(int argc, char **argv)
{
    int i;
    DCB dcb;
    char *port = "COM8:";
    HANDLE h;
 
    if (argc > 1) {
        port = argv[1];
    }

    h = CreateFile(port,
                   GENERIC_READ | GENERIC_WRITE,
                   0, NULL,
                   OPEN_EXISTING, 0, NULL);

    if (h == INVALID_HANDLE_VALUE) {
        fprintf(stderr, "Can't open port %s for reading\n", port);
        exit(EXIT_FAILURE);
    }
    memset(&dcb, 0, sizeof(dcb));
    dcb.DCBlength = sizeof(dcb);
    dcb.BaudRate = 9600;
    dcb.fBinary = 1;
    dcb.fOutxCtsFlow = 1;
    dcb.fRtsControl = DTR_CONTROL_HANDSHAKE;
    dcb.fDtrControl = DTR_CONTROL_DISABLE;
    dcb.Parity = NOPARITY;
    dcb.StopBits = ONESTOPBIT;
    dcb.ByteSize = 8;

    if (!SetCommState(h, &dcb)) {
        fprintf(stderr, "SetCommState failed\n");
        exit(EXIT_FAILURE);
    }

    for (i = 0; i < 1000; i++) { // Or whatever...
        char buf[10] = {0}; // Initialize with zeros
        DWORD read = 0;
        ReadFile(h, buf, sizeof(buf) - 1, &read, NULL);
        printf("%s", buf);
    }
    CloseHandle(h);

    return 0;
}

Regards,

Dave

Hi Dave,

I compiled your program and got no output. Ideally I don't want to use global variables. I would rather have a function that reads the string buffer but I only want to do that when I get back something meaningful.

I'd like to mimic the functionaility of the serial monitor incorporated within the arduino compiler, so it displays only the output send from the arduino.

I intend to eventually use this code in a GUI made using QT creator.

Any idea of how to just print out the data sent from the arduino to console ?

Thanks

....hi again dave,

I added a

Sleep(10);

line to the read loop and this allowed the buffer time to fill and be reported.

Thats a big step forward but I'd still like some kind of function that tells me when the buffer has chars in it so I don't have to constantly poll the buffer as in that example.

of course polling the buffer in a for loop as above mean the program can't be doing anything else at the same time.

Thanks for all your help, please help more if you can.

I really need someway of checking if the buffer is full and only then attempting to read it.

Do you really want to know when the buffer is "full", or do you want to know when it contains a string of data that you are interested in? Buffers usually have a finite size, so when the amount of data matches the buffer size, it is "full". If you are interested in a string of data, then you may need to mark the start/stop of the string and then check for the start/stop marks in the buffer.

Ok, full is a bad word to use.

What I really want is to know when it contains information I'm looking for and I dont' want to have to poll it all the time but rather use some kind of software interupt.

eg: I have a peristaltic pump, every now and then someone may change the speed of it. When they do it'll notify me with a string saying Speed : 50 for example.

Thus I only really want to read the buffer once I know my pump has sent that string, rather than querying it all the time and recieving nothing or other data I don't need.

To elaborate; I want to same kind of thing as is in the serial monitor that comes with the arduino software.

I want to listen to the serial port and report the strings it has sent but I don't want to spend all my CPU time listening, because I want the rest of the program to be executing at the same time.

In C#, you can create threads that monitor the serial port. I've spawned threads in C++, but not for the purpose of reading the serial port, but I expect that you can read from the serial port in a thread with C++.

The thread wouldn't have anything else to do, and wouldn't interfere with the performance of the main thread, whatever that is, until serial data arrived.

Would it be possible to give me an example. I'm a self taught programmer and not that good but I can get by with a little help.

Greatly appreciated.

Would it be possible to give me an example.

In C# or C++?

C++, I'm using a PC with window 7 OS, and netbean or QT creator with the minGW compiler set.

I PM'ed you.

So am I right in thinking there is no simple way to only call a read byte function when a byte is present in the buffer to be read?

I looked at the SerialPort documentation for C#, and I don't see a method of determining whether there is data to read, or not.

On the other hand, the derivation path for SerialPort makes it just another stream reader, and stream readers know to stop when the stream is empty. There might be an eof() function somewhere in it's derivation path that you could use to see if you are at the end of the stream.

If you use a thread to read the port, it doesn't matter that the thread blocks waiting for data.