FileIO in binary mode and Process oddities

Hi all,

I thought this was a relatively simple problem but it's been causing me some agro.

Very simply, I have a USB webcam (LG C270) running great on my Yun. I want my sketch to trigger the camera using a Process and read the resulting png back byte by byte from the microSD as hex values to my PC terminal over serial.

I've tried two approaches to this. Firstly with FileIO.h, however, I cannot use FileSystem.open in binary mode. As this would be the simplest solution, is there a work around for this?

Secondly I have written a simple programme in C to open the image in binary mode and output the values in hex to stdout. However, Process.read is not catching the output.

My sketch:

#include <Process.h>
#include <Bridge.h>

void setup() {
  pinMode(7,INPUT); // button input to trigger the camera
  Bridge.begin();
  Serial.begin(115200);
  while (!Serial);
}

void loop() {
  if (digitalRead(7)==HIGH) {
    capPic();
  }
}

void capPic() {
  Process p;
  p.runShellCommand("fswebcam --png 2 -r 320x240 --save /mnt/sd/arduino/test.png 2>&1");
  while(p.available()>0)
  {
    char c = p.read();
    Serial.print(c);
  }
  p.runShellCommand("bin_reader /mnt/sd/arduino/test.png");
  while(p.available()>0)
  {
    char c = p.read();
    Serial.print(c);
  }
}

and my binary reader

#include <stdio.h>

int main(int argc, char *argv[]) {
    FILE *f;
    f = fopen(argv[1],"rb");
    if (!f)
        return 1;
    int i[1] = {0};
    while (!feof(f)) {
        fread(i,1,1,f);
        fprintf(stdout,"%02x ",i[0]);
    }
    fclose(f);
    return 0;
}

The binary reader works great via ssh, and the fswebcam output is caught by the first p.read() loop. Anyone have any ideas why it isn't catching the stdio output from my bin_reader?

Ta

It looks all good to me. Maybe trying to use two different Process objects?

Process fswebcam;
Process bin_reader;

maybe?

Thanks for the tip - nice idea but wasn't the problem. It did inspire me to try splitting up the data though and I've tracked down my problem. Looks like the Process hangs if more than 65535 bytes are dumped to the console, so perhaps some kind of buffering issue.

BIt of a pain, really. Guess I'll look into parsing the data in 65k chunks.

(Ninja edit to clarify)

Uhmm, this needs debugging... can you open an issue on github Issues · arduino/YunBridge · GitHub ? This way we don't lose track of the problem

Sure, will do!

Logitech HD Webcam C270 supports 1280 x 720 screen resolution, The file size could be much huge. Use ATmega32u4 to transfer the file might not be smart move.
We could use mount networked drives or export networked drives for PC to share. Save image file to mounted networked drives then send command by linux/linino to PC to process.

mount windows share directory/Linux samba at Yun:

http://wiki.openwrt.org/doc/howto/cifs.client

opkg update 
opkg install kmod-crypto-misc
opkg install kmod-nls-utf8 kmod-nls-base kmod-crypto-hmac kmod-crypto-md5 cifsmount
opkg install kmod-fs-cifs
mkdir /mnt/local
mount.cifs //192.168.0.20/Shares /mnt/local -o guest,sec=ntlm
fswebcam --png 2 -r 1280x720 --save /mnt/local/test.png

Thanks for the suggestion, sonnyyu. My objective is not to get the specific file off the linino side but to trigger a file transfer from the mcu and back through the mcu (I'm using my PC as a terminal at the moment, but plan to investigate piping it over I2C/SPI in the future).

When I get some more free time I'm going to try disabling the linino serial bridge for Console, as discussed here, and replicate my functionality with some python (first time for everything!)

Hi Yuntastic,

there is a deadlock in your sketch, since you do:

  p.runShellCommand("bin_reader /mnt/sd/arduino/test.png");
  while(p.available()>0)
  {
    char c = p.read();
    Serial.print(c);
  }

runShellCommand waits for bin_reader to finish, but this can't happen because bin_reader outputs more than 64k, and the Bridge can't buffer more until someone reads and empties his buffer.

A longer explanation is here:

I suggest you to retry with runShellCommandAsynchronously that doesn't wait for the process to finish.