I also ran into an issue updating all my Arch Linux ARM Raspberry Pi systems. They all failed to update (pacman -Suy), and they all failed when attempting to get the catalog from the community repository. A bit of checking on the official Arch wikis turned up nothing. This isn’t the first time I’ve faced this update failure and been forced to reinstall Arch as a consequence. This time, rather than reinstall Arch, I decided to switch completely to the “official” Raspberry Pi distribution, Raspbian.
Raspbian has undergone considerable polish over the last 12 months, to the point where I can easily live within the Raspbian graphical desktop. The desktop has a very nice file browser, terminal, and the Chromium browser is now up-to-date with equivalents across all operating systems. I installed Raspbian by pulling down the image file and using Etcher, all of this on my Ubuntu 16.04 notebook. It’s extremely easy to load-and-go with both Raspbian and Etcher. Before I wiped and reloaded, I made full backups of the older /home/alarm home directories to pick up all my earlier work, then copied them back to the pi account home directory via a separate folder.
With Raspbian everything seems to be working just fine. I was even able to start this post on the older Raspberry Pi 3 Model B using Chromium, although I finished the post on my Mac. I had to transfer a photo I took using my iPhone via Google Drive, and I could have done it on the Pi, but I’m a Mac addict, and I wanted to run something undisturbed on the Pi.
One test I ran was using the tools I wrote in Python for the Sense HAT. I won’t go into the details of how I got the Arch Linux ARM set up to work, but I will say that Raspbian was already set up out-of-the-box to run my Python code unmodified with the Sense HAT plugged into the board, and without installing and/or configuring any other Raspbian packages. I look forward to moving my C++ based Pi code over.
One other observation: The 3B+ runs warm, much warmer than any other Raspberry Pi. I’ve done nothing to tweak the operating frequency of the board. My advice is to buy the heat sink kit for the Raspberry Pi and attach it to the board.
]]>This is the Ruby version of my Cylon LED test cycler that I’ve written in various languages on Arch Linux and the Raspberry Pi. This time it was Ruby’s turn to see if I could use it to manipulate the various I/O subsystems on the Pi. Since setting output pins to drive LEDs is the easiest place for me to start, I wrote the code you see above. Before I could make it work I had to install the rpi_gpio gem. To get some idea of how to use it I looked at the GitHub repository for rpi_gpio. The reason for this is to be able to bridge between the Ruby on Rails work I started earlier this week with both input and output I/O. The only other comment I will make is to make sure that the udev rules have been set up to manipulate the I/O as a regular user. Trying to run the code shown above as root will fail, as the installation of rpi_gpio was local to a regular account, not globally installed.
My only comment on rpi_gpio so far is this: I discovered I had to code a set_low immediately after every enabling of a pin as an output, as the pin was enabled high. I consider this a bug, and as it stands it may not be suitable for what I need. If even a microsecond pulse goes out from those pins after being enabled by Ruby then that’s enough to cause a false start on that pin. The Ruby code isn’t something to write home about, just something to do some very basic testing.
]]>I’ve been asked to create a web monitoring application running on a Raspberry Pi (in this case the 3). The requirements are very modest; run a low-traffic web page to monitor another machine next to it, and provide a simple web report on demand across local WiFi. For this particular project I’ve elected to go back in time, as it were, and install Ruby and Rails as the web foundation. And when I say back in time, I’m talking 2007, when I created another embedded system using a milliwatt CMOS 486 clone chip running a custom built Linux kernel with µclib and BusyBox running Ruby and Rails.
This small post documents the steps, in order, for installing Ruby and Rails peculiar to Arch Linux ARM and the Raspberry Pi 3.
First, make sure that Ruby is installed. That’s as simple as ‘sudo pacman -S ruby’, and for the documentation, ‘sudo pacman -S ruby-docs’. Ruby Gems are a part of Ruby, and you can look to see if they’ve been installed with either a ‘gem -v’ or by looking down /usr/lib/ruby.
Second, add the following line to your .bashrc:
Log out, then log back in. Make sure to do all this before you install Rails, or else Very Bad Things will happen when you do install Rails. It took two attempts to install Rails, all because I failed to add that line to my bashrc file before the first attempt. You can read all about RubyGems setup here.
Third, install Rails with ‘gem install rails’. This will install an account local copy of Rails under ~/.gem, specifically ~/.gem/ruby/2.3.0/gems with this version of Gems. Installing a local account copy is no different than what happens with Node.js installations. There’s always a debate about local vs global installation; due to security and my personal paranoia I always prefer local (non-root) account installation to minimize any unintended consequences a global installation might engender.
Fourth, to be able to reach the Ruby instance outside the Raspberry Pi, I modified the file ~/[project]/config/boot.rb and added the following lines of code at the end of the file:
require 'rails/commands/server'module Railsclass Serverdef default_optionssuper.merge({Port: 8081, Host: '0.0.0.0'})endendend
The merge binds the web server to whatever IP address DNS assigns to the Raspberry Pi (‘0.0.0.0’) instead of using localhost as the defult, and changes the port from the default of 3000 to 8081.
Finally, and this is just extra, I made a tiny modification to the default index file at ~/.gem/ruby/2.3.0/gems/railties-5.0.0.1/lib/rails/templates/rails/welcome/index.html.erb to add the text “Raspberry Pi 3” in order to drive home that the default web page was in fact coming from the Raspberry Pi 3.
Now on to doing something more useful…
]]>tl;dr: It was permissions issues that kept Django from executing properly on Arch ARM and the Raspberry Pi 3. Read on for the details.
Well, looks like I have to walk back that snide comment about Arch running on a Raspberry Pi 3. While I’m certainly no hero, I was irritated considerably by Django’s flagrant failure, enough to find out why. But first, some background.
I don’t have copious amounts of time to work on these kinds of issues. So while I was out working on my honey-do list, while at Trader Joes in the organic produce section, the light went on as to what the probable problem and solution was. Sure enough, when I got home and found a minute to look, that’s when I found the permission settings all wrong. A quick ‘sudo find . -type d -exec chmod 755 {} \+’ and ‘sudo find . -type f -exec chmod 644{}\+’ fixed things up, and I was able to get a quick and dirty Django web server up and running. In fact, to test a capability I’ll need, I tarred up the sample I built on the MBP, secure copied it over to the RPi 3, untarred it there, and got it up and running. Here’s a couple of screen shots of it in action on the RPi 3:
Looks like I’m back in business. The only thing I edited on the RPi 3 was the polls/views.py with vi to change the text output by views.py. Other than that, I simply started it up.
This is the first time I’ve ever had a problem with permissions using pip and Python. In the future I’m going to have to be careful with Arch ARM. It’s a small issue, considering everything else works just fine.
]]>So I did a bit of research and decided to focus on Python, specifically version 3.5 and later. That version of Python is available across all those platforms, and appears to work equally well across them. That means that trivial and not-so-trivial Python applications that aren’t platform specific work equally well across all three. That means I can do a good deal of work on either my Samsung running Windows 10 or my MBP, which includes debugging. I would then transfer the code over to the RPi3 and do final integration there.
The problem I ran into was the choice of a Python web framework. For reasons I won’t go into here I decided to install and learn how to use Django. I’ve successfully followed the getting started tutorials on both the MBP and the Samsung. On the MBP I’ve used Homebrew to install a number of up-to-date software tools, specifically Python 3.5, while on Windows I downloaded and installed Python 3.5 from the Python site. The only comments I have to make about installing Python on Windows 10 are these:
As I said, running the Django utilities works just fine on Mac OS X and Windows 10. Getting Django installed on Arch Linux ARM doesn’t work, either as a pacman package or via pip. There is no package for ARM Arch, and even though the pip install seems to work, trying to create a default site with django-admin on Arch ARM fails, with django-admin complaining there is no django.core. This makes the second major framework failure I’ve run into under Arch ARM, the first being the failure of Express under Node.js. The Express failure was particularly annoying, as it worked about a year ago when I was investigating Express and Node.js on the Raspberry Pi 2. If anything, these failures have proven that the Raspberry Pi 3, at least under Arch Linux ARM, is not the full first-class client that regular installations are.
I suppose I could be a hero (to someone) if I could find and fix the problems I’ve run into on the Raspberry Pi 3, but I don’t feel particularly heroic. I’e gone down multiple paths now with trying to build a full stack of software with a web front end on the RPi 3, and it’s not gone well. One reason for doing the same types of activities on a “regular” computer is to see if the tutorials are repeatable, and they are. It’s trying to move over to the RPi 3 with Arch Linux where it breaks down.
Perhaps it’s time to realize that if I want a better development experience that I need to spend more money and buy a more commercial system than the Raspberry.
As for where the title came from, here it is:
Life’s but a walking shadow, a poor player
That struts and frets his hour upon the stage
And then is heard no more: it is a tale
Told by an idiot, full of sound and fury,
Signifying nothing.
Macbeth, Act 5, Scene 5
The quote about life could just as easily apply to software development.
]]>I’ve had some time to try out both languages and various Raspberry Pi device frameworks, some of them written in Go, another written in Javascript, and at least one written in C/C++. It turns out that the C/C++ framework, WiringPi, is the most complete, and the one that works best for me. The Javascript framework is a very close second. In spite of some intense personal research into Go and Rust, I’m still a better C++ programmer (or at least, I understand it best) than I am in either Go or Rust. All of this combines to lead me one inevitable decision: write my code in C++ with what works best right now. And if I want “better, faster, safer” software then (re-) learn best C++ coding practices and use them diligently. And not just C++ specific best practices, but good old fashioned common sense best software engineering practices. If there’s one thing I’ve learned over time, it’s that no language will save you from a poor design: above all, KISS.
With that in mind, here’s the latest GPIO manipulation application source.
#include <wiringPi.h>#include <boost/algorithm/string.hpp>#include <boost/tokenizer.hpp>#include <iostream>#include <fstream>#include <sstream>struct glyph {unsigned int GPIOpindata = 0;int delayInMillis = 0;};std::vector<glyph> glyphs;bool loadBlinkData(std::string const fileName) {std::ifstream inFile(fileName);glyphs.clear();if (not inFile.is_open()) {std::cout << "Could not open " << fileName << std::endl;return false;}std::cout << "Using " << fileName << std::endl;std::string inLine;while (std::getline(inFile, inLine)) {boost::trim(inLine);if (not inLine.length() or inLine[0] == '#') {continue;}boost::tokenizer<> tokens(inLine);glyph g;for(auto &&token: tokens) {if (token.find("x") != std::string::npos or token.find("X") != std::string::npos) {g.GPIOpindata = std::stoul(token, nullptr, 16);}else {g.delayInMillis = std::stoi(token);}}glyphs.push_back(g);}inFile.close();return true;}std::string defaultDataFile("blinkdata.csv");int main (int argc, char *argv[]) {// Check to see if we passed another file on the command line.// If so, use it instead of the default.//if (argc > 1) {defaultDataFile = argv[1];}// Look to see if we can open and parse the file.// If not, stop.//if (not loadBlinkData(defaultDataFile)) {return 1;}// The input file was opened and parsed.// Now go to work.//wiringPiSetup();pinMode(0, OUTPUT);pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);for (int i = 0; i < 5; ++i) { for (auto &&g : glyphs) { // Just a series of shifts and ANDs to create the bit necessary // write out to the GPIO pin. // digitalWrite(0, g.GPIOpindata & 0x1);digitalWrite(1, (g.GPIOpindata >> 1 ) & 0x1 );digitalWrite(2, (g.GPIOpindata >> 2 ) & 0x1 );digitalWrite(3, (g.GPIOpindata >> 3 ) & 0x1 );delay(g.delayInMillis);}}// Turn everything off.//digitalWrite(0, LOW);digitalWrite(1, LOW);digitalWrite(2, LOW);digitalWrite(3, LOW);return 0;}
Little improvements abound in this re-write.
It’s barely 100 lines long, but it’s an opportunity to get back into good C++ coding habits and to stay there than go off with a new, and unknown-to-me language.
]]># This is an example blink data file# These are comments that can be added to the # data file.## Values are simple: a hex value with the bit pattern# to turn on or off an LED (1 = on, 0 = off) followed# by a delay in milliseconds.## For example: 0x5,50# 0x5 has the bit pattern 0101, meaning LED 0 is on,# LED 1 is off, LED 2 is on, and LED 3 is off# The wait is 50 milliseconds.# 0x0,500x1,500x3,500x7,500xf,500xe,500xc,500x8,500x0,500x8,500xc,500xe,500xf,500x7,500x3,500x1,50
The data are the same hard-coded values that were in the earlier C-based application, including the delay in milliseconds. You can add comments to the data file, as many as you want, anywhere, as long as the comments are on their on line. The comment character, a ‘#’, has to be the first character in the string, although you can have spaces in front of the ‘#’. Blank lines are also considered comments.
Here is the source to the more elaborate blink application.
#include <wiringPi.h>#include <boost/algorithm/string.hpp>#include <boost/tokenizer.hpp>#include <iostream>#include <fstream>#include <sstream>// The data structure and collection into which// we'll place our LED data and millisecond delays.struct glyph {unsigned int data = 0; // LED dataint delay = 0; // in milliseconds};std::vector<glyph> glyphs;void loadBlinkData(std::string fileName) {std::ifstream inFile;std::string inLine;inFile.open(fileName);glyphs.clear();while (std::getline(inFile, inLine)) {boost::trim(inLine);// Skip comments and empty lines.//if (not inLine.length() || inLine[0] == '#') {continue;}// It's not a comment or empty line, so tokenize the lines// using the comma that separates the values.//boost::tokenizer<> tokens(inLine);glyph g;std::stringstream ss;for(auto &&token: tokens) {if (token.find("x") != std::string::npos ortoken.find("X") != std::string::npos) {ss << std::hex << token;ss >> g.data;}else {g.delay = std::stoi(token);}}glyphs.push_back(g);}inFile.close();}int main () {wiringPiSetup();pinMode(0, OUTPUT);pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);loadBlinkData("blinkdata.csv");for (int i = 0; i < 5; ++i) {for (auto &&g : glyphs) {// Just a series of shifts and ANDs// to create the bit necessary to// write out to the GPIO pin.//digitalWrite(0, g.data & 0x1);digitalWrite(1, (g.data >> 1 ) & 0x1 );digitalWrite(2, (g.data >> 2 ) & 0x1 );digitalWrite(3, (g.data >> 3 ) & 0x1 );delay(g.delay);}}// Turn everything off.//digitalWrite(0, LOW);digitalWrite(1, LOW);digitalWrite(2, LOW);digitalWrite(3, LOW);return 0 ;}
The big change is he addition of the loadBlinkData(…) function in place of the hard coded blink data in the prior application. This is where I switched from C to C++ to take advantage of some of C++’s and Boost’s features to both parse the text file as well as store up the parsed results. The main functionality has changed very little.
The datafile name is hard-coded as “blinkdata.csv”. I could have gotten more elaborate and written code to handle command-line input, but I was more interested in writing the parser. Perhaps later.
I am of a very mixed mind about the use of C++. I could have written the parser in a more straight-forward manner with Go’s built-in string package. Instead I had to go rummaging around Boost’s library (and install it) to keep the code down to a readable minimum. The for-each construct was nice to use, allowing me to hide explicit iterator declarations and concentrate on the collection and its individual elements. I also used the C++11 auto keyword and rvalue references (‘&&’), which simplified for-loop coding in significant ways. So C++ has evolved in some very useful ways. But really, the depths I go to to write code on such an itty-bitty machine in C++.
I decided to use C++ because the promise of the Go GPIO frameworks haven’t turned out to work for me. That’s not because of any limitation in the foundational languages. Arch Linux ARM for ARMv7 has native Go v1.6.2 packages, and using yaourt, I installed Rust 1.8 and Cargo. For Python, I have both versions 2.7.11 and 3.5.1. GCC comes out-of-the-box at version 6.1.1, meaning it has full support for C++11. Boost, via pacman, is at version 1.60.0. So I have all the necessary, native, up-to-date language tools that any software folk could want, running natively on my Raspberry Pi 3. When used for other non-trivial applications they seem to work just fine. It’s when I try to mix in libraries and frameworks that I run into issues, except, it would appear, for Wiring Pi’s libraries. And, of course, for node.js and onoff, using Javascript.
I know I wrote earlier about how I’d “permanently” moved to Raspbian. Well, after a bit of a hiatus away from the Raspberry Pi, I decided to go back and give Arch Linux for ARM another whirl. This time I haven’t had any issues, which may be due to my better understanding of how to use Arch, and possibly, just possibly, better quality in the Arch Linux ARM distribution itself. So I’m a happy Arch user again.
And before I forget, here’s the makefile I now use to build this thing. I hate makefiles, which is why I so wanted to use Go’s build or Rust’s cargo system. Anyway…
CC = g++LDFLAGS = -lwiringPiCPPFLAGS = -WallTARGET = blinksall: $(TARGET)clean: $(TARGET); rm $(TARGET)$(TARGET): $(TARGET).c; \$(CC) $(LDFLAGS) $(CPPFLAGS) -o $(TARGET) $(TARGET).c]]>
My second little C-language app using Wiring Pi as the enabling framework. This one flashes the LEDs in a more elaborate pattern and uses bit patterns in a byte array that we move down. The bit patterns in the low nibble of each byte allow any (or all) of the LEDs to be turned on or off. Code follows.
#include <wiringPi.h>// Instead of hard coding a blink pattern, we use bit patterns in a byte// array, which can be set to any low nibble value. A '1' turns on an LED// in that corresponding position, a '0' turns it off.//static unsigned char glyphs[] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0xe, 0xc, 0x8, 0x0, 0x8, 0xc, 0xe, 0xf, 0x7, 0x3, 0x1 };int main () {wiringPiSetup();pinMode(0, OUTPUT);pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);for (int i = 0; i < 20; ++i) {for (int j = 0; j < sizeof(glyphs); ++j ) { // Just a series of shifts and ANDs to create the bit necessary // to write out to the GPIO pin.//digitalWrite(0, glyphs[j] & 0x1); digitalWrite(1, (glyphs[j] >> 1 ) & 0x1 );digitalWrite(2, (glyphs[j] >> 2 ) & 0x1 );digitalWrite(3, (glyphs[j] >> 3 ) & 0x1 );delay(50);}}// Turn everything off.//digitalWrite(0, LOW);digitalWrite(1, LOW);digitalWrite(2, LOW);digitalWrite(3, LOW);return 0 ;}]]>
I’ve been hunting lately for code examples for manipulating the peripherals on the Raspberry Pi, all three versions. Up to this point I’ve been able to work with the peripherals, especially the GPIO pins, using node.js and onoff. But I was looking for something that was more self contained, with the idea I could build it into a stand-alone executable for deployment. I’ve been investigating many projects such as Gobot and embd. Unfortunately, after going to a lot of trouble, such as installing Go 1.6.2 (the current release) and git, and doing pulls for both from Github, and building simple applications using both frameworks, nothing worked for me.
So I went off looking for any C/C++ frameworks and examples, and came across Wiring Pi. From there I downloaded and installed their C framework, and modified one of the C examples, to replicate the Cylon LED cycle I first wrote in Javascript using node.js and onoff. Here’s the sample C code.
#include <wiringPi.h>int main () {wiringPiSetup();// These pins correspond to GPIO 17, 18, 27 and 22.//pinMode(0, OUTPUT);pinMode(1, OUTPUT);pinMode(2, OUTPUT);pinMode(3, OUTPUT);for (int i = 0; i < 20; ++i) {// We'll scale up...//digitalWrite(0, HIGH); delay(50); digitalWrite(0, LOW);digitalWrite(1, HIGH); delay(50); digitalWrite(1, LOW);digitalWrite(2, HIGH); delay(50); digitalWrite(2, LOW);digitalWrite(3, HIGH); delay(50); digitalWrite(3, LOW);// ... then appear to scale back down with the middle two// LEDs. LED 0 will then turn on at the top of the loop// completing the illusion.//digitalWrite(2, HIGH); delay(50); digitalWrite(2, LOW);digitalWrite(1, HIGH); delay(50); digitalWrite(1, LOW);}// Make sure to turn everything off.//digitalWrite(0, LOW);digitalWrite(1, LOW);digitalWrite(2, LOW);digitalWrite(3, LOW);return 0;}
It compiles and works as long as I run it with sudo. So right now, by relaxing some of my requirements (implemented in Go, stand-alone binary, must not use sudo) I have something other than Javascript that works. I’ll investigate further to see if I can create a parallel implementation in Go, or possibly even Rust. I prefer Go over Rust because there’s an Arch Linux ARM package for ARMv7 and later that’s up to date. Tooling under Arch on ARM is excellent, and I’d rather use as much pre-existing languages if possible.
Again it’s late and I’m tired and tomorrow is another workday. The three-day Memorial weekend is coming up; hopefully I can be a bit more verbose about these subjects.
]]>You’re looking at my second Raspberry Pi 3. It arrived in the mail yesterday along with a case and a version 2 camera module. The new RPi 3 replaces the older RPi 2 I photographed just a few days before. Turning on the RPi 3 was as easy as pulling the micro SD card with Arch Linux out of the RPi 2, plugging it into the new RPI 3, powering it up, and sshing into the new machine. I was very impressed with how the WiFi configuration for the RPi 2 worked for the RPi 3. The Linux kernel detected and used the proper driver for the WiFi hardware built into the RPi 3. It was so simple.
It’s late and I’m tired, and another long day awaits tomorrow.
]]>I spent a bit of time today getting my various Raspberry Pi boards up to snuff. I worked with one Raspberry Pi 2 Model B V1.1 (in the foreground) and my newer Raspberry Pi 3 Model B V1.2 (background). Both boards are back to using Arch Linux ARM, my comments about going off on a tangent with Raspbian not withstanding. I’m using the RPi 3 as a “build system”, transferring binaries to the RPi 2. Specifically I’m writing code with Google’s Go (golang). The compilation of Go code on the RPi 3 is quite fast. Test Go binaries are secure copied (scp) from the RPi3 to the RPi2 for testing.
I’d written earlier on this blog about trying to use Go on the older Raspberry Pi B+, back when Go was around version 1.4, and back when there were no installable packages for Arch Linux ARM. Because of Go’s lack of full native support on ARM at that time I went off and used node.js and the onoff package to write code in Javascript to manipulate the GPIO pins. That experimentation proved quite successful. But I wanted the same capabilities using Go if at all possible for one very important reason: Go compiles down to a single binary that doesn’t need a special runtime and supporting packages to be installed.
Recently I came across Embd, a Golang-based framework for manipulating all of a Raspberry Pi’s peripherals. It also claims to perform the same way on the Beagle Bone Black, another strong attractor for me as I have a BBB as well. I installed Go V1.6.2 (the latest release) using the standard Arch Linux ARMv7 packages. git was also installed on the RPi3, so I grabbed a copy of embd on Github (go get github.com/kidoman/embd). Once that was accomplished I started to write simple Go applications and tried to see how it operated. And I ran into more than a few problems getting it to work.
An example of a problem I ran into, and my solution to prove that at least a part of embd works, was the sample application fullblinker.go. It’s a test application that’s supposed to toggle the green LED, next to the red power LED, on the corner of the RPi board. As originally delivered it turned the LED on, but it was a solid light, not blinking. After rummaging around a bit in the source, I modified fullblinker to actually blink the LED on the RPI3, then copied it over to the RPI2 and tested it successfully as well. The photo above shows the on state of the LED during the blink test.
// +build ignore// LED blinker, works OOTB on a RPi.package mainimport ("flag""os""os/signal""time""github.com/kidoman/embd"_ "github.com/kidoman/embd/host/rpi")func main() {flag.Parse()if err := embd.InitLED(); err != nil {panic(err)}defer embd.CloseLED()led, err := embd.NewLED(0)if err != nil {panic(err)}defer func() {led.Off()led.Close()}()quit := make(chan os.Signal, 1)signal.Notify(quit, os.Interrupt, os.Kill)defer signal.Stop(quit)var isOff bool = truefor {select {case <-time.After(250 * time.Millisecond):if isOff {isOff = falseif err := led.On(); err != nil {panic(err)}} else {isOff = trueif err := led.Off(); err != nil {panic(err)}}case <-quit:return}}}
The changes I made to the code are highlighted above. I had to replace the Toggle() function with logic that maintained the LED on or off state, and explicitly call the On() and Off() functions (highlighted lines 43 to 53). Once flashing, this at least validated part of embd. One requirement for running fullblinker is the need to run with sudo (as root), which I’d managed to eliminate with the onoff nodejs GPIO application by using a special group with udev rules. Which appears to cause additional complications with embd, as none of the embd GPIO examples work, failing with a “write /sys/class/gpio/export: device or resource busy” error message. I’ve yet to dig into that problem, but I have several ideas on how to proceed to debug the issue.
embd is a start, along with node.js and onoff. I much prefer how the Javascript application was easy to set up, and I’m mulling over the idea of replicating the Javascript API in spirit to an equivalent GO framework, using what I can pick up from embd.
At this point you’re probably asking why bother? It’s so boring, so mundane. When Google talks about it’s AI TPU, or the net chatters about the rivalry between VR platforms, writing at this low a level on a $35 computer seems like such a waste of time. I can assure you it isn’t. Sooner or later you get back down to this level, and if it doesn’t work at this level then everything further up the stack goes to shit. One major driver to my working on this is my deep appreciation of the Go language, and my desire to use it here. Once I get it working to my satisfaction I’ll have tools that I can build upon, and perhaps something I can share back with the community. I’m just a regular engineer, not a disrupter, and as the Guardian once wrote, it’s the regular people who keep the world afloat.
]]>These are early days for me, but I’ve managed to get Docker up and running on my Raspberry Pi 3 (quad core 1GHz ARMv7 (v7l), 1GB DRAM). I’m running Arch Linux. Here’s what ‘cat /proc/version’ shows:
Linux version 4.1.21-1-ARCH (builduser@leming) (gcc version 5.3.0 (GCC) ) #1 SMP Wed Apr 6 19:29:49 MDT 2016
In order to get Docker installed I ran ‘sudo pacman -S docker’ followed by ‘sudo systemctl enable docker’ followed by ‘sudo systemctl start docker’.
I have yet to learn how to create a container, but I have found at least one to download and run within my Raspberry Pi. I executed ‘sudo docker run -d -p 80:80 hypriot/rpi-busybox-httpd’. This starts a little httpd server which can be reached by any local web browser (i.e. inside the home network). For example, using Vivaldi:
You can read more about this particular container here: Getting started with Docker on your Raspberry Pi
Once up and running, there are some simple CLI commands to monitor and control what’s running:
There is more to come, but for now this is a decent start. Software is installed and from what I can determine by examination the Raspberry Pi 3 is doing a decent job running Docker and at least one container. Not bad for a $35 computer.
]]>sudo node cylon.js
That kicked off the application and allowed me to flash those LEDs back and forth.
Turns out that there’s a straightforward way to do all this without root or rootly powers, using the granularity built into Linux. These are the straightforward steps to run GPIO applications as a regular user. Note that I’m using Arch Linux and the account is ‘alarm’. The following changes are made as root (su to root).
The rules to be placed into the 99-gpio.rules file are:
SUBSYSTEM=="bcm2835-gpiomem", KERNEL=="gpiomem", GROUP="gpio", MODE="0660"SUBSYSTEM=="gpio", KERNEL=="gpiochip*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys/class/gpio/export /sys/class/gpio/unexport ; chmod 220 /sys/class/gpio/export /sys/class/gpio/unexport'"SUBSYSTEM=="gpio", KERNEL=="gpio*", ACTION=="add", PROGRAM="/bin/sh -c 'chown root:gpio /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value ; chmod 660 /sys%p/active_low /sys%p/direction /sys%p/edge /sys%p/value'"
Once all the group and account changes have been made and the rules have been added, reboot the Raspberry Pi.
The two key features to making this work are (1) the new group, gpio, and (2) the udev rules that allow anyone who is a member of the gpio group to access /dev/gpiomem, where the GPIO pins are individually accessed. With these changes in place I no longer have to run as root or type ‘sudo’ before any application that accesses the pins because the alarm account is now a member of the gpio group.
There may very well be an Arch Linux package that does all this for you automatically, but I haven’t found it yet.
]]>This is the Cylon test I created for my original personal Raspberry Pi work over two years ago (see testing gpio with node.js and onoff, February 2014) except this time I executed it on the Raspberry Pi 3, not the original Raspberry Pi. In order to make clear what I did to run this from the RPi3 side, here’s what I installed on Arch Linux via pacman:
I was happy to see that the Arch Linux ARM repositories carried the latest node.js and npm, versions 5.8.0 and 3.8.1 respectively. I used npm to install a local copy of onoff. I needed gcc and make because npm builds part of onoff locally during installation.
This test actually uses the code I posted (and am reposting) back in March 2014. I’m going to use the i2c and port expanders for key input. But for testing the output I use the following simple code:
// cylon.js - JavaScript application to flash four LEDs in// a 'cylon' like fashion from side to side.// Requires node.js and onoffvar Gpio = require('onoff').Gpio, // Instantiate the onoff.Gpio instance.led1 = new Gpio(17, 'out'), // Export GPIO pin #17 as output.led2 = new Gpio(18, 'out'), // Export GPIO pin #18 as output.led3 = new Gpio(27, 'out'), // Export GPIO pin #27 as output.led4 = new Gpio(22, 'out'), // Export GPIO pin #22 as output.iv1,// Function to be called periodically.shifter = 1,// Bit to shift back and forth.multiplier = 2; // Determines shift direction.// This sets up the periodically called function.// Function is called every 50 milliseconds (see end of setInterval(...)// A single bit is shifted low to high, then high to low, and used via// and AND mask, to either turn the LED on (bit is '1') or turn the LED// off (bit is '0'). This single bit, moving back and forth across four// bits, is used to turn on a single LED, giving the illusion of the LED// moving back and forth, like the Cylon head visor in the original// Battlestar Galactica series (which I personally found more enjoyable// than the reboot).iv1 = setInterval(function() {led1.writeSync(shifter & 1 ? 1 : 0); // 1 = on, 0 = offled2.writeSync(shifter & 2 ? 1 : 0);led3.writeSync(shifter & 4 ? 1 : 0);led4.writeSync(shifter & 8 ? 1 : 0);shifter *= multiplier;if (shifter > 4) multiplier = .5;if (shifter < 2) multiplier = 2;}, 50);// Stop blinking the LEDs and turn them off after 10 seconds.setTimeout(function() {clearInterval(iv1); // Stop blinkingled1.writeSync(0); // Turn LED off.led1.unexport();// Unexport GPIO and free resourcesled2.writeSync(0); // Turn LED off.led2.unexport();// Unexport GPIO and free resourcesled3.writeSync(0); // Turn LED off.led3.unexport();// Unexport GPIO and free resourcesled4.writeSync(0); // Turn LED off.led4.unexport();// Unexport GPIO and free resources}, 10000);
With node.js and onoff installed type ‘sudo node cylon.js‘ at the prompt to execute.
The reason I’ve gone back to node.js is because the split that occurred nearly two years ago has been healed between the Node group and io.js, the fork. Things are back to a better state.
The video at the top was created using an Olympus E-M5 Elite and an M.Zuiko 12-40mm PRO zoom in manual focus mode, zoomed out to 40mm. The manual focus eliminates the constant and annoying in-and-out automatic refocusing of the first video I took of the Cylon lighting effect. The output was edited with iMovie on my iPad Air 2. Get used to the trippy little background music, as I’ll be using it on other similar technical videos in the future.
This post concludes my breaking-in of the new Raspberry Pi 3. It also is the start of a small break in RPi3 related work as I start heading back to my regular job. The next posts will be a bit more sophisticated and unique from any prior work.
]]>I chose TWM because it’s the simplest desktop environment and has one of the smallest footprints if not the smallest. On a machine such as the Raspberry Pi 3 with its fixed memory size of 1GB (which is hard-wired into the card and can’t be upgraded, not even with a plugin extension), what the RP3 (and all its predecessors) required of their human programmers was an understanding of its limitations helping to choose the best applications to run on the card. Ever since I bought and powered up the first generation, I’ve always sought software that demanded as little resources as possible, especially memory. TWM, of all the DEs I’m familiar with, demands the smallest memory footprint of all. The screen shot above, the one I used in an earlier post, ran overnight for 14 hours, with the three xterms on the desktop, and top (or htop in this instance) running in one of the windows.
Looking at the upper left corner of the htop terminal, you’ll note that only a fraction of the .9GB (out of 1GBl; remember that part of this is shared and used by the GPU). You should also note that swap hasn’t been touched. In all other distributions and versions I’ve used in the past, some sort of cron job would kick off or the DE would make much more demands of the memory. To be honest I’m not sure that swap is enabled here; after looking at the screen capture I need to go check that. Regardless, the memory footprint of the OS and DE are quite small after 14 hours, something for an embedded computer I’m quite appreciative off.
And this brings up a final point. Eventually I want to tuck this computer into a corner somewhere and not worry about it. Not forget about it, but get it to the point where I don’t have to worry that it’s run out of memory and swap and locked up horribly. I can reach that goal with a custom executive or other non-Linux runtime, but that costs hard cash up front as well as on-going royalties. That’s not a problem if you’re creating a commercial product in which a computer is just an out-of-sight appliance. But for someone such as myself, with no resources, I need to carefully choreograph all of this to create something that I could sell with a clear conscious. I also want to point out that this is not a general purpose computer that would require something like Raspian, that might run Libre Office (and a lot of other applications that are in that distributions). TWM is little more than a light-weight xterm manager, if you will. I could not even install all the X packages to support TWM and just live within the seven virtual logins provided by the ALT function keys, something I did for a number of years when Linux was first released. The DE for my use is thus a means to an end, not an end unto itself, and it doesn’t need all the fancy features that all other contemporary DEs have accumulated over the years. TWM is just fine for my purposes.
]]>This is probably one of the lamest posts I’ve ever written. I leave it here as example of how far into the weeds I tend to get. If you want to use macOS (as it’s now known) to support Raspberry Pi development, and in particular to program Linux images onto micro SDHC cards, then download balena Etcher from https://www.balena.io/etcher/ and install it. Etcher is extremely easy to use, walking you through the three steps necessary to create a bootable image on a card. Don’t do what I did below; that’s just an absolute waste of time.
You’re viewing CentOS 7 running in VirtualBox 5.0.16, with a micro SDHC card mounted and in turn viewing the Arch Linux ARM ext4 native Linux filesystem I created for my RP3. When I originally created the RP3 micro SDHC card I used my Ubuntu 15.10 notebook as the workbench. But I’ve been wanting to do similar work using my MBP as the primary tool bench, with an eye towards retiring the native Ubuntu notebook with the MBP due to the Ubuntu notebook’s age, rather than attempting to replace the Ubuntu notebook as I’ve written I originally wanted to do. The biggest hurdle to using the MBP was just reading the native ext4 file system on the MBP, as Max OS X has no native provisions to read Linux file systems. This post is about getting to that point. As time goes along I’ll be doing more than just reading the microSDHC, but reading (and then writing) is the foundational requirement, else this is all a waste of time and resources.
Before I go much farther let me properly attribute this from another post, “Mount SD card in VirtualBox from Mac OS X Host,” written by Brady Holt on 21 July 2014. Please note this was done nearly two years ago. This is an update to his post using contemporary software and with my observations.
Software and hardware I’ll be using:
I’m going to create a Linux VM with VirtualBox and use that to mount and at least read the micro SDHC card with the Arch Linux ARM ext4 file system. I had originally looked for a Mac OS X utility to do this, but eventually gave up as the utilities that claimed they could do that had allegedly stopped working with the release of El Capitan because of System Integrity Protection, or rootless, mode. Far be it from me to disable in El Capitan what is supposed to add additional security to OS X. I’m somewhat surprised that I could get this to work, but I suppose that if, at some point in the future, Apple releases a Mac OS X update that breaks what I’ve built here that I’ll be back to using a separate Linux machine.
The first step is to install VirtualBox and then to install CentOS 7 within a VirtualBox VM. I won’t cover that here, as there are plenty of existing how-tos for that. Just make sure that the Virtual Box Extension Pack is installed and that you’ve downloaded and installed the VBoxGuesAdditions and have built it within the VM. That gets everything prepared both on the OS X host side as well as within the VM.
The next step is to get the overall system prepared to mount the RP3 micro SDHC card within the CentOS 7 VM.
One caveat. If you shut down the VM and then want to bring it back up, you’ll need to unmount the microSDHC card like before and execute chmod 777 /dev/disk# again, or the VM will fail to start due to lack of permissions on the raw device.
]]>I surprised myself by how little time and effort was required to bring TWM and X back up on Arch Linux running on the RP3. This time around I didn’t try to install any other DE, just TWM. I had copies of my earlier TWM setup on my Ubuntu notebook, so I was able to simply mount the boot volume and make copies into the alarm account. I’ve had to make some minor tweaks to .twmrc, specifically disabling AutoRaise on everything. I discovered that automatic raise where the window pops to the top as soon as the mouse passes over it was a real annoyance, not the nice feature I thought it was in earlier incarnations. I also discovered I had to disable it because I couldn’t fully resize the xterm window. Now everything is back to something useful.
Here’s the list of packages I installed:
Support packages I also installed:
To support WiFi, I installed
After installing for WiFi, I did the following
I need to dig a little deeper into TWM. In particular I want TWM to remember what windows were up and running from prior sessions so that when I start TWM via startx the desktop comes back up the way I want it. I can hard-code some windows and their positions, but I want something more dynamic from session to session. I’ve also NOT installed emacs and medit, as vim is just fine, thank you very much. All I need to install now to get back to where I left off a while back is node.js and its various support packages for GP i/o. Then I need to move on to more than just flashing lights. Something a lot more IoT-ish, something that’s robust against many of the malevolent actors currently out on the Internet (Russia, N. Korea, Iran, NSA, FBI, and GCHQ, just to name a few).
I’m also thinking of creating and supporting a disk image that others can download with all these in place. I tried this once before but gave it up because of the original Arch Linux disk image. But that official disk image is no longer supported. Getting Arch Linux on a Raspberry Pi requires sophisticated Linux skills and experience, way beyond the typical beginner of a Raspberry Pi. This time, unlike the first time, it will be a complete basic install with GP i/o, WiFi, and TWM support installed. I’m also going to support a full 32GB image (compressed via ZIP for easier download).
I’m also going to support the older RP2 while the code still can. Once Arch Linux ARM officially goes 64-bit for RP3, then I’ll probably drop support for RP2.
I’m still playing catchup. Sorry for repeating things here I wrote about over the past few years, but at least it’s been tested with the latest Raspberry Pi 3 board.
]]>Rather than spend an inordinate amount of time trying to debug Raspian I grabbed the second of my 32BG Samsung micro SDHC cards and following the directions on the Arch Linux | ARM wiki, I created a bootable Arch Linux card and brought up the RP3 under Arch Linux for ARM. The current page for the RP3 instructions states up front this is the older 32-bit ARM release. Because this is a bare-bones distribution compared to Raspbian, the RP3 needed to be hard wired into my network in order to update the distribution as well as install additional packages, such as support for WiFi. I should note that it was simple to install Arch Linux WiFi support, and when it was installed, it enabled the RP3’s internal WiFi network. Once that was up and running I pulled the network cable and carried on.
I installed the same packages for the RP3 as I did for the original Raspberry Pi, and when I went back to reboot it, I didn’t see the i2c buss. I did a little digging and discovered I had to edit the /boot/config.txt file on the RP3, making the following changes to the file:
With those three lines uncommented and with the necessary drivers installed from the earlier packages /dev/i2c-1 was finally enabled.
I should note that the same Arch Linux ARM micro SDHC card boots both the RP2 as well as the RP3.
I should also note that I needed to fix how the Apple aluminum keyboard worked as I documented here.
Because the RP3 requires more power than any other Raspberry Pi to date (5v at 2.5A), I’m using an Apple 12W USB power adapter. I’ve got more than a few around the house these days, and their output is rock solid and clean. So far it runs the bare bones system without anything else attached.
Next steps will be to install X and TWM. Or I just might use the seven virtual keyboards that work now (one of the benefits of a properly configured Apple keyboard).
I’m trying to move as fast as I can to catch back up to where I was back in 2014. I’m working towards an IoT framework around Arch Linux with baked-in encryption. For real this time.
And maybe, just maybe, add a dash of some of the CoreOS features that have caught my fancy. A lot has happened these past two years, and I have a lot of serious catching up to do.
]]>Unfortunately for me I couldn’t update Arch. The last time I updated Arch was back in October of 2014. Right after upgrading I created an image, zipped it up, and uploaded it to my Google Drive to share with all. After my failure to upgrade Arch I’ve deleted that image from Google Drive, and I’m now working exclusively with Raspbian Linux released December 2014.
In a way I’m actually glad to now be using Raspbian as opposed to Arch. All my other Linux-powered computers are running some variant of Debian, either Debian directly (Beagle Bone Black) or Ubuntu/Mint Linux (my notebook and virtual machines). While the GUIs might certainly differ, they’re pretty much the same down at the CLI level. Moving between the various machines isn’t as jarring when one of them is as different as Arch is.
The problem came when I tried to update Arch using ‘pacman -Syyu’. The update refused to execute, failing with some sort of version mismatch with pacman itself. After looking on various Arch forums and trying to use Google to find a solution, I decided that perhaps it was time to move over to Raspbian. And so I have. The only minor issues had to do with the Apple keyboard, and I’ve documented how to fix that with Arch. I’d already given an older version of Raspbian a dry run, and found that fixing the Apple keyboard for Arch was also the way to fix it for Raspbian.
I’m now in the process of getting my NodeJS environment rebuilt and getting ready to write some more controller software in Javascript. I’ll have more to post shortly.
]]>I spent some time today working with the latest Raspbian, tweaking it to work with my Apple keyboard.
Just as with Arch Linux (see “tweaking arch on the pi” from February) I had to fix the function keys, i.e. make them functional. Before that could happen, I had to fix the key mappings on the Apple keyboard by running ‘sudo dpkg-reconfigure keyboard-configuration’ and selecting English(US) mappings. For whatever reason they’re set for English(UK). Then I had to create the file /etc/modprobe.d/hid_apple.conf and add the line ‘options hid_apple fnmode=2’. Reboot, and I had a full US English Apple keyboard with working function keys.
One feature I fully appreciated in Raspian is its ability to set the time from the network, once the networking was properly configured. I got the wireless network running through the Lxde desktop and the graphical network utility. Once I had the wireless network connection set up, all further reboots set the time on the board. The board doesn’t have a battery-backed clock. With Arch Linux it always sets to 1969 unless I run a simple script to execute ‘ntpd -q -g’ at startup, which I was forced to add myself.
Performance
Performance was a bit of a mixed bag. If I logged into the command line, Raspian seemed to execute faster and smoother than Arch Linux. But run the graphical desktop, first with LXDE and then XFCE4, and things got slower, many times annoyingly so. I did certainly appreciate the update to the Epiphany browser; it worked as well as advertised, but it also slowed considerably when it hit a site with a lot of complex features, such as this WordPress blog. I had hoped to write this update from the Raspian desktop, but I turned back to my workhorse Ubuntu system on the now-five-year-old Samsung R580 notebook to write this.
General Conclusions
Raspbian’s a good distribution for the Raspberry Pi B+, but for my tastes I think I’ll stick with Arch Linux for Arm. I had thought to try and unify all my Linux environments as much as possible around Ubuntu/Debian, but that won’t happen any time soon. My greatest concern outside of performance is drive footprint. Raspbian came out of the box consuming more drive space than Arch Linux, and I’ve been tinkering with Arch Linux since late January. When I installed Xfce, Raspbian’s overall footprint had grown to 2.7 GB, a good .5GB greater than Arch Linux, and that’s even after uninstalling Lxde from Raspbian.
]]>