Bridging the Raspberry Pi and the Arduino

Easily extend the Arduino capabilities to the Raspberry Pi 2 running Windows 10 IoT Core with C#.

Introduction

I recently had a conversation with a colleague wanting to get into IoT. He was contemplating whether to buy a Raspberry Pi 2 or an Arduino Uno. He asked my opinion and I found I couldn't give him a clear answer.

Through my experience, I have come to understand that these two platofrms are not swappable. Both offer excellent advantages and disadvantages. In fact, they can easily be complementing platforms.

In a recent project I needed to use an Arduino to control some sensors and devices but the core of my project was based on the C# running on the Raspberry Pi. I found the excellent project posted by Christiano Faig titled “Arduino I2C communication with Raspi 2 WIOT” and was inspired. I immediately connected my Arduino Uno to my Raspberry Pi and was on my way.

In the project mentioned I knew exactly how I wanted to use my Arduino. I also knew, however, that I would most likely use this platform combination in future projects. I decided I needed to create a reusable library.

In this article I will share my library with you in the hope that you find it useful too.

C# Universal Library

Since the focus of this library is to control and Arduino from a Universal application running on the Raspberry Pi 2, I will start with the C# library.

Getting the Library

The library is available from two sources. The first, and easiest way to get the library is via NuGet. To install open the NuGet package console and enter

PM> Install-Package IoT.Arduino

The second way to get the library is to download the source code from GitHub and add it directly to your project. The GitHub link is included at the bottom of the page.

Using the Library

The first thing to do is to add the following using statement at the top of your source code file.

using Porrey.Uwp.IoT.Devices.Arduino;

Next, create an instance of the Arduino object and specify the address. The default is 0x04. The address can be changed by updating the Definitions.h file reloading your code to the Arduino.

Arduino arduino = new Arduino(0x04);

before using the library you need to initialize the connection. To do this call InitializeAsync.

await arduino.InitializeAsync();

Currently the library supports basic Arduino commands but will be updated regularly to incorporate more capabilities.

Here are some of the basic commands:

Set the output mode on a specific pin.

await arduino.PinModeAsync(9, ArduinoPinMode.Output);

Set the digital output value on a specific pin.

await arduino.DigitalWriteAsync(9, ArduinoPinValue.Low);

The commands currently implemented are:

Task<bool> PinModeAsync(byte pin, ArduinoPinMode pinMode) 

Maps to the pinMode(pin, mode) command.

Task<bool> DigitalWriteAsync(byte pin, ArduinoPinValue value)

Maps to the digitalWrite(pin, value) command.  

Task<ArduinoPinValue> DigitalReadAsync(byte pin) 

 Maps to the digitalRead(pin) command.

Task<bool> AnalogReferenceAsync(ArduinoAnalogReferenceType type)

Maps to the analogReference(type) command.  

Task<bool> AnalogWriteAsync(byte pin, byte value)

Maps to the analogWrite(pin, value) command.  

Task<ushort> AnalogReadAsync(byte pin)

Maps to the analogRead(pin) command.   

Task<bool> ToneAsync(byte pin, ushort frequency)

Maps to the tone(pin, frequency) command.  

Task<bool> ToneAsync(byte pin, ushort frequency, TimeSpan duration)

Maps to the tone(pin, frequency, duration) command.  

Task<bool> NoToneAsync(byte pin)

Maps to the noTone(pin) command.

Task<bool> ShiftOutAsync(byte dataPin, byte clockPin, ArduinoBitOrder bitOrder, byte value)

Maps to the shiftOut(dataPin, clockPin, bitOrder, value) command

Task<bool> EnableInterruptsAsync()

Maps to the interrupts() command

Task<bool> DisableInterruptsAsync()

Maps to the noInterrupts() command  

Task<byte[]> CustomCommandAsync(int registerId, byte[] data, int resultBufferSize)

Maps to any custom command added to the currently running Arduino sketch

Task<bool> BreatheLedAsync(byte pin, byte rate, byte step, byte offValue)

Cycles the intensity of a single color LED on the specified pin

Task<bool> NoBreatheLedAsync(byte pin)

Disables the call to BreatheLed()

Task<bool> PulsePinAsync(byte pin, ArduinoPinValue valueTimeSpan onDuration TimeSpan offDuration)

Pulses a pin with the given fixed intervals. This is not intended as PWM. This could be used, for example, to flash an LED for status purposes

Task<bool> NoPulsePinAsync(byte pin)

Disables a call to PulsePin()

Future Items

I am currently working on a set of built-in RGB LED effects. Note with the current library you can set any color using the analogWriteAsync method.

As project needs come up I will add additional methods to the C# library as well as the corresponding Arduino code.

Arduino Code

Library

The library is a standard Arduino library that is installed to your Libraries folder. Simply download the zip and add it to the Arduino IDE using the “Add .Zip Library…” menu under Include Library in the Sketch menu.

To learn more about installing libraries see “Installing Additional Arduino Libraries“.

Use this link to download the RPi2 Bridge library: Download Library

The library has detailed logging to the Serial device that can be enabled. Be ware that when enabling this option the application will use more memory and in some cases you may run out of memory to run your code.

See the Definitions.h file for parameters that can be changed. Any changes to this file will require a recompile and upload of the code.

Sketch

There are several samples sketches. The Standard sketch will get you up and running with the basic commands shown above. The Basic sketch is limited to the standard Arduino commands. If you need more advanced interaction use one of the other examples or build your own sketch with custom commands.

To load the various sketches use choose Examples in the File menu of the Arduino IDE and select Rpi2 Bridge and then select one of the sketches.

Advantages/Disadvantages

The greatest advantage to this is that you can get up and running quickly and utilize the Arduino in your C# code. Sensors that are very difficult use on the Raspberry Pi such as the DHT11/21/22 or your NeoPixels can now be used easily. Connect these sensors or devices to your Arduino as usual, load the libraries and then call the commands from the C# code to get them going.

Another advantage is that with the Arduino Bridge you can eliminate the need for extra devices such as a PWM for LED's or an ADC chip. The best “out of the gate” use I found was with the analog pins as well as the PWM ports since both of these are not available on the Raspberry natively (the one PWM port on the Raspberry Pi is not currently available under Windows 10 IoT Core).  

The biggest disadvantage to this approach is that it would be very easy is to under utilize the processing power on the Arduino and over use the processor on the Raspberry Pi. This is one of the reason I left room for custom commands. One of the sample sketches shows how to read the temperature and humidity from a DHT22 (will also work with DHT11). This custom command places the overhead of the specific timing requirements of this sensor on the Arduino instead of the Raspberry Pi. This sketch is called Dht22.ino.

Another disadvantage of this approach is that you lose some flexibility. For example, if you are reading a sensor using the shiftIn() command it would be very difficult to map this back to the Raspberry Pi through a single command. This approach will not fit every situation but will certainly make some previously impossible scenarios now possible.

Source: Bridging the Raspberry Pi and the Arduino


About The Author

Muhammad Bilal

I am highly skilled and motivated individual with a Master's degree in Computer Science. I have extensive experience in technical writing and a deep understanding of SEO practices.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top