Posts

Showing posts from 2017

Uploading custom HEX firmware to MicroPython board

Image
In my last post we setup System Workbench and setup some flashing LED code, we compiled it and uploaded it to the Pyboard.  We had to generate a HEX file in System Workbench, generate a DFU file and then upload the DFU file to the board - phew!  It's actually fairly simple to automate the DFU conversion and upload process.  First, download the DFUSE-commandline utility, here:

Hacking a MicroPython board with custom firmware

Image
I've had a MicroPython board sitting around my work bench for a while.  I think it's a brilliant way of interfacing hardware and using Python in a very straightforward way.  I've thinking about getting into into programming ARM chips for a little bit, and my MicroPython board came to mind.  After all, it's potentially a great development board if only we could hack the firmware that comes with it!

Controlling my quadcopter with a PS2 controller

Image
I can now control my quadcopter with a PS2 controller - really cool!  The magic control box is powered either from the Arduino Nano inside and communicates with the quadcopter via radio, or a lipo battery, which is rechargeable over USB.  LEDs on the top feedback about the drone status and look really awesome. UPDATE: I have now incorporated the control electronics, and a long distance radio module directly into the PS2 controller!

Height and vertical velocity Kalman filtering on MS5611 barometer: part 2

Image
Adding accelerometer data to the Kalman filter In my last post I wrote about a Kalman filter to take the MS5611 barometer data and derive both the quadcopter height, and the vertical velocity.  It worked reasonably well but there was a compromise between noise and latency of the filter.  To get even better results, I have incorporated now the accelerometer.  We could produce a new Kalman filter using the height, velocity and acceleration in the state vector, but it turns out we can simply amend our previous filter and include the acceleration in the control vector to improve the predicted state.

Height and vertical velocity Kalman filtering on MS5611 barometer

Image
Height and vertical velocity from a MS5611 barometer Steps towards vertical flight control This isn't a post explaining how Kalman filters work, I assume some working knowledge.  Instead I wanted to record the process of developing a Kalman filter to derive both the height and the vertical velocity of a quadcopter using a MS5611 barometer, as it may be useful to others.  After recording some flight data on my quadcopter EEPROM, I then spat the output to a PC for post-processing and model training.  In Python I used a Kalman class to generate the following Kalman filter ( Wikipedia: Kalman filter ) based on the barometric height data.

The Fast and the Furious World (of Trigonometric Functions on ATMega328)

Image
Atan2 algorithms - speed vs accuracy Running trigonometric functions on an 8-bit AVR is inevitably going to be slow.  Floating point operations come with speed overheads and the most accurate algorithms usually come at a further timing price.  The arctangent function (atan/atan2) is ubiquitously useful, and especially so for Quadcopter's and robotics.  Briefly, an  atan2   function takes Y and X as arguments and works out which quadrant the tangent angle is in, and uses that to call a corresponding  atan   function.  I have been investigated the timings of various trigonometric functions on an ATMega328p chip running at 16 MHz, and in particular exploring 4 atan2 implementations and their trade-offs for accuracy.

Bluetooth programmer

Image
From breadboard to perfboard I have been busy bending Bluetooth modules to my will.  The typical parameters I need to control are the module name, baud rate, and whether the module is a slave or master.  To program my quadcopter over Bluetooth, I have defined a Bluetooth module as a Master, which connects automatically to the quadcopter slave module when available.  The Master module connects to the PC via an RS232 USB converter - until now this been a mass of wires living on a breadboard, but I've now finally soldered a simple circuit together to allow me to program modules more easily.

Quadcopter code structure

Image
I've been meaning to post this for a while but after soldering everything together and correcting the errors in the PCB (details blogged here: Resolving UART bus conflict and Power control ), THE THING FLIES !  In fact it flies pretty well. I thought I would record the code structure of the quadcopter. Below, psuedo-code for the quadcopter main loop, focusing on stabilisation:

A tale of two UART devices

Image
Resolving UART bus conflicts and voltage levels I wanted to record two potential issues I found with using my custom Atmega328p board with onboard USB FT232 when an HC-05 bluetooth module in introduced, in the hope it may well be helpful to others. Above:   A small piece of perfboard modifies the Bluetooth socket to include a 5V to 3.3V voltage divider on the Bluetooth HC-05 RX line (10 and 20kohm resistors).  The red wire provides a direct line from the Bluetooth HC-05 TX output and the Atmega328p RX input, thereby granting it preference when the HC-05 module is present.  It's not quite clear from the picture, but the RX input pin is bent up out of the socket and a 1k resistor connects the FT232 TX output (see below).

Customising Optiboot

Image
I wanted to setup programming my custom Atmega328p board over Bluetooth.  Some have used the connection pin to control the Reset pin of the AVR.  However I want to use Bluetooth constantly, and only trigger a reset upon receiving a specific string sequence.  This requires tweaking the bootloader, using Optiboot as a basis: (1) Change Baudrate to be mutually compatible with Bluebooth and AVR. (2) Set an EEPROM byte in the main application, which could be read (and written) in the Optiboot routine. Setting up Optiboot in the Atmel environment: - Setup a project as usual in Atmel Studio - Copy files over from github to the project folder: optiboot.c, pindefs.h, stk500.h and boot.h. EDIT: It seems there is an AtmelStudio folder already set up on github . Setting baud rate to be compatible with AVR and Bluetooth module: 57600 bps - Insert #define BAUD_RATE 57600 (as required) into optiboot.c . - Compile and link project with following settings: Compiler Misc: -g -Wall -O

Radio control

Image
Accessing  quadcopter memory over radio The usual method of controlling quadcopters is to transmit a train of PPM signals from a radio transmitter, measure the length of the individual pulses on a microcontroller, via a radio receiver .  As part of my DIY ethos, and as a learning exercise, I have made the above controller with an nrf24l01 moduled and an Arduino Nano.  In a nutshell, the Arduino Nano captures the 2D joystick positions, used for yaw, throttle, pitch and roll, and the button presses.  A data packet is then sent by radio to the Quadcopter.  In fact there is a more powerful implementation going on.  What is interesting is how the controller sends data to the Quadcopter - it actually manipulates the memory directly on the Quadcopter AVR - how does it do that? Well, first of all the Quadcopter defines the memory addresses that the controller has access to by setting recording a pointer to the desired variable - note that the cast means that it doesn't matter w

Stuck in Atmega328 reset loop?

Image
Kill switch killing... but stuck in reset loop I wanted to add a kill switch to my quadcopter project so that in the case of crash/emergency, a button might be pushed on the radio controller, the quadcopter motors stopped and the flight controller chip is reset.  A good way of resetting an AVR is to invoke the watchdog timer and put the chip into an infinite loop - the watchdog times out and the chip is reset.  This is fairly straightforward when the kill/reset signal is received: #include <avr/wdt.h> void kill_drone(void) { USART_Pputstring(PSTR("Kill drone!\n")); wdt_reset(); wdt_enable(WDTO_15MS); while(1){}; } where the two watchdog handling functions are defined in avr/wdt.h. The AVR is reset, but keeps on reseting, initialising and resetting in an infinite loop... Watchdog Groundhog day! It turns out that the watchdog register settings are enabled, even after a reset !  To get around this, the watchdog must be turned off at the earlie