About VK5ZM

Another Ham who was bitten by the Fox Hunting Bug in the early 90's. Participated in numerous National DF championships and likes nothing more than the challenge of finding *any* hidden radio transmitter. Has been involved in HAB experiments since 2010. Goal is to fill his Toyota Hilux so full of DF gear that he has to buy a Landcruiser.... Approximately half way there.

DMX RS485 Interface

After having configured a Color Kinetics RGB LED driver I need a way to generate a DMX stream to validate it worked as expected. I searched my project boxes for some RS485 USB interfaces in my workshop, but as usual I had put them in a “special” place. So there was nothing for it but to crack out an Arduino and the soldering iron.

This isn’t the first RS485 interface I’ve built for an Arduino, but if you haven’t done it for DMX then I suggest reading this article on Instructables (click) that explains why the standard RS485 shields available are not suitable. However this interface (click) is one that I have found to work, just note that the TX and RX should be Pins 1 & 0 respectively and the enable input (ENB) should be connected to Pin 2.

I like to use the Freetronics Basic Protoshields when building with Arduino’s they are different around the connectors and seem to have more clearance. The photo of the interface (right) was taken just prior to the RS485 safety resistors being mounted across the output of the RS485 bus.

I’d caution anyone against building RS485 interfaces without these safety resistors. With new RS485 receivers you can get away with out using them, but with older receivers they are mandatory. In a nutshell the safety resistors ensure there is always a 200mV differential across the receiver input that ensures the output of the receiver sits in the “UART idle” state. Otherwise what you find is the receiver will either not toggle it’s output or oscillate, in either case it doesn’t work. You just never know if the device you’re talking too has an old or new receiver, so it’s safer (boom boom) to have them than to not. YMMV.

Once the basic interface was built I then realised that this wasn’t going to work with your standard Arduino Uno. You can’t share the UART with both the USB programming and serial debug interface with the RS485 driver without their being bus contention problems, steering resistors can be used with varying success. So the simple solution to this problem was to switch to a Arduino Leonardo, since they have both an on-chip USB interface for debugging and programming and a separate UART connected to pins 0 and 1. This was not without it’s own problems, so much so there is separate blog post to deal with these (click).

So all that was missing was a DMX library. Now this is something of a mine field, there are so many DMX libraries it got confusing finding the right one. After a lot of searching, downloading and fiddling I settled on the “DMX Library for Arduino” written by William van der Meeren (click). What set this library apart was it would transmit a full DMX 512 byte frame every 26ms from a much smaller buffer held in RAM that was non-blocking. It also has a mechanism to signal to the main loop when it had finished a full frame (click) allowing the firmware to quickly update the DMX channels and then allow it to carry on. This meant that colour washes could be kept atomic and smooth.

Below is one of the test programs that I wrote using the DMX library to test a few ideas on what may be possible with this interface. I have also included the PlatformIO config file that includes the necessary build flags;

#include <Arduino.h>
#include "Conceptinetics.h"
#include "math.h"

#define debug_output_enable()	Serial.begin(115200); while (!Serial){}
#define debug_output_f(...)    	Serial.print(F(__VA_ARGS__))
#define debug_msg_f(...) 	Serial.println(F(__VA_ARGS__))
#define debug_output(...)      	Serial.print(__VA_ARGS__)
#define debug_msg(...) 	      	Serial.println(__VA_ARGS__)

// structure to hold RGB colour information
typedef struct
{
  uint8_t red;
  uint8_t green;
  uint8_t blue;
} mycolour_t;

// DMX addressing information
const uint8_t DMX_DEVICES = 6;
const uint8_t DMX_CHANNELS_PER_DEVICE = 3;
const uint8_t DMX_CHANNELS_MIN = 1;
const uint8_t DMX_CHANNELS_MAX = (DMX_DEVICES*DMX_CHANNELS_PER_DEVICE);
const uint8_t DMX_BREAK_USEC = 200;
const uint8_t DMX_TXRX_PIN = 2;       // pin 2 used for RS485 TX/RX pin

// setup DMX master control object
DMX_Master dmx_master( DMX_CHANNELS_MAX , DMX_TXRX_PIN );

// convert sine wave to half wave, clamp value to zero for non-negative
// sine ouptut
float non_negative( float degrees )
{
  if( sin( degrees * DEG_TO_RAD ) < 0.0 )
    return 0.0;
  else
    return degrees;
};

// Initialise our hardware
void setup( void ) 
{
  /* Leonardo has separate USB serial port which is enabled when 
     plugged in.
  */
  debug_output_enable();

  // display something to user when deubgging
  debug_output_f("Mallee DMX Test\r\n Initialising...");

  // setup our DMX master
  dmx_master.enable();
  dmx_master.setChannelRange( DMX_CHANNELS_MIN, DMX_CHANNELS_MAX, 0 );
  dmx_master.setManualBreakMode();
  debug_msg_f(" Done!");

  // all done
  return;
}

// our main loop that will do stuff
void loop( void )
{
  /* Check if the DMX master is waiting for a break to happen, 
     the function below runs every 26ms (44Hz) which is the DMX
     maximum frame rate.
  */
  if( dmx_master.waitingBreak() )
  {      
    // Temp storage for RGB information
    mycolour_t colour;

    // local count variable
    static float angle = 0.0;

    // how much we'll increment our counter per frame
    angle += 0.25;

    //if we overflow wrap back to zero
    if( angle > 360.0 )
      angle = 0.0;

    /* calculate out our RGB values, including our phase offsets;
       not a lookup table in sight !
    */
    colour.red = (uint8_t)( 255 * sin( non_negative(angle + 120.0) * \ 
                            DEG_TO_RAD) );
    colour.green = (uint8_t)( 255 * sin( non_negative(angle + 0.0) * \
                              DEG_TO_RAD) );
    colour.blue = (uint8_t)( 255 * sin( non_negative(angle + 240.0) * \
                             DEG_TO_RAD) );
	
    /* Now we can update all of the attached devices, note that the DMX
       channels and the lamps are configured by the Color Kinetics 
       QuickPro software separately.
    */
    for( uint8_t i = 0; i < DMX_DEVICES; i++ )
    {
      //calculate DMX address for each lamp device
      uint8_t addr = (i * DMX_CHANNELS_PER_DEVICE) + DMX_CHANNELS_MIN;

      //update individual channels are sequentially addressed
      dmx_master.setChannelValue(addr+0, colour.red );
      dmx_master.setChannelValue(addr+1, colour.green );
      dmx_master.setChannelValue(addr+2, colour.blue );
    }    

    // Generate break and continue transmitting the next frame
    dmx_master.breakAndContinue ( DMX_BREAK_USEC );
  }
}
;PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:leonardo]
platform = atmelavr
board = leonardo
framework = arduino
monitor_speed = 115200
build_flags =
  -D USE_DMX_SERIAL_1
  -D __DEBUG_ENABLED__

Color Kinetics PDS-150e

The Color Kinetics PDS-150e is an integrated power supply and driver that was popular during the early 2000’s. It is also the “magic” piece that I need for the Solar Mallee Trees project I’ve been working on.

Inside the unit is a power supply and integrated driver. Each of the six output channels are capable of driving up to 25W of RGB LED’s. So this is easily able to power a single Colorburst 4″ RGB LED per channel, they use just 10W. There are four RJ45 connectors across one size of the PCB that present Ethernet, DMX IN, DMX LOOP and DMX Repeater capabilities. I was certainly keen to see what we could do with the Ethernet interface. For these RGB LED drivers Color Kinetics offers a tool called QuickPlay Pro (TM) as a free download for Windows PC’s.

To use the Ethernet interface is relatively straight forward. The PDS-150e device is already programmed with an IP address somewhere within the classic 10.x.x.x Class A network. So I configured a Windows 7 laptop Ethernet interface with the arbitrary IP of 10.0.73.1 with a subnet mask of 255.0.0.0. I was simply crossing my fingers this wasn’t where the controller was, but it would allow the laptop and PDS-150e to find each other. I was pleased once QuickPlay Pro was started that I could find my PDS-150e listed in the “controller” drop down box. At a guess QuickPlay Pro and the PDS-150e either listen to a broadcast address or have some form of mDNS capabilities to “discover” each other.

Once I had connected QuickPlay Pro to the PDS-150e I was able to test the lamps individually, experiment with colour washing and configure the DMX channels and addressing. Below is an example of the colour wash function within QuickPlay Pro;

(C) 2019 Faith Coleman

I will have to say I’ve been doing this type of work for many years and Lighting Control Software has always been a painful experience. Either the software or devices would do “odd” things, not work, fart, spit, sulk or have quirks that required work around’s. However I was pleasantly surprised when QuickPlay Pro just worked, did what it said it would do without any fuss and or bother. So the Color Kinetics Engineering team have done a great job making this system work so well.

Once I’d gotten over my surprise it was a simple task to configure the RGB Lamps that I had into a sequential series of DMX addresses. Each of the Colorburst RGB lamps uses one DMX channel per colour (i.e. 3 channels for RGB), so I simply stringed the lamps together starting at address one;

DMX ADDR:  01  02  03  04  05  06  ........ 13  14  15
CB4 CH#:   R1  G1  B1  R2  G2  B2  ........ R5  G5  B5
Lamp       \---(1)---/ \---(2)---/ ........ \---(5)---/

One thing I did notice is that each Colorburst 4″ RGB lamp has a unique serial number that is displayed in QuickPlay Pro. This suggests that once each lamp is configured this won’t change if you start swapping the port it is connected too. I was pleased to find this is indeed the case, so once I know which tree each lamp is mounted too I can reconfigure the DMX addressing to be a little more logical.

Now I just need to start sending DMX at the controller and see if the lamps respond. Time to go and find a RS485 interface.

Curse of the Black Pearl, Err wires…

Having serviced and re-furbished a good portion of the engine and accessories I had one more small trivial, quick task to perform. That was to replace some very manky looking battery terminals. So out with the beak nosed cutters, lop the terminal off, strip back the wire to reveal, the copper wires were all black. Oh dear it was going to be one of “those” days.

The picture above shows the very manky looking battery terminals and the original orientation of the battery. For reference the terminal in the top of the image is the battery positive, the copper pipe above it is the cold water side of the heat exchanger, err yes that is technically earthed and the battery un-restrained. There is no way we could leave it like that.

So getting back to the wiring, at some point in this poor boats life it had been wired up with standard automotive copper wiring. Now for the majority of the time this is fine in cars and perhaps houses, but in marine environments where corrosion is rife this is a recipe for disaster. The black manky looking stuff is actually a form of copper oxide which is non-conductive and hard to remove. Once it starts to form it doesn’t stop until every strand along the entire length of (and within) the cable has oxidised as well. The worst part is the wires were to the starter motor which relies on a very low impedance.

Thankfully there is a local Jaycar electronics store around the comer that caters to the “Doof Doof” car audio community. This car audio community seems to like big high power amplifiers that use too much gold plating (IMHO) on their connectors and fuse blocks, but it does however mean they stock marine grade Tinned Copper wire in useful sizes from 14 gauge through to 4 gauge in both Red and Black. Better yet it is fine stranded with a soft silicon durable sheath making it very flexible and a pleasure to work with. Below are the ones that I like to work with, hopefully the part numbers out live any URL changes that may occur on the Jaycar site;

If you haven’t already found self sealing automotive crimp terminals I suggest you wander off and google these too I’d never seen one until I stumbled across them on one of my YouTube feeds, a big thanks to Damien & Jess from Project Brupeg for putting me onto these when they wired their wheel house. There are also nice kits you can get from eBay for reasonable prices. This type of connector once crimped, you hit with the heat gun and they shrink and seal the end of the connector. It certainly saves a heap of time not having to cut and use a separate small piece of glued heat shrink. Better yet you can see the internals with the heatshrink being semi-transparent, which means if they corrode you’ll find out before it’s too late.

So once armed with cable, connectors and a few roles of Electrical tape it was time to start cutting wires to find the extent of the black wire syndrome. Needless to say I ended up rewiring the entire engine bay, from battery to starter motor, alternator to battery and the remaining Kettering ignition system.

I was thankful that the wiring between the engine and gauges while not tinned had not suffered anywhere near the same level of corrosion. So I stopped here noting that at some time soon I’ll be up under the dash re-wiring this as well. So the proof is in the pudding, here’s a few photos of the completed work.

You may also notice that I’ve turned the battery through 270 degrees so that the terminals now face the bow of the boat. This puts as much distance between the battery terminals and the engine and accessories as possible. Directly underneath the battery is a false floor where I should be able to screw a hold down strap to secure the battery in place. Not forgetting to seal the screws since this is a wet bilge. Unfortunately the cover that goes over the battery no longer fits, it’s pretty clear why the previous owner had rotated the battery to where I found it. We don’t technically walk where the battery sits, so I’m thinking of raising up the floor here just an inch to clear the terminals. I’ll do this when I make a new engine cover.

Mallee Solar Tree Project

I’m not sure sometimes how I end up getting involved with community projects and this one is no exception. This one started as a three way trade involving my ex-wife, her neighbour and a knee operation which of course all sounds very suspect. However the crux of the problem was a community group had acquired an art sculpture through the usual mate of a mate kind of thing. However as this sculpture was passed along bits were lost, forgotten, used for other things and/or misplaced. In a nutshell it wasn’t complete and no one knew if it even worked, or how. Well my ex-wife knew that I’d worked professionally on lighting control systems in a past life, so could I take a look at it. So here we go !

Image copyright Natasha Stewart
https://www.weekendnotes.com/profile/103314/

So what were we dealing with ? It turns out the art sculpture in question was the “Solar Mallee Trees” that were designed by MPH architects and were previously installed just outside the Festival Theatre in the Adelaide CBD. They were recently removed as part of a “refresh” of the entire site.

These “trees” were made from curved steel structures, had solar panels mounted to the top of them and a Color Kinetics lighting system. It uses LED RGB spot lights to wash the colour under the solar panels. However while the spotlights were present, there was no sign of any Solar Inverters, power supplies or controllers. This was suddenly not going to be easy.

Looking closely at what was present I found the LED spotlights were Color Kinetics Colorburst 4 (TM) and they appeared in good shape. These lamps require three wires so there is more to them than just applying power. Ok time to go and call a few people I know still work in the lighting industry.

Thankfully this was a fairly common lighting control system used in the Noughties and Color Kinetics (CK) still have much of the data, manuals and software available online.

My lighting industries contacts had advised me that I was up for a few thousand dollars to replace lamps, drivers and power supplies. So rebuilding what I had in hand was beginning to look promising.

To drive the Colorburst 4″ spot lights what we needed was a custom PSU that included driver and smarts, called a CK PDS-150e. What I really liked was this PSU/Driver had a separate DMX input and Ethernet programming ports; making it fairly easy to control once configured. Generating DMX information is fairly easy now days with software being available for windows and linux PC’s with the right RS485 serial interface. I’d certainly been there and done that many times in the past, so bringing up this system by rights shouldn’t be hard.

So finding a CK PDS-150e driver turned out to really easy, there were a number of them on eBay for just a few hundred dollars. It was worth the risk to see if I could get this working, if not I could always drop it back onto eBay and pass it on. So a CK PDS-150e was duly ordered and now it was time to read the manual a few times, download some software while the unit was shipped from Greece to Australia.

More to come.

Changing the Raw Water Impeller

During the first sea trials of my Nereus at wide open throttle (WOT) it would slowly overheat with the coolant temperature rising from 85-ish degrees up over 100 degrees celcius. If I slowed down and dropped the revs the temperature would again slowly go back down. So either the cooling system was not quite able to pump enough raw water through the heat exchanger or the engine is producing too much heat. I certainly know that the heat exchanger is not blocked since it had been serviced recently.

When purchasing the boat the original owner had told us he’d changed the raw water impeller “a couple of years ago” so I’d purchased a spare impeller but not bothered to change it. The pump is right at the bottom of the engine in the bilge, so it’s a bit of a pain to get too which might also contribute to why it had not been changed.

Anyway I’d run the engine for about an hour on tap (towns) water but only at or just above idle, not under heavy load. So I decided to change the pump for peace of mind. A quick check on the internet and there was a YouTube video from 350vic that gave me some clues as to what was necessary, it didn’t look that hard.

Famous last words.

So first I had to get the pump out of the boat an supported by something that would make it easy to work on. Getting this pump out of the boat was as hard as I feared. There is not quite enough adjustment on the belt tension bolt to allow the belts to slip on and off the pulleys, in fact it hits the sump and if you’re not careful you can punch a hole in it. The bolts that support the lateral load of the pump and hold it in place you just can’t get a ring spanner on, so you have to feel for them using an open ended spanner and shift them a hairs breath, flip spanner, shift, flip spanner. If you’ve ever been forced to do this you will know how slow it is to back the bolt out just half a turn to loosen things off. With a few minor changes to bolt locations this could have been easily serviceable, oh well I do like a good project.

So after a good hour of extraction I managed to get the pump out an into a vice for support, here’s a series of shots that shows the pump being supported, the rear cover having been removed. The impeller didn’t look that bad, there’s a bit of wear on the rear of the vanes but there were no missing vanes and the pump wasn’t hard.

I’m not a fan of using the two screw drivers method for impeller extraction, bruising the face of the pump is just a no no. So for my first time I used vice grips and a slide hammer, being careful not to loose the bronze Woodroffe key. I will certainly be looking at a set of impeller pullers when I have some spare funds in the bank.

Above you can see the backing plate and Woodroffe key, along side the pump housing with the new impeller ready to go back in. So what they don’t tell you about re-assembling these pumps is you’ve got to bend the vanes of the new impeller, while inserting the impeller into the housing, which is offset to one side AND you need to catch the Woodroffe key in one movement. Oh and if you’re supporting the pump in a vice, then make sure the front of the pump is chocked otherwise everything tries to run away.

Needless to say it took me four attempts and a coffee after two to settle my frustration before I managed to get everything aligned and the pump re-assembled. After the first attempt I also marked the Woodroffe key location on the back of the shaft and the impeller so I had a chance of keeping them aligned. It certainly helped to dob a bit of grease on the back of the Woodroffe key and make sure the front edge was slightly down, but not too far down or it would then force the key down and lock it against the pump wall. Sigh.

To prevent the pump running dry I also lubricated the pump walls with a little marine clear grease, I see on some forums people use silicon spray or lanolin, YMMV.

Hooray ! There’s the proof that I did get it back together and didn’t just go and buy a new pump out of frustration. I also dobbed a little “never seize” on the threads of the screws so it should come apart again in a year or so.

It was then just a matter of putting it back into the boat, reversing the disassembly process. Reminding me again why I need to replace the pump mounting assembly.

First Sea Trials

It’s never a good idea to go and place a new boat in the wire and head off into the blue yonder and not expect problems. So to keep things simple I arranged a couple of mates to help and dropped the Nereus into the North Arm of the Port River.

So far so good, it floats ! You’ll have to excuse the state of the pontoon, the local Pelicans have made it their preferred home during the Winter. Once in the water the obligatory “is water coming in” checks were done, it certainly did not have to go back on the trailer.

There was nothing left but to go for it and take things easy. So while cruising slowly towards the Port River the steering and gearbox (ie reverse) were checked, along with lights, bilge pump and the fish finder. Here’s a video of us just pulling away from the pontoon in the obligatory 4 knot zone coming out of the North Arm,.

Once clear of the North Arm we could then head towards Outer Harbour with a bit more power on keeping within the 7 knot limit. During this time we were watching the temperature of the engine and making sure things were going as planned.

Eventually however we were able to open the throttle and put the old girl up onto the plane.

Of course not everything goes to plan and the Log gland decided to spring a leak. It was certainly letting in a reasonable amount of water. A little more grease forced into the gland helped slow things down, but it will certainly need to have the two seals changed when I can find the time to pull it apart.

On the way back up river we managed a couple of high speed runs at wide open throttle (WOT). It was only then we found that the heat exchanger was not quite keeping up and the engine temp started to rise towards 100 degrees Celsius. Simply lifting the throttle and slowing down was enough to drop the temp back to normal. So this will certainly require some further investigation.

Getting out on the water in any boat is a great way to spend an afternoon even better when you can share it with a couple of friends. The trip was certainly successful with only minor issues found and nothing that resulted in us being towed home. We certainly can’t ask for more than that.

At some point I’ll also either capture a video or some photo’s of putting this boat on the trailer. There is a unique catch on the bow that allows the boat to be driven on and caught without having to get out of the boat. The first time we put her back on I was a little preoccupied with not hitting anything so didn’t capture anything. Next time.

Display a PNG Image on small 128×128 OLED LCD

Now that my small OLED display automatically loads the device drivers on boot, it was time to see if I could display an image on my new frame buffer device.

To start with I went looking for a very basic graphics library that would allow me to experiment on frame buffer devices. There is certainly no shortage of libraries to choose from. The library that I settled on was the “Lightweight C 2D graphics API agnostic library with parallelism support” written by grz0zrg. It had both PNG and JPG routines that could output to a simple frame buffer device, being written in C was also a winner.

Flicking through the various examples the quickstart.c file seemed to have nearly everything I needed to display a PNG file on my OLED. Not so long ago a fellow AREG club member shot me some icon files for our club website; one of these icons was 512×512 pixels in size which made it an excellent candidate for shrinking to 128×128 pixels and using it on my OLED.

Downloading the library was as easy as;

$ cd ~
$ git clone https://github.com/grz0zrg/fbg

If you don’t have git installed use the relevant apt-get command. The example files can then be found in the following directory;

$ cd ~/fbg/examples 

I then copied the quickstart.c file and hacked on it a little, modifying it like so;

#include <sys/stat.h>
#include <stdio.h>
#include <signal.h>
#include "fbgraphics.h"

int file_exists( const char* filename )
{
    //define file handle
    FILE *file;

    //attempt to open file read only
    if( (file = fopen(filename, "r")) )
    {
        fclose(file);    // release file handle
        return 1;        // tell someone we found it
    }
    else
    {
        return 0;         //no one home
    }
}

int main(int argc, char* argv[])
{
    const char* framebuffer_name = "/dev/fb1";
    const char* logo_filename = "logo.png";

    //check we have a framebuffer to talk to
    struct _fbg *fbg = fbg_setup( (char *)framebuffer_name, 0);
    if (fbg == NULL)
    {
        return -1;
    }

    // make sure logo file exists
    if( !file_exists( logo_filename ))
    {
        printf("File not found: %s\r\n",logo_filename);
        return -2;
    }

    //draw something on the display
    struct _fbg_img *logo = fbg_loadPNG(fbg, "logo.png");
    fbg_clear(fbg, 0);
    fbg_image(fbg, logo, 0, 0);
    fbg_flip(fbg);
    fbg_draw(fbg);

    //release memory
    fbg_freeImage(logo);
    fbg_close(fbg);

    return 0;
}

Which was built with the following command line from within the examples directory;

gcc ../src/lodepng/lodepng.c ../src/nanojpeg/nanojpeg.c ../src/fbgraphics.c display_logo.c -I ../src/ -I. -std=c11 -pedantic -D_GNU_SOURCE -D_POSIX_SOURCE -Wno-unused-value -Wno-unknown-pragmas -O2 -Wall -lm -o display_logo

Hacking upon the Makefile is also not that difficult, I simply added the relevant lines the SRC and OUT sections, then copied the quickstart section and renamed display_logo. There is lots of information about on how to do this on the internet so I’ll not repeat it again unnecessarily.

All I had to do then was place my 128×128 PNG file alongside the display_logo executable (renamed logo.png) and run it… wallah ! I was greeted by the AREG logo on my small OLED display in all of its 128×128 pixel glory; see the image at the top of this post.

So the next trick is to move this to the boot process… So by the looks the plymouth package might be the go, only one way to find out.

Starting a fbtft_device on Boot

After having woken up my small 128×128 OLED display I was wondering how to get it to start automatically each time my rPi booted rather than having to log in and run the commands manually.

It turns out this is rather easy and just required me to edit two files. I’m also glad that these Waveshare OLED displays are effectively compatible with the Freetronics OLED 128×128 graphics display. A big thanks to the Freetronics team for making this driver available for SED1351 chip sets.

So I created the following file with my favourite editor (as root) /etc/modprobe.d/fbtft.conf with the following contents;

options fbtft_device name=freetronicsoled128

What this effectively does is tell the system how to configure the fbtft_device as it boots, much like if we started it with modprobe from the command line i.e used the following command;

sudo modprobe fbtft_device name=freetronicsoled128

So now the system knows how to configure the driver, we need to tell modprobe to load it by placing an entry in the /etc/modules file. So using your favourite editor (as root) edit /etc/modprobe and append the last two lines.

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

i2c-dev
spi-bcm2835
fbtft_device

It appears that the SPI bus is a little slow to load if it’s called as a dependency of fbtft_device, which is a classic chicken and egg driver problem. So by starting it manually we make sure it’s available by the time the fbtft driver tries to do anything.

The i2c-dev entry in the same file fires up the i2c bus and was already pre-configured in my system by raspi-config way back when. I’m using it in my project, YMMV. All that is left to do is test it, so reboot and login and run the following command;

$dmesg | grep graphics

We should see something like the following;

[6.128978] graphics fb1: fb_ssd1351 frame buffer, 128x128, 32 KiB video memory, 4 KiB buffer memory, fps=20, spi0.0 at 20 MHz

That tells us that the little OLED display has registered as /dev/fb1 and that it’s ready to go. You can use the con2fbmap trick in my last post to test it’s working.

Now to work out how to get it to throw up an image on boot…

Maple Mini’s & a STM32F103CBT6

I recently found myself at the very limits of what you can ask an Arduino Uno to do, both in terms of flash and speed. I’ve used Atmel AVR processors for nearly 20 years so I know them and their foibles very well.

At work a while back we started using various STM32 processors and that has been somewhat enjoyable, I now like throwing floats around instead of having to resort to fixed point maths and excel for algorithm development. I’d heard that you could run up the Arduino framework on the STM32 platforms so was keen to try it.

So I initially went looking for a well supported board and simply struggled to find one. It seemed that this space had come and gone rather rapidly. Further research showed why, the Chinese clones has effectively decimated this market due to price. I was still keen to give it ago so placed an order for two Maple Mini boards with the STM32F103CBT6 processors on them off eBay for the princely sum of A$20 with free freight. Little wonder everyone abandoned ship in mid 2016.

A big thanks has to go to Leaflabs since they have left all of the circuits, boot-loaders & design files in a GitHub repository here (click).

So what did we have to do to get these working ? It wasn’t as trivial as the Arduino Uno that is for certain.

The first step was to get Windows 7 drivers (yes I know it runs out next year) for the Maple Mini, I found some here (click). I basically hit the green button marked “Clone or Download”, saved the file on my local machine. Extracted the files from the archive to a temp directory, then via the System Manager clicked on the “Maple 003” device that appears, told it I wanted to update the drivers from a specific location then pointed it at the temp directory I’d stored the files in previously. It figured it out and installed the ones I needed. What I found amusing is it then appeared under a category called “Atmel Devices” since I’d installed tools based on libdfu for these devices once upon a time ago. YMMV.

Once I had drivers installed I could then fire up PlatformIO in the VSCode editor and attempt to create a new project. I selected the board type “Maple Mini Original” and “Arduino” for the platform and let it do its business. Unfortunately the processor I have and the one on the original maple mini are different, so I had to change a few things in the platformio.ini file; my config is below. This config is based on a PlatformIO blog post written by Vortex314, can’t thank them enough for sharing this information (click).

[env:maple_mini_origin]
platform = ststm32
board = maple_mini_origin
framework = arduino
board_build.mcu = stm32f103cbt6
board_build.f_cpu = 72000000L
build_flags = 
    -D USBD_USE_CDC
    -D PIO_FRAMEWORK_ARDUINO_ENABLE_CDC
    -D PIO_FRAMEWORK_ARDUINO_USB_FULLMODE
    -D USBCON
    -D USBD_VID=0x0483
    -D USB_MANUFACTURER="Unknown"
    -D USB_PRODUCT="\"BLUEPILL_F103C8\""
    -D HAL_PCD_MODULE_ENABLED

So what is so special? Firstly there are separate board_build definitions to set the processor and speed for the board. Thankfully the cores between the original board and my Chinese clone are similar enough for this to work. Secondly there’s a heap of additional build flags that will build in a USB serial port. So if you’re used to the USB serial to debug your code this will still work. You can find out a little more about why this is necessary on Roger Clark’s website here (click).

It is interesting that the boot-loader contains only DFU code and that the application needs to have the USB serial built in separately. In the above configuration you may notice that the VID is 0x0483 which is by design, this means the Communications Device Class (CDC) will trigger the ST Serial drivers on a Windows installation if you have them installed. If you don’t you can find them here (click).

So from within the PlatformIO environment we can write our code and build for our target. Here’s my very simple test program that flashes the onboard LED (pin 33) and will send some test data to the USB serial port.

#include <Arduino.h>

void setup() 
{
  // put your setup code here, to run once:
  pinMode( 33, OUTPUT );
  Serial.begin(115200);
  
}

void loop() 
{
  static int i = 0;
  
  // put your main code here, to run repeatedly:
  digitalWrite( 33, HIGH );
  delay(500);
  digitalWrite( 33, LOW );
  delay(500);

  Serial.print("Test #");
  Serial.println(i++,DEC);
}

So the last comment I need to make is in the programming of the device. When you hit the upload button from within PlatformIO you’ll see OpenOCD start and then pause with the comment “Searching for DFU device [LEAF:0003]” and if you wait long enough a subsequent message flashes by reading “Couldn’t find the DFU device: [LEAD:0003]” and nothing appears to happen.

Initially I thought my board was dead when it dawned on me… The Arduino uses a separate ATmega8U2 that is capable of resetting the target ATMega328 under software control, the STM32F103Cx is using the internal USB port and does not have this reset function (*face palm*). So when we start the program cycle we need to wait for the “Searching for DFU device” to appear and then manually reset our target to force the boot-loader into DFU mode momentarily where it is then caught and updated. Once done the process carries on as expected and you find you haven’t bricked your device.

Happy programming !

Small OLED Display on a rPi

Recently I was searching for a small graphic display that I could connect to a Raspberry Pi and fit within a Phoenix DIN enclosure I wanted to use.

There isn’t much space in the front of the enclosure I wanted to use, but a small 128×128 OLED colour display seemed it might fit.

Trawling through eBay I found what I thought to be a suitable unit and simply placed an order. There was very little information on the eBay site to tell me which display I had purchased so I just waited. When the display arrived it turned out to be a Waveshare SKU:14747 with the SED1351 controller.

A little searching around the web and I found an excellent tutorial written by the Freetronics Team for their 128×128 OLED display. It turns out our displays share the same SED1351 controller, so it was the logical place to start with my small display.

First task was to map the OLED pins to my rPi 3B+ 40-pin GPIO connector. On the rear of the display the pins and their desired function were clearly marked, so I mapped the pins like so;

OLED    | rPi      (pin)
--------+----------------
+5      | 5V       (1)
GND     | 0V       (3)
MOSI    | SPI_MOSI (19)
SCK     | SPI_SCK  (23)
CS      | SPI_CE0  (24)
DC      | GPIO25   (22)
RST     | GPIO24   (18)

I have also included the rPi pin numbers I used, make sure you plug the display into the right pins if in doubt RTFM. Once it was wired I ran the following commands to make sure the rPi was absolutely up to date;

sudo apt-get update
sudo apt-get dist-upgrade
sudo reboot

The latest version of Raspbian Lite I was using (Buster) came with the fbtft frame buffer drivers already installed, so these steps were unnecessary. Since this Raspbian installation was fairly recent I decided that I didn’t need to update the rPi firmware using the rpi-update command like in other tutorials; YMMV.

I had already enabled the SPI bus on my Pi when I was coming to grips with the I2C bus. I found the tutorial at Sparkfun a really good reference and easy to follow. To create the frame buffer for the OLED device I ran the following command;

sudo modprove fbtft_device name=freetronicsoled128
dmesg | tail -20

Fingers crossed we see the following output in our terminal;

fbtft: module is from the staging directory, the quality is unknown, you have been warned.
fbtft_device: module is from the staging directory, the quality is unknown, you have been warned.
spidev spi0.0: spidev spi0.0 125000kHz 8 bits mode=0x00
spidev spi0.1: spidev spi0.1 125000kHz 8 bits mode=0x00
bcm2708_fb soc:fb: soc:fb id=-1 pdata? no
spidev spi0.0: Deleting spi0.0
fbtft_device: GPIOS used by 'freetronicsoled128':
fbtft_device: 'reset' = GPIO24
fbtft_device: 'dc' = GPIO25
spidev spi0.1: spidev spi0.1 125000kHz 8 bits mode=0x00
spi spi0.0: fb_ssd1351 spi0.0 20000kHz 8 bits mode=0x00
fb_ssd1351: module is from the staging directory, the quality is unknown, you have been warned.
graphics fb1: fb_ssd1351 frame buffer, 128x128, 32 KiB video memory, 4 KiB buffer memory, fps=20, spi0.0 at 20 MHz

The output here shows us that the SPI bus is OK and that we now have a frame buffer /dev/fb1 that is expecting to find a SED1351 LCD controller. So now it was time to display something so I used following command;

con2fbmap 1 1

And here is what I see;

w00t it works ! Now it’s time to go and find some graphics libraries that can talk to this frame buffer device… and to work out how to display text in boxes that is wider than 80 columns in WordPress…