OpenSprinkler Pi (OSPi) Pre-Configured SD Card Image for Download

Update: information on this blog post is outdated. Please check the latest instructions in the OSPi v1.4 user manual.

Good news to OSPi users: a pre-configured SD card image is now available for download at the following url:

NOTE: OSPi v1.4 requires either a microSD card or a low-profile SD card (due to the limited space in the enclosure). A microSD card adapter for RPi is included in the kit.

The image is compressed from an existing OSPi installation that contains Dan’s interval_program, Rich’s sprinklers_pi program, Samer’s OpenSprinkler mobile app, and the Google Calendar-based scheduling program. Download it, burn it to an SD card, and pop it in to your Raspberry Pi. Then you will be ready to go right away. No more pulling your hair or banging your head against the wall (well, hopefully :))!

The process to burn the image to an SD card is the same as burning a raspbian image to SD card. If you’ve used Raspberry Pi before, you’ve probably done this already, maybe even multiple times. If not, you should check the detailed online instructions here:

Here is a quick summary:

  • Decompress the image file to your computer.
  • Insert an SD card (4GB or above). Make sure you back up any important file on the SD card as the procedure below will overwrite the content on the SD card.
  • Depending on what operating system you use:
    • On Windows, use the Win32DiskImager software.
    • On Mac, use the ‘dd’ command in a terminal, for example: sudo dd bs=1M if=name_of_the_image_file of=/dev/partition_to_burn_to
    • On Linux, the same, use the ‘dd’ command on a terminal, for example: sudo dd bs=1M if=name_of_the_image_file of=/dev/partition_to_burn_to
    • VERY VERY IMPORTANT: make sure you have selected the correct drive name (or partition name) to burn the image to!!! If you’ve selected the wrong drive, you might end up wiping out your computer’s hard drive, and I am sure you will be back pulling your hair again!!! Double check before you press enter or click on confirm.

Once the SD card is ready, pop it in to your Raspberry Pi. Since WiFi is not configured yet, you should first connect it directly to your router using a wired Ethernet cable. Alternatively, if you are a Linux user, insert the SD card to your computer, and you directly edit the WiFi SSID and password in file /etc/network/interfaces on the SD card (not your computer!). This way when you pop it in to RPi, it will automatically connect to your WiFi network.

In your home router’s configuration page, find out the IP address assigned to the Raspberry Pi. Next, open a browser, and type in:
where x.x.x.x is your Raspberry Pi’s IP address. You should see a page with further instructions, such as setting up time zone, WiFi etc. If you can see this page, congratulations, you’ve succeeded!

Dan Kimberling’s interval_program is set as the default program to run on start-up. Type in the following url in a browser:
(again, x.x.x.x is your Raspberry Pi’s IP address) and you should see the web interface of the interval_program.

The OpenSprinkler mobile app is also pre-installed to the SD card, which is available at:

You can also switch to run Rich Zimmerman’s sprinklers_pi program on start-up. To do so, ssh (or use a monitor and keyboard) to your Raspberry Pi (the system uses the default user name pi and password raspberry) and run the script in a terminal: sudo /home/pi/select_program. Once you’ve switched to the sprinklers_pi program, you can access its web interface at the same http://x.x.x.x:8080.

These have all been explained in the one-page instruction. For questions, comments, and suggestions, please post them at the Rayshobby Forum: Thanks!


OpenSprinkler Pi (OSPi) has a New Enclosure Option

We’ve just got a new batch of enclosures for OpenSprinkler Pi (OSPi). The dimensions are the same with the transparent cover enclosures we’ve been using so far, but it’s now in solid color (light gray) and comes with a printed label on top. The picture on the left below shows the new enclosure. For comparison, the picture on the right is the current one with transparent cover.


The label makes it clear where each connector is located. Also, an additional cutout is included in the left-hand side to allow an Ethernet cable to pass through. This will be useful for anyone who wants to stick with wired connection. The pictures below show the two pieces of the enclosure and the assembly from three different sides:



A little bit history about this: the transparent cover was originally adopted because it’s exactly the same enclosure used for Arduino-based OpenSprinkler DIY kit. There is a good reason to share the enclosure as it saves cost of having to making a new design. Now as the OpenSprinkler DIY kit will soon step up to use the injection molded enclosure, it’s time to give OpenSprinkler Pi a dedicated ‘shirt’, so that the cutouts can be more tailored to OSPi.

Anyways, the new enclosure option is compatible with all existing versions of OSPi. If you’ve purchased an OSPi in the past and prefers the new enclosure, you can purchase it separately from the store link here. Thanks!

OpenSprinkler DIY v2.1u Prototype

Continuing from yesterday’s post, today’s sneak peak preview is for OpenSprinkler DIY v2.1u — the solder-and-assemble-yourself version of the OpenSprinkler.


This is the first major upgrade of the DIY version since v1.42u. The main differences compared to 1.42u are:

  • The microcontroller is upgraded to ATmega644, doubling the flash and RAM size of ATmega328.
  • Switching regulator changed to LM2596S-5.0, which is beefier than MC34063.
  • Added microSD card slot, space to fit MOVs, and pin headers to fit an RF transmitter.
  • Enclosure is changed to use the injection molded case.

The design is pretty much similar to the fully assembled OpenSprinkler 2.0. To make it easy to solder, some components are been changed to use through-hole version, notably the ATmega644 microcontroller, the ENC28J60 Ethernet controller, triacs, and several capacitors. Due to the limited space (particularly as the through-hole ATmega644 is so much larger than the previous ATmega328), it’s not possible to keep all components in through-hole style. In fact, even with surface mount, I ended up using the trick of hiding some components underneath the microcontroller, as shown in the picture below:


In addition, the microSD card slot and the LM2596S regulator are not well-suited for hand-soldering. So unlike v1.42u, which uses all through-hole components, v2.1u will be in the form of hybrid SMT and through-hole — The SMT components will be pre-assembled, and the through-hole components will be soldered by users. Strictly this should be called semi-assembled OpenSprinkler.

While the hybrid solution may sound disappointing to DIY lovers, I figured this is still an interesting compromise, as it leaves sufficient flexibility for anyone who wants to tinker with it. For example, the mcu can be easily upgraded to ATmega1284, which is pin compatible with ATmega644 but has 128KB flash and 16KB RAM. Also, the triacs can be replaced by transistors or MOSFETs to interface with DC devices. So we will see if there is enough interest in this new experiment. If you are looking for an all through-hole version, I have to say 1.42u remains the best solution.


Now, why is this version numbered 2.1? Is it jumping ahead of the fully assembled OpenSprinkler 2.0? That’s right — there are some minor improvements / changes from 2.0, so I figured a new revision number is necessary to tell them apart. Here are the main differences:

First, the ATtiny45 (which functions as a USBtiny programmer) has been removed, partly to save space, and partly to simplify the design. Instead, the ATmega644 will be flashed with a USBasp bootloader, which allows itself to function as a USBasp programmer in bootload mode. This will take away 2KB of flash memory space, but on the plus side, it eliminates one chip, and the transfer speed of USBasp is actually noticeably faster than USBtiny. Additionally, using ATmega644 to directly handle USB tasks (thanks to the V-USB library) makes it possible to add USB serial functionality. As a result, you can do serial communication to debug the code, without any external USB serial converter. So it’s win-win-win 🙂 The details can be found in my previous blog post about USB HID-class Serial Communication for AVRs.

Next, the 24VAC port has been changed to use a new type of screw terminal that has smaller pin spacing and orange color. This will prevent users from accidentally plugging it into the COM or Rain Sensor port, which would damage the controller. A 2amp fuse on the 24VAC line, and a current limiting resistor for the Rain Sensor port has also been introduced for added protection. Finally, a relay has been added on digital pin D14, to allow general-purpose switching need, such as opening garage door, and power line device etc.

Due to these changes, particularly the USBasp bootloader (which requires ATmega644 to run at 12MHz instead of the current 8MHz on OpenSprinkler 2.0), it’s necessary to use a new revision number to avoid confusion.

In any case, the prototype has been verified and I only identified a couple of minor changes to fix. Otherwise it’s pretty much ready to go. It should be available for purchase within a month. So stay tuned!

OpenSprinkler Beagle First Prototype Done

Update: OpenSprinkler Beagle is officially released, and is available for purchase at Rayshobby Shop.

A lot of prototype PCBs arrived over the weekend. Among them is my long-waited OpenSprinkler Beagle — a sprinkler / irrigation extension board for the BeagleBone Black. Cool, time for some prototyping actions!


The design of OpenSprinkler Beagle largely follows OpenSprinkler Pi (OSPi). As usual, the board contains a 24VAC to 5VDC switching regulator, shift register, triacs, terminal blocks, and zone expansion board connector. It provides 5V power to the BeagleBone Black, uses 4 GPIO pins (specifically P9_11, 12, 13, 14) to interface with the shift register, and SDA2/SCL2 to interface with the DS1307 RTC. Since the BeagleBone and RPi are similar in size, I can reuse the same enclosure as I’ve been using so far.

There are also several changes and improvements. First and probably the biggest design change is that the BeagleBone Black is now oriented face-down, and it plugs directly to the extra long male pin headers as you can see on the pictures above and below. In contrast, on OSPi, the Raspberry Pi is oriented face-up, and connection from RPi to the board is through a pair of 8-pin and 3-pin cables. The biggest advantage of the face-down design is that it saves the cables, and there is now some extra space in the upper-half of the enclosure, making it possible to add additional modules. To make it easy to reuse the available pins on the BeagleBone, I’ve also mapped out all the 46 pins on ports P8 and P9 to the pinout area.

I actually wanted to use the same design for OSPi, but it’s more tricky because RPi uses male pin headers, which means the extension board will have to provide female pin headers. I haven’t been successful at finding extra long female pin headers, but I will keep looking.


Among the other changes: the 24VAC port is now using a new type of terminal block that has different pin spacing and color with the others. This will reduce the chance of accidentally plugging 24VAC into the COM or rain sensor port, which has happened before. Speaking of rain sensor port, yes, there is now a rain sensor terminal — it takes one extra GPIO pin, but there are plenty of GPIO pins on the BeagleBone, so who cares 🙂

Also, I’ve added a 2A fuse, and nine 48V bidirectional TVS (transient-voltage suppressor) — one for the power in, and one for each of the eight zones. This will provide some level of protection to the circuit during power surges and lightening. In the past I’ve used MOVs (metal-oxide varistors). Those are pretty cheap, but they are bulky and have to be hand-soldered since they are through-hole components. TVS is a bit more expensive but can be easily automated using pick-and-place machines.


Also, the analog-digital converter (ADC) has been removed since the BeagleBone has built-in analog pins. As sort of an experiment, I also removed the on-board DS1307 RTC, but instead added pin headers to plug in an external RTC module, as you can see close to the top of the PCB. This was done as an experiment to empty out some space on the PCB to allow future expansion. But it turns out to be not very successful, because the module actually takes quite some space and makes it difficult to close the top cover.

Here are some additional pictures of the assembly:

I quite like the overall design. There are a few minor changes I want to make before the official release. For example, the 100uF capacitor is currently too close to the BeagleBone’s USB port, and it needs to be moved further away. Also, I can make the PCB color black to match the color of the BeagleBone Black. By the way, I learned from the forum that some users want to use the sprinkler controller to control garage doors. I figured it’s it’s pretty easy to add a relay on the board for general-purpose applications. So I am gonna try to add that too.


What would be a good abbreviated name for OpenSprinkler Beagle? Since it’s designed for the BeagleBone Black, I could call it OSBBB, but I want to distinguish it from another product I am working on — the OpenSprinkler Bee (OSBee). OSBBB and OSBee are too close with each other to pronounce. One possibility is to call it OS-Bo, which would put it nicely in a series with OS-Pi and OS-Bee. If you have better suggestions, feel free to leave a comment below. Thanks!

Update: OpenSprinkler Beagle is officially released, and is available for purchase at Rayshobby Shop.

HID-class USB Serial Communication for AVRs using V-USB

A month with no new post? That’s unacceptable. Since my last trip to Shenzhen, I actually have quite a few new ideas and projects to post about. The thing is there are so many of them that I don’t know which one to start with! Anyways, I’ve decided to put a stop to this. In this blog post, I will describe some work I did a little while back about implementing HID-class serial communication for AVR microcontrollers using the V-USB library.


First, let me explain what I am trying to do. As you probably know, V-USB is a very useful software-only implementation of low-speed USB device for AVR microcontrollers. It adds USB functionality for almost any AVR, particularly for those without hardware USB functionality. With this, it’s possible to make a very low-cost standalone Arduino with USB port and without having to use an FTDI chip. I know there is the Arduino Leonardo, which is based on ATmega32u4, and which has hardware-based USB functionality. But mega32u4 only exists in SMT package, and it’s more expensive than mega328 after all. Besides, I am fully embracing the ‘I do it because I can’ spirit, and this is actually a great motivation for me to learn about V-USB.

What do I need the USB for? Mostly for two reasons. One is to flash a program to the microcontroller, so it needs a USB-based bootloader. For this, there is a very nice open-source project called USnoobie, which can bootload mega328 as a USBasp programmer. This way you can flash a program through the USB port directly, without using a serial cable or an external AVRISP programmer. So this is all good.

The second reason to have USB is for serial communication — the ability to transfer data (e.g. strings) in and out between the device and a host computer through the USB port. This is useful especially for debugging (i.e. printing values to a serial monitor), unfortunately this feature is missing in most V-USB projects. There are some related projects. For example, I came across the AVR-CDC project, which turns a mega328 into a CDC-class USB-serial converter. But there seem to be some limitations of using V-USB to implement CDC (i.e. violates USB standard), and also CDC-class devices require installing a driver on Windows. I would like to make a HID-class USB device which does not require driver installation. So overall I didn’t find any available resource that I can use directly.

Circuit Design and V-USB

Now I’ve explained the motivation, let’s see how to go about implementing it. The first step is to learn to use V-USB. I started with the EasyLogger project downloaded from the V-USB website. It is based on the tiny45 mcu. The program reads a sensor (e.g. temperature or light) and presents itself as a USB keyboard to print out the sensor values to a host computer. This is an excellent starting point for me because USB keyboard is a standard HID-class device, and the project is simple enough that I can easily learn and make modifications.

To adapt it to mega328, I first made a circuit based on USnoobie. Here is the schematic and my build of the circuit on a breadboard:


It’s a pretty standard V-USB setup. I assigned digital pin PD2 (INT0) to USB D+, pin PD7 to USB D-, and PD4 to a pushbutton. The pushbutton is used to enter bootloading mode. Specifically, if the button is pressed when the circuit is powered up, the bootloader is activated and the mcu will appear as a USBasp programmer. Different from USnoobie, I’ve decoupled this button from the D- line, so that I can use the button for general-purpose input (otherwise pressing the button will trigger the D- line). This requires changing the USnoobie code slightly to use pin PD4 for bootloading condition. Finally, I’ve also added a MCP9700 temperature sensor (you can replace it by any analog sensor such as photosensor) to analog pin ADC0 for testing later.

The next step is to modify the source code. First, change usbconfig.h to match the D+ and D- pin settings, specifically the following three macro defines:

/* */
#define USB_CFG_DMINUS_BIT      7
/* */
#define USB_CFG_DPLUS_BIT       2
/* */

Next, modify main.c. This step is pretty technical and tedious. It mainly involves changing register names to match mega328 (since the code was originally written for tiny45). Also, the calibrateOscillator(); function can be removed as the mega328 will be running on an external 12MHz clock.

I also modified the Makefile in order to compile and flash the code for mega328. After a few tweaks here and there, the EasyLogger started working on my mega328! It can successfully output numerical values to a text editor through the USB port. This is very encouraging. If these steps don’t make much sense, you can take a look at the code below, and give it a try yourself.

Learning HID

HID stands for Human Interface Device. It’s a USB class designed primarily for keyboard, mice, joystick, and similar human interface devices. The nice thing about HID is that it’s supported on all operating systems. For example, on Windows, the system uses built-in HID driver to handle USB requests, so no driver installation is required. This is why when you plug in a keyboard or mice, you never have to install a driver (imagine how annoying it would be if you had to!).

To implement HID, you first will need to construct a HID descriptor, which describes the number of reports, and the size, meaning, and (optionally) value range of each report. For example, these reports can be the ASCII code of the pressed key, the x and y offsets, and button presses of the mouse. There are also more general-purpose reports like a buffer of bytes. This is what I will be using to transfer bytes in and out between the device and host. To be honest, the whole USB descriptor thing was very obscure to me in the beginning. I didn’t know if there is one correct way to define it, or it can be flexible. As it turns out, Linux is pretty forgiving about it, but Windows is not. After many trials and errors, I finally settled with this HID descriptor:

PROGMEM const char usbHidReportDescriptor[USB_CFG_HID_REPORT_DESCRIPTOR_LENGTH] = {    /* USB report descriptor */
    0x06, 0x00, 0xff,              // USAGE_PAGE (Generic Desktop)
    0x09, 0x01,                    // USAGE (Vendor Usage 1)
    0xa1, 0x01,                    // COLLECTION (Application)
    0x15, 0x00,                    //   LOGICAL_MINIMUM (0)
    0x26, 0xff, 0x00,              //   LOGICAL_MAXIMUM (255)
    0x75, 0x08,                    //   REPORT_SIZE (8)
    0x95, 0x08,                    //   REPORT_COUNT (8)
    0x09, 0x00,                    //   USAGE (Undefined)
    0x82, 0x02, 0x01,              //   INPUT (Data,Var,Abs,Buf)
    0x09, 0x00,                    //   USAGE (Undefined)
    0xb2, 0x02, 0x01,              //   FEATURE (Data,Var,Abs,Buf)
    0xc0                           // END_COLLECTION

It contains an outgoing buffer of 8 bytes (to transfer data to the host) and an incoming buffer of 32 bytes (to receive data from the host). As I said above, Linux is pretty flexible about the descriptor — you can change it in many ways and it still works. Windows, however, is very strict — if you are not careful, it will simply refuse to recognize the device.

The next step is to write functions to handle the USB requests. For transferring data out, I used the usbSetInterrupt function, which allows sending data spontaneously to the host (i.e. whenever the device has something to report). (I should mention here that I wrote the code as an Arduino library called HIDSerial. So everything gets compiled in the Arduino software. You can certainly use avr-gcc to compile the code as well). I made HIDSerial an inherited class from Arduino’s Print class, so I can make use of the many available print functions (e.g. print a string, an integer, a floating point) in the class for serial printing need, without writing extra code. For transferring data in, I implemented the usbFunctionWrite function, as described in the V-USB Document Wiki.

Now, before I can test and debug the code, I need to have some minimal host software to communicate with the device. That’s what I will be describing next.

Write Host Software using Processing

Going the HID route means the device will not appear as a standard serial COM port, so you can’t use the standard serial monitor to send and receive values. Instead, I will have to write host software myself. I can certainly do this in C or Java. But since I want to make the host software cross-platform, I have chosen to implement it in Processing, which allows me to easily export the program as standalone applications on all platforms. Long story short, to do this, I used HIDAPI library. It has all the goodies to handle communications with HID devices, such as finding a device, opening the device, reading from the device, and sending feature report to the device. Also, using the G4P library, you can easily build a GUI with buttons and text fields, and make the interface just like a standard serial monitor. Once the software is finalized, I can simply click on ‘Export Application’, and select all three platforms, and voilà, the host software is all set! Below are two screenshots of the HID serial monitor:


Source Code

The source code of this project is available for download on my GitHub repository:

You can either do a git clone, or directly download the project as a zip file (see the Download .zip button on the right-hand side of the page). The folder contains circuit schematic, part list, Arduino library (HIDSerial), host software (HID serial monitor), and bootloader (optional, but recommended as it allows you to re-flash the microcontroller through USB, without any external programmer). The Arduino library consists of several starting examples, which are also demonstrated in the video above. I am sure there are bugs and issues with the code, but please feel free to leave comments and feedback below, in order for me to improve the code.

Limitations and Issues

The biggest limitation of this implementation is the data transfer speed — it’s much slower compared to a standard USB-serial converter. This will be an issue if you need to pump out data as fast as possible. But I figured that for the purpose of debugging, the transfer speed is usually not that critical. The software works pretty reliably in Linux, but I’ve found that on Windows, the host software starts to lose data after running for a while, so not all data get transferred correctly. Resetting the microcontroller and restarting the host software seem to get it back to work. I am still investigating the cause of this issue. It may still have to do with Windows being very strict with USB communication protocols. Perhaps the USB experts can take a look at the code and point me in the right direction.

Adapting the Code to Other AVRs

It’s relatively easy to adapt the code to other AVRs. For example, ATtiny45/85 is a popular V-USB platform, since it’s small, cheap, and has internal oscillator that can run at 16.5MHz, which meets the USB standard (so it saves a crystal and frees up two pins). By changing a couple of pin assignments in the source code, I was able to get the HID serial functions to work on tiny45. I really should do it on tiny85, since tiny45 has only 4KB flash space (even a simple demo would take more than 3.5K flash space). Here is a picture of the tiny45 breadboard build. You can even program tiny45 in the Arduino software by following the descriptions here.


Thanks for reading the post. Feedback, comments, and questions are welcome.