Switching a 5V DC motor with a microbit.

This post shows how to use a BBC microbit to control a 5V fan or DC motor using a FET switch. The circuit shows how we can use a transistor to control a device that needs more current than the microbit can supply.

A demo showcasing the microbit’s sensor technologies was set up in the office I’m lucky enough to loiter in when not working offshore. One of the demos showed how the microbit can detect temperature. When the microbit is heated up above a certain temperature with a hair dryer, the microbit turns on a  fan to cool itself down. The fan is  turned off the fan when the microbit detects that the temperature has fallen below a pre-set threshold. I don’t have much use for a hair dryer nowadays (baldy matt), but I lashed up a little circuit to enable a fan to turn on when a pin on the microbit goes high. I passed this over to the rest of the team who were setting up the demo to add the temperature sensing code.

The problem is that the fan operates at 5V and needs a fair whack of current compared with what we can squeeze out of a microbit pin. The microbit operates from a 3V battery pack. So how do we use the microbit to turn on a device that operates at 5V and enable enough current for the fan?

Short answer, we use a transistor switch. In this case, I used an N-channel FET, specificially a 2N7000. There are other types of transistor that can be used and different arrangements of circuitry, but this is one of the simplest and most reliable setups for this example.

As we are using 5V battery pack for the fan, we can use the same 5V battery pack to connect with the micro USB connector on the microbit. We could use independent 5V and 3V battery packs, so long as the grounds on the battery packs are connected. Being able to have separate battery packs for the microcontroller and the device being powered is an important idea which allows us to switch e.g. 12V devices using the microbit, where you couldn’t share the same power supply between the microbit and the device. The device being powered is often called a ‘load’, as it loads the power supply.

 

Circuit layout of the fan controller. The pins on the FET are labelled.

A drawing of the circuit can be seen above. I used Fritzing to make this. The three pins of the transistor are called ‘source’, ‘gate’ and ‘drain’. The source and drain are named as they are the source and drain for the charge carriers inside the transistor that allow the current – in this case electrons. The gate, is well, a gate, that enables a current through the transistor when it is held at a higher voltage than the drain

The source of the transistor is connected to the negative of the battery pack, as this supplies the electrons that are the charge carrier in this type of transistor. This negative pin on the battery pack is also connected to the ground of the microbit through the USB connector. The drain on the transistor is connected to the negative pin on the DC motor. The positive pin of the motor is connected to the positive pin on the battery. The positive pin on the battery is also connected to the microbit through the USB connector, as the battery pack supplies +5V, which is the same as USB supplies.

Here’s a photo of the device in real life. The blue oblong is a 5V rechargeable USB power pack. The fan is on in the photo. The transistor can be seen as the tiny black think on the breadboard. A green clip connects pad 0 on the microbit to the gate of the transistor. The wiring connecting all the pins between the USB connectors is hidden underneath the connectors as about the only area I am in any way tidy is with wiring.

So how does this the transistor switch work? Many people better than myself have written on this. I’d recommend having a play on the excellent Falstad circuit simulator. Go to ‘circuits’ ‘MOSFETS’ ‘switch’ and click on the little open switch symbol to close it. Watch the flow of charge (the current). I modified and labelled the example circuit to show how the microbit circuit is laid out and put a screen grab below. In the Falstad simulation, the switch connects to the gate pin on the FET to a 3V power rail. This represents pin 0 on the microbit. Pin 0 going high is simulated by closing the switch and connecting the gate of the FET to 3V. Pin 0 going low is simulated by opening the switch and having the gate of the FET go to 0V.

When the gate is connected high, the FET switch is on and allows a current from the drain to the source. When it is not high, the FET will not allow charge to flow. The 5 Ohm resistor represents the load on the circuit, in my case the fan. I don’t know what the resistance of the fan is, but 5 Ohm is good enough for the simulation.

The battery pack is simulated by the +5V power rail which connects to the positive side of the 5 Ohm resistor. So, using a switch from a lower voltage rail, we can control the current supplied by a higher voltage supply. This idea is used in industrial controllers to allow little microcontrollers to operate machinery that runs at a far higher voltage than the microcontroller and used far more current than a microcontroller can supply from its output pins. I put the Falstad code at the bottom of this page. You can copy and paste it into Falstad. Go to ‘File’ ‘Import from text’ and paste in the code.

Falstad simulator FET switch layout.

The +ve on the fan motor is connected to the battery pack’s +ve rail. The -ve on the fan motor is connected to the drain on the FET. When a high voltage is applied to the gate on the FET (3V from the microbit pad 0), the semiconductors inside the FET are put in a state that allows a current through the drain to the source. As the source is connected to ground, there is now a current from the battery through the fan and to ground. So with the gate voltage high, the circuit is complete and the fan can operate. When the gate voltage is not high (pulled to ground by pad 0 on the microbit), the FET’s semiconductors are in a state that will not allow a current through the FET and the fan, so the fan does not operate.

I wrote some micropython code to test it all out. Please find this below. Button A toggles pad 0 on the edge connector high and low. Note that when the microbit is powered on, I set the pad to a known state, in this case low. You should always configure the state of pins that are being used to control devices to a known state at power up. Sometimes when you start up a microcontroller, the pins will go to a state you didn’t anticipate whatever the data sheet says, which could cause whatever you are controlling to turn on or off when you didn’t expect it to. How do you think I found this out?

Here’s the micropython code I used to test the circuit with.

''' Toggle pin0 on button A press. '''

from microbit import *

TOGGLE = False

def display_leds(toggle_flag):
    if toggle_flag:
        display.show(Image.TARGET)
    else:
        display.show(Image.ASLEEP)

def setup():
    write_pin0(0)
    display.show(Image.ASLEEP)

def write_pin0(toggle_flag):
    if toggle_flag:
        pin0.write_digital(1)
    else:
        pin0.write_digital(0)

setup()
while True:
    if button_a.was_pressed():
        TOGGLE = not TOGGLE
        write_pin0(TOGGLE)
        display_leds(TOGGLE)

Here’s the Falstad simulator code. Copy and paste it into the box you get when you click on ‘File’ ‘Import from text’ in Falstad.

$ 1 0.000005 10.634267539816555 50 5 50
s 288 224 288 304 0 0 false
w 288 128 400 128 0
r 400 128 400 288 0 5
w 400 320 400 336 0
f 288 304 400 304 0 1.5 0.02
R 288 128 240 128 0 0 40 5 0 0 0.5
g 400 336 400 352 0
x 432 213 465 216 4 24 fan
x 416 310 534 313 4 24 2n700\sFET
x 139 195 281 198 4 24 microbit\spin\s0
x -7 284 267 287 4 24 switch\sclosed\s\q\spin\s0\shigh
x -6 258 242 261 4 24 switch\sopen\s\q\spin\s0\slow
x 121 112 251 115 4 24 battery\spack
R 272 208 224 208 0 0 40 3 0 0 0.5
w 272 208 288 208 0
w 288 208 288 224 0

WordPress – displaying code without line breaks or paragraph tags

Since updating WordPress to v5.1, <br> and <p> symbols started appearing in my code snippets in WordPress. I was pasting Python code into the editor. The solution I found was to:

Install the Syntax Highlighter plugin.

Go to the Code Editor. Surround your code with these tags:

<!– wp:syntaxhighlighter/code –>

<!–/wp:syntaxhighlighter/code–>

You can select a Syntax Highlighter block in the Visual Editor under the ‘format’ tab. I found that selecting a language from the syntax highlighter menu in the Visual Editor corrupted my code, converting < or > symbols to &lt or &gt and various other shenanigans. So I stick with adding my code through the Code Editor.

When I go back to the visual editor, for the code block I see this:

Visual Editor interface getting confused over the code block entered in the Code Editor interface.

The code renders well on my web page, without any spurious formatting or addition of <br> and <p> symbols.

To get a smooth looking bash terminal output like displays, surround the output with <pre> and </pre> tags. Remove <p> and </p> tags. and tags put in by wordpress and any other spurious tags. Then you get something nice like:

Hello
    I'm a nicely
      formatted and indented bash terminal output.

I’ve spent an hour of my life fixing a problem I didn’t have with the previous version of WordPress.

Measuring the BBC micro:bit LED current draw

Summary: I looked at the voltage and current supplied to the BBC micro:bit for different numbers of active LEDs. The voltage to the LEDs is pulsed at about 55Hz, with each LED on about 1/3 of the time at maximum intensity. The frequency is high enough that the LED appears continuously lit. The current draw from a single pin is in spec for the microcontroller. The current supplied to each LED decreases as the total number of LEDs being sourced from the same microcontroller pin increases. If the LED ntensity is decreased in code, then the LED is active for a smaller fraction of each voltage cycle.

An interesting question at stackexchange asked how the pins to the microcontroller on the microbit could handle the current to and from all 25 of the LEDs on the board. At first glance, it looks like there are too many LEDs being supplied by too few pins to stay within the 5mA current limit for a single pin on the Nordic nRF51822 microcontroller.

There is a schematic for the microbit board on github. A screenshot showing how the microcontroller pins are connected to the LEDs, taken from sheet 1 and 5 of the github site is shown below.

Microbit schematic showing how the LEDs are connected, taken from the microbit Github site.
Nordic nRF51822 pinout on the microbit from Github, with the pins that connect to the LEDs indicated.

There are three pins called ROW1-ROW3 that supply current to the anodes (the left of the LED symbol) of all 25 LEDs. Pin PO.13 on the microcontroller is connected to ROW1 and supplies 9 LEDs. Pin PO.14 connects to ROW2 and supplies 7 LEDs. Pin PO.15 connects to ROW3 and supplies 9 LEDs. According to the datasheet for the microcontroller, up to 3 pins can supply or sink up to 5mA in 'high-drive' mode. The rest can source or sink 1.5mA each.

The cathode (the bit of the LED connected to the resistor) of each LED is connected to one of nine 220 Ohm resistors. Upto 3 LED cathodes are connected to each resistor. Each of the nine resistors is then connected to a single microcontroller pin, to sink the LED current.

A limit of 5mA from a single pin to source current to 9 LEDs is not a lot. So what is happening? Are the pins being overloaded?

I pulled the C++ microbit compiler code from the lancaster university github. It looks like one row of the microbit display is illuminated at a time and the display constantly scans through the rows.

Anything that turns on and off at a frequency greater than about 15Hz appears as if it is constantly on.

Using a power supply, I measured the current draw with different numbers of LEDs active. The voltage applied was 3.00V from a TTi EX345RD power supply.

The results surprised me:

LEDS current in mA
0         4.74
1         5.79
5         8.63
10      11.31
15      12.75
20      13.45
25      14.01

So about 14.01-4.74 = 9.27mA extra current is being used to supply 25 LEDs.

I used an Analog Discovery 2 with its Wavefroms software to both power the board and as a 'scope. A Fluke multimeter measured the current and was used to verify that the supply voltage stayed constant.

The Analog Discover 2 supply pins were connected to the ground and 3V pin on the edge connector for the microbit. With a supply voltage of 3V from the Analog Discovery 2, I measured 3.001V across the ground and 3V edge connector pins for 1 LED on and 2.994V with all 25 LEDs on, so the voltage drop across the supply pins is 0.2% while increasing the number of active LEDs. Not much of a voltage drop.

With the 'scope, I can see that the voltage to each LED is indeed pulsed. The screen shot taken from the Waveform software below shows what I saw 'scoping the anode of an LED. The red vertical lines show where I measured time intervals. I am fairly sure that I am 'scoping the LED's anthode as I could count 9 of the pins connected to this side of the LED and 3 at the other end. Which agrees with the schematic. Plus I used my Fluke to verify the LED polarity. Matty likes to double check what he is measuring after having made so many, many mistakes over the years.

Voltage on a single LED anode, red lines show where I measured time intervals.

Clearly the current draw I measured from the power supply was showing the average current. The current through the LEDs will vary with the voltage. The resistor is 220 Ohm. The current will be V^2/R, where V is the voltage across the resistor.

The LED voltage at the anode is high for 5.8824ms out of 17.914ms = 32.83% duty cycle. So the pin is high for about 1/3 of the time. This makes sense - one pin out of the three that supply current to the LEDs is active at a time. The pulse frequency is 55.821Hz. So the pulsing is invisible to the eye.

The frequency and pulse widths do not change with the number of LEDs that are on. What does change is the anode and cathode amplitude. This drops as the number of LEDs on increases. The supply voltage to the microbit stayed almost constant though.

The image below shows the anode voltage on two separate supply pins, showing that they are indeed turned on at different times. Should I have three probes, the gap would be filled in by 'scoping the pin supplying the third row of LEDs.

Voltage on the anodes for two LEDs supplied by different pins.

With no LEDs on, the voltage rail was 3.0200 on the 'scope. Fair enough. That's pretty much the supply rail. With all LEDs on, I measured two voltages, 2.0896V and 2.1640V. If you've been paying attention, it won't be a suprise that the higher voltage occurs on 7 LEDs (ROW2 on the schematic) and the lower on the remaining 18 (ROW1 and ROW3 on the schematic).

Let's look at the cathode of one of the LEDs. A screen grab is shown below. With a single lit LED, the cathode is at 3V for 2/3 of the time as the sink pin goes high to prevent current, from, well, being sinked. When it goes low, current can flow from through the LED and the resistor and back to ground through the microcontroller pin. Thus completing the circuit and allowing the LED to light up. When the current is flowing, the voltage drops at the cathode. In this screen grab, with only 3 LEDs active, I measured 912.34mV at the cathode of the lit LED. Which makes for a current of 0.91234^2/220 = 3.78mA through the single LED and resistor. Note: I had the LEDs set on maximum intensity.

Voltage on an LED cathode when only one LED is active. Maximum LED intensity. x-axis: one square is 5ms.

What is interesting, is that the low value of the cathode voltage decreases with an increasing number of lit LEDs. So the current flowing through the LED must similarly decrease. So the voltage and thus current decreases with increasing lit LEDs, which means that the brightness also decreases. Similarly, the fraction of time that the cathode is high also decreases as the number of active LEDs increases, which makes sense, as for a greater fraction of the time the multiplexed cathode will be sinking current.

With all LEDs on, I measure 356.81mV for 1/3 of the time and 292.46mV for 2/3 of the time. Can you guess why the voltage is stepped between the two values? I suspect it as the voltage switches between supplying 9 and 7 LEDs. Please see the two 'scope grabs below.

Cathode voltage, all LEDs active. Maximum intensity. x-axis: one square is 5ms.
Cathode voltage, all LEDs active. Maximum intensity. zoomed. x-axis: one square is 5ms.

The human eye is not so good at discerning different light intensities. I think that having a bunch of LEDs not so brightly lit as a single one also helps fool the eye in judging their individual brightness.

With all LEDs on, the maximum current flow through the 220 Ohm resistor for the pin supplying 7 LEDs is 0.35681^2/220 = 0.5787mA. So for 7 LEDs, the total draw is 4.05mA.

For the 9 LED pins, the current per LED is 0.29246^2/220 = 0.3888mA. So for 9 LEDs, this is 3.499mA, again inside the 5mA spec for a single 'high-drive' pin to supply. However, the pin is only active for about 1/3 of the time. So the average current flow per LED will be 1/3 of the above values.

The current sinking into the pins that sink current is within the 1.5mA spec for a non 'high-drive' pin.

Lets look at all 25 LEDs active. About (7 x 0.5787 x 1/3)+ (9 x 0.3888 x 2/3) is being drawn at any instant. Which is 4.125mA. I measured an increase of around 9mA with all LEDs active. Hmmm, where does the extra current go? I'm open to suggestions. I've gone down the rabbit-hole with this. Time to move onto something else.

Ta-daaaaaaa.

An obvious question is: How do the traces look when the intensity changes? I edited the code shown at the end of the article to have the minimum LED intensity. Prior to this, I'd had everything set at maximum intensity.

Looking at the 'scope, the anode voltage stayed the same as for when we have maximum intensity - it is high for about 1/3 of the time for any given LED. Below see the cathode voltage for minimum intensity, all LEDs lit and a repeat of the image for when the LED intensity is maximum. We can see that the cathode voltage goes low, which allows current to flow, for much less of the cycle when the intensity is at a minimum. Which makes sense. At maximum intensity, current flows for almost all of the time that the anode voltage is high (about 1/3 of the time). I measured the cathode coming low for only 32.637us at minimum intensity, which is only about 0.18% of the illumination cycle, compared with the roughly 32% of the time when at maximum intensity.

Microbit LED cathode voltage, all LEDs lit, minimum intensity. x-scale: one square is 5ms.
Microbit LED cathode voltage, all LEDs lit, maximum intensity. x-scale: one square is 5ms.

I work at sea for half of the year, on a six week on, six week off rota. I first looked at this while I was on a survey ship, with limited test equipment and time as I am paid to do 12 hour shifts, that usually over run. Obviously, the ship would stop operating if Little Matty was not at his station when he is supposed to be.

I found a voltage supply on the ship, lashed this up to the microbit with a set voltage of 3.00V and measured the current draw through a Fluke multimeter for different numbers of LEDs. What I did not have access to was a 'scope. So I finished off my investigations when I was back home.

Looking at the display through a digital camera - I could see that the LED brightness is not constant. The frame rate of the digital camera is not synced with the refresh rate of the display, so as the rows are switched on and off, this is picked up as a variation in intensity in the camera display.

So even without a 'scope, I was pretty sure that the rows were being pulsed on and off. Actually, there is a 'scope on the ship, but as it is connected to the recording equipment to monitor all is well, I figured I should leave it in place.

Here's my micropython script to turn on/off one LED at a time using the A/B buttons:

#
''' Light LEDs using A and B buttons. '''
from microbit import *

# intensity of LED
BRIGHT = '9'
# how many LEDs to turn on at a time
INCREMENT = 1
# maximum number of LEDs allowed on at once
MAX_BRIGHT = 25
# how many LEDs on at boot
START_BRIGHT = 3


def decrease(num_bright, inc):
    num_bright = limit(num_bright-inc, MAX_BRIGHT)
    return num_bright


def increase(num_bright, inc):
    num_bright = limit(num_bright+inc, MAX_BRIGHT)
    return num_bright


def leds_string2(bright):
    ''' return led string '''
    bright = limit(bright, MAX_BRIGHT)
    leds_string = BRIGHT*bright + '0' * (MAX_BRIGHT-bright)
    leds_string = ":".join(leds_string[i:i+5]
                           for i in range(0, len(leds_string), 5))
    leds_image = Image(leds_string + ':')
    return leds_image


def limit(val, limit):
    ''' limit <val> between 0 and <limit>'''
    if val > limit:
        val = 0
    if val < 0:
        val = MAX_BRIGHT
    return int(val)


num_bright = START_BRIGHT
while True:
    if button_a.was_pressed():
        num_bright = (decrease(num_bright, INCREMENT))
    if button_b.was_pressed():
        num_bright = (increase(num_bright, INCREMENT))
    display.show(leds_string2(num_bright))
    sleep(0.1)
Experimental kludge.

pytest and relative imports part 2

I had another tussle with getting pytest to recognise where the modules to be tested are relative to the directory where the testing code is. This time I resolved the issue using relative imports. Last time I tried adding the directory where testing code is to the system path. This is detailed in my post here.

This time I realised that I could solve the issue using relative imports correctly. The blog page here helped me.

Here’s my project structure:

microbit/
microbit/activity_indicator/activity_indicator.py
microbit/tests/test_activity_indicatory.py

To be able to access activity_indicator.py from test_activity_indicator.py I needed to:

  • start the testing code, called test_activity_indicator.py, with the correct relative import for where the code to be tested is:
from microbit.activity_indicator.activity_indicator import *
  • put __init__.py files at the root of the project, in the directory with the code to be tested and in the directory with the testing code. These __init__.py files can be empty, created using ‘touch __init__.py’ in Linux or be saving an empty file in Windows.
microbit/
microbit/__init__.py
microbit/activity_indicator/__init__.py/
microbit/activity_indicator/activity_indicator.py
microbit/tests/__init__.py
microbit/tests/test_activity_indicator.py

yotta, cmake, ninja build tools for the Micro:bit explained

Understanding the offline build tools for the BBC Micro:bit

I use the offline build tools from Lancaster University for compiling and building C-code for the BBC Micro:bit board. I used the toolset without really understanding what was going on under the hood. Understanding our tools gives us a better chance of fixing things when they fail. So I spent a happy afternoon learning about these tools and how they differ from the system I was using for building C-code into executables. These executables are often called binaries.

yotta

yotta is a tool created at mbed to build C code aimed at a range of ARM processors into executable files. The processor on the BBC Micro:bit is an ARM processor. yotta is written in python so python needs to be installed on your system for yotta to run.

yotta uses a file called module.json containing information about the target platform. This information is used by yotta to download files that are required for your target hardware platform to enable your C code to work on that platform. These files are downloaded to a directory named yotta_modules. These files are used during the build process.

An example module.json file for the BBC Micro:bit is:

[code language="shell" light="true"]
{
&quot;name&quot;: &quot;microbit-c&quot;,
&quot;version&quot;: &quot;2.0.0-rc8&quot;,
&quot;description&quot;: &quot;The micro:bit runtime common abstraction with examples.&quot;,
&quot;license&quot;: &quot;MIT&quot;,
&quot;dependencies&quot;: {
&quot;microbit&quot;: &quot;lancaster-university/microbit&quot;
},
&quot;targetDependencies&quot;: {},
&quot;bin&quot;: &quot;./source&quot;
}
[/code]

In the file yotta_targets/bbc-microbit-classic-gcc/target.json is a line:
[code language="shell" light="true"]
&quot;toolchain&quot;: &quot;CMake/toolchain.cmake&quot;,
[/code]

This tells us that the CMake build system is used by yotta. So, what is CMake?

CMake

CMake is a command line tool that uses a file called CMakeLists.txt to create a list of shell commands that are run in a later stage to create the final executable for a C  project. This list of commands ends up in a file called Makefile. The CMakeLists.txt file contains things such as the flags passed to the compiler used to build the executable and the source files to be used in the build process.

Here I digress into the build system I am used to seeing, which uses ‘make’ to create the final binary executable. make is replaced by ninja in the Micro:bit build system. I cover this in the next section.

Github projects often use CMake to enable you to build the project’s source code on your system. To build these projects you often run the command ‘cmake’, which takes the CMakeLists.txt file in the github project and uses this to create the file Makefile. Then, running the command ‘make’ causes each of the commands in Makefile to execute.

As Makefile was created using cmake, the shell commands in Makefile will be the compiler commands to:

  • create .o files for all of our .c files

  • link these .o files together

  • create a /build/src directory

  • place the linked executable into this directory.

Often we run ‘make install’ to complete the installation of the binaries created from C code. The final output from running the commands in Makefile is often an executable binary file. The ‘install’ command copies this to wherever it needs to be in your system for it to run from the command line.

Digression ends.

But, but, but – the Micro:bit build system does not use ‘make’ to build the binary executable. Instead, it uses ninja.

ninja

If you can see the ninja, you are already dead.

ninja replaces make. make has been around for decades. Which is no bad thing. But somebody, somewhere, decided to make a better make.

One of the design goals for ninja is:

very fast (i.e., instant) incremental builds, even for very large projects

A quick search found somebody has compared the speed of make and ninja:

jpopsil – reports an increase in speed using ninja.

ninja creates a file called rules.ninja and build.ninja. ninja looks for build.ninja and uses this file to create the executable. If we look in rules.ninja, we see, well, some rules for how to build the executable. Looking in build.ninja…. there’s a lot of things. From reading the documentation, one of the ideas behind ninja is that all the decisions about how to create the executable are taken prior to the build. It looks like build.ninja has all of these build decisions in it. This allows ninja to do its job and create the binary without having to think too much along the way about what to do.

Edit April 2019

I found an excellent explanation of the micropython stack by Steve Stagg, who clearly understands the tool chain far better than I, about 3/4 of the way down this link:

https://hackernoon.com/the-first-video-game-on-the-bbc-micro-bit-probably-4175fab44da8

This post refers to the micropython stack for the BBC Micro:bit, which  is built on top of the C stack.

The author has a picture, which shows the tool chain to be like this:

make

yotta

cmake

ninja

gcc g++ ld

According to the post ‘Micropython has some extra build stages, so has a Makefile wrapper around yotta,….’. So the make module at the top refers to the micropython implementation.  The post goes on to explain that  Yotta creates the CMake config file. I think I got that in this post as well. Ninja then builds this configuration. So far so good. Looks to be in agreement with what I wrote above. Steve has more details about what the ninja does when it runs. His post is worth a read.

 

 

 

Using the DRV8662 chip to create 105V DC from battery voltage.

This is how I generated a little over 100V of DC using a 3.95 V power supply with about $10 of parts.

Summary:

Using a DRV8662 chip we can create a battery powered board that will generate a 105V DC power rail using around $10 worth of parts. Some surface mount soldering is needed though. If you have an input signal below about 500Hz, you can use the chip to amplify this to have a peak to peak output of up to around 200V.

DRV8662 test board, 3.95V DC input from the middle power supply, 104.7V DC output. What could go wrong?

All right. I said battery voltage but am using a beefy bench power supply. What’s with that? The beefy bench power supply has all kinds of current limiting and safety stuff built in that a battery pack does not have built in. Let’s not start fires until we want to.

Why?

I need a 100+ V DC rail as an input to a circuit to drive some piezoelectric crystals. The crystals I’ve been tasked to use resonate at 40KHz.  How should I go about this? First off, the crystals need a signal with an amplitude of around 100+V. How hard could that be. Errrr….

How?

There are a couple of standard methods to create a boost converter:

Transformer

For instance flyback transformers as used in ‘old school’ television sets. The type with tubes. Remember those? No? I’m old…

Inductor switching circuit

Switching a voltage into an inductor ‘bounces’ the output voltage up. One interesting design based on this idea can be found here. The switching frequency needs to be controlled to maintain a steady output voltage, ideally using some kind of a controller. It is a beautiful piece of electronic design which I think I would enjoy, but it’s all about time.

Have somebody else make it

Of course. The simplest and fastest way. Stand on the shoulders of giants. Now, how many battery powered 100V DC-DC converters can I find on eBay. None. However, after some searching, I did find an integrated chip that does most of the work for me made by Texas Instruments.

Enter the DRV8662

Texas Instrument’s DRV8662 chip is designed to drive a haptic feedback piezoelectric transducer at up to about 500HZ. If we look at the functional block diagram in the data sheet, which I copied below, we can see that an external inductor (L1) is used by the IC to generate a voltage rail at up to about 105 V. This voltage rail is called VBST. This is used to power an internal operational amplifier. This op-amp can be used to amplify an input signal from IN+ and IN-. The output can be applied to a piezoelectric transducer, shown acroos OUT- and OUT+. 

So we have an inductor switching circuit to generate the DC voltage rails and a high voltage op-amp with a gain-width bandwidth somewhere around 500V which can be used to drive a piezo actuator. The chip is designed to be used inside of e.g. mobile phones, to make a piezoelectric crystal vibrate so that your phone shakes. Now you know where that comes from.

The simplified schematic below the functional block diagram is basically the same, but the outline of the chip is dotted in. The components outside of the dotted line are the ones that we need to add to make the circuit work. What values to use? I copied the ones from the demo board that Texas Instruments make.Then started playing.

I used R1=768K and R2=16K gives me a 105V DC output. According to my calcs, R2 = 10K should give me a 105V output. I think the extra inductance from using flying leads on the inductor affected this. On my first board with the inductor soldered close to the IC, using R2=20K gave me about a 52V VBST. On board two, with the inductor on flying leads, I got VBST as 84V.

On a PCB I would place 10K to get the 105V output. Or maybe start with 12K and resolder it if the rail was too low. I used L1 = 3.3uH and Rext = 7.5K, using a recommended inductor from the data sheet. GAIN0, GAIN1 and EN are tied high using 1K resistors. Don’t forget that EN needs to be high. Or the chip no worky.

DRV8662 functional block diagram, from Texas Instrument’s data sheet.
DRV8662 simplified schematic, from Texas Instrument’s data sheet.

If the resonance frequency of the crystals I want to drive was below about 500Hz I could use the DRV8662 on its own to generate the necessary driving signal. Feed a square wave at the crystal’s resonance frequency to the input pins and slap the crystal across the output pins. But I can’t. The resonance frequency of my targets is too high. Once I put a signal over 500Hz into IN+ and IN-, the output amplitude rapidly decreases.

However, the chip does allow me to tap the boost voltage that it creates from the VBST or PVDD pins. I can use this high voltage with some extra circuitry to generate a high voltage oscillating signal at 40 KHz to make my crystals shake. Watch this space.

‘But, but but, you’re using a fraction of the IC’s capability to just generate the 100 V rail, wouldn’t it be cheaper to make your own voltage boost circuit?’. The DRV8662 costs $3 in low quantities. Even Farnell in the UK only charges £3 each. Plus VAT. Plus postage. Even so, no, it wouldn’t be cheaper to spin my own circuit using transformers or a switched inductor, especially when you factor in my valuable time at $1 an hour. I know, I earn the Big Bucks.

So I bought a few DRV8662s from Farnell and soldered one down onto a QFN20 to DIL converter board. Which in plain speak is a little circuit board that converts a stupid small chip with no legs into something that I can plug into some breadboard to play with. The soldering is not too tricky if you use a decent small bit in your soldering iron, plenty of liquid solder flux and have a fan to blow the toxic fumes away. I use a USB powered fan designed to go inside computer cases with a power brick for this. eBay.

The first board I made is on the picture below on the left. Note that I soldered the inductor directly to this board. It worked. Lovely. Then I shorted the VBST pin to ground with a crocodile clip. Careless. Not that I’m bitter. Still, a bit of care would have avoided this. I learned my lesson.

Why is there a bit of brown tape on the second board? I put a corresponding bit of brown tape on one edge of my breadboard to remind me which way around to stick the module into my breadboard as it looks pretty much the say both ways around, but only works one way around and may never work again after being put in the wrong way around. I don’t want to find out if the last statement is true or not.

With the second board, I soldered the inductor onto some leads and stuck this into the breadboard. I found that the output voltage was higher than when the inductor was stuck directly to the surface mount to DIL converter board. Why? I suspect that the extra leads and path to and from the inductor increases the overall inductance.

Why did I use that particular inductor? Because the data sheet said that make and model would work. That’s why.

DRV8662s on surface mount to DIP converter boards. Why two? Because I wrecked the one on the left.

Looking at the picture below, which shows the DRV8662 on the converter board on the test breadboard, you can see that for instance, the two power leads I use are of different lengths. This makes it hard for the crocodile clips to ever come into contact. If you look closely at the flying leads connected to the yellow multimeter in the picture at the top of this article, these are placed so that they cannot easily come into contact. I live and learn. Slowly. I ordered some decent grabber probes.

DRV8662 on breadboard. It works.

Why are there two capacitors daisy chained on the VBST pin?

VBST -||–||- GND

Because the output on VBST is 105V and each of the two capacitors is only rated to 63V. So I daisy-chained two of them. There is probably not much risk of a 63V rated capacitor cooking off at 105V, but if it were to short, then the DRV8662 could die. As I found out when I shorted VBST to ground with a crocodile clip. Not that I’m bitter about this. Not at all.

How smooth is the 105V voltage rail? No way to tell using breadboard. If you want a smooth rail, don’t use breadboard.

I tested using an input from a signal generator. Each output pin generates a signal in anti-phase to the other, so the peak to peak difference is about twice the VBST voltage.

Please find a couple of photos showing this testing below. For these tests I only had a 52V VBST. Then I learned that adjusting R1 in the simplified schematic above changed the output voltage. Reading the data sheet always helps. I started out using an old-school ‘scope as I like them. Then switched to a new-school ‘scope because I could and nobody stopped me.

DRV8662 testing using an old-school ‘scope.
DRV8622 circuit output with 52V VBST rail using a new-school scope..

Useful extra stuff

How do we know if we have soldered down the chip correctly? Please find some impedances that I measured between various pins for a working board below.

Pins   Impedance (Ohms)

1-6  9.61M

5-6   short

4-5   open (despite both being labelled GND)

10-11   short

1-3   5.12M

12-5   26.32M

13-5   23.8M

14-5   23.8M

15-5   16.25M

16-5   16.25M

17-5   16.25M

18-5   16.25M

19-5   16.25M

20-5   8.15M

 

Real time accelerometer display from three BBC Micro:bits

I submitted an article to Circuit Cellar magazine on how I get real time data display from three BBC Micro:bits real time. Please find a video showing this in action below. On the screen to the right of the juggling clown, you can see the accelerometer data. Each BC Micro:bit has a three axis accelerometer in it. For each Micro:bit I get the average from all three axis as a single value. On the screen three are three traces, one for each Micro:bit. As the boards are juggled, the accelerometer values are sent by radio to a receiver Micro:bit connected to the computer. This Micro:bit acts as a go-between for the juggled Micro:bits and the computer. The accelerometer data is plotted real time using a script I wrote in Python, using the pyqtgraph library.

Sharing wifi with a raspberry pi zero w using create_ap

I had a bit of a chicken and egg situation while connecting a raspberry pi zero w to wifi. I work on a ship for six weeks at a time, so my choice of wifi is limited to the cabin network on the ship. This has a two part authentication. First, a password is used to connect to the wifi. Then a user ID and a different password is entered into a login page on a browser. My pi zero w has the lite version of the raspbian operating system. No GUI. No browser. I ssh into it, connecting the pi to my laptop with a USB cable.

Top tip number one – you cannot ssh into the pi zero w if the usb cable is connected between the port labelled pwr (power) on the pi. You need to use the other port.

There are plenty of good sites telling you how to set up the pi zero w to connect with your laptop via ssh by doctoring a couple of files on the micro SD card housing your raspbian OS. There are plenty of sites telling you how to setup a wifi connection using linux. I could get the little pi onto the ship’s wifi, but I could not complete the second stage of browser based authentication as there is no browser on the lite version of the OS. There are text based browsers available for Linux, which would enable me to complete the second stage of the login. But I could not install one of these as I did not have a connection to the internet. I am on a ship remember, no other wifi is available.

So I shared my laptop’s wifi with the pi zero. I use Linux. To share my wifi I used the create_ap library. To set up a new wifi link from your laptop:

sudo create_ap wlan0 wlan0 <new wifi name> <password>

e.g.

sudo create_ap wlan0 wlan0 my_wifi my_password

ssh into your raspberry pi:

ssh pi@raspberrypi.local -p22

If this does not work, try:
nm-applet
Edit wired connection 2 (or whichever is the highest numbered ‘wired connection’. Go to the IPv4 Settings tab. Select Link-Local Only for the method.
After ssh’ing into your pi, check that you can see your new wifi from it:

iwlist scan | grep my_wifi 

Now enter details of your new wifi into the wpa_supplicant.conf file:

sudo vi /etc/wpa_supplicant/wpa_supplicant.conf

Enter this:

network={
        ssid="my_wifi"
        psk="my_password"
}

If an error about authentication is received – go to a browser in the host laptop and log in to the local wifi that is being shared to ensure that it is active.

Now you should have wifi access from your pi.

Using udev to remove the need for sudo with the BBC Micro:bit

A comment on this post hinted that there is a way to remove the need to use ‘sudo’ when interacting with the BBC Micro:bit on Linux. So I left a comment asking how to do this, which the author kindly answered:

The way to make sure there is no need for root permissions to access USB device (like connected MicroBit) is by creating a file into `/etc/udev/rules.d/` directory with proper config. For Microbit this could be like this:

SUBSYSTEM=="usb", ATTR{idVendor}=="0d28", ATTR{idProduct}=="0204", MODE="0666"
and then restarting udev system with:
sudo udevadm control --reload-rules

So I created the file /etc/udev/rules.d/microbit.rules with the above code and it works!

I fired up pyocd to enable command line programming of the BBC Micro:bit without needing to use sudo. See this page for more details on programming the BBC Micro:bit from the command line and using pyocd to help with this.

Using tkinter and python to continuously display the output from a system command

I put an answer to a stackoverflow question. The poster wanted to display the output from a ‘netstat’ command every second. I suggested using a tkinter screen. To run the nestat command every second, the command line entry would be ‘netstat 1’. This is fed to a subprocess. This subprocess is wrapped in a thread to avoid blocking the main thread. The main thread needs to be left to deal with the tkinter display. GUIs like to hog the main thread. Don’t forget to use the ‘undo=False’ option with tk.screen. Otherwise all of the display is continuously saved to a buffer. This results in the python process gobbling up memory continuously as the output from netstat is added to it each second.

import threading
from subprocess import Popen, PIPE
from time import sleep
import tkinter as tk
from tkinter import *

 

PROCESS = ['netstat','1']
class Console(tk.Frame):
    def __init__(self, master, *args, **kwargs):
        tk.Frame.__init__(self, master, *args, **kwargs)
        self.text = tk.Text(self, undo=False)
        self.text.pack(expand=True, fill="both")
        # run process in a thread to avoid blocking gui
        t = threading.Thread(target=self.execute)
        t.start()
 
 
    def display_text(self, p):
        display = ''
        lines_iterator = iter(p.stdout.readline, b"")
        for line in lines_iterator:
            if 'Active' in line:
                self.text.delete('1.0', END)
                self.text.insert(INSERT, display)
                display = ''
            display = display + line           


    def display_text2(self, p):
        while p.poll() is None:
            line = p.stdout.readline()
            if line != '':
                if 'Active' in line:
                    self.text.delete('1.0', END)
                self.text.insert(END, line)
                p.stdout.flush()       


    def execute(self):
            p = Popen(PROCESS,  universal_newlines=True,
                   stdout=PIPE, stderr=PIPE)
            print('process created with pid: {}'.format(p.pid))
            self.display_text(p)

  
if __name__ == "__main__":
    root = tk.Tk()
    root.title("netstat 1")
    Console(root).pack(expand=True, fill="both")
    root.mainloop()