DEV Community

Neil Gall
Neil Gall

Posted on


I grow tomatoes in my greenhouse in the summer. I have an irrigation timer for the tomatoes but setting the right amount of water is a bit of a guessing game and doesn't take the weather into account. And if we're not at home then there's nobody to monitor and tweak the water supply. But I like tinkering with technology, especially a mix of software and hardware, so making this smarter is my project for the first part of this year. I'll use moisture and temperature sensors, a solenoid-actuated water valve and a Raspberry Pi to drive it all. I never like to do things the easy way however; building something has to involve technologies I'm not familiar with, so I've decided to write the control software in Rust.

My first challenge is powering the whole thing. There's no electricity supply in my greenhouse so it needs to run on battery. Luckily there's a 45Ah lead-acid battery from an old car lying in my garage doing nothing and the Raspberry Pi model B, which is what I'll be using, needs up to 1W to run so that's a theoretical maximum run time of over 400 hours. I really want it to run all summer though so I bought a 10W solar panel, which comes with a controller to which you wire the panel, the battery and the load and it takes care of the rest. This will supply enough energy on its own to run continually, even in a typically cloudy Scottish summer. The battery will just provide storage for hours of darkness.

It still being winter here I decided to tackle the software prerequisites this week. If I want to write code in Rust I needed a cross-compiler targeting the BCM2835 processor, which has an ARMv6 instruction set with hardware floating point. In the language of GCC toolchains this is known as arm-unknown-linux-gnueabihf. I used to write embedded code for a living, so cross-compiling toolchains are nothing new to me, but what struck me is how easy it has become in the past decade.

With rustup installed, adding the target is as simple as

rustup target add arm-unknown-linux-gnueabihf
Enter fullscreen mode Exit fullscreen mode

You also need a compatible GCC toolchain (binutils mainly) for linking. My development laptop is running Arch Linux, and the toolchain I need is available in the AUR repository at version 8.2.1 of GCC, so this was a matter of

yaourt -S arm-linux-gnueabihf-gcc
Enter fullscreen mode Exit fullscreen mode

After a few steps of aborting on unknown GPG keys, and adding these keys with

gpg --recv-keys <key-id>
Enter fullscreen mode Exit fullscreen mode

then the toolchain was installed. There's one final step to associate the Rust target with the GCC toolchain. Create or edit ~/.cargo/config and add

linker = "arm-linux-gnueabihf-gcc-8.2.1"
Enter fullscreen mode Exit fullscreen mode

To test it I used cargo to create a new hello world project and compiled it with

cargo build --target arm-unknown-linux-gnueabihf
Enter fullscreen mode Exit fullscreen mode

Then after copying the resulting binary to the Raspberry Pi I tried running it. It printed "Hello World!" on the terminal!

I'm still learning Rust however, so I thought I'd try the guessing game tutorial in chapter 2 of The Rust Programming Language book. When I copied this to the Raspberry Pi and ran it, there was a dynamic linking error about an unsupported version of GLIBC. Oh no! I'm building on Arch and running on Raspbian, which is derived from Debian. I'm going to hit all sorts of library version problems, aren't I? So I decided to keep things consistent by installing Arch on the Raspberry Pi too. One of the things I really like about Arch Linux is the wiki, which is an amazing resource for all kinds of information and instructions. A quick search there revealed that of course there is an Arch Linux on ARM project, which provided the package download and installation instructions.

After rebooting the Raspberry Pi with its new installation, and a few final setup steps, I copied the guessing game binary over a second time and tried it. It works!

Next steps:

  • I can manually bring up wifi on the Raspberry Pi (with the official USB wifi adapter) but I've not managed to get it to start on boot yet. I hope to add a camera and also produce some nice graphs of data over time, so wifi will be needed.
  • Investigate accessing the Raspberry Pi GPIO from Rust.
  • Get the moisture sensors working
  • Get the external temperature/humidity/barometric pressure sensor working
  • Build a relay circuit to activate the solenoid water valve and get that working
  • Start thinking about a program design

Top comments (4)

r4h33m profile image

I really enjoyed this article. Raspberry Pi, Rust and tomatoes. A good combination!

I have a question though. You switched your Raspberry Pi's OS from Debian to Arch since there was some issues, but would it have been possible to do something to fix those issues and compile for Debian on Arch? It should be, right?

Looking forward to reading more about your project.

jeikabu profile image

Nice! Looking forward to reading about your progress.

I've got a Pi B running Raspbian and another with Win10 "IoT Core". I installed Rust/.Net Core and got some of my projects building and running, but haven't done much other than that. I'm putting the finishing touches on a post, but, honestly, it's pretty bland.

What made you choose Arch Linux? I only went with "Raspbian"/Debian because... I didn't really have an opinion.

neilgall profile image
Neil Gall

I run Arch on my laptop and it was just a matter of keeping things consistent. There are few things as demotivating as arbitrary issues with clashing library versions!

jeikabu profile image

Ah, indeed. That makes perfect sense.