Pages: [1] 2 3 ... 6   Go Down
Author Topic: Tty for serial port to Arduino from Linino  (Read 15102 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

All,

I'm trying to implement Firmata using pyfirmata on linino, and the Standard Firmata on the arduino.  I know on the Arduino side I need to use Serial1.

My question is: What /dev/tty to I use to talk to the arduino?  I know that the OS launches a terminal on that TTY which is how you can talk to the Linino over Serial1 from Arduino.  Simply want to treat the arduino as a dumb slave to my Python program running on the Linino.

Logged

Texas
Offline Offline
Newbie
*
Karma: 1
Posts: 20
Honey, it's educational.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Needed this myself.  Just need to ask Linino "nicely". 

Code:
root@arduino:/# dmesg | grep tty
[    0.000000] Kernel command line:  board=Linino console=ttyATH0,250000 mtdparts=spi0.0:256k(u-boot)ro,64k(u-boot-env)ro,14656k(rootfs),1280k(kernel),64k(nvram),64k(art),15936k@0x50000(firmware) rootfstype=squashfs,jffs2 noinitrd
[    0.620000] ar933x-uart: ttyATH0 at MMIO 0x18020000 (irq = 11) is a AR933X UART
[    0.630000] console [ttyATH0] enabled, bootconsole disabled

Found this by searching through the OpenWRT forums.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Excellent!  I didn't even think of using dmesg.  The next question is how to disable the console that runs on that serial port?  I spend some time looking through init.d and didn't find anything.  I'll need to dig some more.  If I can disable the console then I should have a nice clean connection from python to arduino.
Logged

Texas
Offline Offline
Newbie
*
Karma: 1
Posts: 20
Honey, it's educational.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Edit /etc/inittab to disable the serial console.  Specifically, comment or delete:
Code:
ttyATH0::askfirst:/bin/ash --login

More info: https://forum.openwrt.org/viewtopic.php?id=15165

Looking forward to seeing how fast your clean connection python code runs.
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1245
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Me too. Keep us posted. It looks like a much better approach
Logged

Have you upgraded the Yún? If you've just got it, then it needs to be upgraded! Check out the tutorial

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi,
with the tips in this thread I was able to do some very basic IO from python to the atmega:

I disabled the login on ttyATH0 by editing the the file /etc/inittab
Code:
::sysinit:/etc/init.d/rcS S boot
::shutdown:/etc/init.d/rcS K shutdown
#disable the login console on this serial by commenting it out
#ttyATH0::askfirst:/bin/ash --login

I'm not sure if disabling the console will cause any  sideeffects, but as long as I can still ssh into the Yun I feel safe

Here is a very basic sketch to run on the atmega, which reads a character and if it is one of the digits 0-8 it echos the digit value +1, otherwise it simply echos the character just read.
Code:
void setup() {
  Serial1.begin(9600);
}

void loop() {
  char c;

  while (Serial1.available() > 0) {
    c=Serial1.read();
    if(c>='0' && c<'9')
      c++;
    Serial1.print(c);
   }
}
The I wrote the most basic python code to do some IO over serial: It opens the serial given on the first commandline argument and then sends the first 5 characters from the second argument. Then it reads 5 bytes from the serial and closes it.
Code:
#File st.py run like "python st.py /dev/ttyATH0 '123abc'
import serial
import sys

s=serial.Serial(sys.argv[1],9600,timeout=1)
data =sys.argv[2]
s.write(data[0:5])
result=s.read(5)
print result
s.close()

This is what I get, seems to work fine
Code:
root@YunYun:/mnt/sda1/python# python st.py /dev/ttyATH0 'ab3deohg'
ab4de
root@YunYun:/mnt/sda1/python#

Reference to PySerial : http://pyserial.sourceforge.net
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was able to reproduce your results.  This is exciting.  I'm working on making Firmata work.  My first experiment didn't succeed.  I think it just a matter of some tinkering.  I'll keep you in the loop.
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1245
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Very well done wayoda. This is become really interesting. Out of curiosity: could you set up a stress test case?
Something like flooding the 32u4 with random chars (in a 1.000.000 rounds "for" loop) and checking if the output is the expected one
Logged

Have you upgraded the Yún? If you've just got it, then it needs to be upgraded! Check out the tutorial

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Great job!!! This is what I was looking for.
I'll try.
Logged

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Out of curiosity: could you set up a stress test case?
Something like flooding the 32u4 with random chars (in a 1.000.000 rounds "for" loop) and checking if the output is the expected one
I did some quick tests. In short...
  • The maximum baudrate is 115200 baud. Tests with 230400 baud  always failed on the first read attempt.
  • With the simple Arduino Sketch (see below) the IO-throughput is about 10kB/s.

The baudrate in the python script and the Arduino Sketch must (obviously) match to make this work

Here is the python script for testing
Code:
"""
Usage :
    python st.py PORT BAUDRATE KILO_BYTES

example :
python st.py /dev/ttyATH0 115200 10
Will send and receive 10kB of data

turn on profiling:
python -m cProfile st.py /dev/ttyATH0 115200 10
"""

import serial
import sys

data='01234567012345670123456701234567'
expected='12345678123456781234567812345678'

#one packet is 32 bytes so 1kByte is 32 packets
packets=int(sys.argv[3])*32
s=serial.Serial(sys.argv[1],sys.argv[2],timeout=5)
for i in range(packets):
    s.write(data)
    result=s.read(32)
    if result!=expected:
        raise ValueError('Mismatch on run : '+str(i)+'\ndata = "'+data+'"\nresult = "'+result+'"')
print "Done!"
s.close()

On the Arduino I run this Sketch. It blinks the Led after coming out of a reset.
Code:
void setup() {
  pinMode(13,OUTPUT);
  digitalWrite(13,HIGH);
  delay(500);
  digitalWrite(13,LOW);
  delay(500);
  digitalWrite(13,HIGH);
  delay(500);
  digitalWrite(13,LOW);
  Serial1.begin(115200);
 
}

void loop() {
  char c;
 
  while (Serial1.available() > 0) {
    c=Serial1.read();
    c++;
    Serial1.print(c);
  }
 
}


Here is the output of the longest test I ran  (4MB of data).
Takes about 7 minutes to complete!
Code:
root@YunYun:/mnt/sda1/python# python -m cProfile st.py /dev/ttyATH0 115200 4096
Done!
         5392556 function calls in 431.015 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.005    0.005    0.026    0.026 __init__.py:8(<module>)
        1    0.017    0.017    0.022    0.022 serialposix.py:13(<module>)
        1    0.000    0.000    0.000    0.000 serialposix.py:163(Serial)
        1    0.000    0.000    0.001    0.001 serialposix.py:168(open)
        1    0.001    0.001    0.001    0.001 serialposix.py:192(_reconfigurePort)
        1    0.000    0.000    0.000    0.000 serialposix.py:321(close)
   131072  189.347    0.001  392.045    0.003 serialposix.py:340(read)
   131072   11.837    0.000   25.662    0.000 serialposix.py:359(write)
        1    0.001    0.001    0.001    0.001 serialutil.py:111(SerialBase)
        1    0.001    0.001    0.002    0.002 serialutil.py:123(__init__)
        1    0.000    0.000    0.000    0.000 serialutil.py:196(setPort)
        1    0.000    0.000    0.000    0.000 serialutil.py:221(setBaudrate)
        1    0.000    0.000    0.000    0.000 serialutil.py:240(setByteSize)
        1    0.000    0.000    0.000    0.000 serialutil.py:253(setParity)
        1    0.000    0.000    0.000    0.000 serialutil.py:266(setStopbits)
        1    0.000    0.000    0.000    0.000 serialutil.py:279(setTimeout)
        1    0.000    0.000    0.000    0.000 serialutil.py:298(setWriteTimeout)
        1    0.000    0.000    0.000    0.000 serialutil.py:30(SerialException)
        1    0.000    0.000    0.000    0.000 serialutil.py:317(setXonXoff)
        1    0.000    0.000    0.000    0.000 serialutil.py:328(setRtsCts)
        1    0.000    0.000    0.000    0.000 serialutil.py:339(setDsrDtr)
        1    0.000    0.000    0.000    0.000 serialutil.py:35(SerialTimeoutException)
        1    0.000    0.000    0.000    0.000 serialutil.py:355(setInterCharTimeout)
        1    0.000    0.000    0.000    0.000 serialutil.py:40(FileLike)
        1    0.003    0.003    0.004    0.004 serialutil.py:8(<module>)
        1   13.242   13.242  431.015  431.015 st.py:14(<module>)
        3    0.000    0.000    0.000    0.000 {_struct.pack}
        2    0.000    0.000    0.000    0.000 {chr}
        3    0.000    0.000    0.000    0.000 {getattr}
       21    0.000    0.000    0.000    0.000 {hasattr}
   131072    1.061    0.000    1.061    0.000 {isinstance}
  2565176   21.640    0.000   21.640    0.000 {len}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
        1    0.000    0.000    0.000    0.000 {method 'lower' of 'str' objects}
        1    0.000    0.000    0.000    0.000 {posix.close}
        1    0.000    0.000    0.000    0.000 {posix.open}
  1151516   62.691    0.000   62.691    0.000 {posix.read}
   131072   12.070    0.000   12.070    0.000 {posix.write}
        1    0.038    0.038    0.038    0.038 {range}
  1151516  119.062    0.000  119.062    0.000 {select.select}
        1    0.000    0.000    0.000    0.000 {termios.tcgetattr}
        1    0.000    0.000    0.000    0.000 {termios.tcsetattr}
Logged

Offline Offline
Edison Member
*
Karma: 38
Posts: 1245
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you retry with 250000 baud? That's the speed we set for ttyATH0
Logged

Have you upgraded the Yún? If you've just got it, then it needs to be upgraded! Check out the tutorial

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you retry with 250000 baud? That's the speed we set for ttyATH0
Doesn't work. For some reason I get incomplete readings for all speeds above 115200 baud. (230400, 250000 etc.)
I also tried to write smaller data packets of 16 bytes instead of 32 bytes, but no luck. Every baudrate above 115200 baud fails on the first write/read cycle.

But 115200 baud (10kB/s) is fast enough for most usecases where data from the ATmega32u4 is  being forwarded to a webservice.
I can live with that limitation.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 16
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I got Firmata to work between a Python script running on Linino and the Arduino.  I was able to get about 400 messages per second which is sufficient for my needs.  I made the following changes to the StandardFirmata sketch "begin" section.

Code:
void setup()
{
 
  Firmata.setFirmwareVersion(FIRMATA_MAJOR_VERSION, FIRMATA_MINOR_VERSION);

  Firmata.attach(ANALOG_MESSAGE, analogWriteCallback);
  Firmata.attach(DIGITAL_MESSAGE, digitalWriteCallback);
  Firmata.attach(REPORT_ANALOG, reportAnalogCallback);
  Firmata.attach(REPORT_DIGITAL, reportDigitalCallback);
  Firmata.attach(SET_PIN_MODE, setPinModeCallback);
  Firmata.attach(START_SYSEX, sysexCallback);
  Firmata.attach(SYSTEM_RESET, systemResetCallback);

  Serial1.begin(9600); // Set the baud.
  Firmata.begin(Serial1);
  systemResetCallback();  // reset to default config
}

On the python I installed PyFirmata and pyserial.  The following code turns on the LED:

Code:
from pyfirmata import Arduino, util
board = Arduino('/dev/ttyATH0', baudrate=9600)
board.digital[13].write(1)
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 37
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Wayoda,

   when you say a BAUD rate of 250000 fails - do you get characters from Serial, or nothing at all? The Arduino UART should definitely do 250000 , and higher. And since the hard-wired serial connection is very short, there shouldn't be any signal degradation issues.

Maybe you have a marginal board. I will give it a go tonight and let you know results. If necessary we can look at the UART registers for over-run or parity errors....

Con
Logged

Wuppertal/Germany
Offline Offline
God Member
*****
Karma: 1
Posts: 895
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Wayoda,
   when you say a BAUD rate of 250000 fails - do you get characters from Serial, or nothing at all?

The python script writes 32 chars to the ATmega and then reads 32 bytes with a five second timeout.
When used with baudrates above 115200 the read returns unexpected characters and also too few of them.
Logged

Pages: [1] 2 3 ... 6   Go Up
Jump to: