Akkana's Musings on Open Source Computing and Technology, Science, and Nature.
Thu, 05 Apr 2018
A week ago I got back from a trip to the Chiricahua mountains of
southern Arizona, specifically Cave Creek on the eastern side of the range.
The trip was theoretically a hiking trip, but it was also for birding
and wildlife watching -- southern Arizona is near the Mexican border
and gets a lot of birds and other animals not seen in the rest of the
US -- and an excuse to visit a friend who lives near there.
Although it's close enough that it could be driven in one fairly long
day, we took a roundabout 2-day route so we could explore some other
areas along the way that we'd been curious about.
First, we wanted to take a look at the White Mesa Bike Trails
northwest of Albuquerque, near the Ojito Wilderness. We'll be back at
some point with bikes, but we wanted to get a general idea of the
country and terrain. The Ojito, too, looks like it might be worth
a hiking trip, though it's rather poorly signed: we saw several kiosks
with maps where the "YOU ARE HERE" was clearly completely misplaced.
Still, how can you not want to go back to a place where the two main
trails are named Seismosaurus and Hoodoo?
The route past the Ojito also led past Cabezon Peak, a volcanic neck
we've seen from a long distance away and wanted to see closer. It's
apparently possible to climb it but we're told the top part is fairly
technical, more than just a hike.
Finally, we went up and over Mt Taylor, something we've been meaning
to do for many years. You can drive fairly close to the top, but
this being late spring, there was still snow on the upper part of
the road and our Rav4's tires weren't up to the challenge. We'll
go back some time and hike all the way to the top.
We spent the night in Grants, then the following day, headed down
through El Malpais, stopping briefly at the beautiful Sandstone Overlook,
then down through the Datil and Mogollon area. We wanted to take a
look at a trail called the Catwalk, but when we got there, it was
cold, blustery, and starting to rain and sleet. So we didn't hike the
Catwalk this time, but at least we got a look at the beginning of it,
then continued down through Silver City and thence to I-10,
where just short of the Arizona border we were amused by the
Shave dust storm signs about which I already wrote.
At Cave Creek
Cave Creek Ranch, in Portal, AZ,
turned out to be a lovely place to stay, especially
for anyone interested in wildlife. I saw several "life birds" and
mammals, plus quite a few more that I'd seen at some point but had
never had the opportunity to photograph. Even had we not been hiking,
just hanging around the ranch watching the critters was a lot of fun.
They charge $5 for people who aren't staying there to come and sit in
the feeder area; I'm not sure how strictly they enforce it, but given
how much they must spend on feed, it would be nice to help support them.
The bird everyone was looking for was the Elegant Trogon. Supposedly
one had been seen recently along the creekbed, and we all wanted to
They also had a nifty suspension bridge for pedestrians crossing a dry
(this year) arroyo over on another part of the property. I guess I was
so busy watching the critters that I never went wandering around, and
I would have missed the bridge entirely had Dave not pointed it out
to me on the last day.
The only big hike I did was the Burro Trail to Horseshoe Pass, about
10 miles and maybe 1800 feet of climbing. It started with a long hike
up the creek, during which everybody had eyes and ears trained on the
sycamores (we were told the trogon favored sycamores). No trogon.
But it was a pretty hike, and once we finally started climbing out of
the creekbed there were great views of the soaring cliffs above Cave
Creek Canyon. Dave opted to skip the upper part of the trail to the
saddle; I went, but have to admit that it was mostly just more of the
same, with a lot of scrambling and a few difficult and exposed traverses.
At the time I thought it was worth it, but by the time we'd slogged
all the way back to the cars I was doubting that.
On the second day the group went over the Chiricahuas to Chiricahua
National Monument, on the other side. Forest road 42 is closed in
winter, but we'd been told that it was open now since the winter had
been such a dry one, and it wasn't a particularly technical road,
certainly easy in the Rav4. But we had plans to visit our friend over
at the base of the next mountain range west, so we just made a quick
visit to the monument, did a quick hike around the nature trail and
Back with the group at Cave Creek on Thursday, we opted for a shorter,
more relaxed hike in the canyon to Ash Spring rather than the brutal
ascent to Silver Peak. In the canyon, maybe we'd see the trogon!
Nope, no trogon. But it was a very pleasant hike, with our first
horned lizard ("horny toad") spotting of the year, a couple of other
lizards, and some lovely views.
We'd been making a lot of trogon jokes over the past few days, as we
saw visitor after visitor trudging away muttering about not having
seen one. "They should rename the town of Portal to Trogon, AZ." "They
should rename that B&B Trogon's Roost Bed and Breakfast." Finally,
at the end of Thursday's hike, we stopped in at the local ranger
station, where among other things (like admiring their caged gila
monster) we asked about trogon sightings. Turns out the last one to be
seen had been in November. A local thought maybe she'd heard one in
January. Whoever had relayed the rumor that one had been seen recently
was being wildly optimistic.
Fortunately, I'm not a die-hard birder and I didn't go there
specifically for the trogon. I saw lots of good birds and some mammals
I'd never seen before
list), like a coatimundi (I didn't realize those ever came up to
the US) and a herd (pack? flock?) of javalinas. And white-tailed deer
-- easterners will laugh, but those aren't common anywhere I've lived
(mule deer are the rule in California and Northern New Mexico). Plus
some good hikes with great views, and a nice visit with our friend. It
was a good trip.
On the way home, again we took two days for the opportunity to visit
some places we hadn't seen. First, Cloudcroft, NM: a place we'd heard
a lot about because a lot of astronomers retire there. It's high in
the mountains and quite lovely, with lots of hiking trails in the
surrounding national forest. Worth a visit some time.
From Cloudcroft we traveled through the Mescalero Apache reservation,
which was unexpectedly beautiful, mountainous and wooded and dotted
with nicely kept houses and ranches, to Ruidoso, a nice little town
where we spent the night.
Our last stop, Saturday morning, was Lincoln, site of the Lincoln
County War (think Billy the Kid). The whole tiny town is set up as a
tourist attraction, with old historic buildings ... that were all
closed. Because why would any tourists be about on a beautiful
Saturday in spring? There were two tiny museums, one at each end of
town, which were open, and one of them tried to entice us into paying
the entrance fee by assuring us that the ticket was good for all the
sites in town. Might have worked, if we hadn't already walked the
length of the town peering into windows of all the closed sites. Too
bad -- some of them looked interesting, particularly the general store.
But we enjoyed our stroll through the town, and we got a giggle out of
the tourist town being closed on Saturday -- their approach to tourism
seems about as effective as Los Alamos'.
Photos from the trip are at
Cave Creek and the Chiricahuas.
[ 10:04 Apr 05, 2018
More travel |
permalink to this entry |
Mon, 26 Mar 2018
I just got back from a trip to the Chiricahuas, specifically Cave Creek.
More on that later, after I've done some more photo triaging.
But first, a story from the road.
Driving on I-10 in New Mexico near the Arizona border, we saw several
signs about dust storms. The first one said,
ZERO VISIBILITY IS POSSIBLE
Dave commented, "I prefer the ones that say, 'may exist'."
And as if the highway department heard him, a minute or two later
we passed a much more typical New Mexico road sign:
DUST STORMS MAY EXIST
New Mexico, the existential state.
But then things got more fun. We drove for a few more miles, then we
passed a sign that obviously wasn't meant to stand alone:
IN A DUST STORM
"It's a Burma Shave!" we said simultaneously. (I'm not old
enough to remember Burma Shave signs in real life, but I've heard
stories and love the concept.) The next sign came quickly:
PULL OFF ROADWAY
"What on earth are they going to find to rhyme with 'roadway'?"
I wondered. I racked my brains but couldn't come up with anything.
As it turns out, neither could NMDOT. There were three more signs:
TURN VEHICLE OFF
FEET OFF BRAKES
"Hmph", I thought. "What an opportunity missed." But I still couldn't
come up with a rhyme for "roadway". Since we were on Interstate 10,
and there's not much to do on a long freeway drive, I penned an
IN A DUST STORM
PULL OFF TEN
YOU WILL LIVE
TO DRIVE AGAIN
Much better, isn't it? But one thing bothered me: you're not really
supposed to pull all the way off Interstate 10, just onto the shoulder.
IN A DUST STORM
PULL TO SHOULDER
YOU WILL LIVE
TO GET MUCH OLDER
I wasn't quite happy with it. I thought my next attempt was an improvement:
IN A DUST STORM
PULL TO SHOULDER
YOU MAY CRASH IF
YOU ARE BOLDER
but Dave said I should stick with "GET MUCH OLDER".
Oh, well. Even if I'm not old enough to remember real Burma Shave signs,
and even if NMDOT doesn't have the vision to make their own signs rhyme,
I can still have fun with the idea.
[ 16:05 Mar 26, 2018
More travel |
permalink to this entry |
Sat, 10 Mar 2018
Our makerspace got a donation of a bunch of Galileo gen2 boards from Intel
on Wikimedia commons).
The Galileo line has been discontinued, so there's no support and
no community, but in theory they're fairly interesting boards.
You can use a Galileo in two ways: you can treat it
like an Arduino, after using the Arduino IDE to download a
Galileo hardware definition since they're not Atmega chips. They
even have Arduino-format headers so you can plug in an Arduino shield.
That works okay (once you figure out that you need to download
the Galileo v2 hardware definitions, not the regular Galileo).
But they run Linux under the hood, so you can also use them as a
single-board Linux computer.
The first question is how to talk to the board. The documentation is terrible,
and web searches aren't much help because these boards were never
terribly popular. Worse, the v1 boards seem to have been more widely
adopted than the v2 boards, so a lot of what you find on the web
doesn't apply to v2. For instance, the v1 required a special serial cable
that used a headphone jack as its connector.
Some of the Intel documentation talks about how you can load a special
Arduino sketch that then disables the Arduino bootloader and instead
lets you use the USB cable as a serial monitor. That made me nervous:
once you load that sketch, Arduino mode no longer works until you
run a command on Linux to start it up again. So if the sketch doesn't
work, you may have no way to talk to the Galileo.
Given the state of the documentation I'd already struggled with for
Arduino mode, it didn't sound like a good gamble. I thought a real
serial cable sounded like a better option.
Of course, the Galileo documentation doesn't tell you what needs to
plug in where for a serial cable. The board does have a standard FTDI
6-pin header on the board next to the ethernet jack, and the labels on
the pins seemed to correspond to the standard pinout on my Adafruit
FTDI Friend: Gnd, CTS, VCC, TX, RX, RTS. So I tried that first, using
GNU screen to connect to it from Linux just like I would a Raspberry
Pi with a serial cable:
screen /dev/ttyUSB0 115200
Powered up the Galileo and sure enough, I got boot messages and was
able to log in as root with no password. It annoyingly forces orange
text on a black background, making it especially hard to read on
a light-background terminal, but hey, it's a start.
Later I tried a Raspberry Pi serial cable, with just RX (green), TX (white)
and Gnd (black) -- don't use the red VCC wire since the Galileo is already
getting power from its own power brick -- and that worked too. The Galileo
doesn't actually need CTS or RTS. So that's good: two easy ways to talk to
the board without buying specialized hardware. Funny they didn't bother
to mention it in the docs.
Blinking an LED from the Command Line
Once connected, how do you do anything? Most of the
tutorials on Linux are useless, devoting most of their space
to things like how to run Putty on Windows and no space at all to
how to talk to pins. But I finally found a
with a Python example for Galileo. That's not immediately helpful
since the built-in Linux doesn't have python installed (nor gcc,
natch). Fortunately, the Python example used files in /sys
rather than a dedicated Python library;
we can access /sys files just as well from the shell.
Of course, the first task is to blink an LED on pin 13. That
apparently corresponds to GPIO 7 (what are the other arduino/GPIO
correspondences? I haven't found a reference for that yet.) So you
need to export that pin (which creates /sys/class/gpio/gpio7
and set its direction to
out. But that's not enough: the
pin still doesn't turn on when you
echo 1 > /sys/class/gpio/gpio7/value. Why not?
I don't know, but the Python script exports three other pins --
46, 30, and 31 -- and echoes 0 to 30 and 31. (It does this without
first setting their directions to
out, and if you try
that, you'll get an error, so I'm not convinced the Python script
presented as the "Correct answer" would actually have worked. Be warned.)
Anyway, I ended up with these shell lines as
preparation before the Galileo can actually blink:
# echo 7 >/sys/class/gpio/export
# echo out > /sys/class/gpio/gpio7/direction
# echo 46 >/sys/class/gpio/export
# echo 30 >/sys/class/gpio/export
# echo 31 >/sys/class/gpio/export
# echo out > /sys/class/gpio/gpio30/direction
# echo out > /sys/class/gpio/gpio31/direction
# echo 0 > /sys/class/gpio/gpio30/value
# echo 0 > /sys/class/gpio/gpio31/value
And now, finally, you can control the LED on pin 13 (GPIO 7):
# echo 1 > /sys/class/gpio/gpio7/value
# echo 0 > /sys/class/gpio/gpio7/value
or run a blink loop:
# while /bin/true; do
> echo 1 > /sys/class/gpio/gpio7/value
> sleep 1
> echo 0 > /sys/class/gpio/gpio7/value
> sleep 1
Searching Fruitlessly for a "Real" Linux Image
All the Galileo documentation is emphatic that you should download
a Linux distro and burn it to an SD card rather than using the Yocto
that comes preinstalled. The preinstalled Linux apparently has no
persistent storage, so not only does it not save your Linux programs,
it doesn't even remember the current Arduino sketch.
And it has no programming languages and only a rudimentary busybox shell.
So finding and downloading a Linux distro was the next step.
Unfortunately, that mostly led to dead ends. All the official Intel
docs describe different download filenames, and they all point to
generic download pages that no longer include any of the filenames
mentioned. Apparently Intel changed the name for its Galileo images
frequently and never updated its documentation.
After forty-five minutes of searching and clicking around,
I eventually found my way to
Intel® IoT Developer Kit Installer Files,
which includes sizable downloads with names like
- iss-iot-linux_12-09-16.tar.bz2 (324.07 MB),
- intel-iot-yocto.tar.xz (147.53 MB),
- intel-iot-wrs-pulsar-64.tar.xz (283.86 MB),
- intel-iot-wrs-32.tar.xz (386.16 MB), and
- intel-iot-ubuntu.tar.xz (209.44 MB)
From the size, I suspect those are all Linux images. But what are they
and how do they differ? Do any of them still have working repositories?
Which ones come with Python, with gcc, with GPIO support,
with useful development libraries? Do any of them get security updates?
As far as I can tell, the only way to tell is to download each image,
burn it to a card, boot from it, then explore the filesystem
trying to figure out what distro it is and how to try updating it.
But by this time I'd wasted three hours and gotten no
further than the shell commands to blink a single LED, and I ran out of
enthusiasm. I mean, I could spend five more hours on this, try several
of the Linux images, and see which one works best. Or I could spend
$10 on a Raspberry Pi Zero W that has abundant documentation,
libraries, books, and community howtos. Plus wi-fi, bluetooth and HDMI,
none of which the Galileo has.
Arduino and Linux Living Together
So that's as far as I've gone. But I do want to note
one useful thing I stumbled upon while searching
for information about Linux distributions:
sketch from Linux terminal shows how to run an Arduino sketch
(assuming it's already compiled) from Linux:
sketch.elf /dev/ttyGS0 &
It's a fairly cool option to have. Maybe one of these days, I'll pick
one of the many available distros and try it.
[ 13:54 Mar 10, 2018
More hardware |
permalink to this entry |
Thu, 01 Mar 2018
I updated my Debian Testing system via
as one does during the normal course of running a Debian system.
The next time I went to a locally hosted website, I discovered PHP
didn't work. One of my websites gave an error, due to a directive
in .htaccess; another one presented pages that were full of PHP code
interspersed with the HTML of the page. Ick!
In theory, Debian updates aren't supposed to change configuration files
without asking first, but in practice, silent and unexpected Apache
bustage is fairly common. But for this one, I couldn't find anything
in a web search, so maybe this will help.
The problem turned out to be that /etc/apache2/mods-available/
includes four files:
$ ls /etc/apache2/mods-available/*php*
The appropriate files are supposed to be linked from there into
/etc/apache2/mods-enabled. Presumably, I previously had a link
to ../mods-available/php7.0.* (or perhaps 7.1?); the upgrade to
PHP 7.2 must have removed that existing link without replacing it with
a link to the new ../mods-available/php7.2.*.
The solution is to restore those links, either with
or with the approved apache2 commands (as root, of course):
# a2enmod php7.2
# systemctl restart apache2
Whew! Easy fix, but it took a while to realize what was broken, and
would have been nice if it didn't break in the first place.
Why is the link version-specific anyway? Why isn't there a file called
/etc/apache2/mods-available/php.* for the latest version?
Does PHP really change enough between minor releases to break websites?
Doesn't it break a website more to disable PHP entirely than to swap in
a newer version of it?
[ 10:31 Mar 01, 2018
More linux |
permalink to this entry |
Fri, 23 Feb 2018
Dave and I are giving a planetarium show at PEEC tonight on the analemma.
I've been interested in the analemma for years and have
written about it before,
here on the blog
and in the SJAA Ephemeris.
But there were a lot of things I still didn't understand as well as
I liked. When we signed up three months ago to give this talk, I had
plenty of lead time to do more investigating, uncovering lots of
interesting details regarding the analemmas of other planets,
the contributions of the two factors that go into the Equation of Time,
why some analemmas are figure-8s while some aren't,
and the supposed "moon analemmas" that have appeared on the
of the Day. I added some new features to the analemma script I'd
written years ago as well as corresponding with an expert who'd written
some great Equation of Time code for all the planets. It's been fun.
I'll write about some of what I learned when I get a chance, but
meanwhile, people in the Los Alamos area can hear all about it
tonight, at our PEEC show:
The Analemma Dilemma,
7 pm tonight, Friday Feb 23, at the Nature Center,
admission $6/adult, $4/child.
[ 10:23 Feb 23, 2018
More science/astro |
permalink to this entry |
Sat, 17 Feb 2018
In the previous article I talked about
input/output using shift registers for a music keyboard project.
I ended up with three CD4021 8-bit shift registers cascaded.
It worked; but I found that I was spending all my time in the
delays between polling each bit serially. I wanted a way to read
those bits faster. So I ordered some I/O expander chips.
I/O expander, or port expander, chips take a lot of the hassle out of
multiplexing. Instead of writing code to read bits serially, you can use I2C.
Some chips also have built-in pullup resistors, so you don't need all
those extra wires for pullups or pulldowns.
There are lots of options, but two common chips are the MCP23017,
which controls 16 lines, and the MCP23008 and PCF8574p, which each
handle 8. I'll only discuss the MCP23017 here, because if eight is good,
surely sixteen is better! But the MCP23008 is basically the same thing
with fewer I/O lines.
A good tutorial to get you started is
To Use A MCP23017 I2C Port Expander With The Raspberry Pi - 2013 Part 1
2, Python and
3, reading input.
I'm not going to try to repeat what's in those tutorials, just
fill in some gaps I found. For instance,
I didn't find I needed sudo for all those I2C commands in Part 1
since my user is already in the i2c group.
Using Python smbus
Part 2 of that tutorial uses Python smbus, but it doesn't really
explain all the magic numbers it uses, so it wasn't obvious how to
generalize it when I added a second expander chip. It uses this code:
DEVICE = 0x20 # Device address (A0-A2)
IODIRA = 0x00 # Pin direction register
OLATA = 0x14 # Register for outputs
GPIOA = 0x12 # Register for inputs
# Set all GPA pins as outputs by setting
# all bits of IODIRA register to 0
# Set output all 7 output bits to 0
DEVICE is the address on the I2C bus, the one you see with
i2cdetect -y 1 (20, initially).
IODIRA is the direction: when you call
bus.write_byte_data(DEVICE, IODIRA, 0x00)
you're saying that all eight bits in GPA should be used for output.
Zero specifies output, one input: so if you said
bus.write_byte_data(DEVICE, IODIRA, 0x1F)
you'd be specifying that you want to use the lowest five bits for output
and the upper three for input.
OLATA = 0x14 is the command to use when writing data:
bus.write_byte_data(DEVICE, OLATA, MyData)
means write data to the eight GPA pins. But what if you want to write to
the eight GPB pins instead? Then you'd use
OLATB = 0x15
bus.write_byte_data(DEVICE, OLATB, MyData)
Likewise, if you want to read input from some of the GPB bits, use
GPIOB = 0x13
val = bus.read_byte_data(DEVICE, GPIOB)
The MCP23017 even has internal pullup resistors you can enable:
GPPUA = 0x0c # Pullup resistor on GPA
GPPUB = 0x0d # Pullup resistor on GPB
bus.write_byte_data(DEVICE, GPPUB, inmaskB)
Here's a full example:
You can also talk to an MCP23017 using the WiringPi library.
In that case, you don't set all the bits at once, but instead treat
each bit as though it were a separate pin. That's easier to think
about conceptually -- you don't have to worry about bit shifting
and masking, just use pins one at a time -- but it might be slower
if the library is doing a separate read each time you ask for an input bit.
It's probably not the right approach to use if you're trying to check
a whole keyboard's state at once.
Start by picking a base address for the pin number -- 65 is the lowest
you can pick -- and initializing:
pin_base = 65
i2c_addr = 0x20
Then you can set input or output mode for each pin:
and then write to or read from each pin:
val = wiringpi.digitalRead(pin_no)
WiringPi also gives you access to the MCP23017's internal pullup resistors:
Here's an example in Python:
on GitHub, and one in C:
Using multiple MCP23017s
But how do you cascade several MCP23017 chips?
Well, you don't actually cascade them. Since they're I2C
devices, you wire them so they each have different addresses on the
I2C bus, then query them individually. Happily, that's
easier than keeping track of how many bits you've looped through ona
Pins 15, 16 and 17 on the chip are the address lines, labeled A0, A1
and A2. If you ground all three you get the base address of 0x20.
With all three connected to VCC, it will use 0x27 (binary 111 added to
the base address). So you can send commands to your first device at 0x20,
then to your second one at 0x21 and so on. If you're using WiringPi,
you can call mcp23017Setup(pin_base2, i2c_addr2) for your second chip.
I had trouble getting the addresses to work initially, and it turned
out the problem wasn't in my understanding of the address line wiring,
but that one of my cheap Chinese breadboard had a bad power and ground
bus in one quadrant. That's a good lesson for the future: when things
don't work as expected, don't assume the breadboard is above suspicion.
Using two MCP23017 chips with their built-in pullup resistors simplified
the wiring for my music keyboard enormously, and it made the code
cleaner too. Here's the modified code:
What about the speed? It is indeed quite a bit faster than the shift
register code. But it's still too laggy to use as a real music keyboard.
So I'll still need to do more profiling, and maybe find a faster way
of generating notes, if I want to play music on this toy.
[ 15:44 Feb 17, 2018
More hardware |
permalink to this entry |
Tue, 13 Feb 2018
I was scouting for parts at a thrift shop and spotted a little
23-key music keyboard. It looked like a fun Raspberry Pi project.
I was hoping it would turn out to use some common protocol like I2C,
but when I dissected it, it turned out there was a ribbon cable with
32 wires coming from the keyboard. So each key is a separate pushbutton.
A Raspberry Pi doesn't have that many GPIO pins, and neither does an
Arduino Uno. An Arduino Mega does, but buying a Mega to go between the
Pi and the keyboard kind of misses the point of scavenging a $3 keyboard;
I might as well just buy an I2C or MIDI keyboard. So I needed some sort
of I/O multiplexer that would let me read 31 keys using a lot fewer pins.
There are a bunch of different approaches to multiplexing. A lot of
keyboards use a matrix approach, but that makes more sense when you're
wiring up all the buttons from scratch, not starting with a pre-wired
keyboard like this. The two approaches I'll discuss here are
shift registers and multiplexer chips.
If you just want to get the job done in the most efficient way,
you definitely want a multiplexer (port expander) chip, which I'll
cover in Part 2. But for now, let's look at the old-school way: shift
PISO Shift Registers
There are lots of types of shift registers, but for reading lots of inputs,
you need a PISO shift register: "Parallel In, Serial Out."
That means you can tell the chip to read some number -- typically 8 --
of inputs in parallel, then switch into serial mode and read all the bits
one at a time.
Some PISO shift registers can cascade: you can connect a second shift
register to the first one and read twice as many bits. For 23 keys
I needed three 8-bit shift registers.
Two popular cascading PISO shift registers are the CD4021 and the SN74LS165.
They work similarly but they're not exactly the same.
The basic principle with both the CD4021 and the SN74LS165:
connect power and ground, and wire up all your inputs to the eight data pins.
You'll need pullup or pulldown resistors on each input line, just like
you normally would for a pushbutton; I recommend picking up a few
high-value (like 1-10k) resistor arrays: you can get these in SIP
(single inline package) or DIP (dual-) form factors that plug easily
into a breadboard. Resistor arrays can be either independent
two pins for each resistor in the array) or bussed (one pin in
the chip is a common pin, which you wire to ground for a pulldown or
V+ for a pullup; each of the rest of the pins is a resistor). I find
bussed networks particularly handy because they can reduce the number
of wires you need to run, and with a job where you're multiplexing
lots of lines, you'll find that getting the wiring straight is a big
part of the job. (See the photo above to see what a snarl this was
even with resistor networks.)
For the CD4021, connect three more pins: clock and data pins (labeled
CLK and either Q7 or Q8 on the chip's pinout, pins 10 and 3),
plus a "latch" pin (labeled M, pin 9).
For the SN74LS165, you need one more pin: you need clock and data
(labeled CP and Q7, pins 2 and 9), latch (labeled
PL, pin 1),
and clock enable (labeled CE,
At least for the CD4021, some people
a 0.1 uF bypass capacitor across the power/ground connections of each
If you need to cascade several chips with the CD4021, wire DS (pin 11)
from the first chip to Q7 (pin 3), then wire both chips clock lines together
and both chips' data lines together. The SN74LS165 is the same: DS
(pin 10) to Q8 (pin 9) and tie the clock and data lines together.
Once wired up, you toggle the latch to read the parallel data, then
toggle it again and use the clock pin to read the series of bits.
You can see the specific details in my Python scripts:
on GitHub and
For wiring diagrams, more background, and Arduino code for the CD4021, read
For the SN74LS165, read:
74HC165 8 bit Parallel in/Serial out Shift Register,
Of course, you can use a shift register for output as well as input.
In that case you need a SIPO (Serial In, Parallel Out) shift register
like a 74HC595. See
Serial to Parallel Shifting-Out with a 74HC595
74HC595 Serial Shift Register with Raspberry Pi.
Another, less common option is the 74HC164N:
a SN74HC164N Shift Register With Raspberry Pi
For input from my keyboard, initially I used three CD4021s. It basically worked,
and you can see the code for it at
(older version, for CD4021 shift registers), on GitHub.
But it turned out that looping over all those bits was slow -- I've
been advised that you should wait at least 25 microseconds between
bits for the CD4021, and even at 10 microseconds I found there wasa
significant delay between hitting the key and hearing the note.I
thought it might be all the fancy numpy code to generate waveforms for
the chords, but when I used the Python profiler, it said most of the
program's time was taken up in time.sleep(). Fortunately, there's a
faster solution than shift registers: port expanders, which I'll talk
about in Multiplexing Part 2: Port Expanders.
[ 12:23 Feb 13, 2018
More hardware |
permalink to this entry |
Fri, 02 Feb 2018
When I work with a Raspberry Pi from anywhere other than home,
I want to make sure I can do what I need to do without a network.
With a Pi model B, you can use an ethernet cable. But that doesn't
work with a Pi Zero, at least not without an adapter.
The lowest common denominator is a serial cable, and I always
recommend that people working with headless Pis get one of these;
but there are a lot of things that are difficult or impossible over
a serial cable, like file transfer, X forwarding, and running any
sort of browser or other network-aware application on the Pi.
Recently I learned how to configure a Pi Zero as a USB ethernet gadget,
which lets you network between the Pi and your laptop using only a
It requires a bit of setup, but it's definitely worth it.
(This apparently only works with Zero and Zero W, not with a Pi 3.)
The first step is getting the cable.
For a Pi Zero or Zero W, you can use a standard micro-USB cable:
you probably have a bunch of them for charging phones (if you're
not an Apple person) and other devices.
Set up the Pi
Setting up the Raspberry Pi end requires editing
two files in /boot, which you can do either on the Pi itself,
or by mounting the first SD card partition on another machine.
In /boot/config.txt add this at the end:
In /boot/cmdline.txt, at the end of the long list of options
but on the same line, add a space, followed by:
Set a static IP address
This step is optional. In theory you're supposed to use some kind of
.local address that Bonjour (the Apple protocol that used to be called
zeroconf, and before that was called Rendezvous, and on Linux machines
is called Avahi). That doesn't work on
my Linux machine. If you don't use Bonjour, finding the Pi over the
ethernet link will be much easier if you set it up to use a static IP
address. And since there will be nobody else on your USB network
besides the Pi and the computer on the other end of the cable, there's
no reason not to have a static address: you're not going to collide
with anybody else.
You could configure a static IP in /etc/network/interfaces,
but that interferes with the way Raspbian handles wi-fi via
wpa_supplicant and dhcpcd; so you'd have USB networking but your
wi-fi won't work any more.
Instead, configure your address in Raspbian via dhcpcd.
Edit /etc/dhcpcd.conf and add this:
This will tell Raspbian to use address
its USB interface. You'll set up your other computer to use 192.168.7.1.
Now your Pi should be ready to boot with USB networking enabled.
Plug in a USB cable (if it's a model A or B) or a micro USB cable
(if it's a Zero), plug the other end into your computer,
then power up the Pi.
Setting up a Linux machine for USB networking
The final step is to configure your local computer's USB ethernet
to use 192.168.7.1.
On Linux, find the name of the USB ethernet interface. This will only
show up after you've booted the Pi with the ethernet cable plugged in to
The USB interface will probably start eith en
and will probably
be the last interface shown.
On my Debian machine, the USB network showed up as enp0s26u1u1.
So I can configure it thusly (as root, of course):
ip a add 192.168.7.1/24 dev enp0s26u1u1
ip link set dev enp0s26u1u1 up
(You can also use the older ifconfig
rather than ip
sudo ifconfig enp0s26u1u1 192.168.7.1 up
You should now be able to ssh into your Raspberry Pi
using the address 192.168.7.2, and you can make an appropriate entry
in /etc/hosts, if you wish.
For a less hands-on solution, if you're using Mac or Windows, try
USB gadget tutorial.
It's possible that might also work for Linux machines running Avahi.
If you're using Windows, you might prefer
ethernet gadget tutorial.
[ 14:53 Feb 02, 2018
More linux |
permalink to this entry |