user30147: I've started to prototype something using an Arduino Mega and Yún Shield.
It's simple. It reads an ADC at 50Hz and sends data to a server through a socket. But because of that combination, I need to use Bridge to send data through the socket. It's very slow.
Should I change the Arduino Mega for a Leonardo or a Due to get better performance?
Here is my code, maybe I did something wrong.
Arduino code:
#include <Bridge.h> 
#include <Process.h>
#include <Time.h>
#include <TimeLib.h>
#include <stdlib.h>

boolean interruptFlag = 0;
int HD = A0;
int HG = A1;
int CD = A2;
int CG = A3;
int ECG = A5;
String analogSignals = "";
static char outstr[15];
int count = 0;
float x = 0.0;

void setup() {
  // Bridge startup.
  Bridge.begin();  
  // Initialize Bridge values.
  Bridge.put("data", "");  
  noInterrupts(); // Stop interrupts.
  TCCR1A = 0; // Set entire TCCR1A register to 0.
  TCCR1B = 0; // Same for TCCR1B.
  TCNT1  = 0; // Initialize counter value to 0.
  // Set compare match register for 50Hz increments.
  OCR1A = 39999; // = 16000000 / (8 * 50) - 1 (must be <65536)
  // Turn on CTC mode.
  TCCR1B |= (1 << WGM12);
  // Set CS12, CS11 and CS10 bits for 64 prescaler.
  TCCR1B |= (0 << CS12) | (1 << CS11) | (1 << CS10);
  // Enable timer compare interrupt.
  TIMSK1 |= (1 << OCIE1A);
  interrupts(); // Allow interrupts.
  // Launch Python script.
  /*Process p;
  p.begin("python");
  p.addParameter("/root/test/send.py");
  p.run();*/
}

ISR(TIMER1_COMPA_vect) {
  if (!interruptFlag) {
    interruptFlag = 1;    
  }  
}

void loop() {
  if (interruptFlag) {
    writeAnalogSignals();
    interruptFlag = 0;
  }
}

void writeAnalogSignals() {
  String HDReading = convertToVoltage(analogRead(HD));
  String HGReading = convertToVoltage(analogRead(HG));
  String CDReading = convertToVoltage(analogRead(CD));
  String CGReading = convertToVoltage(analogRead(CG));
  String ECGReading = convertToVoltage(analogRead(ECG));
  if (analogSignals.length() == 0) {
    analogSignals =  String(x, 2) + ";" + HDReading + ";" + HGReading + ";" + CDReading + ";" + CGReading + ";0.0;0.0;" + ECGReading;
  } else {
    analogSignals += "|" + String(x, 2) + ";" + HDReading + ";" + HGReading + ";" + CDReading + ";" + CGReading + ";0.0;0.0;" + ECGReading;
  }
  x += 0.02;
  count += 1; 
  if (count >= 50) {
    Bridge.put("data", analogSignals);
    analogSignals = "";
    count = 0;
  }
}
// Convert the analog reading to voltage.
String convertToVoltage(int analogSignal) {
  dtostrf(analogSignal * (5.0 / 1023),8, 6, outstr);
  return outstr;
}

Python code:
import socket
import sys
import getopt
import time

def main(argv):
    try:
        sys.path.insert(0, '/usr/lib/python2.7/bridge/')
        from bridgeclient import BridgeClient as bridgeclient
        # Create a UDP socket.
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        server_address = ('192.168.1.100', 9050)
        bridge = bridgeclient()                              
        previous = ""

        # Send data
        while 1:   
            data = bridge.get("data")   
            if data != previous:                        
                sent = sock.sendto(data, server_address)
                previous = data
            time.sleep(0.5)

    finally:
        sock.close()


user30198: The Bridge running in Python in Linux is the biggest problem. Open a terminal (for example with putty) and run top to see the CPU usage. Try to keep it under 50%.
A few parameters at 5 times per second with Bridge.put() is possible, but I don't recommend it, because of the CPU load in Linux. The 50Hz is way too much. Beside that you have also a Python script to send them to a server.
There is about 30 MB of fast RAM storage in /tmp and more storage if you add an SD memory card. You could do a test to write the data to a file, and upload the file every few seconds.
If you really need 50Hz, then I suggest to try the Raspberry Pi (or the ESP8266, as mentioned).
The dtostrf() function does not return a String, but a buffer. You could easily get rid of the Strings, to have more time in the Arduino. A good use ofmillis() is just as accurate as a timer. I think you can do the same without the hardware timer and without the interrupt.
ADDED: Chris Stratton pointed out that the Bridge is not the problem, so I did a small test.
Using 4 values with short names (like: "temp"). Writing them with Bridge.put() every second, and reading them in a webpage via zepto.min.js every second is a CPU load of 6% for python -u bridge.py.
Writing them 50 times per second and reading 1 time per second is a CPU load of 25% for the bridge.
Writing them 50 times per second and reading them 50 times per second does not change a lot, it adds extra load for uhttpd, resulting in a total of about 60 to 70%. That is still okay to run commands from a terminal.
This 'clean' test is different from my previous tests. It is therefore indeed possible to send data through the Bridge at 50 times per second. Sorry for my wrong answer.

user29178: Both Mega 2560 and Due can handle 4 channels of 1,440 samples per second A-to-D and the least significant byte of the system time stamp sent as a continuous stream of vectors through the USB port to Linux.
In the lab I train at, we see almost no variance in time increment between samples or between receiver read operations, indicating that the bottleneck is our deliberate delays between samples.
The Due is running at full resolution too and communicates via the native port. The receiver process is running in normal user process priority, not boosted for real time.
We use C++ for both endpoints, the embedded Arduino code and the receiver, but the C++ on the Arduino side runs just as fast as the same loop in Arduino sketch language. Python low-level reads are generally able to handle this same level of throughput with ease too, so it is not likely that your hardware or speed goals that are the problem.
I can see a few design issues right away.

Don't use libraries for what one can do in just a few low level lines of code.
Don't place numbers in strings. Keep them as numbers.
Send the numbers as messages placed carefully into byte arrays using bitwise operations.
Don't convert raw samples to voltages on the Arduino. That can be done in the receiver or elsewhere on the Linux side.
Most importantly, find the various code examples that people posted on the Arduino blogs when testing USB baud rates (speed).

The lab engineers started with that speed testing code, replicated the throughput published with it, and then added A-to-D conversion and other features one step at a time.
It is recommended that you place the code under version control and then, with each change, test the speed again. That way you'll notice any bottleneck you introduce immediately and can see the exact changes that must have caused it.

30147: <p>I've started to prototype something using an Arduino Mega and Yún Shield.</p>

<p>It's simple. It reads an ADC at 50Hz and sends data to a server through a socket. But because of that combination, I need to use Bridge to send data through the socket. It's very slow.</p>

<p>Should I change the Arduino Mega for a Leonardo or a Due to get better performance?</p>

<p>Here is my code, maybe I did something wrong.</p>

<p>Arduino code:</p>

<pre><code>#include &lt;Bridge.h&gt; 
#include &lt;Process.h&gt;
#include &lt;Time.h&gt;
#include &lt;TimeLib.h&gt;
#include &lt;stdlib.h&gt;

boolean interruptFlag = 0;
int HD = A0;
int HG = A1;
int CD = A2;
int CG = A3;
int ECG = A5;
String analogSignals = "";
static char outstr[15];
int count = 0;
float x = 0.0;

void setup() {
  // Bridge startup.
  Bridge.begin();  
  // Initialize Bridge values.
  Bridge.put("data", "");  
  noInterrupts(); // Stop interrupts.
  TCCR1A = 0; // Set entire TCCR1A register to 0.
  TCCR1B = 0; // Same for TCCR1B.
  TCNT1  = 0; // Initialize counter value to 0.
  // Set compare match register for 50Hz increments.
  OCR1A = 39999; // = 16000000 / (8 * 50) - 1 (must be &lt;65536)
  // Turn on CTC mode.
  TCCR1B |= (1 &lt;&lt; WGM12);
  // Set CS12, CS11 and CS10 bits for 64 prescaler.
  TCCR1B |= (0 &lt;&lt; CS12) | (1 &lt;&lt; CS11) | (1 &lt;&lt; CS10);
  // Enable timer compare interrupt.
  TIMSK1 |= (1 &lt;&lt; OCIE1A);
  interrupts(); // Allow interrupts.
  // Launch Python script.
  /*Process p;
  p.begin("python");
  p.addParameter("/root/test/send.py");
  p.run();*/
}

ISR(TIMER1_COMPA_vect) {
  if (!interruptFlag) {
    interruptFlag = 1;    
  }  
}

void loop() {
  if (interruptFlag) {
    writeAnalogSignals();
    interruptFlag = 0;
  }
}

void writeAnalogSignals() {
  String HDReading = convertToVoltage(analogRead(HD));
  String HGReading = convertToVoltage(analogRead(HG));
  String CDReading = convertToVoltage(analogRead(CD));
  String CGReading = convertToVoltage(analogRead(CG));
  String ECGReading = convertToVoltage(analogRead(ECG));
  if (analogSignals.length() == 0) {
    analogSignals =  String(x, 2) + ";" + HDReading + ";" + HGReading + ";" + CDReading + ";" + CGReading + ";0.0;0.0;" + ECGReading;
  } else {
    analogSignals += "|" + String(x, 2) + ";" + HDReading + ";" + HGReading + ";" + CDReading + ";" + CGReading + ";0.0;0.0;" + ECGReading;
  }
  x += 0.02;
  count += 1; 
  if (count &gt;= 50) {
    Bridge.put("data", analogSignals);
    analogSignals = "";
    count = 0;
  }
}
// Convert the analog reading to voltage.
String convertToVoltage(int analogSignal) {
  dtostrf(analogSignal * (5.0 / 1023),8, 6, outstr);
  return outstr;
}
</code></pre>

<p>Python code:</p>

<pre><code>import socket
import sys
import getopt
import time

def main(argv):
    try:
        sys.path.insert(0, '/usr/lib/python2.7/bridge/')
        from bridgeclient import BridgeClient as bridgeclient
        # Create a UDP socket.
        sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        server_address = ('192.168.1.100', 9050)
        bridge = bridgeclient()                              
        previous = ""

        # Send data
        while 1:   
            data = bridge.get("data")   
            if data != previous:                        
                sent = sock.sendto(data, server_address)
                previous = data
            time.sleep(0.5)

    finally:
        sock.close()
</code></pre>
 30198: <p>The Bridge running in Python in Linux is the biggest problem. Open a terminal (for example with putty) and run <code>top</code> to see the CPU usage. Try to keep it under 50%.</p>

<p>A few parameters at 5 times per second with <code>Bridge.put()</code> is possible, but I don't recommend it, because of the CPU load in Linux. The 50Hz is way too much. Beside that you have also a Python script to send them to a server.</p>

<p>There is about 30 MB of fast RAM storage in /tmp and more storage if you add an SD memory card. You could do a test to write the data to a file, and upload the file every few seconds.</p>

<p>If you really need 50Hz, then I suggest to try the Raspberry Pi (or the ESP8266, as mentioned).</p>

<p>The <code>dtostrf()</code> function does not return a String, but a buffer. You could easily get rid of the Strings, to have more time in the Arduino. A good use of<code>millis()</code> is just as accurate as a timer. I think you can do the same without the hardware timer and without the interrupt.</p>

<p><strong>ADDED:</strong> Chris Stratton pointed out that the Bridge is not the problem, so I did a small test.</p>

<p>Using 4 values with short names (like: "temp"). Writing them with <code>Bridge.put()</code> every second, and reading them in a webpage via <code>zepto.min.js</code> every second is a CPU load of 6% for <code>python -u bridge.py</code>.</p>

<p>Writing them 50 times per second and reading 1 time per second is a CPU load of 25% for the bridge.</p>

<p>Writing them 50 times per second and reading them 50 times per second does not change a lot, it adds extra load for uhttpd, resulting in a total of about 60 to 70%. That is still okay to run commands from a terminal.</p>

<p>This 'clean' test is different from my previous tests. It is therefore indeed possible to send data through the Bridge at 50 times per second. Sorry for my wrong answer.</p>
 29178: <p>Both Mega 2560 and Due can handle 4 channels of 1,440 samples per second A-to-D and the least significant byte of the system time stamp sent as a continuous stream of vectors through the USB port to Linux.</p>

<p>In the lab I train at, we see almost no variance in time increment between samples or between receiver read operations, indicating that the bottleneck is our deliberate delays between samples.</p>

<p>The Due is running at full resolution too and communicates via the native port. The receiver process is running in normal user process priority, not boosted for real time.</p>

<p>We use C++ for both endpoints, the embedded Arduino code and the receiver, but the C++ on the Arduino side runs just as fast as the same loop in Arduino sketch language. Python low-level reads are generally able to handle this same level of throughput with ease too, so it is not likely that your hardware or speed goals that are the problem.</p>

<p>I can see a few design issues right away.</p>

<ol>
<li>Don't use libraries for what one can do in just a few low level lines of code.</li>
<li>Don't place numbers in strings. Keep them as numbers.</li>
<li>Send the numbers as messages placed carefully into byte arrays using bitwise operations.</li>
<li>Don't convert raw samples to voltages on the Arduino. That can be done in the receiver or elsewhere on the Linux side.</li>
<li>Most importantly, find the various code examples that people posted on the Arduino blogs when testing USB baud rates (speed).</li>
</ol>

<p>The lab engineers started with that speed testing code, replicated the throughput published with it, and then added A-to-D conversion and other features one step at a time.</p>

<p>It is recommended that you place the code under version control and then, with each change, test the speed again. That way you'll notice any bottleneck you introduce immediately and can see the exact changes that must have caused it.</p>
