3d Printing, arduino, Making, Robotics

Thing #1 in 2018 – building a servo calibrator

This is a very quick (self promoting) post – I’ve just added a new entry to my Hackster.io profile for a device I’ve built using 3d printing and electronics to help me improve the accuracy and performance of my 9g servos.

You can read more about it here – I’ve included a few images of the project below.

First, here’s the design in my CAD package (Autodesk 123D).

Servo calibrator

And here are a couple of views of the front and back – you can see that I can adjust the servo position using the dial in the top left corner. I can read the PWM signal sent to the servo from my Arduino IDE.

WP_20171230_18_00_24_Pro

WP_20171230_18_02_03_Pro

I’m going to use this device more in the coming year – I’ve planned some robotics projects which require accurate and repeatable performance from servos, which is a tall order from my cheap 9g hobby servos.

arduino, IOT, Making, Raspberry Pi 3, Robotics

Making things in 2017

I haven’t posted here in a while – I’ve kept this site mainly for programming projects, though recently I’ve been trying to concentrate more on building physical projects. I’ve posted these projects to hackster.io. Most of these use 3d printing, a Raspberry Pi 3 or an Arduino and involve some simple C/C++ programming, and interacting with a sensor.

I also created my first Arduino library for the HC-SR04 distance sensor – I use this sensor a lot in projects, and I’ve found that some existing implementations use libraries which aren’t available on all the Arduino family of devices that I use. It was good to learn how to create a re-useable Arduino library, and share my work.

I’ve pasted links to my Hackster projects below. I’ve got some plans for more projects which I’ll start in the New Year, using a lot of the knowledge that I’ve gained and shared in 2017 – more robotics, with the intention of sending data from my Arduino to a Raspberry Pi over USB serial, and using some of my .NET knowledge to monitor and control the robotics from a mobile device using a Xamarin app. I’ve a lot of things to learn and proofs of concept that I need to get through, but I’ll enjoy the journey and share as I go!

PS – I’ve started posting at Instagram – so if you’d like to see more, follow me there, and at Twitter!

Upload a sketch to an Arduino Uno with Bluetooth

arduino_bluetooth

3d printed case for a Raspberry Pi 3, and Arduino and a 5″ display

rasp_pi_arduino_printed_rig

See colours with the Adafruit TCS34725, and Arduino and a RaspberryPi 3

rasp_pi_arduino_tcs34725

A model lighthouse using an Adafruit NeoPixel ring

the_lighthouse

How accurate are my servos?

servo_rig

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.

arduino, AZ3166, MXChip

Using the MXChip AZ3166 Azure DevKit with Arduino – pulse-width modulation and servos

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: Programming the MXChip AZ3166 Azure DevKit – getting started

Part 2: Programming the MXChip AZ3166 Azure DevKit – mapping virtual Arduino pins to physical digital I/O pins

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

Another feature of the AZ3166 is its ability to output pulse-width modulated (PWM) signals. In each period, a PWM signal spends some time “on” and some time “off”. The fraction of time spent on in relation to off is known as the duty-cycle. This concept is particularly useful to control servos, as varying the duty-cycle allows us to control the angular position of the servo wiper.

Testing with on-board devices – using PWM to make the green LED glow brighter and dimmer

We can use the analogWrite function with physical pin PB3 (physical pin 7;Arduino virtual pin 19) to write a PWM signal – this pin is shared with the on-board green LED, so even without an external device, we can see the PWM make the green LED glow brighter and dimmer with the sketch below.

The sketch also writes the PWM values to the on-board OLED display.

int GREEN_PWM_PIN_PB3 = 19; 
 
void setup() 
{
 
}
 
void loop() 
{  
  for (int i = 1; i < 50; i++)
  {
    analogWrite(GREEN_PWM_PIN_PB3, i);
 
    Screen.print("PWM Value:", false);
    char buf[10];
    sprintf(buf, "%d", i);
    Screen.print(1, buf);
  }
 
  for (int i = 50; i > 1; i--)
  {
    analogWrite(GREEN_PWM_PIN_PB3, i);
 
    Screen.print("PWM Value:", false);
    char buf[10];
    sprintf(buf, "%d", i);
    Screen.print(1, buf);
  }
}

The MXChip documentation suggests that there’s actually three PWM pins – PB4 (the red LED) and PC7 (the blue LED). However I’ve not been able to prove these work on my board.

Using PWM with a servo

I mainly use PWM for controlling servos – there’s already a great library for the Arduino and servos – check out the example here – but this doesn’t work with the MXChip AZ3166.

At the time of writing, when I try to use the servo example with the AZ3166, I get the error message:

WARNING: library Servo claims to run on [avr architecture(s) and may be incompatible with your current board which runs on sam architecture(s).
#error "This library only supports boards with an AVR, SAM or SAMD processor."
exit status 1
Error compiling for board MXCHIP AZ3166.

So to get a servo working, it looked like I was going to have to directly use PWM from the AZ3166.

Unfortunately, I don’t know what the PWM pulse frequency of the AZ3166, so I can’t calculate what PWM value that I need to set in the AnalogWrite function (from 0 to 255) to Pin 7. However, I can carry out a few experiments with a servo which has analog feedback.

Normal cheap servos just receive a signal to move from a controller, and the wiper sweeps to a certain angular position, without any feedback supplied to the controller regarding whereabouts the position of the wiper. However, some servos have a means to measure the wiper’s position (usually with a potentiometer) by sending an analog voltage signal back to the controller.

I wrote a sketch (pasted below) to vary the PWM value and send to a servo. With my servo with analog feedback, I can use the analogRead function to see how the output varies with the PWM values. After some experimentation, I found that varying the PWM values between 7 and 30 swept the wiper between its minimum and maximum positions. Sending PWM values outside of this range didn’t make the wiper move.

#include <OledDisplay.h>
 
int pwmPin = 19;
int analogIn = 4;
int inputValue = 0;
 
void setup() {
	Serial.begin(9600);
	Screen.init();
}
 
void loop() {
	for (int i = 5; i < 31; i++)
	{
		analogWrite(pwmPin, i);
 
		inputValue = analogRead(analogIn);
 
		Serial.print("PWM = ");
		Serial.print(i);
		Serial.print(": Analog In = ");
		Serial.println(inputValue);
 
		Screen.print("PWM Value:", false);
		char buf[10];
		sprintf(buf, "%d", i);
		Screen.print(1, buf);
 
		sprintf(buf, "%d", inputValue);
		Screen.print(2, buf);
 
		delay(1000);
	}
}

I plotted the results (shown below).

Analog Feedback servo - AZ3166 - input vs angle

Wrapping up

The MXChip AZ3166 sends a PWM signal through pin 7 (Arduino virtual pin 19). This pin is connected to the green LED on board, and we can use PWM to adjust the brightness of this LED. I’ve also used PWM through this pin to control a servo – originally using a servo with analog feedback to measure the analog position of the servo’s wiper and determine what PWM values can be used to move the wiper back and forth.

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, MXChip

Programming the AZ3166 MXChip Azure DevKit – mapping virtual Arduino pins to physical digital I/O pins

Last time I wrote about getting started with the AZ3166 device – just a brief introduction to the on-board sensors and outputs, and I also wrote a simple application to demonstrate how to turn the red, green and blue LEDs on and off.

In that application, I mentioned that we can control the on/off status of the LEDs by writing a high or low value to three of the digital pins on the device. The numbers that I wrote digital values to were:

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

WP_20171015_19_27_55_Pro

The photo above shows a Kitronik edge connector – but you can see that the number of pins only goes up to 16. So there was a mystery here – how is it that we switch the blue LED on in the Arduino code by accessing pin 39, when there aren’t actually 39 pins on the device?

Of course the answer is that the Arduino pin numbers don’t correspond to physical pins on the device – I prefer to think of them as virtual pins. I wasn’t able to find anyone else’s research on how to map physical pin numbers to Arduino virtual pin numbers, so I’ve mapped them out in the table below.

I’ve combined data from the official pin breakout notes on GitHub and some of my own research.

AZ3166 Edge Connector

So if I want to switch on the User LED, I need to change the status of physical pin 8 (i.e. pin 8 on the Kitronik connector). And if I want to access this pin through the Arduino IDE, I need to change the status of virtual pin 45 in the Arduino IDE.

int PIN_8 = 45;
 
void setup() {
  // initialize the pins as digital output.
  pinMode(PIN_8, OUTPUT);
 
}
 
void loop() {
  // turn user LED on
  digitalWrite(PIN_8, HIGH);
  delay(1000);

  // turn user LED off
  digitalWrite(PIN_8, LOW);
  delay(1000);
}

So with the table above, we can access the all the physical digital pins on the AZ3166 MXChip device with virtual pins numbers in Arduino code.

But what about analog I/O? Next time I’ll write about measuring external analog voltages using the AZ3166 device.


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!