Fast pin switching in Arduino

I’ve been playing around with my Arduino Uno and Arduino Mega for the last few weeks, but I didn’t think I had discovered anything interesting enough to post about. In the last day or so, though, I was interested in finding out just how fast one could switch an Arduino digital pin on and off.

binary comment

The Uno’s ATmega328P processor is driven by a 16Mhz processor, so one might hope to get a 16Mhz signal out of a pin. But you need several processor instructions to create the signal: one to bring the pin HIGH, one to bring the pin LOW, and then one to jump back to the beginning of the loop. Per the data sheet, those each require two clock cycles. So, 6 instructions, meaning ~2.7 Mhz is a more reasonable expectation.

Implementing this code with the digitalWrite C function, what I got in the end was only a measly 150 Khz. Turns out that the digitalWrite function call is incredible slow. But fortunately, with the ATmega328P, you can simple write the HIGH or LOW directly to the IO register, which gets you back down to your 6 instructions. You’ve get to spend some time looking at the Atmel data sheet and the Uno pin diagram (or ask the helpful folks at #arduino IRC channel) to figure out how to do that. This is for digital pin 2:

void setup() { 
  pinMode(2, OUTPUT);
  digitalWrite(2, HIGH);
  delay(2);
  noInterrupts();
}

void loop() {
  start:
  PORTD |= (1<<PD2);
  PORTD &= ~(1<<PD2);
  goto start;
}

Note that I called the noInterrupts procedure. noInterrupts suspends processor interrupts, which normally do various things in the background like keeping your microsecond counter running. They introduce some randomness and delay that I didn’t want here.

The above code produced about 2.7 Mhz on the oscilloscope, as expected.

binary comment

Notice there is some lack of symmetry in the signal, since the pin stays low while doing the loop jump. It occurred to me afterwards that maybe a better way to do this, while saving a few more clock cycles, would be to just bit-toggling that register bit instead, but I haven’t had a chance to explore that idea yet.

Guix: Manifest Functions

A technically unnecessary but hopefully interesting introduction: One cool thing about Gnu Guix is the ability to use manifests, which are a declarative definition of the package outputs of a profile. In other words, instead of running the commands

guix install emacs
guix install frozen-bubble
guix install git

You can just have a manifest file like

(specifications->manifest
  '("emacs"
    "frozen-bubble"
    "git"))

saved in a file, say, “christopher-home.scm”, and then feed it into the package manager to define your whole package profile at once:

guix package -m /home/christopher/Manifests/christopher-home.scm

That is nice, because then you can just edit that file to change your package set. Also, you can backup that file, copy it to another computer, or put it under version control.

Another great feature of Guix is the ability to have multiple profiles. A profile is basically a set of package outputs that are exposed in the same place with accompanying environment information. My default profile is programs, libraries, etc. that I want to have easy access to most of the time (not including their dependencies, which is another matter taken care of “behind the scene”). But I can create another profile that just exposes a few programs and libraries that I need for some special purpose.

Probably the most likely example would be certain libraries or programs needed for building or for running some piece of downloaded software. My real life example is trying to run the downloaded (pre-built) version of the Arduino IDE, which is not yet packaged in Guix. To do this I needed some particular system libraries, as well as Java, leading to this specification:

(use-modules (gnu packages gcc))

(concatenate-manifests
 (list
  (specifications->manifest
   '("avr-toolchain"
     "dfu-programmer"
     "gcc-toolchain"
     "glibc"
     "icedtea"
     "libx11"
     "libxrandr"
     "libxtst"))
  (packages->manifest
   `((,gcc "lib")))))

In my case, I install this profile with

guix package -m /home/christopher/Manifests/arduino.scm -p /home/christopher/.guix-extra-profiles/arduino/arduino

And so we come to the ostensible purpose of this post, to describe two features useful in constructing manifests, not really covered well in the Guix reference manual:

First, there is the concatenate-manifests procedure from the (guix profiles) module. This allows you to combine together a manifest constructed by specifications->manifest, along with one constructed by packages->manifest. For most packages you want to use specifications->manifest, because that convenient procedure saves you the bother of having to explicitly import the required package definitions. But, sometimes you need packages->manifest, which leads to the second thing I wanted to mention:

When using packages->manifest, you can specify your manifest entries as tuples containing the package object followed by a string describing the specific package output you need. In my case, this is critical, as I need to use the “hidden” package gcc (in order, if you must know, to get the libstdc++ library exposed) as well as the specific package output lib, since the default output did not expose the required library.

Further reading:

Amateur Radio Log 2020-06-27

Callsign KL1TL. I parked for mobile-stationary operation at Hagelbarger lookout, Fairbanks, AK, around 3 or 3:30pm AKDT. Transmitting 100W with a Hustler multi-band antenna mounted on my GMC. Today was some kind of field day event, so there was lots of activity on multiple bands, but I only made one actual contact myself.

Contact: 4:10pm AKDT. 3920 Khz. KL7QZ (John). Transmitting from Summit Lake for Field Day. I suppose he must have meant Mat-Su Region’s Summit Lake State Recreation Site. That would be a few hundred miles away. His signal was coming in very quiet to my station, but I could read him. He mentioned static on his end.

I couldn’t hear much activity on 80 meter, but there was a moderate amount on 40 meter, and a lot of traffic on 20 meter, though much of it weak and difficult to follow. I also remember trying to copy some slow CW signals coming in on 30 meter.

Here is an interesting Eielson Ionosonde report for 4pm AKDT: