Saturday, 31 March 2018

DC motor control with an RPi - writing the software

This explains some of the lessons learned and techniques I have used to develop Raspberry Pi software to provide accurate and responsive control for DC motors using feedback from rotary encoders.

It follows on from my previous post, showng the results of some initial testing on the feasability of good motor control using just a Raspberry Pi (i.e. without an arduino or other micro controller).

I very much liked the approach described by David Anderson explaining his approach to basic robot control, so the overall approach I used was to write software that is called from a regular timer function to run the control loop.

Such software can then be run directly from some higher level control loop, or wrapped up to provide a freestanding process controlled through a pipe or web service.

My usual approach to time / function critical software is to start with Python and get to a point where:
  • it all works well - great - job done.
  • it is hopeless - its never going to work this way - try something completely different or give up.
  • its working, but not quite well enough - perhaps a couple of small key parts can be re-implemented -possibly in C.
In this case - so far at least - the pure python version looks to be doing the job well.

I have a couple of repositories on github with the code for this, but these are still very much a work in progress.

motor drivers are here.

simple robot control is here. - So far this only does remote control from a web browser.

Wednesday, 21 February 2018

U3A robot - get the motors running

This is a record explaining the build on the robot RaspberryPi.

For now we're using the adafruit DC motor hat
  1. Fresh SD card image with Raspbian stretch lite
  2. Add wpa-supplicant file and ssh file to card
  3. Boot up pi and log in via ssh
  4. expand filesystem, change password, and change machne name (raspi-config)
  5. enable i2c (raspi-config)
  6. mkdir github, cd github
  7. sudo apt-get install git python3-dev python3-pip
  8. sudo apt-get install nfs-kernel-server  # if you want to remotely access files on this pi
  9. install the adafruit python library and setup
  10. make sure you are in the Adafruit examples library:
    cd ~/github/Adafruit-Motor-HAT-Python-Library/examples
Here's the motor HAT plugged into an Rpi Zero, the power is taken from the RPi's 5V supply (these are only little motors) and motors 3 & 4 are hooked up on my baby robot chassis. The example program DCTest.py now happily drives one of the motors.

Sunday, 4 February 2018

DC motor with rotary encoder feedback control using only a Raspberry Pi

In messing about with DC motors I knew I wanted to track position accurately, and I hoped I could do this with just an RPi, but all the advice and even some youtube videos said it couldn't be done reliably without using an arduino or other external controller - usually because the feedback loop timing requirements can't be met by an RPi. But having done a few very simple sums, it seemed to me it should be quite practical:
  • motor running at 10,000 rpm, with (say) 3 pole rotary encoder gives 500 pulses / second
That's pretty slow really - a package like pigpio says it can reliably time things to 5 microseconds or around  40 times faster than the pulse rate - so where's the problem? This nice thread here looked encouraging......

2 problems at least in what others have tried:
  1. trying to do this on an RPi running the full gui. Well gui's are well knows for being *really* nasty if you're trying to do anything time critical, if you want  an RPi to do something that has previously been done on dedicated hardware or low level machines like arduinos, starting by running a gui is like swimming in concrete boots!
  2. The VAST majority of code examples on picking up edges / pulses are using code looping reading the GPIO until it changes. Good grief, nice and simple, but REALY shouldn't be used other than a quick breadboard test to see if something appears to be working. Programming 101 grade F code.
So lets try and do this sensibly:
  1. Use a raspbery Pi Zero - cos we want something small, low power and cheap and if it works on a zero it will work on any other recentish Pi.
  2. Use raspbian lite. We can put the gui somewhere else - or use a web browser with the Zero running a baby web server.
  3. Use pigpio's daemon to do the hard work.
  4. Write in python - 'cos if it works reasonably well in python we can always use C++ to hand crank the 1 or 2 little bits that are critical.
  5. Use a pipgio callback to pick up the edges - in fact better still just use the callback tally function, because we probably only need the feedback loop to run 20 times a second or so.
So after couple of days messing about I have an untidy but working dc motor controller:
  1. Raspberry Pi Zero
  2. 2.5Ah power bank - Promate Aidbar-2
  3. Pure python3
  4. micrometal DC motor
  5. pololu magnetic rotary encoder
  6. H bridge in a pHat to drive the motor. (in fact I use pigpio PWM to drive the H bridge - it's about 1/2 the cpu load of the pimoroni library)
  7. home rolled motor control class with simple PID feedback running at 20Hz
The motor runs smoothly; although the low level control is quite jittery this is smoothed out pretty well by the motor's rotational inertia. Maybe some smoothing on the derivative component would help - I'll try that later.
The motor flat out no load runs at just over 500 ticks per second, this test is at 300 ticks per second and once initial correction has completed, the error is only 1% - 2%. This is with no load. The next graph shows the response to load changes:

This is a very basic test - I just squeezed the output wheel and released it a few times - sometimes to the point of nearly stalling the motor.

Wednesday, 5 April 2017

Final updates on driving stepper motors with pololu A4988 boards and pigpio

Nearly a year ago I blogged about my experiences with driving stepper motors from a Raspberry Pi. This was very much just a step towards writing my own telescope mount driving software.

In the meantime I found that although I was getting 800 full steps a second, it tended to stall at random intervals - typically after a couple of minutes, so reliability was not that great. It looked pretty likely that this was linux failing to run my pigpio script on time, resulting in occasional glitches in the timing which were enough to stall the motor.

I now have a version of the driver using waves (in fact 'wave_send_using_mode') and this delivers much better reliability at higher step rates.

I've put the demo code on github here.

It took a bit of messing about. I initially intended to use wave chains, but as I wanted to properly control the ramp up (and ramp down) for smooth transitions, my waves were getting rather large and with the added requirement to control 2 motors with subtly different settings at the same time, I was going to need far too much wave data to handle in this way.

So I have written this to generate waves on the fly, with 2 loaded and one ready to go in the code. This runs 1 stepper in double step mode on a Pi 2B quite happily at 1000 full steps per second (so 4000 wave transitions per second). My motors don't quite want to go this fast - about 900 is the max rate they reliably run at.

As a wave finishes, it is deleted and a new one created and tacked on the end.

Now, back to making goto work.........

Sunday, 4 December 2016

Really? starting services properly is that hard

I reaaaaally don't care if it's Raspbian or Debian screwing up the startup of nfs-kernel-server, it should have been fixed long ago.

And there are endless posts on debian raspbian and other forums about this, many with fixes that only work in very specific (unstated) circumstances.

In the end I just got out me Glasgow screwdriver and
stuck a new line in crontab to postfix the mess.

sudo crontab -e

and add the line
@reboot              sleep 5 ; /usr/sbin/service rpcbind start ; sleep 10 ; /usr/sbin/service nfs-kernel-server restart

Saturday, 3 December 2016

Astrophotography - the mount driver

I am using an old Vixen GP mount with the Vixen MT1 stepper motors.

I am using a raspberry pi with Pololu stepper drivers. I've described this in an earlier post.

Now comes the job of making this work - initially for guiding and hopefully later for 'goto' as well (albeit that will be a bit slow with these motors).

The ingredients are:
  1. pi model B
  2. 2 pololu drivers mounted on a little HAT card as described here
  3. a 24v power supply to drive the stepper motors
  4. CAREFULLY set the current limit on the pololu driver carriers
  5. write a test program to do some basic testing of the drivers / motors
  6. Prepare a second raspberry pi to run this nice autoguiding software
  7. do a quick hack to enable Gordon'd autogider software to talk to my driver software.

I have done a quick video of the test program running the code to slew the scope as fast as the steppers can go here.
and below is the gory details.....

Sunday, 28 August 2016

Very simple web serving for timelapse with Python on Raspberry Pi

Why?

I messed about with few different stacks for running a web server on pi, and most are complicated, in particular being complicated to configure as well as being large complicated animals that provide a lot of functionality (and overheads) that were of no real use to me. I wanted something that was:
  1.  simple to install / set up
  2. suitable for use as an 'inside' home web service (i.e. not exposed to the nasty world outside)
  3. able to run reasonably fast
  4. really simple to use (from python in particular)
Some very simple ways to do this use cgi, but I soon found this method awkward to use as well as looking like there were significant performance overheads. I switched to http.server.HTTPServer which I like and provides a 'shape' of framework I am comfortable with.

What?

On a LAN connected raspberry pi 3 this approach will happily serve up to 200 requests per second - as long as the overall network bandwidth doesn't get too high.

The test I used serves up images on demand to create a virtual movie. It is driven from javascript in the web page. The individual images were just under 20k bytes on average.

I wanted to minimise the load on the Raspberry Pi and keep the user interface simple to use and responsive. To do this the python web server is very simple and - after serving up the initial page - just responds to requests from the client.

The web page implements the user interface control functions in javascript and fires off requests to the web server.

The web server runs happily on Raspberry Pi (including zero) and on my ubuntu laptop. It appears to work well with Firefox, Chrome and Internet Explorer on laptops / PCs. It does not work in Edge, but as I have little interest in Windoze , I'm not really interested in the ie / edge use.

It will run on reasonably fast phones / tablets, but not at high framerates; my old Galaxy S2 isn't much use, but a Hudl2 works well as long as the framerate is kept low.

This is just a proof of concept, so presentation and error handling are minimal / non-existent, and functionality is limited.

How?

There are 2 files:
  • a python3 file (the server) of around 100 lines
  • an html file (the client) of around 200 lines
The simple webserver builds an index to all the jpeg files in the given folder, and serves a web page which then allows various javascript functions to move around within the images and play them back at various speeds by controlling framerate and stride.