0

I am trying to transmit a constantly changing 5 digit value over serial, to fake this I have a program called jsfake

int main() {
while (1) {
    printf("02000\n");
    fflush(stdout);
    sleep(1);
}
return 0;
}

Then i have my actual python script which is designed to transmit the stdout from the C program over serial. I have then added a section on the bottom to receive the serial as well as I am testing it from one raspberry pi to the same one, so I can be sure it is working before trying to receive it from another computer.

from serial import Serial
import subprocess

subp = subprocess.Popen("./jsfake",stdout=subprocess.PIPE)
port = Serial("/dev/ttyAMA0",115200,timeout=3)

while True:
    for line in iter(subp.stdout.readline, ''):
        port.write(line)
    if port.inWaiting!=0:
        rcv = port.read(6)
        print rcv

However my code waits at the line for line in iter(subp.stdout.readline, ''): as this is the point it is always at when I interrupt it with ctrl-c. However it prints no values.

EDIT: I have tried replacing the last 4 lines with print line and print line.rstrip() but neither generate any values either.

edward.ij
  • 55
  • 1
  • 8
  • Can you recreate the problem if you strip everything serial out of this? You could replace the `port.write` by, e.g. `print`. Is the problem still there, if you do that? – DrV Jun 22 '14 at 08:00
  • Have a look at: http://stackoverflow.com/questions/2804543/read-subprocess-stdout-line-by-line – DrV Jun 22 '14 at 08:01
  • @DrV please see my edit. I took the second print suggestion from that link, however that may well not be the part of the link you though I should look at? – edward.ij Jun 22 '14 at 08:11

2 Answers2

0

This is one of these "should work" things. I tried the following two pieces of code:

#include <stdio.h>
#include <unistd.h>

int main(void)
    {
    int i = 0;

    for (;;)
        {
        printf("%05d\n", i % 1000000);
        i++;
        fflush(stdout);
        sleep(1);
        }
    return 0;
    }

which was compiled with:

gcc -Wall -Wstrict-prototypes -o test test.c

and test.py:

import subprocess

subp = subprocess.Popen("./test",stdout=subprocess.PIPE)

for line in iter(subp.stdout.readline, ''):
    print line

When I run python test.py in the same directory, I get what I expected:

00000

00001

00002

and so on. (Double line spaces are to be expected.)

If you cannot replicate this success, debugging requires two steps:

  1. Could it still be a buffering problem? This can be debugged by sending a lot of data. Easiest thing is to replace the sleep(1) by, e.g., usleep(1000). Then there will be a lot of data flowing, and the buffering will fill in a few seconds. (If you print 6 chars every second, you don't probably wait for 10 minutes to see if it is buffering problem.)

  2. If it is not a buffering problem, make your C program print something to stderr, as well. E.g., fprintf(sterr, "Hello?\n")so that it can be seen that the process is really running.

When the problem has been isolated, it is easier to find a cure. Also, this sounds like something to do with the operating system. Which OS?

DrV
  • 22,637
  • 7
  • 60
  • 72
  • I am using raspbian, I shall try what you suggested and get back to you, many thanks! – edward.ij Jun 22 '14 at 17:05
  • I should've realised it by the tags of your post... Are you using it on local terminal (display + kbd connected to the Pi) or over SSH? – DrV Jun 22 '14 at 17:16
  • ^ Shouldn't make a difference. Subprocesses (and serial) are unaffected by ssh. – theo-brown Jun 22 '14 at 17:55
  • Yep. But it should work anyway, and it does not. SSH adds one link to the chain. (Also, the question was because I can try to reproduce the problem with SSH but I do not have any kbd or display at hand.) – DrV Jun 22 '14 at 18:24
  • @edward.ij: I tested with my Raspberry: works as described above, no problems. I am in my 'berry through SSH, the commands, code, and results are exactly as above. Do you experience problems with this minimal code? – DrV Jun 22 '14 at 19:16
0

Try this:

import subprocess
from serial import Serial
port = Serial("/dev/ttyAMA0",115200,timeout=3)

subp = subprocess.Popen("./test",stdout=subprocess.PIPE)

for line in iter(subp.stdout.readline, ''):
    port.write(line,)
    print line,

I'm not sure how this works, but as per here What's ending comma in print function for? I think that it prevents the output from being line-buffered, so that your program will no longer block while reading lines.

Community
  • 1
  • 1
theo-brown
  • 653
  • 10
  • 27
  • Should the comma in port.write(line) be before or after the closing bracket? Thanks very much – edward.ij Jun 22 '14 at 18:08
  • @theoB610: The question you link to actually seems to say that the trailing comma omits the newline (it should), and that stdout is usually line buffered, i.e. omitting the comma should make things worse. Well, in this case it doesn't, as there are newlines coming from the C program (that's why the output in my code contains double line spaces). The added comma in `port.write` should actually throw an exception, as there the comma does not have the same magic as in the `print` statement. – DrV Jun 22 '14 at 19:05