Russell's Blog

New. Improved. Stays crunchy in milk.

Trouble with SoftSerial on the Arduino Leonardo

Posted by Russell on May 25, 2012 at 12:05 p.m.
While I was wandering around at Maker Faire last weekend, I heard someone say, "Woah, is this the Leonardo?" And lo, there was a handful of Arduino Leonardo boards lined up on a shelf for sale. I instantly grabbed one, and bundled it home to play with it.

The Leonardo is Arduino's latest board, announced last September. It uses the Atmega32u4 chip, which has onboard USB. This has two important implications; first, the Leonardo costs less than the Uno, and second it will be able to operate in any USB mode. That means people can make Human Interface Devices (HID), like mice and keyboards and printers, with Arduino, and present themselves to the host using the standard USB interfaces for those devices. That means you can build things that don't need to talk via serial, and use the host's built-in drivers for mice and printers and whatnot. This is a big step forward for Open Hardware.

Anyway, I'm developing an little remote environmental data logger to use for part of my dissertation project, and I thought I'd see if I could use the Leonardo board in my design. I'm using the Arduino board to talk to an Atlas Scientific pH stamp, which communicates by serial. It works fine on the Uno with SoftwareSerial (formerly known as NewSoftSerial until it was beamed up into the Arduino Core mothership).

Unfortunately, it didn't go so well on the Leo. The board can send commands to the pH stamp, but doesn't receive anything. I swapped in an FTDI for the pH stamp, and confirmed that the Leonardo is indeed sending data, but it didn't seem to be able to receive any characters I sent back. I tried moving the rx line to each the digital pins, and had no luck. Here is my test program :

#include <SoftwareSerial.h>

#define rxPin 2
#define txPin 3

SoftwareSerial mySerial( rxPin, txPin );

byte i;
byte startup = 0;

void setup() {

  mySerial.begin( 38400  );
  Serial.begin(   9600   );
}

void loop() {
  
  if( startup == 0 ) {             // begin startup
    for( i = 1; i <= 2; i++ ) {
      delay( 1000 );
      mySerial.print( "l0\r" );    // turn the LED off
      delay( 1000 );
      mySerial.print( "l1\r" );    // turn the LED on
    }
    startup = 1;                   // don't re-enter
  }                                // end startup

  Serial.println( "taking reading..." );
  mySerial.print( "r\r" );
  delay(1000);
  
  Serial.println( mySerial.available() );
  
}
On the Uno, I see the number increasing as the read buffer fills up :
taking reading...
0
taking reading...
0
taking reading...
7
taking reading...
16
taking reading...
16
On the Leo, it seems that nothing ever gets added to the read buffer, no matter how any characters I send over from the FTDI or which pins I used for the rx line :
taking reading...
0
taking reading...
0
taking reading...
0
taking reading...
0
taking reading...
0
taking reading...
I really wanted to see if I was crazy here, but I'm one of the first people among the General Public to get their hands on a Leonardo board. So, I started talking with Ken Jordan on #arduino on Freenode (he goes by Xark) who has a similar board, the Atmega32u4 Breakout+. It's based on the same chip as the Leonardo, but it has different pinouts and a different bootloader. He flashed the Leonardo bootloder onto his board, and worked out the following pin mapping :
Arduino 1.0.1     Adafruit         ATMEL
digitalWrite pin  atmega32u4+ pin  AVR pin function(s)
----------------  ---------------  ------------------
D0                D2               PD2 (#INT2/RXD1)
D1                D3               PD3 (#INT3/TXD1)
D2                D1               PD1 (#INT1/SDA)
D3#               D0               PD0 (#INT0/OC0B)
D4/A6             D4               PD4 (ICP1/ADC8)
D5#               C6               PC6 (OC3A/#OC4A)
D6#/A7            D7               PD7 (T0/OC4D/ADC10)
D7                E6 (LED)         PE6 (INT6/AIN0)
D8/A8             B4               PB4 (PCINT4/ADC11)
D9#/A9            B5               PB5 (OC1A/PCINT5/#OC4B/ADC12)
D10#/A10          B6               PB6 (OC1B/PCINT6/OC4B/ADC13)
D11#              B7               PB7 (OC0A/OC1C/PCINT7/#RTS)
D12/A11           D6               PD6 (T1/#OC4D/ADC9)
D13#  (LED)       C7               PC7 (ICP3/CLK0/OC4A)
D14   (MISO)      B3               PB3 (PDO/MISO/PCINT3)
D15   (SCK)       B1               PB1 (SCLK/PCINT1)
D16   (MOSI)      B2               PB2 (PDI/MOSI/PCINT2)
D17   (RXLED)     B0               PB0 (SS/PCINT0)
D18/A0            F7               PF7 (ADC7/TDI)
D19/A1            F6               PF6 (ADC6/TDO)
D20/A2            F5               PF5 (ADC5/TMS)
D21/A3            F4               PF4 (ADC4/TCK)
D22/A4            F1               PF1 (ADC1)
D23/A5            F0               PF0 (ADC0)
-     (TXLED)     D5               PD5 (XCK1/#CTS)
-     (HWB)       -  (HWB)         PE2 (#HWB)
This was derived from the ATmega 32U4-Arduino Pin Mapping and ATMEL's datasheet for the ATmega32U4 chip. Once that was worked out, he flashed my test program onto his board, and also found that SoftwareSerial could transmit fine, but couldn't receive anything.

Ken rummaged around a little more, and had this to say :

The SoftSerial seems to use PCINT0-3 so there seems to me a minor problem in Leo-land in that only PCINT0 appears to be supported (and it is on "funky" output for RXLED). Hopefully I am just misunderstanding something (but it imay be the interrupt remap table is incorrect for Leo).
Then he disappeared for a little while, and came back with :
I have confirmed my suspicion. When I disassemble SoftSerial.cpp.o I can see that only __vector_9 is compiled (i.e., one of 4 #ifdefs for PCINT0-3) and the interrupt vector 10 is PCINT0 (0 is reset vector so offset by one makes sense). So, unless you hook serial to RXLED pin of CPU I don't believe it will work with the current libs.

Also I believe the Leo page is just wrong when it says pins 2 & 3 support pin change interrupts (I think this was copied from Uno but it is incorrect, the only (exposed) pins are D8 D9 D10 and D11 that support PCINT according to the ATMEL datasheet (and these are PCINT 4-7 not the ones in the interrupt mapping table AFAICT).

I believe this is where I can stop worrying that I'd be wasting the time of the core Arduino developers, and say quod erat demonstrandum; it a bug in SoftwareSerial. Hopefully they can update the Arduino IDE before the boards hits wider distribution.

Update : So, it turns out that this is a known limitation of the Leonardo. David Mellis looked into it, and left this comment :

You're right that the Leonardo only has one pin change interrupt, meaning that the software serial receive doesn't work on every pin. You should, however, be able to use pins 8 to 11 (inclusive) as receive pins for software serial. Additionally, the SPI pins (MISO, SCK, MOSI) available on the ICSP header and addressable from the Arduino software as pins 14, 15, and 16 should work.
He is, of course, correct. I'm not sure why my testing didn't work on pins 8-11, but they do indeed work fine. Unfortunately, this means that the Leonardo is not compatible with a number of cool shields. The Arduino SoftSerial Library Reference documentation has been updated with a more detailed list of limitations.

Happy 60th, Mom and Dad!

Posted by Russell on February 10, 2012 at 2:24 p.m.
As is often the case, odd people had odd children. Readers of this blog have no doubt long noted a certain... peculiarity of the author, and hypothesized about the individuals who raised me. I can proudly confirm that they are every bit as odd as I am. Anyway, they both turned sixty in the last couple of weeks (my mom in December, and my dad a few days ago), and I wanted to post a little celebration of our great family tradition of crossgrainedness.

For my mom's birthday, she and my sister came over and slept on the floor of my apartment in Davis, despite the availability of perfectly comfortable and reasonably priced lodgings downtown. For her birthday, we found a fetid puddle of water near Lake Berryessa with some tadpoles in it. She was delighted.

For my dad's birthday, he's celebrating his election to the National Academy of Engineering (the sister organization to the Institute of Medicine. He also got this birthday card from his longtime college friend Bruce Reznick :


Bruce is a professor of mathematics at the University of Illinois. He studies the identities of high-order polynomials. So, this really is the a birthday card only he would think to send.

A desirable extinction

Posted by Russell on March 25, 2010 at 3:19 p.m.
Some weeks ago, Buzz (my cat) escaped out my front door while I was carrying my bicycle into the apartment. For ten or twenty minutes, he romped through the ivy and bushes around my apartment while I followed him around rattling a bag of cat treats. Eventually, he let me pick him up and take him back inside. Naturally, he picked up a few fleas. Naturally, they have multiplied.

Oddly, the fleas don't seem to like Neil very much, nor do they like me. It's just poor Buzz that's beset by the nasty little critters.

Figure 1: A flea.


As it happens, I've been thinking about endogenous metrics for estimating the sampling quality of an environmental shotgun sequencing dataset, and Buzz's little problem presented an opportunity to play with a simplified problem. So, I have decided to make Buzz, or rather his fleas, into a small experiment in ecology. I am going to try to see if I can drive them into extinction.

Now, this is normally what a pet owner does when they discover their pet has contracted some sort of annoying parasite, but I decided to take a more quantitative approach.

Figure 2: A cat.


It's simple enough to count fleas on a cat, if the cat is willing to cooperate. Buzz loves the flea comb, and will gleefully hop onto the coffee table and wait to be combed if you show it to him. So, in the interest of science, I convinced my roommate to count the number of passes I made with the flea comb and how many fleas I captured (posterity will remember your efforts, Mehdi). Using his tally, I plotted the cumulative number of passes verses the cumulative number of fleas.

Figure 3: Fleas captured

As expected, it became somewhat more difficult to capture the next flea as more fleas were captured, suggesting a depletion curve. The value of the asymptote should be the actual number of fleas on Buzz at the time, and reaching that number would imply local extinction for the fleas. Of course, there are probably other fleas lurking about that would recolonize Buzz. In principle, if I were to repeat the exercise frequently enough, Buzz would become a sink for fleas, and their migration to his fur would gradually deplete them from the environment.

There are a couple of different ways to model the impact of the combing on the flea population, with various advantages and disadvantages. All we really want to do here is to estimate the value of the asymptote, and so a simple model is probably sufficient. I showed this data to my fried Sharon Shewmake, an economics graduate student. Sharon, after editorializing on the endeavor ("Ew."), suggested this very simple model.

Assume that Buzz is not going to sit still long enough for the fleas to reproduce, for more fleas to migrate to his fur, and that the fleas already on his fur are going to stay put unless captured. Thus, there is a fixed initial population which only changes as a result of capturing fleas. Next, we assume that any given flea is equally likely to be captured on a single pass of the comb. So, the expectation value for number of fleas captured on a single pass is the product of the current population and the probability of capturing a flea.

where N is the population of fleas and p is the probability of any particular flea being captured on a single pass. One could tart this up a bit by modeling it as a stochastic process and executing a bunch of Monte Carlo trials until the outcomes converge, but that seems like overkill for a simple single variable problem like this. We will put up with the intellectual inconvenience of capturing fractional fleas.

This is a little easier to see if we let N represent the number of fleas remaining on the cat, rather than the number of fleas captured.

If we stretch our credulity far enough to imagine this as a continuous function, we can express it as a differential equation.

Sorry if this bothers you. Not only are we extracting fractional fleas, but we are now modeling the combing process as a sort of flea-killing-combine continuously mowing its way through the fur. This is a model, so you shouldn't be surprised to find massless rope and spherical cows. Anyway, it has a nice easy solution.

Well, what the heck. This is a decaying function, so let's pluck a minus sign out of the exponential factor, and maybe tack on a scale factor for the initial population.

While we're at it, why don't we go back to letting the function stand for the number of fleas captured, rather than the fleas on the cat.

This gives us a nice function to use for a linear regression. A little help from scipy, and we find that the initial population is estimated at 39.7 fleas, and the decay factor is 0.011.

Figure 4: Flea population

I captured 34 fleas, so that means I missed about five or six. In order to be reasonably confident that I'd captured all 39 fleas, I would have had to continued for about 400 passes with the comb, instead of 173. Buzz is a patient cat, but he started to loose interest around 120 passes, and had to be fetched back onto the coffee table a few time times during the last 50 passes. My guess is that 400 passes would require some kind of sedative. On the other hand, he does seem to like Guinness, so there may be something to that.

Science has been served. I'm going to the pet store to buy some flea collars.

Why is printing terrible?

Posted by Russell on November 26, 2009 at 3:53 p.m.
Mimi and I spent a good chunk of yesterday trying to print a three page PDF document. First, her dad's year-old HP OfficeJet 6300 stripped a gear in its paper feeder with no paper in the loading tray. It now seems to be beyond repair. So, we went over to her cousin's house, and a her HP all-in-one choked on a strangely formatted paper size directive. The error codes suggest that the printer's firmware got corrupted, but we couldn't get any more detail on account of Vista's printer stack simultaneously shitting itself, and remaining resolutely shat even after the usual Windows hokey-pokey of uninstalling/reinstalling, rebooting and banging the table and swearing.

We emailed the damn thing to her sister at her office, and she spent an hour futzing around with it before getting it to live uncomfortably on an 8.5"x11" sheet of paper, only to discover that someone had swiped the fuser wire from the big office laser printer. Six hours after we started, the three pages finally emerged from an old printer Lan found somewhere in a closet.

This seems to be the normal experience when you want to print an important document. Why is it still so awful? Why do people not riot in the streets and burn HP executives alive on pyres of new-but-broken plastic-crap printers? Why do people continue to allow PostScript to live?

No love for X.org today

Posted by Russell on April 19, 2009 at 8:37 p.m.
I'd like to give a big fat raspberry to the X.org people today, and possibly the Debian X.org maintainers, for pushing busted X.org packages. Booo!

If you should happen to download said packages, you will find mouse and keyboard input on your computer completely disabled once the login manager comes up. If you log in via ssh (or boot with "single" in your kernel boot options), and look at /var/log/Xorg.0.log and observe the following,

(II) The server relies on HAL to provide the list of input devices.
	If no devices become available, reconfigure HAL or disable 
        AllowEmptyInput.
(WW) AllowEmptyInput is on, devices using drivers 'kbd', 'mouse' or
        'vmmouse' will be disabled.
(WW) Disabling Keyboard0
then you have contracted this particular affliction.

Dear X people, why the fuck would you make the default behavior to ignore properly configured devices? Especially when this can brick peoples' computers? Yes, I know about this. I stand by my raspberry. HAL still doesn't enable the right quirks for my motherboard, even though I submitted FDI files more than two years ago. HAL does not, and will not ever, work for everyone. When it works, it's nice, and I'm in favor of it. But please, please stop making life suck for people HAL doesn't help.

A pox on you all!

Anyway, the way you fix this particular bug is to add the line

Option "AllowEmptyInput" "false"
to the ServerLayout section of your xorg.conf file. For example
Section "ServerLayout"
    Identifier      "Default Layout"
    Screen          "Default Screen"
    InputDevice     "Generic Keyboard"
    InputDevice     "Configured Mouse"
    Option          "AllowEmptyInput"    "false"
EndSection
Props to K.Mandla for figuring it out.

Ubuntu X.org frustrations

Posted by Russell on May 04, 2007 at 11:20 p.m.
To those of you who may be struggling to get your non 4:3 aspect ratio monitor working under the new Ubuntu release (Feisty), here is the magical incantation that will make it happy:
russell@riouj:~$ gtf 1440 900 60

  # 1440x900 @ 60.00 Hz (GTF) hsync: 55.92 kHz; pclk: 106.47 MHz
  Modeline "1440x900_60.00"  106.47  1440 1520 1672 1904  900 901 904 932  -HSync +Vsync
Place the output into the "Monitor" section of /etc/X11/xorg.conf, and restart X. Obviously, choose the resolution and frequency that is suitable for your monitor. The one above is appropriate for an iMac G5.