Pages

Tuesday, 7 April 2020

The micro:bit is talking to theVL53L0X ToF sensors!

This chip is no more :(
This morning I got my Arduino sensor driver talking to a micro:bit using SPI.

The Arduino Uno runs at 5 volts, and the micro:bit works at 3v3, so I used a level shifter to connect the two.

My first attempt failed disastrously.

The level shifter I used was based on the TI TXB0108.
I managed to connect the 5v power and inputs to the 3v3 side, and I fear the magic smoke has left the chip.

It's a shame, as the board was my first attempt at soldering SMD devices. It's been sitting unused in my bits box for a few years, though, so it's not the end of the world.

Fortunately I had an Adafruit level shifter breakout based on the same IC. It's well laid out with very clear pin markings and I managed to connect it correctly.

The replacement worked perfectly and the micro:bit MicroPython code was very straightforward. I've listed it below, and it's with the other code on GitHub.

from microbit import *
import struct
from time import sleep

SENSORS = 2

def spi_read(sensor):
    pin16.write_digital(0)  # Chip select
    ibuffer = struct.pack('<B', sensor)
    spi.write(ibuffer)
    result = spi.read(1)
    pin16.write_digital(1)  # Chip select off
    return result

spi.init(baudrate=100000)
while True:
    for i in [0, 1]:
        print(i, ord(spi_read(i)))
        sleep(0.1)


The technology is working. The next step is to build a compact version for Anastasia. I'll report on progress.

Monday, 6 April 2020

Read distances from up to 8 VL53L0X sensors via SPI

I'v now got my two-Arduino version of a multiiple ToF sensor LiDAR working.

I have only tested it with two sensors; I'll add one more later, and report, but the code should work with more.

I'm a little hesitant about that claim. The Slave Arduino code has little spare memory but I've tried to  reduce requirements to a minimum. I have more VL53L0X sensors on order, and I am hoping I can handle up to eight.

That would allow a robot to get a good sense of the closest obstacles.

The Slave code uses an SPI interrupt routine modified from Nick Gammon's excellent example.

The code that configures and then reads from the ToF sensors is a complete rewrite of Adafruit's example code for dual VL53L0X sensors.

I'm no expert at C programming, so if you can see improvements (or bugs), let me know!

The code is on GitHub, along with some minimal documentation.

The next step will be go get the Arduino slave working with a micro:bit master; then I'll need to work out how to install hardware and software on Anastasia to help her avoid collisions.

Here's the core code for the slave:

const byte MAX_OK = 253; // largest acceptable range / 2
const byte NO_SUCH_SENSOR = 255;
const byte INVALID_READING = 254;
const int SENSORS = 2; // two sensors for now
// addresses we will assign to sensors
byte address[SENSORS];
// pins to shutdown
byte shutdown_pin[SENSORS];
// scaled distances
byte distance[SENSORS];

// create array of sensors
Adafruit_VL53L0X lox[SENSORS];
VL53L0X_RangingMeasurementData_t measure;

void setID() {

  int i;
  for (i=0; i < SENSORS; i++) {
    shutdown_pin[i] = i + 2; // pins go from 2 to SENSORS + 2
    address[i] = (byte) 0x30 + i; // addresses go from 0x30 to 0x37
    pinMode(shutdown_pin[i], OUTPUT);
    digitalWrite(shutdown_pin[i], LOW);
  }
  delay(10);
  for (i=0; i < SENSORS; i++) {
    digitalWrite(shutdown_pin[i], HIGH);
    delay(10);
    bool result = lox[i].begin(address[i]);
    if(!result) {
      while(1);  // loop forever if the setup didn't work
    }
  }
  delay(10);
}

void readSensors() {
  for (int i=0; i < SENSORS; i++) {
    float range;
    lox[1].rangingTest(&measure, false);
    if (measure.RangeStatus != 4) {
      range = measure.RangeMilliMeter;
      distance[i] = min(range / 2, MAX_OK);
    } else {
      distance[i] = INVALID_READING;
    }

  }
}

void setup() {
  // turn on SPI in slave mode
  SPCR |= bit (SPE);

  // have to send on master in, *slave out*
  pinMode(MISO, OUTPUT);
  setID();
  SPI.attachInterrupt();
}

// SPI interrupt routine
ISR (SPI_STC_vect)
{
byte c = SPDR;  // grab byte from SPI Data Register
SPDR = c < SENSORS ? distance[c] : NO_SUCH_SENSOR; // return scaled distance or error code
}  // end of interrupt routine SPI_STC_vect


void loop() {
  readSensors();
  delay(100); // read all sensors every 1/10 second
}

Saturday, 4 April 2020

SPI access to multiple ToF sensors is working

I've been ploughing through the steps towards my goal of connecting multiple distance sensors to Anastasia's micro:bit.

I now have a pair of Arduinos connected via SPI, with the slave reporting distances from two VL53L0X sensors.

The wiring is a mess and the code needs cleaning up.

But it's working, and replacing the Arduino master by a micro:bit should be pretty straightforward.

I'll report on progress.

The code is on GitHub.

Friday, 3 April 2020

7 steps to add multiple ToF LiDAR sensors to a micro:bit

I'm happy with the solution I came up with to attach multiple Time-of-Flight (ToF) sensors to a Raspberry Pi or CircuitPython board.

Now I want to add one or more ToF sensors to Anastasia, my Python-powered micro:bit robot.

Anastasia needs at least one distance sensor to stop her running into things.

Since she can travel backwards as fast as she goes forwards, she really needs two sensors: one looking forwards, and one looking behind.

I've been looking for a simple solution but I have hit a snag.

I've found several Python drivers for the VL53L0X chip I'm using, but none will run on the micro:bit.

Some are Python wrappers for C code; others are just too big to fit on the micro:bit.

I finally came up with an approach which looks as if it may work.

The goal is to use a board with an Arduino-ish clone, programmed in C, driving the sensors and returning results via SPI.

Seven steps to ToF success


I've broken the project plan into seven steps which will build up into a complete solution.

  1. Arduino driving one sensor
  2. Arduino with more than one sensor
  3. Arduino(s) with one as SPI slave
  4. Arduino with more than one sensor that's interrupt-friendly
  5. Arduino with more than one sensor as SPI slave
  6. Arduino with level shifter and micro:bit
  7. 8MHz 3V3 Arduino and micro:bit
So far I've got, and run, sample code for the first three steps. The code so far has all come from reliable sources on the web. The core driver code and code for multiple sensors are Adafruit Arduino libraries for the VL53L0X. The SPI slave code comes from Nick Gammon's excellent site.

Step 4 needs a bit more thought. It's tempting to return floating-point values that show the measured distances, but there's a potential snag. The SPI save code is interrupt-driven, and I'd need to make sure that the code does not try to return a multi-byte value while that value is changing.

Concurrency rules


Rule one of concurrent programming is to avoid it if you can! Concurrent code is often hard to write, hard to read, and hard to test.

What I'll do is allow an SPI request that specifies which sensor to read. I'll return a single byte of data which will be a scaled distance measurement. If a valid distance can't be read I will return a value of zero.

I will be working on this over the next day or two and will report progress as I go.

Update


I forgot to mention that the code I'm using/developing is on GitHub.


Wednesday, 1 April 2020

Muliplexing I2C with the Adafruit TCA9548A multiplexer

I want to attach multiple VL53L0X Time-of-flight sensors to a single I2C bus. It looks as if that should be easy, but it's not.

One solution involves disabling the sensors and then enabling them one at  a time to change their address. It's workable, but fiddly.

If you only have two sensors you could use different I2C buses, but I eventually want to run 8 sensors, so that won't work.

The TCA9548A I2C multiplexer


There is another approach that is easy to implement and works out of the box.

The TCA9548A is an I2C device that acts a little like a telephone exchange.

You can use it to route I2C transactions to one of eight separate I2C busses. That allows you to have eight devices with the same I2C address, one on each bus.

I did a first experiment using an Adafruit CircuitPython m4 feather.

That worked well, and I've just confirmed that it works just as well with a Raspberry Pi. Since I'm using Adafruit's CircuitPython libraries, the same code runs on the Adafruit m4 and the Pi.

As you can see from the image above, the Pi I used was a veteran Pi model 2.

Kudos to the team at Raspberry Pi for maintaining software compatibility, and to Adafruit for making CircuitPython so portable.


Monday, 30 March 2020

Build details for Anastasia

I've uploaded pdf files with full build instructions for Anastasia the micro:bit robot and the power strip I made for her.

These are free/immediate downloads, no email required.

Links:

Build Anastasia the micro:bit robot
Power Strip Build Guide


Saturday, 14 March 2020

Bill of Materials for Anastasia - build instructions coming soon.

I've added a Bill of Materials for Anatasia the home brew micro:bit robot in her GitHub project. They are in the project README.

I'll add building instructions here and on GitHub over the week-end.

Meanwhile, here is a video showing her in action:


Wednesday, 11 March 2020

Driving Anastasia's Kitronik motor controller via radio

Anastasia with the controller
This is the fourth in a series of articles about Anastasia - a home-brew robot based on the micro:bit.

In my previous post I shared the micropython code that runs on Anastasia's remote micro:bit controller.

The controller can send one of five commands to Anastasia:
  1. stop applies a brake to the motors.
  2. left spins the robot anti-clockwise.
  3. right spins the robot clockwise.
  4. forward ( you guessed it1) drives the robot forwards.
  5. backward also does what you'd expect.

In this post I'll step through the code than implements these commands on Anastasia.

The code looks for incoming radio messages. It translates those messages into methods on a Driver class. These methods then send control signals to the  Kitronik motor controller.

Here's Anastasia's code



The code starts with the necessary imports, and then begins the definition of the Driver class.

from microbit import *
import radio


class Driver:
    """
    Read incoming radio messages and send commands to the motor controller.
    """
    def __init__(self, left_pins=(pin16, pin0), right_pins=(pin8, pin12)):
     
        self.pins = left_pins+right_pins
        radio.on()
        self.commands = {
            'stop' :    self.stop,
            'forward':  self.go_forward,
            'backward': self.go_backward,
            'left':     self.spin_left,
            'right':    self.spin_right,
        }


The Driver's __init__ method allows you to pass in the pins you use to control the motor, but has default values recommended by Kitronik in their documentation for their Motor Controller.

The left and right motor pins are concatenated and stored in the pins instance variable which is used later.

The commands variable contains a dictionary which maps text commands to methods on the driver class.

Let's look at the definitions of the methods.


    def stop(self):
        self.set_control_pins(1, 1, 1, 1)

    def go_forward(self):
        self.set_control_pins(0, 1, 0, 1)

    def go_backward(self):
        self.set_control_pins(1, 0, 1, 0)

    def spin_left(self):
        self.set_control_pins(1, 0, 0, 1)

    def spin_right(self):
        self.set_control_pins(0, 1, 1, 0)


Each method uses the set_control_pins method to apply high (1) or low (0) voltages to the pins that are connected to Anastasia's two motors.

Here is the set_control_pins method:

    
    def set_control_pins(self, *pin_values):
        for pin, pin_value in  zip(self.pins, pin_values):
            pin.write_digital(pin_value)


Handling commands



When Anastasia tries to read a command over the radio it will either get the next command as a text string, or None if no command has been received.

The obey method does nothing if its argument is None. If a message has been received obey looks it up in the commands dictionary. If it's an unknown command obey ignores it.

If it's a known command obey translates the command to the corresponding method. Then the method is executed.

    def obey(self, message):
        if message is None or message not in self.commands:
            return
        # execute the method if a valid message was received.
        self.commands[message]()


The run method loops forever, looking for a message to obey every 50 milliseconds.

    def run(self):
        while True:
            self.obey(radio.receive())
            sleep(50) # 50 ms


Finally, the script creates a Driver instance and tells it to start running.

Driver().run()

That completes the second iteration of my Anastasia project. For the next step there are two possibilities.

  1. I could add a VL53L0X ToF (Time of Flight) LIDAR sensor.
  2. I could replace the micro:bit with the more powerful Adafruit Clue.
Let me know which you'd prefer to see next by posting a comment here or in the micropython and micro:bit group on Facebook.

Tuesday, 10 March 2020

Controlling Anastasia from a second micro:bit

This is the third in a series of four articles about Anatasia, a home-brew micro:bit based robot.

Here's the full list of articles:

1. The original article introducing the robot.
2. A short update when I released the code on GitHub.
3. This detailed walk-though of the controller code.
4. A detailed walk-through of the code that runs on the robot

The code for Anatasia and her controller is finished. It's simple and it's all working well.

You control Anastasia via a separate hand-held micro:bit, which communicates using the micro:bit's built-in radio.

You tilt the controller and Anastasia responds by advancing, retreating or spinning to the left or right. Anastasia stops when you hold the controller level.

Here's the controller code:

Controller Code

 

The controller code starts with a bit of set-up

from microbit import *
import radio

radio.on()
# The critical value for tilt detection.
# A lower value makes the controller more sensitive.
RANGE = 250

Next, the say function checks to see if there is a command to send and sends it if necessary.

It returns a boolean value which tells you whether anything was sent.

def say(command):
    if command is not None:
        radio.send(command)
        return True
    return False

The micro:bit has a built-in accelerometer which can be used to detect if the micro:bit is tilted or level.

react_to_tilt checks a value to see how much the micro:bit is tilted.

If the size of the tilt is less than the RANGE value the tilt is ignored. If the tilt is big enough, the appropriate command is returned.

def react_to_tilt(tilt, low, high):
    if tilt > RANGE:
        return high
    if tilt < - RANGE:
        return low
    return None

The check_tilt function measures the tilts in the x and y directions and sends the appropriate command over the radio.


def check_tilt():
    if say(react_to_tilt(accelerometer.get_x(), 'right', 'left')):
        return
    if say(react_to_tilt(accelerometer.get_y(), 'forward', 'backward')):
        return
    # micro:bit is more or less level, so stop the robot.
    say('stop')


The final while loop runs forever. It looks for commands to send ten times a second.

while True:
    sleep(100) # on the micro:bit, times are in ms
    check_tilt()


I'll explain Anastasia's code tomorrow. If you can't wait, the code is already on GitHub.

Monday, 9 March 2020

Anastasia is a simple home-brew robot - now on GitHub

Anastasia V1
Anastasia (my latest home-brew robot) is now on GitHub.

The code is described in a series of articles on this blog. I've listed them at the end of this post.

I've made rapid progress with Anastasia and will do more work on her today.

Anastasia is currently driven by a pair of micro:bits. The motor is managed by an on-board micro:bit connected to a Kitronik motor controller and I control Anastasia over radio using a second micro:bit.

Anastasia is working, but needs some minor enhancements to the code and electronics. I may also need to replace the motors which run a bit unevenly. Once I've done the upgrades I'll post a video of Anastasia in operation.

Soon I'll replace the on-board micro:bit by an Adafruit clue which will be controlled via Bluetooth.

Eventually I'll add an on-board camera.

Articles in this series:

1. The original article introducing the robot.
2. This short update.
3. A detailed walk-though of the controller code.
4. A detailed walk-through of the code that runs on the robot.

Saturday, 7 March 2020

How to program a simple homebrew micro:bit-based Robot

This afternoon I assembled a simple micro:bit mobile robot.

It uses the Kitronik motor driver board and some Adafruit motors.

I like the Kitronik board. It's easy to use, well documented, and the build quality is good.

I'll be making some minor mods over the next couple of days. It needs a ToF Lidar sensor to make sure it doesn't bump into things and I plan to power it from a phone charger battery with an additional on-off switch.

I'll use a second micro:bit to control it via radio.

Update! There are now four articles in this series, and the robot has been named. It's called Anastasia.

Here are the articles:

1. This introduction.
2. An short update when I released the initial code on GitHub.
3. A detailed walk-though of the controller code.
4. A detailed walk-through of the code that runs on the robot.

Simple control code


The test code I wrote to check the wiring was very simple.


from microbit import *

left = (pin16, pin0)
right = (pin8, pin12)

forward = (0, 1)
backward = (1, 0)
coast = (0, 0)
brake = (1,1)

def set(side, direction):
    for i in range(2):
        side[i].write_digital(direction[i]) 
 
# wait for button A to start
while True:
    if button_a.is_pressed():
        sleep(10)
        break

set(left, forward)
set(right, forward)
sleep(2000)
set(left, brake)
set(right, brake)
sleep(500)
set(left, backward)
set(right, backward)
sleep(2000)
set(left, brake)
set(right, brake)

Clued up soon


In the longer term I'll replace the micro:bit with an Adafruit Clue and add some more intelligence.

Friday, 28 February 2020

An I2C keypad for the micro:bit - part 2

A working prototype
I've now got a home-brew Arduino clone reading the keyboard and sending key-presses to a micro:bit using I2C.

Preparing the Arduino clone was trickier than usual.

As I mentioned in yesterday's post, the Arduino needs to run at 3.3 volts. That's the working voltage (Vcc) for the micro:bit, the Pi and the Jetson Nano. Connecting I2C lines from a 5v device would damage them, so 3.3 v operation is essential.

I have a good stock of ATmega328P chips left over from the days when I was running Shrimping workshops. The ATmega328P  works well at 3.3 volts, so long as the clock frequency is no more than 8 MHz. Most Arduinos run at 5v with a clock speed of 16 MHz, so there's work to do.

 

8 MHz clock issues


If I2C is to work reliably at 8 MHz the Arduino needs to be configured for an 8 MHz clock, and it needs a bootloader that works at that clock rate.

My first step was to wire up a working clone on a breadboard with an 8 MHz crystal and install the correct bootloader.

 

Installing the bootloader


These days it's pretty easy to burn a bootloader on an ATMega328. The Arduino IDE has a bootloader-burning sketch; I connected a Uno to my clone, following the excellent instructions on the Arduino website. I specified the target board as an Arduino pro mini with a 382 chip and 8 MHz clock and installed the bootloader.

Programming the Arduino clone


Once I'd done that I had a functioning, programmable clone running at 8 MHz on my breadboard. I wired it up to the keyboard and dug out a 3.3 volt FDTI cable.

Using the Arduino IDE and the FTDI cable I programmed my clone and did a smoke test to make sure that it was working. I'd modified the I2C keyboard sketch so that it flashed the on-board LED on start-up, and turned the LED on whenever the keyboard buffer filled up. I installed the sketch and verified that the keyboard was working.

Testing the keypad


Nearly there! I wrote a simple micropython test program for the micro:bit and connected it to the clone board. Using the mu REPL I could see the output from the keyboard. I've got the rows of the keyboard inverted, but that's easy to fix. The core is working and my next step will be to transfer the clone to an Adafruit perma-proto board, add a Grove connector, and document the whole construction and programming process. I've already added the Arduino and micro:python code to the babelboard software repository.

The micro:bit code


The microbit code is pretty simple.
from microbit import *
from time import sleep


class Keyboard:
    def __init__(self, addr=0x08):
        self._addr = addr

    def read_char(self):
        return i2c.read(self._addr, 1)



def run():
    kbd = Keyboard()
    while True:
        key = kbd.read_char()
        if (key != b'\x00'):
            print(key)
        sleep(0.01)

run()


I'll add comments and more code so you can use the keyboard with a Pi, an Adafruit CircuitPython board or a Jetson Nano.

Don't forget to follow @rareblog on Twitter if you want to see the final write-up!

Thursday, 27 February 2020

An I2C keypad for the micro:bit - part 1

I love the micro:bit. It's affordable, it runs micropython, and it's instantly engaging. These days it's supported by a huge range of add-ons that extend its capabilities, but there's always room for more.

A lot of the add-ons that I buy or build use are based on the I2C protocol. I2C is a  widely-supported way of connecting and controlling add-on boards to single board computers like the micro:bit, Arduino and Raspberry Pi.

There's lots of sample I2C code for the Arduino and the Pi, but not so much for the micro:bit. A few days ago I posted about an experiment connecting a micro:bit to a numeric keypad using I2C. That worked well, and the code is on GitHub. As you can see, the program needed quite a bit of code, and space on the micro:bit is at a premium. Since I wanted to add an LCD display I started looking for a more compact approach.

Help from Arduino


I decided to try out a design that used a home-brew Arduino clone to scan the keypad and make key-presses available with a simple I2C interface.

I'd previously used Arduinos in I2C slave mode, and there's a great example in the Arduino docs. Next I found a keypad library that looked as if it would fit the bill. It handles 3x4 and 4x4 keypads and it deals with contact debouncing.

Since the client can look for a key-press at any time, and the user can press a key whenever they want, my code includes a ring buffer to store key-presses until they are asked for. I used code from this excellent article on Hackaday.

 

The Uno Protoype


I put together a prototype using two Arduino Unos, one acting as a slave and one as the master.

It worked, and I've added the code and a fritzing diagram to the babelboard software project. It should be a simple matter to replace the slave Uno with a home-brew Arduino clone, but I've got one minor challenge to overcome.

The Uno runs on 5 volts, but the micro:bit and the Pi use 3.3 volt signals and 5 volt inputs will damage them. I'll need to run my Arduino clone on 3.3 volts. It's not hard, but causes a few complications. I'll describe them (and, I hope, the solutions) in the next blog post.

Follow me  (@rareblg) on twitter if you want to catch the next exciting episode :)


Friday, 21 February 2020

Adding a DS1307 Real Time Clock to Raspberry Pi

Grove RTC
The DS1307 RTC (Real Time Clock) is widely available, but adding one to a Raspberry Pi turned out to be a bit of a Yak shave.

I'm gradually adding code and wiring instructions to my babelboard hardware and software projects, and I thought it was time to cover an RTC.

I had a Grove RTC board from years ago and decided I'd document connecting that to a Raspberry Pi.

The need for Battery Power


First Yak Shave moment: RTCs normally use a coin battery to maintain power so they can keep time when their host is off, and the battery in my Grove board was way past its use-by date.

This happened on Sunday evening, and the local supermarkets were shut, but the local convenience store was open. No CR1220, though, so I had to wait until the next day to get started.

While I was waiting I read the data sheet for the DS1307 chip and realised I had another problem.

Don't connect this chip directly to your Pi!


Seeed Studios describe the DS1307 breakout as Pi-compatible, and so it is, if you connect it via a GrovePi board. The DS1307 is an I2C device and it requires a 5 volt supply.

If you do a direct connection to the Pi's I2C pins and apply 5v to the Grove RTC board, the pullup resistors will apply 5v to the Pi and bad things will eventually happen to the Pi.

Babelboard to the rescue


babelboard
One of my babelboards is designed to fix this very problem. It connects to the Pi header, but it has two Grove I2C connectors.

One is directly connected, so it runs at 3.3V.

The other is connected via a level shifter. It provides a 5v supply and handles 5v on the SDA and SCL I2C lines, but the level shifter means that the Pi only ever sees 3.3 v signals.

That's just what's needed for the DS1307, so I thought I was away to the races.

Not so fast!

Numpy? Why?


why numpy?
I installed the Grove script for the DS1307 and tried to run it. I got an error message telling me that Python couldn't find numpy.


What? Why does an RTC program need numpy's fast array handling?

It turns out that the Grove software assumes you want to install the whole Grove library, and everything depends on a Grove package, which in turn needs numpy for one particular board!

working output
Fortunately Adafruit has code to drive the DS1307 on the Pi. Once I'd installed that I could interface with the RTC and everything went swimmingly.

I'll document what I did and add it to the babelboard projects over the weekend.

After that, I'm an I2C keypad reader which uses an Arduino to do the heavy lifting, followed by a similar I2C 'old skool' LCD display. I'll post about those when they are ready.

If you're based in London, I'll be talking about micropyhon, CircuitPython and Blinka at the Raspberry Pint meeting at the Microsoft Reactor next Tuesday (25 Feb). There are other interestin talks; you can sign up here.




Saturday, 15 February 2020

I2C and SPI on the micro:bit; additions to the babelboard range

micro:bit Keypad using I2C+ MC23008
For some reason there's not a lot on the web about using I2C and SPI with the BBC micro:bit.

The I2C and SPI protocols allow single board computers like the micro:bit, the Raspberry Pi and Jetson Nano to drive hundreds of different types of useful peripheral chips.

There are lots of widely available drivers for the Raspberry Pi, the Arduino and  Adafruit boards. I've seen fewer for the micro:bit, and I have started writing some more as part of my babelboard project. I am also building a babelboard for the micro:bit.

The babelboard project


Babelboards allow you to connect a range of I2C and SPI devices to several popular single board computers.

The image on the right shows an mcp23S08 reading a hex keypad driven by a micro:bit using SPI.

The micro:bit babelboard allows you to connect Grove I2C devices and the Quick2Wire port expander and analog boards. You can get adapters that connect Grove to Qwiik, so you can also connect the range of Qwiik devices to the micro:bit. Planned enhancements will make it easy to connect to the Pimoroni breakout garden range, and the Adafruit STEMMA/STEMMA QT ranges.
A babelboard for the Jetson Nane

Existing babelboards allow you to connect I2C and SPI peripherals  to the Raspberry Pi, the Jetson Nano and Adafruit feather range. Since the Adafruit Clue has a micro:bit compatible pinout you'll be able to connect to that as well.

Most of these exist as prototpyes at present, but the designs are Open Source and I'll be publishing them as part of the babelboard hardware project. Some use stripboards, some use Adafruit permaProto boards, and a growing number use custom PCB designs created in Fritzing or KiCAD.

Connecting the hardware is not much use without software to drive it. If the the computer you're using supports CircuitPython or Adafruit Blinka you've got all you need to start using any device included in the CircuitPython library.

I'll be adding code to drive things from the micro:bit as time permits, and I'll also be adding code for more of the Grove peripherals.


Wednesday, 12 February 2020

The bistable flip-flop 60 years on

flip-flop from 'Electronic Computers'  - T.E. Ivall
About 60 years ago I started to teach myself about how digital computers worked. I'd already written some simple programs and I wanted to build a computer of my own. In 1960 that was a bit ambitious, but I did manage to build a few simple digital circuits including a flop-flop. (A few years later I hand-wired a core store, but that's another story).

The flip-flop lies at the heart of digital electronics.The thing that makes digital computers so powerful is memory. Memory  can store the data that programs work on, and it can also store the the programs themselves. Early computers used a variety of techniques for storage but almost all of them used flip-flops to some extent.

The bistable flip-flop is a very simple circuit. It can store a single binary digit (bit) of information.  The flip-flop was not new in 1960. The original patent was granted to the inventors (Eccles and Jordan) in 1918. That was long before the transistor was invented: the first flop-flops used valves (US: vacuum tubes).

Valves were still used in computers in 1960, but transistors were beginning to replace them. Transistors were expensive but I managed to buy a few from Proops*, a famous electronic components store in Tottenham Court Road, and I soldered two transistors together with a few other components to make a flip-flop.

* Proops still exists, albeit in a rather different format. They now support hobbyists, jewellers, craft makers and modelling enthusiasts, and run a mail order business from rural  Leicestershire.


A bistable flip-flop is a symmetrical circuit. At any given time one of the transistors is 'on' and the other 'off'. In an S-R flip-flop (the one I made back in 1960) a pair of buttons allowed you to put the flip-flop into either of its stable states.

I had to check the output using a multimeter; the transistors I used couldn't drive a light bulb, and LEDs were not yet invented.

A few days ago I decided to recreate the circuit using modern components. I started with a breadboarded version but since then I've built a more permanent flip-flop using stripboard. The layout reflects the symmetry of the circuit.

The physical version is reassuringly similar to the fritzing design.

Modern memory is based on a more complex version of the circuit, and modern computers contain a lot. You'd need 8 billion flip-flops to store a Gigabyte of data!

In last Wednesday's #MakersHour session on twitter, someone suggested that we should be capturing knowledge of original computer technology while olders like me are still around to recall it. Tweet to me (@rareblog) if you'd like to see more about early computer technology!

Adafruit Clue - love at first sight

My Adafruit Clue has just arrived, and I am delighted with it.

The Clue is a small single board computer that has the same format and connectors as the BBC micro:bit. It's more expensive than the micro:bit but it's a much, much more capable device.

micro:bit Pros and Cons 


I still love the micro:bit. It invites you to interact with it as soon as you power it on and it's introduced a huge audience to the pleasures of programming.

There are a range of programming options for the micro:bit, including micropython, and it's easy to program using the free mu editor.

 However, it has some frustrating limitations.

The micro:bit's 5x5 LED display is cute, but scarcely high-resolution. There are a few on-board sensors - an accelerometer and a magnetometer - and you can coax the processor chip into telling you how hot it is. It has a couple of buttons, and it supports radio communication with other micro:bits. But that's all.

It also has quite limited memory which can limit the complexity of the programs you write.

The micro:bit hardware has Bluetooth support, but its limited memory means that Bluetooth is not accessible from micropython.

The Clue blasts those limitations away.

Clue Power


Like the micro:bit, the clue can be programmed in Python. It supports CircuitPython, Adafruit's fork of micropython. That means that you get access to a library that's well documented, works reliably and supports a huge and growing range of peripherals from Adafruit and third parties. There's on-board Bluetooth and CircuitPython provides easy access.

My personal preference is to develop in Python but there's also support for the Arduino development environment.

The Clue has a great selection of peripherals on-board. Like the micro:bit, it has an accelerometer and compass, but it also has a gyroscope. You'll also find a light/colour/gesture sensors, a microphone, a buzzer and sensors to measure temperature, humidity and pressure. For me, though, the thing that instantly captured my heart was its crisp, colourful 1.3″ 240×240 TFT display.

Quick Start


Overall impressions of the Clue have been great. The hardware is very capable, and Adafruit's documentation is superb. Even if you have no Python experience, the Getting Started Guide will have you writing and running simple Python programs on the Clue in no time.

I bought an early alpha version of the Clue which has sold out. PyCon US attendees will be getting one as a freebie thanks to Adafruit and Digi-Key.
 It may be a little while until  the final production version is available but it will be worth the wait!

I'm currently working on some I2C applications on the original micro:bit, and I need an I2C monitor to help me troubleshoot. I have a couple of PC-based scopes that could do the job, but I think the Clue is up to the task, and it would be a fun project. I'll report on progress.

Tuesday, 28 January 2020

Totem - the Meccano replacement for 21C Makers

Totem kit
Totem and Pimoroni have combined forces to make my Christmas very early this year!

Earlier this month I discovered Totem Maker kits. I bought a 2 wheel drive bluetooth robot and was delighted at how easy it was to assemble and drive.

Totem are based on Vilnius, but my first order arrived quickly.

I have a couple more robot designs in the pipeline and decided to use one of the larger Totem kits for prototyping them. Some of the kits are now stocked by Pimoroni, so I ordered one, along with the extra components I needed for the next robot. The kit appeared the next day.

Instructions 
The Totem kit is beautifully packaged and the instructions are outstanding: visually attractive, clear and easy to follow.

I'll report on progress as I work on the robot design. I'll be showing the end result at next month's Margate Raspberry Jam and at the London Arduino Maker day in March. I'll post more details here as they become available.

Jetson Nano Upgrade

The Jetson Nano goes Stereo


The robot project after that will be based on the Jetson Nano. I'll probably get a third nano as the new upgrade can support two cameras - perfect for stereo vision.

Lazydoro


Lazydoro

Last week was mainly spent on finishing the lazydoro project - my automated Pomodoro timer. Lazydoro is working well enough for everyday use, and the code is on GitHub. There's more detail on https://hackaday.io and I will be presenting the project at tomorrow's Raspberry Pint meetup.


Lazydoro is going in the book


Get it on Leanpub!
I'm also going to add a chapter about Lazydoro to my book on the Pimoroni Explorer HAT  which I used for prototyping it. The chapter isn't there yet, but if you buy the book now you'll get it as a free upgrade when it's added.

I'll spend next week on the book, and I hope to have it 50% complete by mid-February.  The price will then increase, but current buyers will get all future upgrades free.

It's currently just $5, you get a 45 day money back guarantee, and there's a free sample available to see if you get on with the level and style.