Hi,
due to the limitations mainly of Memory-size in the MCU, I would like to do most of the processing with a C-program running on the onboard Linux.
Is there a simple way of sharing data between the arduino and the Linux?
Up to now I thought of using files on /tmp ramdisk and use signals to tell the c-program, that there is new data available. Has someone done this? Or is there a simple better method?
There are several ways. The following uses the Bridge library:
Bridge.put() will write named values to a data store. They can be read from the Linux side using get(), or from a remote system using http://arduino.local/data/get. There is a library to get() the values with Python, but I've not found one for C. The downside of this method is that it is limited to strings, and there is no notification that a value has been written: the code must poll the values and look for a change, and will not see a the case where the same value is written twice. This mechanism is still useful for cases where the sketch continually reads sensor values and puts them to the bridge, and the Linux side asynchronously reads the latest value as needed.
The Process Class can start your C program using runAsynchronously(). Then, the sketch can use the process object's write(), print(), println(), etc. functions to send data to the C program's STDIN, and anything that the C program writes to STDOUT can be read by the sketch by using process.read().
You could use the FileIO class to write a file, like you suggested, then use the Bridge.put() function to write a flag that new data is available.
Or, you could skip the Bridge altogether and write your own serial communications between the sketch and Linux. The sketch would read/write Serial1. You could start the C program manually or through a startup shell script, in which case the C program would read/write /dev/ttyATH0. Or, the first thing the Sketch writes to Serial1 could be the shell command to run your C program, in which case the C program would read from STDIN and write to STDOUT. This method is very similar to using the Bridge's Process class, except that it would be faster and have less overhead. The downside is that none of the Bridge functions will work while you are doing this.
The serial communication( <1Mb) is no longer count as fast communication, if you are working on PHY 100Gb then C is even too slow, The assembly language is the way to go. Plus to make C work at Yun openwrt we need either cross compile or load gcc into Yun. Last thing, python or lua use c extension to access serial port and no speed lost here.
I decided to try: "The Process Class can start your C program using runAsynchronously(). Then, the sketch ....
Linux C-Program:
/* addij.c */
#include <stdio.h>
long i, j;
FILE *fp;
int main(void)
{
while(1)
{
//printf ("Input 1 number ");
scanf("%d%d", &i, &j);
fp= fopen("/mnt/sda1/addij_log.txt","a");
fprintf(fp,"%d %d\n",i,j);
fclose(fp);
if(i==-999999)
{
printf("Ende\n");
return(0);
}
i += j;
printf ("%d\n", i);
}
return(0);
}
Arduino Sketch:
#define NAME "Process_A"
/* origin:
Running process using Process class.
This sketch demonstrate how to run linux processes
using an Arduino Yún.
created 5 Jun 2013
by Cristian Maglie
This example code is in the public domain.
http://arduino.cc/en/Tutorial/Process
*/
#include <Process.h>
void setup() {
// Initialize Bridge
Bridge.begin();
// Initialize Serial
Serial.begin(9600);
// Wait until a Serial Monitor is connected.
while (!Serial);
// run various example processes
//runCurl();
runMyProc();
}
void loop() {
// Do nothing here.
}
void runMyProc() {
unsigned long pt, number;
Serial.println("runMyProc gestartet");
Process p; // Create a process and call it "p"
p.begin("/mnt/sda1/C-Source/addij"); // Process that launch the "curl" command
//p.addParameter("http://arduino.cc/asciilogo.txt"); // Add the URL parameter to "curl"
p.runAsynchronously(); // Run the process and wait for its termination
pt = millis();
p.print(50);
p.print(" ");
p.println(51);
delay(1000);
//number= p.parseInt();
//pt= millis() - pt;
//Serial.println(number);
//Serial.println(" empfangen");
while (p.available() > 0) {
char c = p.read();
Serial.print(c);
}
Serial.println("1=========");
p.println("10 20");
while (p.available() > 0) {
char c = p.read();
Serial.print(c);
}
Serial.println("2=========");
p.println("-999999 -999999");
delay(1000);
number= p.parseInt();
Serial.print(number);
Serial.println(" empfangen");
Serial.println("3=========");
while (p.available() > 0) {
char c = p.read();
Serial.print(c);
}
Serial.print(pt);
Serial.println(" msec runMyProc beendet");
Serial.flush();
}
I have posted a Python program called EzScrn that does not use the Bridge. The communication part of it may be of interest. I presume the same general ideas are appropriate for a C program.
cebersp:
So, yes, you can send numbers to a c-program but unfortunately all the results are only there after program end. :o
I ran into a similar problem with Python. The problem there turned out to be buffered I/O. I could start the the Python script in unbuffered mode, by using the command "/sbin/Python -u program.py" (note the addition of the -u parameter to python, making it use unbuffered mode.)
I'm not sure how you would do this with a C program, but there must be something similar you can do in C to disable buffering. I just wish I knew the exact command...