Tag: hardware

I’m using a Beaglebone Black to log some science data around the house. My internet connection isn’t the most reliable in the world so I first cache the data locally on the BBB and upload it separately; this means I need to capture accurate timestamps for the data. If the BBB reboots due to a power outage or something, I want the timestamps to be accurate even if the device can’t immediately sync the time from the internet, so I need a battery-backed real-time clock.

As I researched the proper way to do this, I discovered that there are a lot of articles and forum posts that discuss the topic but most of them had one or both of these problems:

They explained how to enable the RTC for the current session but not in a way that would survive reboots.

They gave instructions based on old or different OSes that weren’t valid for my device.

I finally put together something that I’m happy with so I’m documenting what I found. None of this information is original discovery on my part but hopefully it’ll be in a form that’s useful to others. However, it’s important to note that these instructions are for the Beaglebone Black running Debian 9 (Stretch), specifically “Linux beaglebone 4.4.91-ti-r133 #1 SMP Tue Oct 10 05:18:08 UTC 2017 armv7l GNU/Linux”. They might be helpful for other devices or other Linux flavors but some things are likely to be different.

Hardware

I’m using a really cheap I2C-based DS1307 RTC that I ordered from China, called the Tiny RTC. This device is available from a bunch of different sources but the design is exactly the same. It’s actually a poorly-designed device but it’s dirt cheap and can be fixed with a bit of surgery.

Problems

The first problem is that the Tiny RTC is designed to trickle-charge a rechargeable LIR2032 battery, but a) the charging circuit isn’t very good and b) LIR2032 batteries aren’t widely available and tend to be of poor quality. A regular CR2032 battery will last for years anyway, so it’s better to just disable the charging circuit. Don’t put a non-rechargeable CR2032 into the device without first disabling the charging circuit; the battery may eventually explode if you do.

The second problem is that the Tiny RTC is designed as a 5V device but the BBB is a 3.3V device. Fortunately the I2C bus lets us interoperate with 3.3V safely as long as we remove the pull-up resistors from the RTC.

The third problem is that the crystal oscillator is supposed to be soldered to the ground pad underneath it, according to the internet, but usually it’s not. This can cause stability problems.

Another potential problem is that DS1307 chip doesn’t keep very good time and is sensitive to temperature variations, but since I planned to have the BBB regularly update the time on the RTC, that didn’t matter much to me.

Fixing the hardware

Here’s a picture of the board:

To disable the charging circuit, remove D1, R4, R5, R6, and short the R6 pads together.

To make the device compatible with the 3.3V BBB, remove R2 and R3. If you plan to use the square wave output, remove R8 too.

Carefully solder the body of the crystal to the ground pad underneath it. Do this rapidly so you don’t overheat the crystal.

Connecting to the Beaglebone

Note that the I2C pins on the BBB are for I2C-2. This may be different on other devices, which would change many things below.

Test the hardware

You can test your work so far by running this command on the BBB:

i2cdetect -y -r 2

If the RTC is wired correctly and is communicating properly, you’ll see this output indicating that there’s a device at address 0x68:

Software

As I mentioned earlier, the challenge with setting up the RTC is to do it in a way that survives reboots and doesn’t require further manual intervention. Most of the following instructions came from Mike Kazantsev’s excellent blog post with a few details filled in or tweaked for my specific environment. He wrote some great technical explanations which I won’t attempt to duplicate here; if you want to know why the following steps work, read his post.

Add the RTC to the device tree

To make the kernel aware of the RTC device and to have it enabled at boot, we need to add it to the device tree. Create a file named i2c2-rtc-ds1307.dts in your home folder with this content:

Now we need to tell the kernel to load that device overlay on boot. Edit /boot/uEnv.txt and find the line that says, “###Custom Cape”. Directly below that line, enable the example overlay line and make it look like this:

###Custom Cape
dtb_overlay=/lib/firmware/BB-RTC-02-00A0.dtbo

Now reboot and run this command:

ls -al /dev/rtc*

You should see this output:

Notice that we now have RTC0 and RTC1 devices. RTC0 is the built-in hardware clock in the BBB but it has no battery backup. RTC1 is the DS1307 that we connected to the BBB, so now we have two hardware clocks available. We’re not done, though, because the /dev/rtc symlink is pointing to RTC0, not RTC1.

Make our RTC the default

We can add a udev rule that will symlink to our battery-backed RTC instead. Create a new file named /etc/udev/rules.d/55-i2c-rtc.rules with this text:

Set system time from RTC

Now we have our new RTC set up but the system time still won’t be set on boot. The systemd-timesyncd service is responsible for time syncing in this build of Debian. As it syncs the time from a time server it writes that time to disk. If the device reboots and has no internet connection, systemd-timesyncd will see that the system time is unset and will load the last-synced time from disk and use that to set the system time (which wouldn’t be correct, but at least closer than a totally unset time). We need to set the system time from our RTC before systemd-timesyncd checks it, and we can do that by creating a new systemd service.

Create a file named /etc/systemd/system/i2c-rtc.service with this text:

Set the RTC from system time

As mentioned above, systemd-timesyncd will regularly correct the system time from a time server whenever you have an internet connection. I thought that systemd-timesyncd would also update the default hardware clock at the same time, but it doesn’t. Turns out it’s the kernel’s job to regularly copy the system time to the hardware clock, but the kernel actually targets /dev/rtc0 directly rather than using the /dev/rtc symlink, and this is set as a compilation option, not a runtime option, so it can’t be easily changed. Instead of recompiling the kernel we’re just going to add another systemd service which will regularly update our RTC with the correct time. This is particularly important since the DS1307 isn’t a very good clock and will drift significantly in only a few days.

First create a service file named /etc/systemd/system/systohc.service with this text:

At this point we’re done with the software configuration, but don’t reboot yet because we want to do some testing.

Testing

To test that everything is working as expected, first set the DS1307 clock to some obviously incorrect date using this command:

sudo hwclock -f /dev/rtc1 –set –date=”2017-01-01 00:00:01″ –utc

Next, physically unplug any internet connection (wifi/ethernet) from the BBB and reboot. When the BBB comes back up without an internet connection, running date at the command line should show you the incorrect date you set above. This tells us that the date was loaded from the DS1307 on boot, which is what we want.

Now reconnect your internet connection, wait a minute or two, then check the system clock and both hardware clocks with this command:

This will print out three date/time strings and they should all be the same (to within a few seconds since the commands to print each one are running sequentially). This tells us that the system clock was synced from the time server and the updated time was also copied to both hardware clocks, which is what we want.

If you walk through these instructions and find errors or clarifications, leave a comment below.

Programming the sensor module

Once you finish soldering a sensor module, the next thing you have to do is to set some configuration options and upload the firmware. To do this, you’ll need an AVR programmer device of some kind. We can’t use a simple USB cable like you can with an Arduino because a) we didn’t include USB components on the board and b) the processor doesn’t have any bootloader firmware installed.

Once you have a programmer you need to connect it to the ICSP header on the sensor module. You can either solder on headers and use a cable option of your choice or you can get this nice pogo-pin adapter, also from Femtocow:

Setting the fuses

Once you have your programming system set up, the first thing we need to do is set the “fuses” which are hardware level configuration options that control certain behaviors of the microprocessor. In particular, we want to set the processor frequency to 8Mhz, tell the processor to preserve its EEPROM memory when it’s programmed, and set the brown-out detection feature to trigger at 2.7V. If you’re using one of the USBtinyISP programmers I linked above you can use this command line to set the fuses:

If you use a different kind of programmer you’ll probably have to use a different value for the –c parameter to tell avrdude which programmer you’re using.

Setting the ID

For reasons that will be clear a little later, the next thing we have to do is to give the sensor module a unique ID. To do that, I use the id sketch in my GitHub repository. (I’m not going to copy the source code here so that it won’t get out of date.) Open the id.ino sketch in the Arduino IDE and set the nodeId variable to an integer between 1 and 9. This value will become the ID of the sensor module (stored in EEPROM so it survives reboots) after it runs this sketch. Once you’ve set an ID, upload the code to the sensor and you should see the onboard LED repeatedly blink a pattern that indicates the ID you set. If you don’t see the LED blinking at all then either the programming didn’t complete successfully or you forgot to change the nodeId variable from its default value of 0.

The sensor module firmware

Finally we can upload the sensor module firmware sketch from GitHub. Note that there are also two supporting files MCP9808.h and MCP9808.cpp in the same folder that you have to have in order to compile the sketch. You can upload this sketch to the sensor module, overwriting the ID sketch, because the ID you programmed is saved in EEPROM memory.

Let’s look at some of the highlights of this code. I’ll include relevant snippets here but remember that the version on GitHub is always the most up-to-date.

Setup

Configure the GPIO pins (that aren’t otherwise configured by libraries) for our use. Right now there’s only the LED output pin.

Load the node address from EEPROM. That function verifies that the ID it loaded is between 1 and 9 and if it’s not, it’ll blink the LED rapidly and continuously to indicate an error condition.

Initialize the radio and temperature sensor. The radio is configured to transmit at maximum power and the slowest bitrate in order to get decent range. We don’t transmit very often or for long so this doesn’t hurt our battery life too badly.

Loop

Once everything is initialized we can start running the code that collects data and transmits it to the base station. The high-level loop looks like this:

We wake up the peripherals from their sleep states, then we send the our collected data to the base station, then we put the peripherals back to sleep, then we put the processor itself to sleep. Eight seconds later a timer wakes up the processor and we do the whole thing again, and this repeats forever.

Waking

Waking up the peripherals is interesting because the temperature sensor has some special considerations. This is how we do it:

void wakePeripherals()
{
// When we wake the sensor it takes time to do another conversion.
// The time depends on the configured resolution (250ms for highest res.). We need to wait
// until the sensor has had time to do another conversion after
// waking or we'll just end up reading the previous conversion.
sensor.wake();
shortSleep();
radio.powerUp();
}

When the MCP9808 temperature sensor first wakes up, it starts doing another reading but if you immediately ask it for a reading before it’s finished it’ll just give you the result of the last reading it took. We need wait long enough to allow the sensor to finish taking its new reading, then we can ask it for the new data. The code wakes up the sensor then puts the processor back to sleep for 288 milliseconds. Once that time elapses then we can wake up the radio because we’re about to send out new data.

We’re sending two 16-bit integers to the base station. The first is the temperature in Celsius, encoded to an integer by multiplying it by 16 (the sensor measures temperature in 1/16 degree increments). The second integer is the voltage that the processor is receiving from the voltage regulator.

I considered adding circuitry to allow the processor to sample the unregulated battery supply voltage, which would be a more interesting number, but at the time I was worried about input pin leakage current, so I decided to do something a little less cool and just have the processor measure its own supply voltage. That will be really close to 3.0V constantly until the battery pack is close to exhausted and the regulator is forced out of regulation and the voltage starts to drop below 3V. When that happens I know it’s time to change the battery. In hindsight I think leakage current would be trivial and I should have at least included the ability to sample the raw voltage, so I’ll probably add that if I spin a new rev of the sensor module board.

By the way, I didn’t write the code that measures the processor’s power supply voltage; I got it from Nick Gammon’s blog (which is amazing and highly recommended).

If we’re successful in sending the data then nothing further happens. We don’t want to blink an LED in this case because that’s just wasted power. But if the transmit doesn’t succeed for some reason then we do blink the LED to indicate that something went wrong. If the sensor is transmitting and being received correctly then this will hardly ever happen and if it’s not working correctly then battery life doesn’t really matter.

Sleeping

There’s some very specific code that needs to run in order to put the processor into its lowest-power sleep state, and once again I didn’t write it myself but instead got it from Nick Gammon’s blog, so go there to understand the mechanics of how it works.

I studied Software Engineering in college. Most of the major classes were about various software topics, of course, but I was also required to take a couple of hardware/electronics classes where we soldered together transistors and logic gates and such things. At the time I didn’t particularly enjoy it – software was logical and always worked the same way while hardware was messy and was constantly not working due to bad solder joints or “letting the magic smoke out” or what have you. Very frustrating.

Fast forward 20 years and I’ve been doing the software thing for a long time. I’m still passionate about programming and love what I do but I was looking for something new to spend hobby time on. Preferably something relatively cheap, that I could combine with my interest in amateur science, and that would bring me back to a state of “beginner mind” where I could have fun learning again. I decided to turn my attention back to the world of electronics to see if it would “take” any better the second time around.

It turns out that the world of hobby electronics is currently in a golden age and it’s amazing! Between the ocean of free information available on the internet, the fantastic companies that cater to hobbyists, and the wide availability of low-cost, high-quality tools and equipment, there’s never been a better time to get into the hobby.

So you want to hack some hardware?

I’ve been working with this new hobby for about a year now and while I’m certainly no expert, I thought I’d share the results of some of my research to maybe save others some time and to “give back” to the internet community that’s helped me so much. This post will be a high-level overview of some of the interesting directions in which one can explore, and resources I’ve found to be the most useful. It’s adapted from a talk I did for the South Sound Developers User Group earlier this year.

As a software developer, it’s pretty easy to ease into the electronics field, starting with high-level things that are comfortably familiar and working your way down to raw electronics with transistors and opamps and stuff. There are a huge array of options available and I can’t possibly cover them all, so I’ll just describe the journey I took and the results I got.

Microprocessor boards

Probably the easiest place to start is with one of the many types of small microprocessor boards available today. Two of the most popular right now are the Raspberry Pi and the BeagleBone Black. These are full self-contained computers on a single small board, usually running some kind of Linux-based OS on an ARM processor. The fact that they’re small and low-power is nice, I guess, but the really interesting thing about them is that they usually include a number of general purpose I/O pins that you can hook up to external electronic circuits in order to control them or to acquire data from them. These GPIO pins aren’t tied to any kind of complex protocol like USB or even serial; instead you can directly set each output pin on or off, or check the current state of each input pin. This allows you to do something trivial like blink an LED on and off, or things that are far more complex.

One of my first electronics purchases was a BeagleBone Black and I’m very happy with it. It has enough processing power to run Linux, lets me program in my language of choice (Python, Javascript, C, etc.), and is easy to hook up to my home network and thus to the internet. It has a wide array of GPIO pins, both digital and analog, and also has USB and HDMI ports to connect a monitor and keyboard if desired (though I usually just SSH into it).

I bought the BeagleBone Black along with an inexpensive beginner’s electronics parts kit (see below) and had a lot of fun wiring up LEDs, switches, and other components on a breadboard and connecting them to the BeagleBone. I refreshed my memory about the basics of simple electronic circuits but soon found myself wanting to go a bit more low-level. After all, the BeagleBone Black wasn’t too much different than the laptop I work on every day and I wanted something a little more different than my day job.

Microcontroller boards

Having the power of a full Linux OS is nice but I wanted to get a little closer to the hardware. I picked up an Arduino Uno, which is a microcontroller board. Like the BeagleBone Black, the Arduino has several digital and analog GPIO pins which which to interface with external electronic circuits. However, unlike microprocessor boards, the hardware resources available on a microcontroller board are much more limited. The Arduino Uno has only 32 KB of storage and 2 KB of RAM, so you aren’t going to be running Linux on this thing. In fact, you don’t have any kind of OS available at all.

Instead, you write self-contained programs which are uploaded to the board over USB and get directly executed by the microcontroller. There’s no OS to get in the way; your program is the only code running and you have full control over and responsibility for everything that happens. This is simultaneously limiting (no networking, video, or keyboard/mouse supported out of the box) and also liberating because your code executes predictably in real time without being preempted by other threads or processes. This allows you to do things that require precise timing control such as operating servo motors for robotics projects.

It’s still pretty easy to program, though, because there’s an IDE and libraries available to help you with the dirty work. Using the Arduino IDE on your computer, you write code in Arduino-flavored C++, cross-compile it for the Atmel AVR ATmega328 microcontroller on the board, and upload the resulting binary via a USB cable.

The Arduino is an extremely popular hobbyist board and there are a ridiculous number of tutorials, project descriptions, and forums to give you advice and inspiration.

Bare microcontrollers

The Atmel AVR ATmega328 microcontroller that runs the Arduino is not a particularly modern chip but it’s well understood and a huge community has grown up around it. It’s quite inexpensive and easy to experiment with. It turns out that it’s not particularly difficult to buy the chip all by itself, whack it and a couple of other cheap components onto a breadboard, and make your own homebrew Arduino.

Furthermore, the AVR line of microcontrollers includes chips that are both larger and smaller than the ATmega328 used in the Arduino but they’re all software-compatible, so you can choose precisely the minimum amount of silicon you need to build your project. Using a bare chip in your project is a little more inconvenient than using an Arduino board but if you’re soldering stuff together anyway and you need it to be small, including an AVR chip directly in your circuit is the way to go. Besides which, soldering bare chips makes you feel like you’re actually doing electronics!

Analog circuits

So far, everything we’ve discussed is primarily centered around writing code for a processor of some kind with some ancillary circuitry thrown in. That’s a great way for a software developer to start but since my goal was to do something completely new, I needed to break out of the programming paradigm completely.

It turns out that there are all kinds of things you can do with just analog components and a breadboard; no digital code required. That was a revelation to me. I mean, duh, of course I knew that, but after 20 years as a software developer I had some pretty deep-seated biases toward digital logic. The first time I wired up a 555 analog timer chip to blink an LED and was able to change the rate of the blinking by merely swapping one resistor value for another, I realized that this was the “totally new” thing I’d been looking for. I still do a lot of stuff with microcontrollers in my projects but it’s become a game of sorts to see how little code I can get away with, with zero being the ideal. I’ve learned a lot about low-level electronics over the past year and I’ve barely scratched the surface. I’m having a ton of fun, though!

Tools and resources

There are several tools I’ve purchased and valuable resources I’ve found that have helped me in my learning. Below are some of the highlights. This is by no means an exhaustive list and there may well be even better choices out there, but these are the things that I found valuable to me.

Hobbyist stores and distributors

There are a lot of online stores out there that offer all kinds of electronics components. Some of them are good, a lot of them are sketchy. Adafruit and Sparkfun are two companies that I can highly recommend. They both carry high-quality components suitable for hobbyists, both carry lots of custom-designed components and boards to make building projects easy, and both publish a wide range of tutorials and project guides to help you use what you buy. Their prices aren’t the cheapest you can find, but I strongly recommend sending your business to these companies because they stand behind their products and are actively building up the hobbyist community. Just beware – browsing either one of those websites can be hazardous to your wallet. So much awesome stuff!

If you’re shopping for unusual components, or components with very specific characteristics, or a large quantity of components, then you might want to try a large distributor house. Mouser and Digikey are both well-regarded, reliable distributors that stock literally hundreds of thousands of different electronics parts. If you need it, they probably have it. Your biggest problem will be deciding exactly what you want to order. You want a capacitor? Mouser has 346,459 different kinds. You’ll need to get proficient with their catalog search tools and know how to read datasheets because there’s no handholding here.

Also be aware that these distributors focus on large-volume orders. They’re willing to sell you singles of most things but it’s not going to be particularly cheap. You need to buy in reasonable quantities to get discounts.

Electronic parts and kits

To get started, I purchased a couple of breadboards, the Beginner Parts Kit, and the Resistor Kit from Sparkfun. These are nice little kits that gives you a few of each of the most commonly-used components for beginning electronics projects. This is a great way to get jumpstarted with building simple electronics circuits to connect to your BeagleBone Black or Arduino. There’s lots of other options out there, of course, but I was happy with these.

Multimeter

A good multimeter is the first tool you should invest in as you pursue a hobby in electronics. A good choice is the Extech EX330. It’s reliable, has a good set of features, and is reasonably priced.

Soldering Station

I learned a long time ago that if you’re going to invest in equipment for a hobby, you should buy quality stuff that actually works well. There are lots of low-end soldering irons out there but most of them will simply cause you to be frustrated and maybe give up on the whole thing altogether. After some research I purchased an Aoyue 9378 soldering station that I’ve been happy with. There are several other good choices in this price range, too, but this one seemed to be recommended a lot.

Power supply

One of the first “from scratch” projects you can build is a breadboard power supply to feed 3.3V or 5V power to your circuits. It’s fun and satisfying to build your own tools. However, when your needs expand to higher voltages or high current, and you need features like current-limiting to avoid blowing stuff up, then it’s time to get a real power supply. I purchased a Mastech HY3005F-3 power supply. It’s solid and reasonably priced. It’s not programmable or anything (that stuff is found in higher price levels) but it gets the job done.

Oscilloscope

An oscilloscope is an incredibly useful tool for understanding and diagnosing non-trivial circuits. Where a multimeter will tell you the voltage at a particular contact point right now, an oscilloscope allows you to see how it varies over time. This is the sort of tool where it’s hard to imagine how it would be useful until the first time you actually use one, then wonder how you ever got along without one. I chose the Rigol DS1102E and like it a lot. There are fancier ones available for more money but this one seems to do everything I need for now.

Blogs

There are a ton of great resources for the electronics hobbyist on the internet and I won’t attempt to list them all. One of them particularly stands out in terms of being both instructive and entertaining, though: EEVBlog. Dave has hundreds of video episodes covering everything from electronics fundamentals and theory to teardowns of various pieces of equipment to live repair jobs. I learned a tremendous amount just from watching how he uses his tools. I recommend starting with episode #168: How To Set Up An Electronics Lab.

Circuit simulation

Sometimes you don’t want to take the time to actually build a circuit on a breadboard to see if it will work. Or maybe you don’t have the correct parts at hand, or you’re afraid you might screw it up and blow up a component, or whatever. In such cases it’s very useful to be able to simulate your circuit ideas in software first before you commit to the real thing. There are software packages you can download for this purpose, but I’ve been pleased with CircuitLab.com. It’s not free but the user interface is very intuitive and it’s helped me better understand how transistors and opamps work because I can quickly set up various scenarios and see instantaneous voltage and current values, or chart them over time.

Go forth and learn!

So that’s a lot of high-level information about how to get started with an electronics hobby. You’ll notice that I didn’t discuss the “how-to” on anything, but a few web searches should turn up lots of resources for any particular topic that catches your interest. The most important thing is to actually do something. Start small, understand and master what you’ve purchased, then move on to the next step. Personally, I’ve found it to be very rewarding and I hope you will too.