Reputation: 445
I am trying to correctly read from a rs232 com port, which is fetching info from a truck weight scale. I know that the weight scale sends out roughly 10x the weight per second, and it does not need any input, it just constantly send it out.
I can read the weight already but the problem is that I cannot read a single line only of the text that is sent by the weight scale. So I was hoping that someone might shape up a litle the C code so that it reads a single line.
By the way, I found the source code here, it is not mine.
#include <stdlib.h>
#include <stdio.h>
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
#include "rs232.h"
int main()
{
int i, n,
cport_nr=0, /* /dev/ttyS0 (COM1 on windows) */
bdrate=9600; /* 9600 baud */
unsigned char buf[4096];
char mode[]={'8','N','1',0};
if(RS232_OpenComport(cport_nr, bdrate, mode))
{
printf("Can not open comport\n");
return(0);
}
while(1)
{
n = RS232_PollComport(cport_nr, buf, 4095);
if(n > 0)
{
buf[n] = 0; /* always put a "null" at the end of a string! */
for(i=0; i < n; i++)
{
if(buf[i] < 32) /* replace unreadable control-codes by dots */
{
buf[i] = '.';
}
}
printf("received %i bytes: %s\n", n, (char *)buf);
}
#ifdef _WIN32
Sleep(100);
#else
usleep(100000); /* sleep for 100 milliSeconds */
#endif
}
return(0);
}
So, what I would like to accomplish here is that this C program should read a single line from the weight scale, outputs it and then exits. The line, should be 'marked' with delimiters, something like EOL
or ##
or something else. Thanks in advance
EDIT1: - sample output of each one of the scales -
1st:
000000.,001000001,99
000000.,001000001,99
000000.,001000001,99
000000.,001000001,99
000000.,001000001,99
2nd:
+ 0.0
+ 0.0
+ 0.0
+ 0.0
+ 0.0
3rd:
+ 0
+ 0
+ 0
+ 0
+ 0
+ 0
EDIT2: Ok, i've found the scale rs232 protocol manual. this is the corresponding table of the scale's protocol
Data | ascii code | Description
SP 20h white space
D6 0-9 1st weight digit
D5 0-9 2nd "
D4 0-9 3rd
PD 2Eh decimal mark
D3 0-9 4th weight digit
D2 0-9 5th "
D1 0-9 6th "
CR 0Dh carriage return
LF 0Ah line feed
Upvotes: 1
Views: 7397
Reputation: 154592
The key issue is that the data is arriving asynchronously to when code is searching for it - data arrives when it will - code is looking for data with no timing relationship to arrival.
So when code seeks a message with RS232_PollComport()
: zero, a partial, a complete, or complete and partial messages may result.
Various approach depending on performance goals: let us try a simple one: look for ' '
and continue printing until '\n'
.
void Service_Port(int cport_nr) {
char *front_delimiter = "<";
char *end_delimiter = ">";
int start_of_frame = ' ';
int end_of_frame = '\n';
int start_of_frame_found = 0;
for (;;) {
char buf[1];
int n = RS232_PollComport(cport_nr, buf, sizeof buf);
if (n > 0) {
if (buf[0] == start_of_frame) {
fputs(front_delimiter, stdout);
start_of_frame_found = 1;
}
if (start_of_frame_found) {
fputc(buf[0], stdout);
if (buf[0] == end_of_frame) {
fputs(end_delimiter, stdout);
return;
}
}
}
} // end for
}
The above spends a lot of time looping and waiting for a '\n'
.
Various improvements possible, yet this meets OP's goal of
read a single line from the weight scale, outputs it and then exits ... The line, should be 'marked' with delimiters
Upvotes: 1