Bike Spoke images; PIC + LEDs

As per the plan (https://astrospanner.wordpress.com/2014/01/13/bike-spoke-images-the-plan), the PIC needs to drive a whole bunch of LEDs. The PIC I’m baselining (12F675) has 5 output pins (+two power + 1 input; 8 pin DIP package), and so driving more than 5 needs something extra. Some kind of multiplexing is clearly in order. For this, I’ve chosen to use a shift register. (An alternative is to use a binary to decimal converter; which expands 4 outputs to 10, but it doesn’t scale).

74×595

Mainly because I already know about it, I’ve chosen the 74HC595 shift register. It has 5 control lines, and 8 outputs. If you already know about it, feel free to skip this bit…

Because it’s an HC series, its relatively beefy, and so can supply enough current to drive an LED. The control lines are

  1. Data in
  2. Data Clock
  3. Parallel Load
  4. Output Enable
  5. Master Reset

The idea is that you “present” a logic high or low on the Data in, and then drive Data Clock high. Do this 8 times, and the internal registers contain the 8 values you presented on Data In. Send Parallel Load high, and the internal registers are loaded to the external registers, which are tied to the output pins. The output pins are then either high or low, based on the pattern you shifted in. And they stay there whilst you shift more stuff along…

Multiple ‘595s can be daisy chained together, all driven from the same Data Clock, same Parallel Load, so with, say 8 chips 64 leds can be addressed. Output Enable can be kept low, and Master Reset high, so they don’t have to be tied to the PIC. Lovely.

The circuit is as shown:

Breadboard 2

And when built (on a breadboard) it looks like this:

Boardboard 4, the reality

Boardboard 4, the reality

I’m using the Microchip MPLAB IDE for writing the code (it came with the PicKit1 programmer I’ve got) and I’ve installed the Microchip MPLAB XC8 Compiler so that I don’t have to bang my head against the wall in assembly code too much.

Installing XC8 was easy; download from https://www.microchip.com/pagehandler/en_us/devtools/mplabxc/

and install. When I started the new project in the MPLAB IDE, I just had to select the right toolsuite, which was already detected, and everything worked.

The code is split into four routines: first, init()

void init() {
 // disable interrupts
 INTCON = 0;
 // set internal oscillator freqeunecy
 OSCCAL = 0x80; // set internal oscillator to mid frequency
 // GP0,1,2 as outputs (=0) rest as inputs
 TRISIO = 0b00001000;

 // disable ADC 
 ANSEL = 0b00000000; // set ANS[0:3] bits to zero
 GPIO = 0; // clear GPIO
}

And then two routines that either send a byte (ie 8 bits) to the 595, and another to "display" them. 

void send_byte_to_595(char a) {
// Sends the byte a, LSB first, to the 74'595 shift register
 int i; 
 char b;
b = a;
 for (i=0; i<8; i++) {
   if ((b & 0x01) == 0x01) {
      GPIO = GPIO | 0b00000010; // data is high...
     _delay(2);
   } else {
      GPIO = GPIO & 0b11111000; // data is low
     _delay(2);
   }
   GPIO = GPIO | 0b00000100; // clock high
   _delay(2);
   GPIO = GPIO & 0b11111000; // clear the bits
   b = b >> 1; // shift it right
  }
}

_delay(x) is a provided routine that adds x cycles of nops to the code. GPIO is a defined register that maps directly to the hardware outputs; each bit is an output. Nice and easy to use.

void display_595() {
// toggle the parallel load bit of the output to display the byte(s) that have been sent.
 _delay(2);
 GPIO = GPIO | 1;
 _delay(2);
 GPIO = GPIO & 0b11111110;
}

In this circuit they don’t need to be split, but it allows flexibility for different number of chips later (if need be).

The main() routine just then calls init()  and then enters an infinite loop:

main() {
 char i;
 init();
 while ( 1==1 ) {
   for (i=0; i<255; i++) {
     send_byte_to_595(i); 
     display_595();
     GPIO = GPIO ^ 0b00100000; 
     _delay(1000000); // delay 1000000 cycles
   }
  }
}

Whilst I would love to claim this all worked first time, it didn’t. The debugging process added the additional LED onto pin 2, which worked sometimes, and didn’t work other times. This was most frustrating as it always worked whilst on the PICkit1 programmer board. I was poking around with a DVM checking wiring and then it would work for a couple of ticks, and then stop. After a while I actually read the datasheet and found the “master reset” function. I had it set to external, with pin 4, the master reset pin, floating. So it was reseting randomly. Change the config option to “internal”, and it worked happily.

Next step; synchronizing with the magnet sensor…

Addendum

One of the nice things about writing the code in C is that I now have two utility functions that I know work, and can be pulled into other projects, or at least other breadboards as required. But the XC8 compiler doesn’t do any optimization whilst in free mode. For the code I’ve written here, the memory summary is reported as

Memory Summary: 
   Program space used 74h ( 116) of 400h words ( 11.3%) 
   Data space used     Ch ( 12)  of 40h bytes ( 18.8%)

11% is OK at the minute, but the plan called for storing 128 * 3 bytes of just picture data, ie an additional 384 bytes of the 1024 words allowed. The overall memory usage may get bigger, and I’m not convinced that re-writing in assembly will be worth the trouble. Shifting to a bigger PIC will be though…

 

Advertisements

Magnetic switching; POV

Part of the POV circuit is a Hall effect switch.The magnet is held on the fork and provides the “zero degree” reference for starting the display.

I’ve not used a hall effect switch before, so thought a quick test circuit was in order. Allegro do a number of Hall effect switches, which I found from a quick glance through the Farnell website. I randomly picked the A1120. Not too expensive; 88p each. The user (i.e. me) supplies power, ground and a pull up resistor to pull the output high. When the device is “on”, the output gets pulled low.

For this test circuit, I’ve added an LED to give a visual indication of the voltage.

Circuit:

mag switch circuit diag

Breadboard:

Easy to setup, as shown in the photo below. With no magnet nearby:

mag switch circuit on

And with a magnet nearby:

mag switch circuit off

Success! Next step; input into a PIC…

Bike Spoke Images: The Plan

I want to build something that displays an image over a (push)bike wheel whilst the bike is in motion.

I know these exist: for example Ladyada used to sell a kit based on this Instructable: http://www.instructables.com/id/SpokePOV%3A-LED-Bike-Wheel-Images/

But what’s more fun: building it from scratch or buying a kit? And which way will I learn more? For me, the answer is the former, so here we go. This post is the baseline plan, along with some calculations. Because they already exist, there shouldn’t be a problem with the overall concept, just as long as I get it right…

Oh, and I’m a systems engineer, so I approach things from a top down aspect, and tend to define required functionality to help me decide on the build/test flow. Top level functionality has already been decided (“display images on a bike wheel”), so it’s time to come up with a first iteration. Ideally, this would then flow back to define more requirements, but at some point my hands get itchy and I want to build something…

First: pick the architecture. As I have a PICkit programmer, and a bunch of PICs lying around, I pick the PIC. A load of LEDs are required, so I’ll use a shift register to drive all the LEDs. And a timing signal needs to come from somewhere: a magnet on the bike fork sensed by a hall effect sensor will complete the package.

Basic diagram is then as shown:

Basic system diagram

Low level functions of this circuit are:

  • Respond to magnet
  • Light LEDs in addressable manner

Higher level function of this circuit is:

  • Display an image based on magnet based switching.

I’ll add another, not defined by the circuit

  • Go into sleep mode after 5 minutes of no magnet based switching
  • Wake from sleep mode on a magnet based switching event.

These last two mean that it can be left on a bike, and there is no power switch, and you can never forget to turn it on.

Note that this is very simple; the image will be hardcoded into the PIC.

Testing flow

Each function has to be tested, so this leads to three demo/breadboards/tests

  1. Hall Effect switch response to magnet. The PIC need not be present for this.
  2. Hall Effect switch response to magnet. “Read” by PIC, lights an LED. (No Shift Register required for this). Should also demonstrate sleep (ie low power consumption mode) of PIC.
  3. LEDs controlled by PIC via shift register. Should be representative of final model
  4. Full up demo with test pattern.

Operating frequency

This is going to be mounted on a 700C sheel, ie diameter ~700mm (Yes, I know the actual diameter is a little bigger for a MTB). So the circumference is pi times that, = 2.2m. Let’s use two speeds, 10mph and 30 mph (as people go downhill on bikes as well!). 10mph = 16 km in 3600s = 4.4m/s. (30mph = 13.2m/s). So at 10mph, with a 2.2m circumference wheel, need to update the entire image in 500ms. At 30mph, this drops to 166ms.

Lets assume ~24 LEDs (3 shift registers). Seperated by 10.16mm (which form 5mm LEDs might be a bit too far apart, but would work for 8mm nicely), 24 LEDs covers 243.8mm. This gives a bit of space at both ends of the radius for the hub.

Lets assume that there’s a gap for another 8 LEDs where the hub is, so really it’s a going to sweep out a circle inside a square 64 by 64 LEDs. Convert to angular space, and we need to split into 32×4 = 128 seperate angles. ie every 360/128 degrees will have a different pattern displayed on the LED. 166ms / 128  = 1.29ms, which corresponds to 780 Hz. As PICs can run upto 2MHz, there will be plently of instruction cycles to figure out which pattern to display and shift them out along the shift register.

Next step is to start some breadboarding, as well as thinking about the code architecture. That’s for another post…

Why do we build?

What drives people to build, make and experiment to create new things? Some people are driven to solve a problem that faces humanity; they are driven to make the world a better place. Two examples: Bill Gates wants to rid the world of malaria and so is throwing money at the problem. The team behind the citizen science project SpaceWarps  (http://spacewarps.org/)) are driven to find out large scale things about the universe and so is trying to engage the public in processing the data to allow further measurements.

I wish I had such lofty goals; mine are far more selfish.

I don’t particularly want to be remembered (although it would be nice!), I want my finite time on Earth to have made a difference. I also want to have fun doing it.

That sounds very grand, but it’s not really. It just means that I want to leave a mark that will inform future generations, and possibly inspire current generations to do stuff, whilst having doing something I enjoy.

Whilst I was doing my GCSEs, in my English Language lessons[1] I wrote a short piece of fiction about a detective investigating a murder in a train tunnel[2]. In that, the detective expounded about how nothing really mattered as humans are just bags of cells operating to reproduce the DNA. It was a distilled version of the ideas from Richard Dawkin’s book The Selfish Gene, which, as a precocious teenager, I’d been reading . My teacher at the time declared (without debate) that it was a “marvellous pastiche”  because such “extreme views” wouldn’t be held by normal rational people, and so gave it top marks. [3] Unfortunately, it wasn’t a pastiche. I think that we are just self replicating bags of meat, with the unfortunately side-effect of conciousness.

However! This doesn’t mean we can’t do useful things. We clearly can build things that outlast us. Brunel built tunnels that are still used today (the Thames Tunnel for example) and had fun doing it; Box Tunnel is allegedly deliberately aligned so that a shaft of light shines through it on his birthday.  (Although, according to Wikipedia[5] “Brunel is credited with turning the town of Swindon into one of the largest growing towns in Europe during the 19th century”, so it wasn’t all good.)

Some may say that this gives us license to be entirely hedonistic. In the short term, yes.[4] But in the longer term, if we took the entirely hedonistic view, there is no requirement to hope that future generations will benefit from our lives.

Initially, I wanted this to be scientific knowledge. I have written, and contributed, to papers, and so have helped the sum total knowledge of humans increase. In a hundred years, my name will be found in copyright libraries where copies of these journals will be found. So, done that.

Second option is to have kids. I have kids, and they are wilful, fantastic people who, hopefully, will remember their Dad.

Third option is to build things. I’ve been lucky enough to get involved in building “general purpose” scientific instruments that will help others find out things (the the parlance, they are “common user” instruments) as well as more specific instruments that will measure a particular quantity to high accuracy. I have found this one the most satisfying. These instruments can take many man-years to put together, and so can seem frustrating during the process. Looking back, it can be worth it. Because of the very long time scales involved, it can be fun to throw together a shop-bought kit to produce something over a weekend or two.

To summarize: We build things to give our lives meaning whilst enjoying ourselves.

To summarize the summary: Because it’s fun.

[1] This dates me. And probably geographically places me. Fine

[2] As a piece of fiction, it’s an idea I want to return to.

[3] Had the debate happened, I would have probably not got top marks.

[4] I am writing this with a beer by my keyboard.

[5] http://en.wikipedia.org/wiki/Isambard_Kingdom_Brunel

Obligatory first post

This is the required “first post” for this blog.

This blog shall contain project postings for my “built at home” electronics projects. These will start with PIC programming projects, and, hopefully, build up to larger scale projects.

Intended audience is those with some electronics interest, and at least a basic knowledge of Ohm’s law. The ability to pick up a soldering iron without burning yourself (on at least the second attempt) is also assumed.