Bridge Speed

Hi,

I'm new to the Yun but loving it so far.

I did a quick test controlling a PWM pin via Bridge and added a minimal html page with a range input slider to control it.

It seems to work fine if I make a GET request when releasing the slider, but it's pretty slow when making multiple GET request as I drag the slider. I'm guessing this isn't how this should be done (flooding the Arduino with GET requests).

Is it possible to use Bridge to send continuous/realtime requests to the MCU ? If so, how ?

At the moment I'm thinking I should probably write a Python script that opens a socket and the serial port and does the communication this way. Any other suggestions in this direction ?

Thanks,
George

That's how most users have solved the problem: disabling ttyATH0 as linux terminal and use it as pure serial. However, this is hard stuff. Since premature optimization is the root of all evil, I suggest you to postpone this phase until the very last minute.

for the record, if you google for things like "yun python tornado" or use SpaceBrew (there is an example with the IDE) you'll get much better performances

I agree 100%. Specially count kernel command line flood boot message into ttyATH0 (at first 2 mins booting time) plus afterwards send all error and warning messages to ttyATH0 which make using ttyATH0 without error detection and correction become useless. I recall my professor told me more than 3 decades ago "setup serial communication without error detection and correction just like 'left hand hold gun shoot right hand'"

Profile bridge speed:

Arduino Yun Bridge example from IDE.

ab - Apache HTTP server benchmarking tool

http://httpd.apache.org/docs/2.2/programs/ab.html

ab -n 20 -c 1 http://192.168.0.186/arduino/analog/2/123

Concurrency Level:      1
Time taken for tests:   3.425 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Non-2xx responses:      20
Total transferred:      2100 bytes
HTML transferred:       0 bytes
Requests per second:    5.84 [#/sec] (mean)
Time per request:       171.275 [ms] (mean)
Time per request:       171.275 [ms] (mean, across all concurrent requests)
Transfer rate:          0.60 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.0      0       0
Processing:   164  171   7.9    169     192
Waiting:      153  159   6.2    156     171
Total:        164  171   7.9    169     192

171.275 [ms] (0.17 s) is average speed of bridge speed, and should meet average application's requirement.

Hi,

Thank you all for the helpful responses!

I'm afraid I only have more questions at the moment.

@sonnyyu

I've just done a similar test and it generally seems about twice as slow:

ab -n 20 -c 1 http://192.168.240.1/arduino/byte/-1
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.240.1 (be patient).....done


Server Software:
Server Hostname:        192.168.240.1
Server Port:            80

Document Path:          /arduino/byte/-1
Document Length:        18 bytes

Concurrency Level:      1
Time taken for tests:   6.843 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      2380 bytes
HTML transferred:       360 bytes
Requests per second:    2.92 [#/sec] (mean)
Time per request:       342.163 [ms] (mean)
Time per request:       342.163 [ms] (mean, across all concurrent requests)
Transfer rate:          0.34 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        2    3   1.3      3       6
Processing:   228  339  46.5    346     421
Waiting:      211  322  47.4    329     418
Total:        231  342  46.5    348     423

Percentage of the requests served within a certain time (ms)
  50%    348
  66%    351
  75%    376
  80%    390
  90%    397
  95%    423
  98%    423
  99%    423
 100%    423 (longest request)

ab -n 20 -c 1 http://192.168.240.1/arduino/byte/-1
This is ApacheBench, Version 2.3 <$Revision: 1430300 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking 192.168.240.1 (be patient).....done


Server Software:
Server Hostname:        192.168.240.1
Server Port:            80

Document Path:          /arduino/byte/-1
Document Length:        18 bytes

Concurrency Level:      1
Time taken for tests:   6.654 seconds
Complete requests:      20
Failed requests:        0
Write errors:           0
Total transferred:      2380 bytes
HTML transferred:       360 bytes
Requests per second:    3.01 [#/sec] (mean)
Time per request:       332.717 [ms] (mean)
Time per request:       332.717 [ms] (mean, across all concurrent requests)
Transfer rate:          0.35 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        1    3   1.6      3       8
Processing:   234  329  46.7    328     452
Waiting:      214  309  48.8    311     430
Total:        239  332  46.3    333     455

Percentage of the requests served within a certain time (ms)
  50%    333
  66%    351
  75%    361
  80%    367
  90%    372
  95%    455
  98%    455
  99%    455
 100%    455 (longest request)

Any hints on what I should do to improve this ?

@Federico Fissore
I installed tornado and tried a sample:

import tornado.ioloop
import tornado.web
import tornado.websocket
import serial
from tornado.options import define, options, parse_command_line
ser = serial.Serial('/dev/ttyATH0', 57600)
define("port", default=8888, help="", type=int)
class WebSocketHandler(tornado.websocket.WebSocketHandler):
    def open(self, *args):
        print "Connected"
    def on_message(self, message):
        dato_1 = str(message)
        print (message)
	ser.write(dato_1)
    def on_close(self):
        print "Disconnected"
app = tornado.web.Application([
    (r'/w/', WebSocketHandler),
])
if __name__ == '__main__':
    parse_command_line()
    app.listen(options.port)
    tornado.ioloop.IOLoop.instance().start()

and a test client:

<!doctype html>
<!--[if lt IE 7]> <html class="no-js ie6 oldie" lang="en"> <![endif]-->
<!--[if IE 7]>    <html class="no-js ie7 oldie" lang="en"> <![endif]-->
<!--[if IE 8]>    <html class="no-js ie8 oldie" lang="en"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js" lang="en"> <!--<![endif]-->
<head>
	<meta charset="utf-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">

	<title></title>
	<meta name="description" content="">
	<meta name="author" content="">

	<meta name="viewport" content="width=device-width,initial-scale=1">

	</head>
<body>

	<script>
		//ws://192.168.0.9:8888
		//weso://ARDUINO.YUN.IP.ADRESS:8888/w/
		var connection = new WebSocket('ws://192.168.0.9:8888/ws/', ['soap', 'xmpp']);
		
		connection.onopen = function () {
		  connection.send('Ping'); // Send the message 'Ping' to the server
		};

		// Log errors
		connection.onerror = function (error) {
		  console.log('WebSocket Error ' + error);
		};

		// Log messages from the server
		connection.onmessage = function (e) {
		  console.log('Server: ' + e.data);
		};
		
	</script>

</body>
</html>

but I always get a 404:

WebSocket connection to 'ws://192.168.0.9:8888/ws/' failed: Error during WebSocket handshake: Unexpected response code: 404

I've tried ws://192.168.0.9:8888 as well and I can see all these errors on my Yun as well:

root@yun:/www/ws# python ws.py
[W 140923 22:03:22 web:1811] 404 GET / (192.168.0.4) 12.83ms
[W 140923 22:07:42 web:1811] 404 GET /ws/ws.py (192.168.0.4) 10.97ms
[W 140923 22:13:11 web:1811] 404 GET /ws/ (192.168.0.4) 9.35ms

How do people get the example working on a yun ?

Also, regarding Spacebrew, I'm afraid I've tried that before with little success on the Yun so far:
http://forum.spacebrew.cc/t/issues-using-arduino-yun/57

Thank you all again for your contributions.
Looking forward to your responses.

I am traveling and not access Yun. But quick peak;-

  1. Base ip you are on wifi, I use wire ethernet.
    2.base on HTML transfer 360 bytes, you did not use bridge sample from IDE.
  2. Use powerful machine run 'ab'

sorry George, I don't know Tornado, I was just mentioning some users were successful in using it. You should google for an hint

Hi,

Thank your for the suggestions.

@sonnyyu

  1. I am planning to use wifi most of the time, not ethernet.
  2. I started with the Bridge sample from the IDE, but then tried to simplify as much as I could.
    My test code so far looks like this:
#include <Bridge.h>
#include <YunServer.h>
#include <YunClient.h>
#include <SoftwareSerial.h>

const int pwm = 11;
int value = 255;

YunServer server;

void setup() {
  pinMode(pwm,OUTPUT);
  
  Bridge.begin();
  server.begin();
}

void loop() {
  YunClient client = server.accept();
  if (client) {
    process(client);
    client.stop();
  }
  analogWrite(pwm,value);
}
void process(YunClient client) {
  String command = client.readStringUntil('/');
  if (command == "pwm"){
    pwmCommand(client);
  }
}
void pwmCommand(YunClient client){
  int pin, pwmVal;
  pwmVal = client.parseInt();
  pwmVal = constrain(pwmVal,0,255);
  value = pwmVal;
}

and a simple html test:

<!DOCTYPE html>
<html>
<head>
    <title>Arduino REST demo</title>
  <meta name="viewport" content="width=device-width,initial-scale=1.5">
  <script src="../jquery.min.js"></script>
  <script>
    function pwmSet(value){
      console.log(value);
      var url = "/arduino/pwm/"+value+"/";
      $.get(url).done(getCallback);
    }
    function getCallback(data){
      console.log(data);
    }
  </script>
</head>
<body>
  <form>
    <label for="pwm">PWM pin 11</label><input id="pwm" type="range" min="0" max="255" value="255" oninput="pwmSet(pwm.value);">

  </form>
</body>
</html>

Moving the slider results in a queue that moves quite slow. Is there any way to improve this ?

  1. I've run the ab on a machine with a machine with with 4GB of RAM and a core i7 Intel CPU. This should suffice ?

@Federico Fissore

The errors with tornado can be resolved by overriding the check_origin method of the WebSocketHandler subclass

def check_origin(self,origin):
   return True

I can confirm using tornado and pyserial gives me responsive results dimming a PWM LED.

Has anyone had success with Spacebrew on the Yun ?

@sonnyyu My guess is even if I go with the Ethernet option it won't be fast enough for something like controlling a PWM LED in realtime (probably because of the large amount of separate request flooding). Can you please confirm if this is the case or not when you get a chance ? With your setup can you control a PWM LED in realtime ? If so how ?

Also, I still haven't managed to get Spacebrew working with the Yun. Has anyone else had any luck with this ?

Thanks,
George

If you need more than 5s /second then you need by pass bridge, but Cyclic Redundancy Check (CRC) is needed at both Openwrt and arduino sides.