Pedro Sousa
Pedro Sousa

Reputation: 445

Reading from rs232 port with C

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

Answers (1)

chux
chux

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

Related Questions