Arduino for Visual Studio: Come Over to the Dark Side

As a guy who earns his living writing software in the corporate world, I’ve always felt a little out of place in the Arduino world.

The Arduino platform hardware and software is, to quote the Arduino home page, “intended for artists, designers, hobbyists, and anyone interested in creating interactive objects or environments“.

Good artists borrow code, great artists steal code, but no artist should have to write code.

And yet most do, or at least try to.  Coding is hard for beginners, and coding in C is not a great place to start.  Case sensitive names, mismatched parentheses, strongly typed variables: these are the things that trip up every newcomer, and there is no getting around them.   The minimalist Arduino IDE hides these issues, but it doesn’t solve them.

In fact, I feel that the Arduino IDE undermines the software side of Arduino projects by pretty much guaranteeing that beginners will quickly learn to hate programming.  Writing and debugging code in the Arduino IDE is time-consuming and frustrating: a drudgery of trial and error.

It doesn’t have to be this way!  Artists, designers, hobbyists: throw down your primitive tools and join the technological revolution!  Behold…  Arduino for Microsoft Visual Studio!!

No, seriously!

The Reason Not to Switch

OK, let’s get this over with.  Your reaction to this is probably one of 3 things:

1. Oh great, Microsoft.  How much is that going to cost me?

2. Oh great, Microsoft.  How long is that going to take me to learn?

3. #@*&! Microsoft!!!! You expect me to use a closed-source, over-engineered hairball sold by a shameless monopolist to cubicle-dwelling corporate drones??

The answers are:

1. Probably nothing

2. Less than you think

3. Bah, occupy this, hippy.

Clearly, I don’t have a good answer to the 3rd issue.   Yes, Microsoft makes tons of money, Visual Studio is never going to be open source, and it only runs on Windows.  If that’s a dealbreaker for you, then you can stop reading.  You may not want to know what you’re missing.

Cost and the Learning Curve

Visual Micro’s Arduino add-on requires Visual Studio Professional, not Visual Studio Express.  Back in the day, Microsoft targeted Visual Studio at large corporations, and it was priced accordingly.

Fortunately, that’s no longer true.  Visual Micro’s web page has details on how you can legally get a copy of Visual Studio for free.  Another option for young whippersnappers is Microsoft’s Dreamspark program for  students.

Don’t worry — it’s not a trick.  Over the last 10+ years, Microsoft has increasingly lowered the barrier to developers acquiring their development tools.  Microsoft is not being purely altruistic here.  Their motivation is to attract new developers to the cult platform — come over to the dark side, we have candy — but the end result is that Visual Studio is a lot easier to get than it used to be.

As for the learning curve, Visual Micro has done a good job at reducing to 3 steps the process of loading/creating a sketch and uploading it to your Arduino.   (I should mention that Visual Micro’s documentation is extensive — you don’t have to rely on blogs and forums to figure out how to use their product.)

Yes, Visual Studio is bristling with menus, toolbars and windows, but you can safely ignore 95% of them, just like you already do in Microsoft Word. The remaining 5%  of these features will, on the other hand, save you a ton of time.

Not convinced?  Let’s get into what I feel are the 6 coolest features in Arduino for Visual Studio.  Most of these will be familiar to anyone who’s used Visual Studio with other languages: the cool thing is that Visual Micro has brought them to the Arduino world.

1. Code Completion

Do you ever have trouble remembering what the exact syntax of an Arduino statement is?  Is it Serial.Print, or Serial.print, or Serial.Write?  What are the parameters.

Yeah, us professionals have the same problem.   A dirty little secret of our profession is that we tend not to memorize things unless we have to, and thanks to Code Completion in Visual Studio (and to Google), we rarely have to.

As you begin to type in a statement in Visual Studio, a pop-up list of options for completing the statement will appear.  Rather than typing the whole thing, just use the arrow keys to select the one you want, then click the Tab key to fill in the rest.

When you aren’t sure which one you want, just pause at one of the options and a tooltip will appear listing the parameters that the methods takes.

2. Error Highlighting

The process of correcting typos in the Arduino IDE is a tedious grind: build, decipher the error message, figure out what line of code its referring to, take a stab at fixing the error, build, repeat….

That’s the way we professionals coded software too, 20 years ago.  Then we smartened up, and put some effort into building better tools.

One result of this is on-the-fly error highlighting.  Each new version of Visual Studio has got better at this, and it’s now at a point that you can fix 90% of your errors before you get to the build stage.

And, of course, it’s a lot easier to figure out which line of code is wrong when it’s underlined for you.

3. Intelligent Search

The one-result-at-a-time search feature is another area where the Arduino IDE is about 15 years behind the state of the art.  Given that we’ve all learned to leverage search engines when looking for all sorts of answers, it’s puzzling that this hasn’t been improved.

There are lots of different ways to search for information in Visual Studio:

  • Need to quickly review the code that uses a variable?  This happens all the time: you aren’t sure whether its a string or number, or you aren’t sure what value you initialized it to, or you aren’t sure where its being read or updated in your program.  In Visual Studio, just right-click and select Find All References.  A window will open listing all the code that uses that variable.
  • Forgotten what a variable is called?  If you know part of the name, Visual Studio’s Find feature will list all the lines of code that contain a particular search string. Wildcards are supported.  Double-clicking on one of the search results will bring you directly to that line of code
  • You know that cool “search as you type” feature when searching for text on a web page, where the cursor automatically jumps to the first match as you type in your search term?  Visual Studio has that too: just type Ctrl-I to search.

4. Libraries: My God, it’s full of code!

Libraries are the Arduino’s greatest strength.  Brilliant coders have created packaged libraries to handle all the complicated stuff: reading and writing to devices, handling Strings, connecting to web sites, and so on.  You don’t know how they work, and you don’t care. They just work.

Except when they don’t.  When you call a library function, and it hangs, returns a generic error message, or does nothing, you’re left high and dry.  What’d I do wrong?  Wrong parameter? Wrong settings?  Google?!!

In Visual Studio, there are a few different ways to pull back the curtain and have a good look at the library you’re using.

If you right-click on a class or function and select Find Declaration, Visual Studio will automatically load it  into the editor.  Often, the comments added by the coder will give you the information you’re missing.  If not, have a look at the code.  Don’t be intimidated: if you can write it, you can read it.  Open source isn’t just a buzzword, you know?

In the Visual Studio Find In Files dialog, it you change the “Look In” field to “Current Project”, it  will list all occurrences of a variables, including ones that appear in libraries.  This is useful when you’re searching for a particular constant: you have an idea what you want, but you’re not sure what the exact spelling is.

Lastly, when you want to pull back and have a look at the bigger picture, the Object Browser lists everything about a library in one convenient place.   The left hand pane lists all classes in the libraries that are included in your project.  Selecting a class lists the functions in that class in the upper right pane.  Double-clicking on a function opens the library source code and takes you to the function definition

If you really want to blow your mind, turn on the “Show All Arduino Files” option, then check the Solution Explorer.  Yikes, where did all those files come from?  Those have all been in your project all along, covered by Arduino’s invisibility cloak.    You’ll probably want to leave the “Show All Arduino Files” setting off most of the time (I do), but it’s handy to be able to easily look through that code on the few occasions when you need to.

5. Serial Console: Not Just an Afterthought

The Arduino Serial Console has also seemed to me like something reluctantly tacked on to the software.  Arduino code is supposed to “just work”.  Who needs a debugger?  Why bother to put work into something that nobody’s going to use?

Visual Micro did put some work into their’s, and it has several nice features that Arduino’s lacks.

First and foremost, they’ve done away with that silly limitation of having to close the Console every time you upload code to the Arduino.   Debugging using print statements is hard enough: taking away that information every time you run your code is just nasty.  In Visual Studio, you don’t have to close the Console, ever.  When you transfer your code to the Arduino, the Serial Console quietly and automatically frees up the serial port, then reconnects when the transfer is done.

When you select some text in the Serial Console and right-click, a context menu lists all of your options: Select All, Copy, Cut, etc.. It’s a small thing, but a timesaver that any text window should have.

Another timesaver is the ability to quickly re-enter text by selecting it from a pull-down menu.  Trial-and-error debugging is always a pain, but being able to enter input in one click makes the trials less painful.

6. No Java

Java is beginning to rival Internet Explorer as software that is more trouble than it’s worth.  The passive aggressive auto-updater is bad enough, but malware authors are increasingly targeting Java as a means of sneaking their software onto PCs.  The only Java software I run is Arduino, so replacing the Arduino IDE has a major side benefit.

A lot of newcomers to Arduino get the impression that Java is central to Arduinos; some think that the Arduino programming language is Java.  In actual fact, Java and the Arduino are an odd couple.  Arduinos are coded in C++, the same language Visual Studio is written in, and a language that the Visual Studio IDE has supported for 15 years .  Visual Studio gets C++ in a way that a Java-based IDE cannot.   Visual Micro has done an amazing job at leveraging Visual Studio’s rich support for C++ development.

Wrapping Up

Arduino for Visual Studio has actually been around for awhile now, and I’d intended to write about it back in the spring.  It drifted off my radar when I stopped using the Arduino in my projects.

My main problem with the Arduino is the lack of debugger.   Trial-and-error debugging is a major time-waster.

Arduino for Visual Studio popped back up on my radar recently when Visual Micro released an Arduino Debugger for beta testing.  If you thought “Visual Studio for Arduino” was an odd-looking phrase, how about “Arduino Debugger”?  This is a software debugger, with no need for JTAG or other hardware add-ons, something I had previously thought impossible.  It’s not such a crazy notion, though.  Like I said earlier, Visual Studio is closely integrated with C++, and its debugger has been connected to various C++ runtimes.    Visual Micro has figured out how to connect the Arduino to it.

An Arduino debugger, integrated into Visual Studio,  is a potential game-changer, something that will make it possible to do a lot more ambitious coding projects in a lot less time.  I’m eager to give it a try.  If you are too, head over to Visual Micro’s web site and read all about it.

Posted in Electronics, Programming | Tagged , | Leave a comment

Beaglebone Coding 101: SPI Output

It’s been too long since my last “Beaglebone Coding 101″ article.  Perhaps many of you have graduated to Beaglebone Coding 201 by now, but I’m going to continue with the 101 level for us less gifted students.

I’ve been experimenting with SPI and I2C on my Beaglebone lately.  When I first tried using them at the beginning of the year, I found they required a level of Linux Kung Fu that was beyond me.  However, both of these protocols are now supported from “userland” applications  in both Angstrom and Ubuntu.  A Google search turns up plenty of working examples for SPI and I2C on the Beaglebone, along with some more advanced projects.  I think the water’s safe safe for the rest of us.

I’m going to begin with SPI.  Ultimately I’ll be using a graphical LCD, specifically an Adafruit ST7565-based LCD, but in this article I’m going to use a simpler character LCD backpack, also from Adafruit, that uses the popular and well-documented 74HC595 SPI chip.

Beaglebone Connected to SPI LCD
Beaglebone Connected to SPI LCD

My coding language of choice is Python.  I really wanted to do this in Bonescript instead, since I like Jason Kridner’s idea of using it as a way for Arduino coders to ease into the embedded Linux world. Unfortunately, I haven’t found the time to get the hang of coding in node.js.  Bonescript has added SPI support through a shiftOut method.  If you’re interested in learning how to use SPI with Bonescript, I’d recommend Ken Keller’s blog and Github code library.

Updating the Kernel

SPI has been supported in the Angstrom kernel for awhile now, and was added to Ubuntu’s kernel relatively recently.  A quick way to check if you have SPI support is to look in the /dev directory:

ubuntu@omap:~$ ls /dev/spi*
 /dev/spidev2.0

Note that bus 2, device 0 is the only option available to “userland” code in the current Angstrom and Ubuntu kernels.  Multiple SPI buses and devices are possible, but require that you build a custom kernel.

If you don’t see an SPI device in the /dev directory, you’ll need to upgrade your kernel.  If you are running Angstrom, either download a new image (I use the top entry on the Beaglebone demo files page), or follow the instructions in the “Enabling PWM Support in the Kernel” section of my Buttons and PWM article.

[Update Sept 11: I just noticed that Angstrom kernel 3.2.28 was automatically enabled on my Beaglebone when installed via opkg. I didn't have to manually copy the uImage file onto the boot partition, just reboot.   Whoa!  

I'm using the 2012.08.14 image from the Beaglebone demo files page.  I'm not sure yet whether this feature is only to be found in newer Beaglebone images. If you find that the latest kernel isn't automatically installed for you, then you'll have to manually update it as described in the Buttons and PWM article.]

If you’re running Ubuntu, see my recent article on updating the kernel.

(If you’re running Android or another OS, sorry, dunno :-( .)

Adding an SPI Extension Module to Python

If you Google Python SPI, you’ll find various references to a C extension for Python, py-spi.  It was written back in 2009 by Volker Thoms, but as far as I can tell its still the best method for giving Python full access to SPI on Linux.

The module consists of  C code with Python bindings, spimodule.c.  It limits the amount of data being sent to 32 bytes, and the speed to 8 Mhz — both unnecessarily low limits on the Beaglebone — but for now we’ll use it as-is.  We’ll need to lift those limitations later when we use it with an SPI graphical LCD.

(If you’d rather avoid building the extension on your Beaglebone, I’ve built binaries for Angstrom and Ubuntu.  See the Python Extension Binaries section below).

Before we can install it, we need the python-dev package.

On Angstrom

opkg update
opkg install python-dev

On Ubuntu

sudo apt-get update
sudo apt-get install python-dev

To install the py-spi module, you’ll need to download a few files into any directory on your Beaglebone:

wget http://elk.informatik.fh-augsburg.de/da/da-49/trees/pyap7k/lang/py-spi/src/setup.py
wget http://elk.informatik.fh-augsburg.de/da/da-49/trees/pyap7k/lang/py-spi/src/spimodule.c

Note: if you have problems downloading these files (I downloaded them without problems a few weeks ago, but got 0-length files when I tried today), you can download my slightly customized versions instead:

wget http://gigamega-micro.googlecode.com/files/setup.py
wget http://gigamega-micro.googlecode.com/files/spimodule.c

If you download the original setup.py, you’ll need to make a couple of changes to the setup.py file.  (You can skip this if you download my customized version). The original looks like this

#!/usr/bin/env python
from distutils.core import setup, Extension
setup( name="spi",
 version="1.1",
 description="Python bindings for Linux SPI access through spi-dev",
 author="Volker Thoms",
 author_email="unconnected@gmx.de",
 maintainer="Volker Thoms",
 maintainer_email="unconnected@gmx.de",
 license="GPLv2",
 url="http://www.hs-augsburg.de/~vthoms",
 include_dirs=["/usr/src/linux/include"],
 scripts=['scripts/93LC46_LAtest.py','scripts/93LC46_test2.py',
'scripts/93LC46_test.py','scripts/ds1305_test.py',
'scripts/mcp3304.py','scripts/mcp3304_test.py',
'scripts/mcp4922.py','scripts/spitest3.py'],
 ext_modules=[Extension("spi", ["spimodule.c"])])

We’ll need to change the include_dirs line to match the correct location of the Linux include files, /usr/include.  Otherwise, when you compile on Angstrom you’ll get an error “no include path in which to search for limits.h“.  Incidentally, this appears to be one of those error messages for which Google returns 1000 explanations, none of them being this one.  I hate it when Google makes me think for myself!

We’ll also remove the scripts line, since we aren’t using those files.  The setup.py should look like this:

#!/usr/bin/env python
from distutils.core import setup, Extension
setup( name="spi",
 version="1.1",
 description="Python bindings for Linux SPI access through spi-dev",
 author="Volker Thoms",
 author_email="unconnected@gmx.de",
 maintainer="Volker Thoms",
 maintainer_email="unconnected@gmx.de",
 license="GPLv2",
 url="http://www.hs-augsburg.de/~vthoms",
 include_dirs=["/usr/include"],
 ext_modules=[Extension("spi", ["spimodule.c"])])

To compile and install the Python extension, enter the following as root:

python setup.py install

On Ubuntu, you should get the following.  (The warnings won’t be there if you use my customized version – 10 points for Gryffindor!):

 
 running install
 running build
 running build_ext
 building 'spi' extension
 creating build
 creating build/temp.linux-armv7l-2.7
 gcc -pthread -fno-strict-aliasing -DNDEBUG -g -fwrapv -O2 -Wall 
  -Wstrict-prototypes -fPIC -I/usr/include -I/usr/include/python2.7
 -c spimodule.c -o build/temp.linux-armv7l-2.7/spimodule.o
 spimodule.c: In function ‘SPI_readbytes’:
 spimodule.c:156:7: warning: unused variable ‘addr’ [-Wunused-variable]
 spimodule.c: In function ‘SPI_xfer’:
 spimodule.c:204:10: warning: unused variable ‘ret’ [-Wunused-variable]
 creating build/lib.linux-armv7l-2.7
 gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,
  -Bsymbolic-functions -Wl,-z,relro 
  build/temp.linux-armv7l-2.7/spimodule.o 
  -o build/lib.linux-armv7l-2.7/spi.so
 running install_lib
 copying build/lib.linux-armv7l-2.7/spi.so -> 
  /usr/local/lib/python2.7/dist-packages
 running install_egg_info
 Removing /usr/local/lib/python2.7/dist-packages/spi-1.1.egg-info
 Writing /usr/local/lib/python2.7/dist-packages/spi-1.1.egg-info

An Extra Step on Angstrom

On Angstrom, you’ll run into a problem:

 python setup.py install
 running install
 running build
 running build_ext
 building 'spi' extension
 arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize
   -mthumb-interwork -mfloat-abi=softfp -mfpu=neon 
  -mtune=cortex-a8 -D__SOFTFP__ 
  --sysroot=/OE/angstrom-v2012-05/build/tmp-angstrom_v2012_05-eglibc/sysroots/beaglebone 
  -fno-strict-aliasing -O2 -pipe -g 
  -feliminate-unused-debug-types -DNDEBUG -g -O3 -Wall 
  -Wstrict-prototypes -fPIC -I/usr/include 
  -I/usr/include/python2.7 -c spimodule.c 
  -o build/temp.linux-armv7l-2.7/spimodule.o
 arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize
   -mthumb-interwork -mfloat-abi=softfp -mfpu=neon 
  -mtune=cortex-a8 -D__SOFTFP__ 
  --sysroot=/OE/angstrom-v2012-05/build/tmp-angstrom_v2012_05-eglibc/sysroots/beaglebone 
  -shared -Wl,-O1 -Wl,--hash-style=gnu -Wl,
  --as-needed build/temp.linux-armv7l-2.7/spimodule.o 
  -L/usr/lib -lpython2.7 -o build/lib.linux-armv7l-2.7/spi.so
 /usr/lib/gcc/arm-angstrom-linux-gnueabi/4.5.4/../../../../arm-angstrom-linux-gnueabi/bin/ld: 
  this linker was not configured to use sysroots
 collect2: ld returned 1 exit status
 error: command 'arm-angstrom-linux-gnueabi-gcc' failed with exit status 1

OK,  whose idea was it to use sysroots??  Anyone?

Actually, I have no idea who or what is telling setup.py to include that “sysroot=..” parm (another seemingly unGoogleable solution), so I just created stripped the sysroot part out of the compile and link commands:

arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 -D__SOFTFP__ -fno-strict-aliasing -O2 -pipe -g -feliminate-unused-debug-types -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/include -I/usr/include/python2.7 -c spimodule.c -o build/temp.linux-armv7l-2.7/spimodule.o
arm-angstrom-linux-gnueabi-gcc -march=armv7-a -fno-tree-vectorize -mthumb-interwork -mfloat-abi=softfp -mfpu=neon -mtune=cortex-a8 -D__SOFTFP__ -shared -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed build/temp.linux-armv7l-2.7/spimodule.o -L/usr/lib -lpython2.7 -o build/lib.linux-armv7l-2.7/spi.so

Having generated the object file, you can rerun python setup.py install to complete the process.

 python setup.py install

 running install
 running build
 running build_ext
 running install_lib
 copying build/lib.linux-armv7l-2.7/spi.so -> /usr/lib/python2.7/site-packages
 running install_egg_info
 Writing /usr/lib/python2.7/site-packages/spi-1.1-py2.7.egg-info

Python Extension Binaries

If above process left you totally confused, or simply didn’t work, you can try downloading a binary of my customized version of the Python extension.

If you’re running Ubuntu on your Beaglebone:

wget http://gigamega-micro.googlecode.com/files/spi.so.gz
gunzip spi.so.gz

If you’re running Angstrom:

wget http://gigamega-micro.googlecode.com/files/spi-angstrom.so.gz
gunzip spi-angstrom.so.gz
mv spi-angstrom.so spi.so

Writing to an SPI Device  from the Python Shell

Before running some Python code to write to an SPI-attached LCD, we can test the setup using an 74HC595 chip.  (If you don’t have a 74HC595 chip, you can skip ahead to the example Python commands: they would be basically the same for any SPI-controlled device).

The 74HC595 is commonly used as a GPIO-extender: by using the 3 SPI pins on the Beaglebone, we get 8 extra GPIO pins.  This isn’t a particularly attractive tradeoff on the GPIO-rich Beaglebone, but the 74HC595 makes a good testbed for playing with SPI before moving on to more sophisticated (and finicky) devices.

The HC74595 pinout looks like this, as taken from the datasheet.  You can find a thorough and easy-to-understand explanation of this chip on the Arduino web site.  Note that the latch pin, aka the Chip Select pin, is aaka the “storage register clock input” pin here.  Don’t ask me!

An easy way to test SPI output is by hooking by LEDs (through resistors) to each of the 8 GPIO pins on the 74HC595.

The following diagram shows this kind of setup. I used an LED bar instead of individual LEDs.  If you’re lazy and/or don’t have an LED bar or 8 LEDs, you can hook up a couple of LEDs — I’d suggest Q0 and Q 1 — and still verify that everything is working OK.

The Beaglebone pins involved in SPI Bus 1 are as follows:

  • Port 9 Pin 28 – Chip Select – connected to pin 12 of the HC74595 with yellow wire
  • Port 9 Pin 29 – Data 0 (aka MISO – Master In Slave Out) – unused in this project, but could be connected to pin 9 of the HC74595
  • Port 9 Pin 30 – Data 1 (aka MOSI – Master Out Slave In) – connected to pin 14 of HC74595 with green wire
  • Port 9 Pin 31 – Clock – connected to pin 11 of the HC74595 with white wire

The “master”, in this case, is the Beaglebone.  Since at this point we are only writing, not reading, we’ll leave Pin 29 unconnected.  This gives us the liberty of connecting the 74HC595′s voltage pin, Pin 16 (to the right of the chip’s semicircular imprint), to 5V if we want to make those LEDs sweat.  More usefully, it also allows us to safely connect the Beaglebone to SPI write-only devices that run at 5V, as we will with the LCD.  Do not connect Pin 29 to an SPI device running at 5V!

Note that the spidev2.0 device is identified as SPI1 in the System Reference Manual.  Note also that the pinmuxing for the SPI1 pins all default to SPI mode (mode 3).

Now that we have things hooked up, let’s fire up Python and send a command to the 74HC595.   Note that this needs to be done as root, so run sudo python if you are on Ubuntu:

root@beaglebone:# python
 Python 2.7.2 (default, Apr 27 2012, 09:45:45)
 [GCC 4.5.4 20120305 (prerelease)] on linux2
 Type "help", "copyright", "credits" or "license" for more information.


 >>> from spi import SPI
 >>> leds = SPI(2, 0)
 >>> leds.writebytes([0x00])

Even if you don’t know Python, you probably figured out that this should turn all of the LEDs off (by setting all of the 74HC595 pin’s low).  To turn the LEDs on:

>>> leds.writebytes([0xFF])

If that’s not working for you, check the wiring: aside from the GPIO pins, there are a bunch of pins on the 74HC595 that need to be connected to ground or to voltage, as shown in the figure above.

Let’s see which pins correspond to which bits:

>>> leds.writebytes([0x80])

This will set high the lowest GPIO pin on the 74HC595, Q0, which is connected to the leftmost LED in the circuit diagram and photograph.  Similarly, if we had written 0xC0, it would set Q0 and Q1 to high.  So, the data is sent LSB first — the opposite of what you might expect (but the same as the Arduino, by the way).  We’ll have to keep this in mind when coding.

Beaglebone connected to 74HC595. Yellow is SPI CS, green is Data, white is Clock.
Beaglebone connected to 74HC595. Yellow is SPI CS, green is Data, white is Clock.

Although we won’t need it when dealing with the 74HC595, sending multiple bytes of data is pretty simple from Python:

>>> leds.writebytes([0x01, 0x02, 0x03, 0x04])

Technically, that command turns on each of pins Q0 to Q3 in  turn, though of course it occurs too quickly to see any but the last one.

There are a bunch of other commands that are supported by the spi Python extension:

>> dir(SPI)
 ['__class__', '__delattr__', '__doc__', '__format__', 
'__getattribute__', '__hash__', '__init__', '__new__', 
'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', 
'__sizeof__', '__str__', '__subclasshook__', 'bpw', 'close', 
'cshigh', 'loop', 'lsbfirst', 'mode', 'msh', 'open', 
'readbytes', 'threewire', 'writebytes', 'xfer', 'xfer2']

I haven’t experimented with most of these, but 2 that are worth pointing out are:

  • writeBytes – writes a list of byte data, as shown in the example above.  The original spimodule.c had a hard-coded limit of 32 bytes, which I increased to 1024.  I don’t know what the practical limit is: 1024 is enough for my current uses.
  • msh – Sets the clock frequency.  For example, the following displays the clock rate being used in our connection to the 74HC595, then changes it to 1 Mhz.
>>> leds.msh
 8000000
 >>> leds.msh = 1000000

The default of 8 Mhz is actually the maximum clock rate allowed by the original spimodule.c code, though I removed that in the version I customized.

Having said all that, changing the clock rate is completely unnecessary for this project, either with the LEDs or the LCD. The 74HC595 is very flexible about the frequency (it supports up to 100 Mhz, and anything from 1 Mhz up worked fine when I tried it), and neither the LEDs nor  a character LCD require much bandwidth.  The speed setting will be more useful when dealing with graphical LCDs.

Writing to an I2C/SPI LCD Backpack from Python

Adafruit’s I2C/SPI LCD Backpack is a handy accessory for testing SPI and I2C.   It uses 2 common GPIO extenders ( the 74HC595 and, for I2C, the MCP20008) to connect to a standard character LCD, allowing you to test SPI and I2C without much wiring.  It’s also the cheapest LCD connector that I’ve seen: $10. I’ll be using it again in a future article about using I2C with the Beaglebone.

Assembly instructions for the backpack are at http://learn.adafruit.com/i2c-spi-lcd-backpack.  Note that, by default, it uses I2C, so you’ll need to put a blob of solder on the SPI bridge for use with the code below.

The 5 screw terminals on the backpack should be connected to the Beaglebone as follows:

  • LAT – Port 9 Pin 28 (i.e. Chip Select)
  • DAT – Port 9 Pin 30
  • CLK – Port 9 Pin 31
  • 5V – Port 9 Pin 5 or 6
  • GND – Port 9 Pin 1 or 2

Beaglebone connected to Adafruit I2C/SPI Backpack.  White is SPI CS (Latch), yellow is data, green is Clock.
Beaglebone connected to Adafruit I2C/SPI Backpack. White is SPI CS (Latch), yellow is data, green is Clock.

I’ve written some Python class modules to make it easy to write to a backpack-connected LCD:

wget http://gigamega-micro.googlecode.com/files/spilcd.py
wget http://gigamega-micro.googlecode.com/files/gmspi.py
wget http://gigamega-micro.googlecode.com/files/hd44780lcd.py
wget http://gigamega-micro.googlecode.com/files/bone.py

You will also need the spi.so Python extension, either installed as a Python library or as a file in the same directory as the other files. If you don’t have it, go back to the section Adding an SPI Extension Module to Python section above for instructions.

Once you have all the files, run the following as root to write some text to the LCD

root@beaglebone:# python
Python 2.7.3 (default, Aug 1 2012, 08:09:58)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.


>>> from spilcd import spilcd
>>> lcd = spilcd(2, 0)
>>> lcd.begin(16, 2)
>>> lcd.setBacklight(True)
>>> lcd.home()
>>> lcd.Print("Hello world")
>>> lcd.setCursor(0, 1)
>>> lcd.Print("Hello line 2")

(You should, of course, use begin(20, 4) for a 4-row, 20-character LCD.)

As you can see, the syntax is based on the Arduino LiquidCrystal library.  I’ve implemented many (but not all) of the same methods: enter help(spilcd) from Python to get the list.

I’ve also written a plant light controller application which makes use of the spilcd class, along with the Arduino-like bone class for accessing the GPIO .  It uses the LCD to display the current date and time, the sunrise and sunset times, and the plant light settings.  While it doesn’t break any new ground in terms of Beaglebone functionality, you might want to refer to it for sample code on how to use my Python classes for SPI and GPIO access.

You can download the plant light controller code from here.

Wrapping Up

This article covers one of the simpler uses of SPI, but this protocol opens the door to a lot of inexpensive LCDs.  I’m currently working on a Beaglebone project that uses an Adafruit ST7565-based 128×64 LCD, and Adafruit has an assortment of other SPI-based LCDs for sale.  SPI-based input devices are less common: I2C is the standard protocol used by sensors.  I’ll look at I2C in upcoming “Beaglebone Coding 101″ article.

Posted in Electronics, Programming | Tagged , , , | 16 Comments

Adding a Linux CUPS Printer to Windows 8

On my home network, I have an elderly HP Deskjet 932C printer connected to a middle aged Beagleboard running Ubuntu.  This combination has served me well as a print server for many years.  As such, they’ve borne silent witness to a sad little ritual that’s been repeated many times: I add or upgrade a Windows PC, then stomp, wail and curse as I try to remember the settings for convincing that PC to write to the printer.

The latest iteration of that ritual featured more cursing than usual, only partially because it involved Windows 8.  This convinced me to finally write down the steps involved.  That will save me some grief the next time I setup a PC, and will hopefully be of use to others too.

1. The trick is that you need to use a URL as the printer address.  I don’t know if it’s listed elsewhere, but one place you’ll find it is in the CUPS Printer list.  I was inexplicably surprised to find it displayed as a link, rather than displayed in plain text.

2. Open the Windows “Add Printer” dialog.  Every new version of Windows seems to make this a little harder to find than the previous version.  In Windows 8, here’s what I think is the most direct method:

  • Press Windows Key + Q to bring up the Search textbox
  • Type “printer”, then click the Settings bar below
  • Rather than selecting the enticingly named “Add printer” option, select “Advanced printer setup”.

(“Add printer” launches a Metro app, which attempts to find the printer, predictably fails, then offers you no option for finding it on your own.  Incidentally, I actually like Windows 8 overall: it’s Windows 7  + a lot of nice enhancements + a lot of Metro stuff that isn’t that useful on a PC  minus the Start menu.  It all adds up to a significant improvement over Windows 7, even on a desktop PC.)

The “Advanced printer setup” brings you back to the Desktop and familiar ground.  The process from this point on is pretty much identical to Windows 7.

3. The  Add Printer dialog (nee “Advanced printer setup”) attempts to find the printer, predictably fails, but gives you an option: “The printer I want isn’t listed”.  Select that option.

4. Here’s where that printer URL from step 1 comes into play (and where I usually go down the wrong path).  Paste that URL in the “Select a shared printer by name” textbox, then click Next.

5. The next dialog allows you to specify the printer model so that it can install the right drivers.  If you have a well known printer model of recent vintage, it might be listed in this dialog.  Mine isn’t, and hasn’t been since XP days.  At some point HP stopped offering the driver as a download, and instead made the surprisingly useful suggestion of using the “Windows Update” button to automatically locate the driver.  Holy smokes, it actually works!  So, give that a shot, even if your printer isn’t an HP 932C.   Otherwise, you’re left with the old school “Have Disk” option.

6. Ta da!  You’re done.  You might want to change the name, but up to now it’s been my only clue that a URL was involved, so I’m keeping it.

7. As a bonus step, check out the banner of the new Windows 8 “Print Test Page” output.  Those guys got  into the Metro spirit, too.

 I kind of like the fact that the test page no longer puts a dent in my ink supply.  It’s not so great if you’re checking to see that your printer can print more than 1 colour, but that’s Windows 8: one step forward, one aesthetically pleasing step back.

 

Posted in Uncategorized | Tagged | 3 Comments