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.
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.
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
::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.
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.
#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()
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.
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
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
"""
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.
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.
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.
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....
GreyCon:
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.
GreyCon:
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....
I tried everything to create a bad environment for the Yun to provoke an error at 115200 baud...
Wind an active Lan-cable several times round the Yun
Place the Yun on to of my cellphone, and call myself
...but the python script runs without problems
Raise the speed to 250000 and it fails .
BTW:
Sketch programming from the Yun side (not over USB) does not use the serial port. It uses the avrdude -c linuxgpio option which emulates a SPI programmer. See file /etc/avrdude.conf line 976
Hi,
there is a serious problem with my little echo sketch on the ATmega.
The changes in /etc/inittab detach the serial line to the ATmega, but this happens very late in the boot process.
Until just before the login prompt for the shell is shown, all kernel messages are still forwarded to the ATmega.
Because my test sketch more or less echos what is read from the serial, the boot process seems to be stopped by the random data coming back over Serial1.
The effect is that because of the echo sketch the WiFi setup never completes. Login over ssh is not possible.
When the simple Blink Sketch or even the Yún Serial Terminal runs on the ATmega the Yun boots fine because these Sketches don't throw any random data back at the linux machine. If you are stuck like that because you tried the test at home, simply upload a Sketch not writing to Serial1. http://arduino.cc/en/Tutorial/YunSerialTerminal
For an application using the Serial1 to communicate with the ATMega this means, you are only allowed to listen on the Serial1 until the Linux machine was sucessfully booted.
If you look in the Bridge.cpp source code you'll se that they deal with this.
// Wait for U-boot to finish startup
do {
dropAll();
delay(1000);
} while (stream.available()>0);
This doesn't seem very fool proof. Its counting on the fact that during the boot process you see some data at least once per second come over serial. If there was a > 1 sec pause then you'd be out of luck.
I'd be happy to see a robust code snippet I could insert into my sketches.
Hmmm....I have used the serial console of the early boot process before to debug a bad dd-wrt (openwrt fork) image on a router. I suspect that this "feature" is enabled by default in the openwrt build process since this is a relatively good way to unbrick a board with a corrupt flash image.
Took a bit of digging, but it appears the only way to stop the "terminal chatter" early in the boot process is to rebuild the kernel to disable "Early printk". Not something that most folks (including me) will be excited about for many reasons. Seems like the best workaround is exactly what scrot and wayoda are doing: find a way to make sure the 32u4 does not respond to this "terminal chatter".