arduino, AZ3166, IOT, MXChip

Hacking with the MXChip AZ3166 Azure DevKit – a better PWM implementation

This is another post about the AZ3166 MXChip DevKit – this post builds on part 4 of my getting started series, and describes another way to implement pulse-width-modulation (PWM) in code.

You might wonder why I’m spending so much time with servos and this device – my personal use-case is that I’d like to use the sensors on the device alter something in the physical world – to use a classic example, when the temperature falls below a certain value, I’d like to use a servo to change the position of a thermostat.

Recap

I normally use PWM for controlling servos where I’ve not been able to use a pre-packaged library (like the one that ships with the Arduino IDE). That package doesn’t work with the AZ3166 hardware, so in a previous post I described how to use PWM and the Arduino function analogWrite to control a servo position.

The code below describes how to control a servo by sending a PWM signal to the PWM_OUT pin, and allowing 1s for the wiper to reach its final position.

#define analogIn A2
 
int inputValue = 0;
 
void setup() 
{
}
 
void loop() 
{
  for (int i = 5; i < 31; i++)
  {
    analogWrite(PWM_OUT, i);
    inputValue = analogRead(analogIn);
    delay(1000);
  }
}

My servo is a little bit special in that it has an extra pin that allows me to measure an analog value corresponding to the wiper position between 0 and 180, so I’m able to graph the position against the value that I pass to analogWrite.

The graph below shows the position of the servo against the value passed to analogWrite.

Analog Feedback servo - AZ3166 - input vs angle

I found a couple of things which were a bit odd:

  • The documentation for the device says I can control PWM through three pins corresponding to RGB_R, RGB_G, RGB_B – but I could only issue a PWM signal using analogWrite through physical pin 7 (corresponding to the software pin PWM_OUT). I could physically observe this PWM through the servo, and also through the green LED, but I couldn’t replicate this with the red or blue LEDs or their pins.
  • I can control the position of the servo by changing what value I pass to the analogWrite function – however, through a process of trial and error, I found that even though I can pass integers between 0 and 255 to analogWrite, the only values which allow me to control the servo position are between 5 and 31. Given there’s 180 degrees in a full servo sweep, that means I don’t have very much control over the servo’s angular position using analogWrite and the AZ3166. Also, guessing/trial and error isn’t a great way to achieve repeatable control.

Since writing that post, I’ve found a different way of controlling servos. The AZ3166 uses the MBED microcontroller library, mbed.h, which refers to another useful library, PwmOut.h.

I found the code for mbed.h on my machine at:

C:\Users\jeremy\AppData\Local\Arduino15\packages\AZ3166\hardware\stm32f4\1.2.0\cores\arduino\system\mbed.h

Also the code for PwmOut.h is on my machine at:

C:\Users\jez_l\AppData\Local\Arduino15\packages\AZ3166\hardware\stm32f4\1.2.0\system\drivers\PwmOut.h

How to use the PwmOut.h functions to create and control a PWM signal

I found the comment by Arthur Ma on Github very helpful when writing this post.

So let’s say I wanted to instantiate one of the three pins available for PWM use – let’s choose PB4, which is shared with the red onboard LED, RGB_R – I could declare it in my arduino code in this way.

PwmOut myServoPin(RGB_R);

which is equivalent to:

PwmOut myServoPin(PB_4);

This just says “make pin PB_4 available to send a PWM signal”.

The next bit is really useful – I can control the frequency and period of the PWM signal using the functions available in the PwmOut.h library. So if I wanted my pin’s PWM signal to have a frequency of 50Hz, i.e. a period of 20ms (because 1/50 = 0.02), I could send the instruction:

myServoPin.period_ms(20.0f)

The servo’s position is determined by the width of the pulse sent each cycle, and typically a pulse width of 1.5ms will turn the servo to its central (90 degree) position. So if I wanted to do this, I could send the instruction

myServoPin.pulsewidth_us(1500);

1500 microseconds is the same as 1.5ms. The function pulsewidth_us allows me to set the width in microseconds, and pulsewidth_ms allows me to set it in milliseconds.

I wrote the program below and uploaded it to my AZ3166 to see how the analog signal varied with pulse width, and found I can control the position of the wiper much more accurately now, and I can control it on any of Pins 5, 7, and 10 (corresponding to RGB_R, RGB_G, and RGB_B).

#define analogIn A2
 
PwmOut myServoPin(RGB_R);
 
void setup()
{
}
 
void loop()
{
  myServoPin.period_ms(20.0f);
  
  for (int i = 1; i < 3000; i++)
  {
    myServoPin.pulsewidth_us(i);
    delay(50);
  }
}

I’ve included the graph of results below.

Analog Feedback servo - AZ3166 - input vs angle - using PwmOut

There are some limitations of the cheap hobby servo which are now obvious.

  • You can see that the servo only reliably sweeps between pulse-width values of about 690 and 2270.
  • The servo jumps from 0 degrees to about a 40 degree position at a pulse width of 253microseconds, after which there is a very linear relationship.
  • The servo output reports a higher than expected value quite often, as shown by the data points above the main trend line – with this knowledge, I can anticipate this behaviour and code for it.

Wrapping up

I’ve discovered a better way of controlling pulse-width-modulation signals on the AZ3166 device using PwmOut – previously I used analogWrite with a single pin, and now I can use three pins, and control the period and pulse width to much higher degree of accuracy.

 

arduino, AZ3166, IOT, MXChip

Using the MXChip AZ3166 Azure DevKit with Arduino – coding with pin names instead of numbers

This post is part of my series on the MXChip AZ3166 DevKit – the device has lots of built in sensors, but this series focusses on interactions with external devices through the physical pins on the edge connector.

Part 1: Getting started

Part 2: Mapping virtual Arduino pins to physical digital I/O pins

Part 3: Reading analog values through physical pins

Part 4: Pulse-width modulation and servos

I own a couple of edge connector breakout boards – one from Kitronik, shown below..

Kitronik Edge Connectors

…and the other is from Sparkfun, shown below.

Sparkfun Edge Connectors

In part 2, I looked at how the physical pins on the edge connector mapped to numbers that I could use in my Arduino code. But I wasn’t really happy with this – it seemed a little unintuitive to access a green LED through the (seemingly arbitrary) virtual pin number 19.

Fortunately I’ve found a better solution. After some hunting through the source code, I’ve discovered a file named PinNames.h. This file is buried way way way down in the bowels of my computer – it’s located on my machine at the directory below:

C:\Users\jez_l\AppData\Local\Arduino15\packages\AZ3166\hardware\stm32f4\1.2.0\system\targets\TARGET_MXCHIP\TARGET_AZ3166

And this file provided me with the solution to my problem – I was able to find all the reserved variable names corresponding to pins and features on-board the AZ3166.

So instead of having to access the green LED through pin 19, instead I can access it through the alias RGB_G which the Arduino IDE already knows about.

And if I’m using it to produce a PWM signal, I can access it through PWM_OUT – which makes a lot of sense too.

From analysing the PinNames.h file, I’ve gathered these aliases together into a single image, shown below. This shows the aliases in the column named “Reserved Arduino variable name” below.

AZ3166 Edge Connector with Arduino AliasesAs well as naming all the LED pins, this matrix makes it clear that there are:

  • 2 analog pins (PA4 and PA5),
  • 11 digital pins (PB3, PB6, PC13, PB10, PB2, PB7, PB13, PB14, PB15, PB8, PB9),
  • I2C pins (PB8 and PB9),
  • SPI pins (PB13, PB14, and PB15),
  • 2 button pins (PA4 and PA10), and
  • 1 PWM pin (PB3).

How is this useful?

Previously, if I’d wanted to turn on the user LED on my AZ3166, I could have written code like this:

int USER_LED = 45;
 
void setup() 
{
  pinMode(USER_LED, OUTPUT);
}
 
void loop() 
{
  digitalWrite(USER_LED, HIGH);
}

I’ve declared the USER_LED as 45, but it’s a bit weird – someone coming to the code will maybe wonder why I’ve used this number when there’s not 45 pins on the edge connector.

But now if I want to turn on the user LED on my AZ3166, I can write code like:

void setup() 
{
  pinMode(LED_USER, OUTPUT);
}
 
void loop() 
{
  digitalWrite(LED_USER, HIGH);
}

Because the variable LED_USER isn’t declared in the code, it’s more obvious that it’s a reserved Arduino variable, and the number 45 isn’t thrown into the mix to add unnecessary cruft to the code.

Now I have a nice (and supported) way to clearly identify intent in my code, and I just need to make sure that I hook the right pin up to any external device (using my table above).

Yes – it’s just one less line! But it all counts towards cleaner and more standard code. I’ll be using this matrix in future to make my device code better.

.net core, Cake, IOT, nuget, Raspberry Pi 3

Deploying a .NET Core 2 app to a Raspberry Pi with Cake and PuTTY saved sessions

I’ve written previously about creating a .NET Core 2 template for a simple IoT application which can be deployed to the Raspberry Pi. Recently I was asked if this could be extended to use PuTTY saved sessions, which I thought was an interesting challenge.

I’ve used Cake to help me deploy my .NET Core 2 code – you can see the build.cake file up on GitHub for my template – and this script uses an add-in called Cake.PuTTY to allow me to deploy cross platform .NET Code from my Windows development machine to the Linux based Raspbian Jessie system running on my Raspberry Pi.

I’ve always just supplied my Raspberry Pi’s IP address and username through configurable parameters in the build.cake script, as shown below.

///////////////////////////////////////////////////////////////////////
// ARGUMENTS (WITH DEFAULT PARAMETERS FOR LINUX (Ubuntu 16.04, Raspbian Jessie, etc)
///////////////////////////////////////////////////////////////////////
var runtime = Argument("runtime""linux-arm");
var destinationIp = Argument("destinationPi""192.168.1.73");
var destinationDirectory = Argument("destinationDirectory"@"/home/pi/DotNetConsoleApps/RaspbianTest");
var username = Argument("username""pi");
var executableName = Argument("executableName""HelloRaspbian");

And these are used in the Cake build script in the “Deploy” target – I’ve pasted a snippet of code below which does a few things I’ve listed below the code:

var destination = destinationIp + ":" + destinationDirectory;
var fileArray = files.Select(m => m.ToString()).ToArray();
Pscp(fileArray, destination, new PscpSettings
                                    { 
                                        SshVersion = SshVersion.V2, 
                                        User = username 
                                    }
);
 
var plinkCommand = "chmod u+x,o+x " + destinationDirectory + "/" + executableName;
Plink(username + "@" + destination, plinkCommand);
  • First, it uses the PSCP function (which securely copies files) and supplies the destination in the format of an IP address, then a colon, then the directory that I want to copy files to on the remote machine – as shown below:
"192.168.1.73:/home/pi/DotNetConsoleApps/RaspbianTest"
  • The snippet also supplies the username “pi” to the PSCP function – I supplied this username in the configurable parameter section described earlier.
  • Finally it uses the Plink function to run a custom linux command on remote files – in this case, I change the permissions of the file I need to run to make it executable. Again, here I need to specify a username, and IP address and a location in the format below:
"pi@192.168.1.73:/home/pi/DotNetConsoleApps/RaspbianTest"

So my existing mechanism to deploy a file is really tightly coupled to knowing the username and the destination IP address in the code.

Can we do better with a saved PuTTY session?

I plugged my IP address and username into PuTTY, and saved them as a session named “Raspbian”. I’ve included a couple of screenshots below showing where I entered key bits of data. The first one shows the IP address, and where I name the saved session as “Raspbian”.

Putty saved session with IP address

The second one shows where I enter the username that I’d like to log on with:

Putty saved session with username

Once this “Raspbian” session was saved, I needed to find out how to use it with PSCP and Plink tools.

Using PSCP with Cake.PuTTY

This turned out to be pretty easy – instead of passing the destination IP address, I just passed in the session name. So now instead of:

"192.168.1.73:/home/pi/DotNetConsoleApps/RaspbianTest"

I’ve got:

"Raspbian:/home/pi/DotNetConsoleApps/RaspbianTest"

And I don’t need to pass the username in the settings anymore, so my code in the Cake build script for PSCP looks like this:

var destination = sessionname + ":" + destinationDirectory;
var fileArray = files.Select(m => @"""" + m.ToString() + @"""").ToArray();
Pscp(fileArray, destination, new PscpSettings
                                    { 
                                        SshVersion = SshVersion.V2 
                                    }
);

Using Plink

This turned out to be a little harder – but not too much. I couldn’t get the Cake.PuTTY plugin to work for this, but fortunately I’m able to use the StartProcess C# method with Cake to just run a Plink command.

The command I’d like to run looks like:

plink -load Raspbian [[insert a custom linux command here]]

And the C# code for this, where sessionname = “Raspbian”, is pasted below:

var plinkCommand = "chmod u+x,o+x " + destinationDirectory + "/" + executableName;
 
StartProcess("plink"new ProcessSettings {
        Arguments = new ProcessArgumentBuilder()
            .Append(@"-load")
	    .Append(sessionname)
            .Append(plinkCommand)
        }
);

So now that I can deploy with a saved session, I create a new configurable parameter in my build.cake script called “sessionname”, and leave the username and IP address fields blank.

///////////////////////////////////////////////////////////////////////
// ARGUMENTS (WITH DEFAULT PARAMETERS FOR LINUX (Ubuntu 16.04, Raspbian Jessie, etc)
///////////////////////////////////////////////////////////////////////
var runtime = Argument("runtime""linux-arm");
var destinationIp = Argument("destinationPi""<<safe to leave blank>>");
var destinationDirectory = Argument("destinationDirectory"@"/home/pi/DotNetConsoleApps/RaspbianTest");
var username = Argument("username""<<safe to leave blank>>");
var sessionname = Argument("sessionname""Raspbian");
var executableName = Argument("executableName""HelloRaspbian");

And use the target “DeployWithPuTTYSession”, which is detailed below:

Task("DeployWithPuTTYSession")
    .IsDependentOn("Publish")
    .Does(() =>
    {
        var files = GetFiles("./publish/*");
        
		var destination = sessionname + ":" + destinationDirectory;
		var fileArray = files.Select(m => @"""" + m.ToString() + @"""").ToArray();
		Pscp(fileArray, destination, new PscpSettings
					{ 
						SshVersion = SshVersion.V2 
					}
		);
 
		var plinkCommand = "chmod u+x,o+x " + destinationDirectory + "/" + executableName;
 
		StartProcess("plink"new ProcessSettings {
        		Arguments = new ProcessArgumentBuilder()
            		.Append(@"-load")
			.Append(sessionname)
            		.Append(plinkCommand)
        }
);

Updating the open source code, and how to use it

I’ve updated the source code on Github and also updated the NuGet package – you can check out my previous post on how to install this .NET Core template, and there are instructions on the project ReadMe, but the short version is that you can run the command below at a command prompt:

 dotnet new -i RaspberryPi.Template::*

And then you can create a new RaspberryPi IoT project (I called mine HelloRaspbian, yours can obviously be different) with the command:

dotnet new coreiot -n HelloRaspbian

From the generated project, run the command in the ReadMe.txt file to generate a build.ps1 file so we can run Cake:

Invoke-WebRequest http://cakebuild.net/download/bootstrapper/windows -OutFile build.ps1

Now open the build.cake file and update the parameters you want to use – the focus of this post is on a PuTTY session, and now we can update the sessionname parameter. Then in the project folder, run the command:

.\build.ps1 -target DeployWithPuTTYSession

This command will use your saved PuTTY session when deploying from a Windows machine to a Raspberry Pi running Linux, and allow you to deploy without specifying a username or IP address in your build.cake file.

Wrapping up

I’ve extended my RaspberryPi.Template for .NET Core to allow users to deploy to their Pi using a saved PuTTY session. Hopefully this small extension makes the template easier for the community to use.

arduino, AZ3166, IOT, MXChip

Programming the AZ3166 MXChip Azure DevKit – reading analog values through physical pins

In this series of posts about the AZ3166 MXChip Azure Devkit, I’ve already written about:

This post is going to be about another fairly basic concept – reading analog values – but this is the first post in the series where I’ll connect external physical components to the device. In this post, I use a potentiometer to control the size of a potential difference, and use the AZ3166 MXChip device to read and display that difference.

WP_20171022_19_25_48_Pro

Setting up the device and potentiometer

The physical set up of this experiment is straightforward, as shown in the photo above – I just connected a potentiometer to the external edge connector, with 3v and 0v connectors to each end of the potentiometer, and using physical pin 5 to measure the potential difference as the rotating element moves between the ends.

My potentiometer was 2K, but that was just what I had closest to hand.

Writing the code

This code is very similar to the standard Arduino example to measure analog potential difference.

Physical pin 5 on the edge connector translates to Arduino virtual pin 4, so in my code the sensor pin is set to 4.

The analogRead function stores a representation of the potential difference in values from 0 to 1023, where 0 represents 0v and 1023 represents 3v.

I decided added a little bit of extra functionality to the sketch:

  • The red LED’s brightness blinks with a delay in milliseconds corresponding to the analog value read – at 3v, the analog value is 1024 so the LED is red for 1.024s, and then switched off for 1.024s.
  • I’ve also used the built in OLED display function to write the analog value on the device’s screen.

The code for the sketch is below:

#include <OledDisplay.h>
 
int sensorPin = 4;
int RED_LED = 20;
int inputValue = 0;
 
void setup() {
  Screen.init();
}
 
void loop() {
 
  // Write heading to OLED display
  Screen.print("Analog Value:", false);
 
  // Read potential difference through sensor pin
  inputValue = analogRead(sensorPin);
 
  // Write this value to the OLED screen
  char buf[10];
  sprintf(buf, "%d", inputValue);
  Screen.print(1, buf);
 
  // Now flash the red LED.
  // The analog input is between 0 and 1024
  // and therefore the delay will be between
  // 0ms and 1024ms
  digitalWrite(RED_LED, HIGH);
  delay(inputValue);
  digitalWrite(RED_LED, LOW);
  delay(inputValue);
}

And the photo below shows the analog value written to the OLED display.

reading_on_oled

Wrapping up

This was a very short post about reading analog values with the AZ3166, which is a well understood concept in the Arduino world. We can use the analogRead function with the AZ3166 in the same way as we use it in Arduino code, and can read analog signals through physical pin 5 (Arduino virtual pin 4). The example where we read the how a voltage is divided by a potentiometer isn’t hugely useful on its own, but it’s a useful concept to understand to the AZ3166 for other projects – we can read values many other external peripherals using the same principles.

arduino, AZ3166, IOT, MXChip

Programming the AZ3166 Azure DevKit – getting started

I’ve been looking forward to the release of the Azure AZ3166 “MXChip IoT DevKit” – a device with lots of sensors and outputs built into the device, that I can securely connect to IoT Hubs in the Azure cloud.

I’ve a few different posts planned about this device – in this post, I’ll write about the installation process, some small issues I found, and a basic application to interact with on-board LEDs by configuring pins as digital outputs.

WP_20171015_19_26_41_Pro

The device has the on-board features:

You can read more about the Azure AZ3166 here.

So because these are all on-board, that makes accessing them and using them really easy (particularly because all of the items above have great API documentation, and most have example code).

A couple of the features of this device I found very interesting were compatibility with Arduino code, and the connecting finger which has the same form factor as the BBC micro:bit – I’d like to find out how I can use this device to work with some of the breakout boards I use with my Arduino.

Software installation and getting started

There’s already a really good description of how to get started with this kit – check it out here. There’s no point in me repeating all of that here, so in summary:

mxchip_install

Things that didn’t go as well

This almost perfectly worked out of the box for me – but I like to share the small issues I experienced because I hope they’ll be roadsigns that help other developers avoid wasting time on the same problems.

  • The DevKit only works on 2.4GHz Wi-Fi. This is in the FAQ, but I didn’t read this right off the bat, and spent some time wondering why my hardware couldn’t find my Wi-Fi. Turned out that it was because I was running both 2.4GHz and 5GHz signals out of my router – when I changed the router settings to only broadcast on 2.4GHz, my device found the Wi-Fi straight away.
  • There are lots of warnings when you try to compile any application for the device through the Arduino or VSCode environments. The Arduino compiler output, even for ‘Hello World’ type applications, was absolutely littered with warnings. I’ve pasted a few below.
#warning toolchain.h has been replaced by mbed_toolchain.h, please update to mbed_toolchain.h [since mbed-os-5.3]
...
#warning wait_api.h has been replaced by mbed_wait_api.h, please update to mbed_wait_api.h [since mbed-os-5.3]
...
#warning sleep.h has been replaced by mbed_sleep.h, please update to mbed_sleep.h [since mbed-os-5.3]
...
#warning rtc_time.h has been replaced by mbed_rtc_time.h, please update to mbed_rtc_time.h [since mbed-os-5.3]

I spent some time uninstalling and re-installing different programs, and I even to the extent of installing the software on a fresh instance of Windows 10 in case another application or library conflict was causing this – it made no difference. But ultimately, these warnings didn’t impact any applications that I deployed.

arduino_output

  • Problems displaying serial output in the Arduino IDE Serial Monitor. I’m used to deploying applications to the Arduino using the Arduino IDE, specifically targeting a COM port at deployment time. I created an application for the AZ3166 with a few “Serial.println” statements, hoping to use the Serial Monitor built into the Arduino IDE to read the output. But after deploying to the AZ3166 DevKit device, I tried to open the Serial Monitor, and got an error message saying the IDE couldn’t find the COM1 port. The solution was to manually set the COM port through the “Tools -> Port” sub-menu, and the default port selected by the IDE isn’t actually the port that serial output is sent through.

A simple blinky application for the DevKit

There is already an example for the on-board RGB LED, but I wanted to work at a lower level to access on-board LEDs, rather than using existing libraries. I just needed to find out what Arduino pin numbers corresponded to the LEDs on the DevKit device.

I found that the numbers corresponding to the three basic LED colors are:

  • Red LED – Arduino pin 20
  • Green LED – Arduino pin 19
  • Blue LED – Arduino pin 39

I’ll post more about DevKit to Arduino pin mappings in a later post.

With this knowledge, it was very simple to create a variation on the standard “blinky” application, where I turn the red LED on and off, then the green LED, and finally the blue LED.

I’ve pasted the code below – just like regular Arduino C code.

int RED_LED = 20;
int GREEN_LED = 19;
int BLUE_LED = 39;
 
void setup() {
  // initialize the pins as digital output.
  pinMode(RED_LED, OUTPUT);
  pinMode(GREEN_LED, OUTPUT);
  pinMode(BLUE_LED, OUTPUT);
}
 
void loop() {
  // turn red LED on
  digitalWrite(RED_LED, HIGH);
  delay(1000);
 
  // turn red LED off
  digitalWrite(RED_LED, LOW);
  delay(1000);
 
  // turn green LED on
  digitalWrite(GREEN_LED, HIGH);
  delay(1000);
 
  // turn green LED off
  digitalWrite(GREEN_LED, LOW);
  delay(1000);
 
  // turn blue LED on
  digitalWrite(BLUE_LED, HIGH);
  delay(1000);
 
  // turn blue LED off
  digitalWrite(BLUE_LED, LOW);
  delay(1000);
}

So much for modifying the status of an LED on-board – now how about using code to adjust the digital statuses of pins on the connecting finger?

WP_20171015_19_27_55_Pro

First we have to be able to physically attach to the connecting finger, which I was able to do using a connector breakout. But I didn’t know what the numbers on the connector board corresponded to…next time I’ll write about using the connector.


About me: I regularly post about Microsoft technologies – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

.net core, arduino, Bifröst, IOT, Making, Raspberry Pi 3

Using .NET Core 2 on Raspbian Jessie to read serial data from an Arduino

I’ve previously written about how to use the System.IO.Ports library in .NET Core 2 to read serial data from an Arduino using a Windows 10 PC – but this library doesn’t work for Linux machines. This time I’m going to look at how to read data from an Arduino over USB with .NET Core running on a Raspberry Pi 3 with Raspbian Jessie.

There’s a few steps to getting this running.

  • First you’ll need:
    • A development machine (I’m using Windows 10),
    • A Raspberry Pi 3,
    • An Arduino,
    • A USB cable to link your Arduino and Raspberry Pi.
  • Next I’ll write a simple sketch and deploy it to my Arduino.
  • I’ll connect the Arduino to my Raspberry Pi 3, and check that the Pi can see my Arduino and the serial input using minicom.
  • Finally I’ll write and deploy a .NET Core application written in C# to my Raspberry Pi, and I’ll show how this application can read serial input from the Arduino.

As usual, I’ve uploaded all my code to GitHub and you can see it here.

For a few of the steps in this guide, I’ll refer to other sources – there’s not a lot of value in me writing a step by step guide for things which are commonly understood.

For example, I have a fresh install of Raspbian Jessie on my Raspberry Pi 3, and then I set up SSH on the Pi. I also use Putty, PSCP, Plink and Cake.net to deploy from my Windows machine to the Raspberry Pi (I’ve blogged in detail about this here).

Writing a sketch that writes serial data from the Arduino

In a previous post, I use VSCode to deploy a simple Arduino application that writes serial data. I could have used the Arduino IDE just as easily – and it’s widely known how to verify and upload sketches to the Arduino, so I’m not going to go into this part in great detail.

The code for the Arduino sketch is below:

int i = 0;
 
void setup(){
  Serial.begin(9600);
}
 
void loop(){
  Serial.print("Hello Pi ");
  Serial.println(i);
  delay(1000);
  i++;
}

One thing worth noting is that the Baud rate is 9600 – we’ll use this information later.

I can test this is writing serial data by plugging the Arduino into my Windows 10 development machine, and using VSCode or the Arduino IDE. I’ve shown a screenshot below of the serial monitor in my Arduino IDE, which just prints the text “Hello Pi” followed by a number. This confirms that my Arduino is writing data to the serial port.

screenshot.1502137097

Let’s test the Raspberry Pi can receive the serial data

Before writing a C# application in .NET Core to read serial data on my Raspberry Pi, I wanted to test that my Pi can receive data at all (obviously after connecting my Arduino to my Raspberry Pi using a USB cable).

This isn’t mandatory for this guide – I just wanted to definitely know that the Pi and Arduino communication was working before starting to write my C# application.

First, I need to find the name of the serial port used by the Arduino. I can find the names of serial ports by using PuTTY to SSH into my Pi 3, and then running the command:

ls -l /dev | grep dialout

Before connecting my Arduino UNO to my Raspberry Pi, this reports back two serial ports – ttyAMA0 and ttyS0.

screenshot.1502138314

After connecting my Arduino to my Raspberry Pi, this now reports back three serial ports – ttyACM0, ttyAMA0, and ttyS0.

screenshot.1502138155

Therefore I know the port used by my Arduino over USB is /dev/ttyACM0.

As an aside – not all Arduino boards will use the port /dev/ttyACM0. For example, I repeated this with my Arduino Nano and Arduino Duemilanove, and found they both use /dev/ttyUSB0, as shown below:

screenshot.1502211857

But for my Arduino Yun and my Arduino Primo, the port is /dev/ttyACM0.

screenshot.1502212282

So the point here is that you need to check what your port name is when you connect it to a Linux machine, like your Pi – the port name can be different, depending on what kind of hardware you connect.

Finally, if you’re interested in why “tty” is used in the Linux world for ports, check out this post.

Tools to read serial data

Minicom is a serial communication program which will confirm my Pi is receiving serial data from the Arduino. It’s very easy to install – I just used PuTTY to SSH into my Pi 3, and ran the command:

sudo apt-get install minicom

Then I was able to run the command below, using the port name (/dev/ttyACM0) and the Baud rate (9600).

minicom -b 9600 -o -D /dev/ttyACM0

If the Raspberry Pi is receiving serial data from the Arduino, it’ll be written to the SSH terminal.

Some posts I’ve read say it’s necessary to disable serial port logins to allow the Arduino to send messages to the Raspberry Pi, and modify files in the “/boot” directory – but on Jessie, I didn’t actually find this to be necessary – it all worked out of the box with my fresh install of Raspbian Jessie. YMMV.

Another alternative to prove serial communication is working is to install the Arduino IDE onto the Raspberry Pi, and just open the serial monitor on device. Again, installing the IDE on your Pi is very easy – just run the command below at a terminal:

sudo apt-get install arduino

This will even install an Arduino shortcut into the main Raspbian menu.

screenshot.1502139590.png

Once you’ve started the IDE and connected the Arduino to a USB port, select the serial port /dev/ttyACM0 (shown available on the Tools menu in the screenshot below):

screenshot.1502139935

Then open the serial monitor to check that the “Hello Pi” messages are coming through correctly (as shown below):

screenshot.1502140145

Writing the C# application

Now that I’m sure that the physical connection between the Arduino and Pi works, I can start writing the C# application.

TL:DR; I’ve uploaded my working code to GitHub here.

When writing my code, I wanted to stay close to the existing API provided by Microsoft in their library System.IO.Ports, which allows Windows machines to read from the serial port (I’ve blogged about this here). I was able to look at their source code on GitHub, and from this I designed the serial port interface below:

using Bifrost.IO.Ports.Core;
using System;
 
namespace Bifrost.IO.Ports.Abstractions
{
    public interface ISerialPort : IDisposable
    {
        int BaudRate { getset; }
 
        string PortName { getset; }
 
        bool IsOpen { getset; }
 
        string ReadExisting();
 
        void Open();
        
        event SerialDataReceivedEventHandler DataReceived;
 
        void Close();
    }
}

I like interfaces because consumers can use this interface, and don’t care if change my implementation behind the interface. It also makes my libraries more testable with mocking libraries. You can see this interface on GitHub here.

The next task was to design a .NET Core implementation for this interface which would work for Linux. I’ve previously done something similar to this for I2C communication, using P/Invoke calls (I’ve written about this here). After reading the documentation and finding some inspiration from another open source sample here, I knew I needed the following six P/Invoke calls:

[DllImport("libc", EntryPoint = "open")]
public static extern int Open(string portName, int mode);
 
[DllImport("libc", EntryPoint = "close")]
public static extern int Close(int handle);
 
[DllImport("libc", EntryPoint = "read")]
public static extern int Read(int handle, byte[] data, int length);
 
[DllImport("libc", EntryPoint = "tcgetattr")]
public static extern int GetAttribute(int handle, [Outbyte[] attributes);
 
[DllImport("libc", EntryPoint = "tcsetattr")]
public static extern int SetAttribute(int handle, int optionalActions, byte[] attributes);
 
[DllImport("libc", EntryPoint = "cfsetspeed")]
public static extern int SetSpeed(byte[] attributes, int baudrate);

These calls allow me to:

  • Open a port in read/write mode and get an integer handle to this port;
  • I can also get a list of attributes, specify the baudrate attribute, and then set these attributes.
  • Given the handle to the port, I can read from the port into an array of bytes.
  • Finally, I can also close the connection.

I’ll look at the most important elements below.

Opening the serial port

If we have instantiated a port with a name (/dev/ttyACM0) and a Baud rate (9600), we can use these P/Invoke calls in C# to open the port.

public void Open()
{
    int handle = Open(this.PortName, OPEN_READ_WRITE);
 
    if (handle == -1)
    {
        throw new Exception($"Could not open port ({this.PortName})");
    }
 
    SetBaudRate(handle);
 
    Task.Delay(2000);
 
    Task.Run(() => StartReading(handle));
}

You’ll notice that if the request to open the port is successful, it’ll return a non-negative integer, which will be the handle to the port that we’ll use throughout the rest of the class.

Setting the Baud rate is straightforward – we get the array of port attributes using the port’s handle, specify the Baud rate, and then send this array of attributes back to the device.

private void SetBaudRate(int handle)
{
    byte[] terminalData = new byte[256];
 
    GetAttribute(handle, terminalData);
    SetSpeed(terminalData, this.BaudRate);
    SetAttribute(handle, 0, terminalData);
}

I give the port a couple of seconds to settle down – I often find that the first few messages come through out of order, or with missing bytes – and then run the “StartReading” method in a separate thread using Task.Run.

Reading from the serial port

Reading from the port is quite straightforward too – given the handle, we just use the P/Invoke call “Read” to copy the serial data into a byte array which is stored as a member variable. Before invoking an event corresponding to a successful read, I check that there actually is valid data returned (i.e. the return value is non-negative), and that any data returned isn’t just a single newline character. If it passes this test, I pass control to the event handler for the DataReceived event.

private void StartReading(int handle)
{
    while (true)
    {
        Array.Clear(serialDataBuffer, 0, serialDataBuffer.Length);
 
        int lengthOfDataInBuffer = Read(handle, serialDataBuffer, SERIAL_BUFFER_SIZE);
 
        // make sure there is data in the buffer, and check if it's just one character that it's not just a newline character
        if (lengthOfDataInBuffer != -1 && !(lengthOfDataInBuffer == 1 && serialDataBuffer[0== ASCII_NEWLINE_CODE))
        {
            DataReceived.Invoke(thisnew SerialDataReceivedEventArgs());
        }
    }
}

Putting it all together

I’ve put my interfaces and implementations into separate .NET Standard libraries so that I can re-use them in my other .NET Core applications. And when I write a sample program for my Raspberry Pi to read from my Arduino, the implementation is very similar to the implementation that works for Windows x86/x64 devices reading from an Arduino (covered in this post).

using Bifrost.IO.Ports;
using Bifrost.IO.Ports.Core;
using System;
 
namespace SerialSample
{
    class Program
    {
        static void Main(string[] args)
        {
            var serialPort = new SerialPort()
            {
                PortName = "/dev/ttyACM0",
                BaudRate = 9600
            };
 
            // Subscribe to the DataReceived event.
            serialPort.DataReceived += SerialPort_DataReceived;
 
            // Now open the port.
            serialPort.Open();
 
            Console.ReadKey();
 
            serialPort.Close();
        }
 
        private static void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            var serialPort = (SerialPort)sender;
 
            // Read the data that's in the serial buffer.
            var serialdata = serialPort.ReadExisting();
 
            // Write to debug output.
            Console.Write(serialdata);
        }
    }
}

Once I’ve compiled my project, and deployed it to my Raspberry Pi (using my build.cake script), I can SSH into my Pi and run the .NET Core application – and this displays the “Hello Pi” serial output being sent by the Arduino, as expected.

screenshot.1502145572

Wrapping up

It’s possible to read serial data from an Arduino connected by USB to a Raspberry Pi 3 using C#. Obviously the code here is just a proof of concept – it doesn’t use handshaking, parity bits or stop bits, and it only reads from the Arduino, but writing back to the serial port could be achieved using the P/Invoke call to the “write” function. Hopefully this post is useful to anyone trying to use serial communications between a Raspberry Pi 3 and an Arduino.


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!

 

arduino, IOT, Making, PCB Manufacture

Upload a sketch to an Arduino UNO with bluetooth using the Adafruit Bluefruit EZ-Link breakout

I’m working on ways to make my Arduino UNO communicate with my Raspberry Pi 3 over a serial connection, and I’ve used a USB cable to connect the two devices together.

But because the Type-B USB connector on the Arduino is being used, I don’t have a convenient way to upload sketches to the Arduino UNO from my development machine.

I can obviously disconnect the USB connector from the Arduino UNO and connect it to my development machine, but this gets kind of old after a while, and I’d like an easier way to upload sketches.

So I dug deep into my box of electronic bits and pieces, and fortunately found I’ve got another way to do this – I can add bluetooth capability to my Arduino UNO with the Adafruit Bluefruit EZ-link breakout board.

First connect the board to the Arduino UNO

I could have done this with wires and a breadboard, but I decided to make a custom shields with some copper clad PCB board and my Shapeoko.

WP_20170803_11_23_20_Pro

Fortunately there was very little soldering to be done on my custom PCB as my soldering could be better!

WP_20170803_11_23_35_Pro

 

I designed the PCB according the pinout recommended by Adafruit, which is:

EZ-Link Arduino UNO
GND GND
DSR Not connected
V-IN 5V
Tx Digital Pin 0 (Rx)
Rx Digital Pin 1 (Tx)
DTR 1uF in series with Reset

Attaching the breakout board to a custom made PCB makes the whole device more self contained and I can also add other Arduino shields on top.

I found out afterwards that Adafruit actually sells something similar to this already – a Bluefruit EZ-Link Shield.

Now pair the Bluefruit board with a development machine

Adafruit provide some really good documentation for pairing the Bluefruit module with a Windows 7 machine – but I’ve written my own notes before for the Windows 10 operating system.

My Arduino is powered by the USB connection to my Raspberry Pi, so once I attached the shield to the Arduino the blue power light came on immediately. The next step was to pair the Bluefruit device with my development machine.

My machine has bluetooth v4.0 on board, but I could have used an after-market bluetooth dongle like this one – it’s important to get one that supports bluetooth v4.0, some of the cheaper dongles do not support v4.0.

From Windows 10, I typed “Bluetooth” into the search box on the taskbar, and the results gave me the option to select “Bluetooth and other devices settings”.

screenshot.1501708578

I clicked on the “+” button beside the text “Add Bluetooth or other device”, which opened the screen below.

screenshot.1501679214

I clicked on the Bluetooth option, which opened the screen below, and this shows the Adafruit EZ-Link device.

screenshot.1501679192

I selected the Adafruit device for pairing, and received the success message below.

screenshot.1501679253

So at this point, it’s possible to upload sketches to the Arduino through the Bluetooth COM port – and in the image below, you can see that even though my Arduino isn’t connected by USB cable to my development machine, the serial port COM6 is available to me.

screenshot.1501710670

I talked about how to use VSCode to develop and deploy to the Arduino last time, and it works exactly the same way in VSCode.

And as far as the Arduino is concerned, this is just another COM port, as if the Arduino was directly connected to the PC using a USB cable. I don’t need to do any further set up, and I can verify and upload my sketch to the Arduino UNO wirelessly through COM6 (it’ll probably be different on another machine). It’s a little bit slower to transfer a sketch over the air, but at least it’s wireless.

Wrapping up

This was a short post about how to wirelessly deploy sketches to the Arduino using the Adafruit Bluefruit EZ-Link breakout. When I can’t use the Arduino’s on board USB port, this device makes my Arduino development much more convenient. If you have this device in your toolkit, hopefully you find this post useful!


About me: I regularly post about .NET – if you’re interested, please follow me on Twitter, or have a look at my previous posts here. Thanks!