简体   繁体   中英

C++ reading data from external device - connection: OPTO-USB

I was looking for some information about connecting a dial gauge (I'm not sure if it is called like that) made by Sylvac with program written in C++. The connection is by OPTO-USB cable (number 926.6621.10). Data format: X.XX (in millimeters).

I tried to use MSDN functions: CreateFile , ReadFile . There is no error, neither any value. Transmission settings should be correct (I found them on CD attached to the cable).

Does someone have any idea how to read data from dial gauge? I tried to convert data in a few ways. "cout" under each function was used to find the place, where program stops. I wrote this code using some on the Internet.

Edit on 2014-01-10

There is still problem with my program. The dial gauge shows "0,04" on the display, so I expect the same value in my program in "buffor" variable, but there is nothing. Even "read" is zero.

My code:

#include <iostream>
#include <windows.h>

using namespace std;

int main()
{
    LPBYTE buffor = new BYTE[64];
    *buffor = 1;
    HANDLE file;
    COMMTIMEOUTS timeouts;
    DWORD read;
    DCB port;
    char port_name[128] = "\\\\.\\COM3";
    cout << "pierwszy: " << endl;

    // open the comm port.
    file = CreateFile((port_name), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

    if ( file == INVALID_HANDLE_VALUE ) {
        cout << "1 1";
        return 1;
    }
    else
    {
        // get the current DCB, and adjust a few bits to our liking.
        memset(&port, 0, sizeof(port));
        port.DCBlength = sizeof(port);
        if ( !GetCommState(file, &port))
            cout << " 2 ";
        if (!BuildCommDCB(("baud=4800 parity=e data=7 stop=2"), &port))
            cout << " 3 ";
        if (!SetCommState(file, &port))
            cout << " 4 ";

        port.fDtrControl = DTR_CONTROL_ENABLE;
        port.fRtsControl = RTS_CONTROL_ENABLE;

        BOOL success;
        success = GetCommTimeouts(file, &timeouts);
        if (!success)
        {
            cout << "error";
            CloseHandle(file);
            return 1;//INVALID_HANDLE_VALUE;
        }
        timeouts.ReadIntervalTimeout = 1000;
        timeouts.ReadTotalTimeoutConstant = 1000;
        timeouts.ReadTotalTimeoutMultiplier = 0;
        timeouts.WriteTotalTimeoutConstant = 1000;
        timeouts.WriteTotalTimeoutMultiplier = 0;
        success = SetCommTimeouts(file, &timeouts);
        if (!success)
        {
            cout << "error";
            CloseHandle(file);
            return 1;//INVALID_HANDLE_VALUE;
        }

        if (!EscapeCommFunction(file, CLRDTR))
           cout << " 7 ";
        Sleep(200);
        if (!EscapeCommFunction(file, SETDTR))
           cout << " 8 ";

        // check for data on port and display it on screen.
        if(ReadFile(file, &buffor, sizeof(buffor), &read, NULL))
        {
            cout << "buffor: " << buffor << endl;
            cout << "read = " << read << endl;
            for (int i = 0; i < read; i++ )
                cout << i+1 << ". " << buffor[i] << endl;

            cout << "." << endl;
        }
        else
            cout << "error read";

        delete buffor;
        CloseHandle(file);
    }

    system("pause");
    return 0;
}

I put here the result in console: console

Variables expected: buffor -> 0,04; read -> number of read bytes

Output variables: buffor ???? Nothing?; read = 0

With the additional information provided in the comments, we can start to diagnose this. The actual problem for you is that junk is getting printed after the word "odczytane". This information should have been in the first post, by the way.

First of all, you need to ensure that your program is set up to do blocking reads. You have set some very short reading timeouts, which means that whenever you try to read data from the file your program will give up very quickly. Your program is probably giving up before any data is ready. Try increasing each of those to 1000 ms by doing something similar to he following code:

    BOOL success;
    success = GetCommTimeouts(port, &timeouts);
if (!success)
{
    fprintf(stderr, "Error: Unable to get comm timeouts.  Error code 0x%x.\n", GetLastError());
    CloseHandle(port);
    return INVALID_HANDLE_VALUE;
}
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier = 0;
success = SetCommTimeouts(port, &timeouts);
if (!success)
{
    fprintf(stderr, "Error: Unable to set comm timeouts.  Error code 0x%x.\n", GetLastError());
    CloseHandle(port);
    return INVALID_HANDLE_VALUE;
}

You might need to make those even longer depending on the details of your device.

Another basic problem here is that you are not thinking carefully about the format of the data returned by ReadFile.

ReadFile is a generally useful function for reading any kind of data (ie binary). It does not append a null termination character at the end of the data as far as I know. (It shouldn't, because you might want to read some 0 bytes.) You need to look at the value of read after calling ReadFile to know how many bytes were read.

Things like printf and cout need to be passed a null-terminated string.

Printing sizeof(read) will always give you a 4 because read is just defined to be a 32-bit integer ( DWORD ).

Putting all this knowledge together, here is a reasonable way we could call ReadFile and print the results. I don't know if the returned data is ASCII or binary so I will just print the numeric value of each byte:

if(ReadFile(file, buffor, sizeof(buffor), &read, NULL))
{
  cout << "bytes read:" << read << endl;
  for (int i = 0; i < read; i++)
  {
    cout << buffor[i] << " " << endl;
  }
}
else
{
  cout << "ReadFile failed" << endl;
}

I haven't looked carefully at how this particular serial device works, so there might be a problem with how you set it up that would cause it to not send data.

If you continue to have trouble, please simplify your program to a single file less than 100 lines long and provide the entire code, along with the output and the expected output. http://www.sscce.org/

I was looking long time for the solution until I found. The answer is very simple! There are two ways to transfer data from this dial gauge to the computer:

  1. You can set event-mask using function SetCommMask and then wait for event that you declared using function WaitCommEvent .

  2. You can send some character to the dial gauge using WriteFile and then just read with: ReadFile .

My code:

if(WriteFile(Sensor, " ", 1, &read, NULL))
    ReadFile(Sensor, buffer, sizeof(buffer), &read, NULL);

buffer is LPBYTE so I have to convert it:

char buf[4];

for (int i = 0; i < 4; i++)
    buf[i] = buffer[i];

double buff = 0;
buff = atof(buf);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM