The downside of Arduino…

First of all, I really like the Arduino. There are lots of reasons: great community, relatively inexpensive, wide hardware availability and variety, and often a good “impedance” match to projects. But there are a few design choices (both hardware and software) that can be a nuisance, especially as you try to push the limits of what can be done on such inexpensive and low power hardware.

First of all, there is the basic software philosophy. I love the fact that it is a single download: this simplifies installation, and whether you are an expert or a novice doesn’t matter, that’s simply more convenient. But using the program editor provided is simply not that desirable for experts who might be more used to Eclipse, or to an old fashioned kind of guy like myself for whom vi and Makefiles is more reasonable. With a little work you can find out where avr-gcc, avr-libc and avrdude are installed and add them to your search path, but you still have some work to build a Makefile which can compile your sketch from the command line. That’s a little annoying.

But more annoying are the design choices of the libraries themselves.

High among them are the heavy use of delay and the relative invisibility of interrupts. This may simplify short programs, but it provides no help to more sophisticated programs, and may in fact hinder them. Consider my experiments of last night (which fueled the rant of this morning). I merely wanted to implement a serial terminal using the TVout library and some serial communications library. The idea would be “read from serial, print to TVout”, voila, should be simple.

TVout generates NTSC video on the fly, and it basically works great. To do so, it uses regular timer interrupts. and if you dig into the library itself, you might find out that it uses Timer1. At regular interval, the timer 1 counter overflows, and the library knows that it’s time to bitbang out the video using some carefully constructed code. It also appears to use Timer2 to generate audio tones. Hmmm. The AVR chip that underlies the normal Arduino has only three timers… is that going to be a problem? How can I tell if another library also uses those timers?

You won’t find it in the documentation to any library. Arduino programming is supposed to be easy, and remove the need to understand how the underlying hardware works. Except that when you try to use two libraries together, and they happen to both use the same underlying timer resources, it doesn’t work right. There are no compile issues, it’s just one or both of the modules fail.

Which it did of course last night. You’d think that a loop like:

void
loop()
{
    TV.print((char)Serial.read()) ;
}

might have a chance of working, but it doesn’t. It drops and mangles characters horribly. While you might be able to poll some switches, apparently typing is something that is simply beyond the realm of expectation.

Some of you are probably going to leap to TVout’s defense, claiming that “You’re not doing it right! There is an example sketch which shows you the right way to do Serial and TVout!” Let’s have a look at that little sketch, shall we?

#include <TVout.h>
#include <pollserial.h>
#include <fontALL.h>

TVout TV;
pollserial pserial;

void setup()  {
  TV.begin(_NTSC,184,72);
  TV.select_font(font6x8);
  TV.println("Serial Terminal");
  TV.println("-- Version 0.1 --");
  TV.set_hbi_hook(pserial.begin(57600));
}

void loop() {
  if (pserial.available()) {
    TV.print((char)pserial.read());
  }
}

Okay, we have some new library, which we never heard of before. It’s apparently part of the TVout download. Documentation? No. It calls a function I haven’t seen before, “set_hbi_hook”. Is that documented? No. I am pretty sure it’s a hook which will get called at the end (or the beginning?) of a horizontal blanking interrupt (this isn’t my first rodeo) but what’s really going on here. The pserial.begin call must return a function… time to crack open the source code.

And, it’s about what you expect. There is a hook function that gets called on every line, right before the line is rendered. My guess is that it’s bad if the timing of the hook function is in anyway indeterminate, because then the rows will start at odd intervals. But each render routine starts with a line which waits… for some length…. maybe there is some amount of time (undocumented, different for PAL/NTSC, maybe just the front part of each scanline, read more code) that if you don’t exceed, you’ll be fine. What does pollserial do? Well, it snoops at the serial data registers (polling!) to see if a new character has arrived. It then puts it in a ringbuffer, so that it can be made available to the read call later. Okay, I understand.

But did I mention the reason I didn’t use this code in the first place? It’s that pollserial didn’t compile on my Arduino 1.0 setup (most libraries that aren’t part of the core don’t out of the box yet, in my experience). I could probably figure that out (has something to do with inheriting from the Print class and a prototype mismatch) but in my real, ultimate application, I wanted to read from a PS/2 keyboard. It will of course have the same (but differing in details) issues, and I’ll have to tweak their driver code to make it work with TVout too. Sigh.

Ultimately, I guess I disagree with one part of the Arduino philosophy: that programming can ever really be simple. Writing a program to blink an led, or read a switch isn’t hard, no matter what language or processor you use. Simple programs are simple, but the virtue of computers is that they can do things which are complex. If your software environment doesn’t give you sufficient help in organizing and doing complex actions, then you are missing out a great deal of the purpose of computers.

Addendum: While trying to fix the compile errors in pollserial, I found this fragment:

int pollserial::read() {
        if (rxbuffer.head == rxbuffer.tail)
                return -1;
        else {
                uint8_t c = rxbuffer.buffer[rxbuffer.tail];
                //tail = (tail + 1) & 63;
                if (rxbuffer.tail == BUFFER_SIZE)
                        rxbuffer.tail = 0;
                else
                        rxbuffer.tail++;  
                return c;
        }
}

Can you spot the problem? Hints: BUFFER_SIZE is defined to 64, and rxbuffer.buffer is malloced to be BUFFER_SIZE bytes long.

9 thoughts on “The downside of Arduino…

  1. Stephen

    Perhaps if you are “pushing the limits” of hardware or software you should consider looking for more appropriate tools to continue your project unless you are trying to see how far you can go and then you should not blame your tools.

  2. Mark VandeWettering Post author

    Sure, I could solve this problem by using bigger, faster more expensive hardware. But it is inspiring or virtuous to do with more, what can be done with less? Part of the reason that Arduino and microcontrollers interest me is that they allow a kind of crafstmanship spawned from minimalism that other kinds of programming don’t display. At issue isn’t whether the underlying hardware can do what I am asking (it clearly can, since projects like the Tellymate do even more than I was asking) but whether the Arduino environment helps one get at this underlying power. It mostly does not, and in some cases actually hinders, by saddling the programmer with abstractions that do not help him in meeting his task.

    People do indeed blame their tools, but that’s not to say that bad tools don’t exist. You can tell the difference between a $5 soldering iron and a $200 one. Try to use the first, and it’s a recipe for frustration. Tools matter.

  3. Chris Johnson

    The last paragraph of your post sums up my attitude to Arduino perfectly.

    Have you tried programming the Atmel chip in assembly? While I have only used PICs (rather than Atmels), I find assembly a very good way to get the ‘craftsmanship spawned from minimalism’ that you refer to. While one wouldn’t want to use assembly for everything, there’s a certain simplicity in dealing with the chip directly. I find the additional complexity of using assembly much less frustrating than the complexity of having to work around a high-level interface that doesn’t do what I want it to…

  4. Kenneth Finnegan

    I’m kind of embarrassed how long it took me to find the problem in the addendum.

    I stopped using Arduino for anything big and dropped down to Vim, makefiles, and avr-gcc a long time ago. It’s kind of a drag when finding libs takes more work/have to write them yourself, but once you build your toolbox, I find it much nicer than dealing with the Arduino environment.

  5. Brent Jones

    I have to agree Mark. There are some good things about the Arduino but they can also be a pain to work with. I built a Morse Code simulator with an Arduino and it was fairly simple just turn on/off the Morse code sounder at the right time. The Arduino is good for this job.

    But I a have built a Teleprinter driver which I used Avr Studio because to do it in Arduino would have mean’t mixing Arduino Code with explicit C code as well. For example the Teleprinter uses 5 BIT Baudot code. The Arduino Serial library does not appear , as standard, to let you set the bit lengths.

    Just having one cable to program the arduino is handy. It can be used as a good proof of concept tool. I tried using a Duemilanove for the Teleprinter driver but found a problem when I wanted to use the serial port to drive the Teleprinter. If you had the serial out pin connected to what you wanted to drive eg transistor you couldn’t program the board. I had to keep disconnecting my transistor. I could understand if my device was sending data but would have thought it should have had no effect when receiving except providing some wrong characters on the Teleprinter.

    The boot loader can be handy but for somethings the lag between switch on and your program starting can be too long. Is it documented anywhere what state the Ports are in while the bootloader is checking for serial input?

    The main thing going for the Arduino is it has got a lot more people using microcontrollers now then before it exsited.

  6. Pingback: » I love my Arduino, but… Matt Quadros . com

  7. Pingback: » I love my Arduino, but… Matt Quadros . com

  8. Pingback: Asciimation » Blog Archives » Taipan! on the Arduino. Part 2.

  9. mike

    No no noduino.. Librarys makes C look like a very easy language to novices.
    C was preferred back in the days when C compiled into faster machinecode.
    Basic makes just as fast and small code as C today, and it’s much more structured.
    Learn the real way if you want to make a project that really is going to end up on a circuitboard! Get a AVR, a breadboard, usb-isp cable and download Bascom-avr..

    C takes more time to master and nowdays doesn’t have any advatages over the much easier Basic language.

Comments are closed.