Matrix LED testing

In the drive to be able to control more and more LEDs, there is the matrix format. Here’s a circuit diag from Kingbright that produce bulk devices. The circuit diagram is:

matrix_diag

Here’s a picture of the device

led_matrix

35 LEDs in an 7 by 5 package, and so only 13 pins. And so can be driven (in theory) by 2 shift registers.

For example, if C1 is 5V, and pin 9 is 0V, then current flows through the top left LED and that LED is lit. In fact, if all of the R1 to R7 are 0V, all 7 LEDs are lit. So as long as the R? are high (i.e. 5V) and C? are low (i.e. 0V) everything is off.

So we can control this by driving a particular column high, and then Rx low for the LEDs we want to be lit. Current will then flow and the LEDs lit. And this can then be done for each column in turn. We can take advantage of the fact that human eyes are, in terms of temporal response, rubbish and just light the LEDs as quickly as we can, it’ll look like a static picture.

HC magic

The 74hc595 shift registers have a bit of magic in them. The outputs can be driven high, and we are used to the idea that a driven high output can supply current, i.e. be a current source. Upto 20mA, which as LEDs are fully lit with 5 to 15mA (dependent on colour), is nice. In addition, an output driven low can sink current. No connection to ground required. So an LED can be placed between two outputs; if one end is driven high, and the other low, it’ll light. Any of the other three cases, the LED would not be lit.

History

A couple of years ago, I built a circuit to test this, using a Kingbright matrix, 2 74595s and a PIC. Due to a shortage of DIP scokets, an excess of enthusiasm, and a lack of planning (read: not drawing a circuti diagram before putting together) some mistakes were made. I traced through what was made, and identified the mistakes.

matrix_errors

Major thing to do here was to identify the mistakes. I then fixed up the board, and then it looked like

matrix_fixed

Code

The code is then simple. With the circuit above, the idea is to drive each column high in turn, and set the rows to low for the LEDs that are wanted to be lit, and high the others. I used the same send_byte_to_595 and display_595() routines that I used for the Spoke Pov project, making sure to send the row first, and then the column. i.e.

void display_5x7_matrix(char v1, char v2, char v3, char v4, char v5) {

    send_byte_to_595(v1);
    send_byte_to_595(0x08);
    display_595();

    send_byte_to_595(v2);
    send_byte_to_595(0x10);
    display_595();

    send_byte_to_595(v3);
    send_byte_to_595(0x20);
    display_595();

    send_byte_to_595(v4);
    send_byte_to_595(0x40);
    display_595();

    send_byte_to_595(v5);
    send_byte_to_595(0x80);
    display_595();
}

The main() is just then a repeated set of calls with the right values

 
{
    v1 = 0b00010000;
    v2 = 0b00100100;
    v3 = 0b01000000;
    v4 = 0b00100100;
    v5 = 0b00010000;

    while ( 1==1 ) {
        display_5x7_matrix(~v1, ~v2, ~v3, ~v4, ~v5);
    }
}

Simples.

The pattern is designed by my daughter as a smily face. And it works!

Demo image, along with design requirements from daughter.

Demo image, along with design requirements from daughter.

Interestingly, the different colours are not as obvious to human eyes as to the camera…

Code for this is on github as [to be filled in]

This was all a test. The idea is to push to a larger, homemade, matrix of LEDs for another project. But this circuit allows a little experimention with the “output enable” control pin to change brightnesses (the subject of a forthcoming post) and a general proof of concept of driving a matrix without having to wire up 35 LEDs…

 

 

Advertisements

Bike Spoke Images; final breadboard?

With the interrupts at least demonstrated (https://astrospanner.wordpress.com/2014/02/02/bike-spoke-images-timer-interrupt-woes/), hall effect switching demonstrated (https://astrospanner.wordpress.com/2014/01/24/magnetic-switching-pov/) and LED control demonstrated (https://astrospanner.wordpress.com/2014/01/27/bike-spoke-images-pic-leds/), two things are true:

  1. all the hardware has been demonstrated to work
  2. conceptually, the “hard” bits of the software have been demonstrated to work.

So there are two more steps; a final software build and a final hardware build.

Feel free to listen to this (http://www.youtube.com/watch?v=9jK-NcRmVcw) whilst reading this post.

Final Software Build

The software is structured into three sections: a timer interrupt routine, a hall effect interrupt routine and a main() routine. It’s generally a good idea for interrupt routines to be quick to execute, so that further interrupts are not missed. As such, the display driving has been moved to the main() routine. The three routines communicate via a set of global variables. The global variables are:

Global variable Timer Switch Main
Counter increment read, reset
Change Display Flag Set Set Read & Reset
DisplayCounter Read, Write
DisplayCounterSet Read Set
ToDisplay Increment Reset Read

Flowcharts for the three sections are

main()

main

hall effect switch

switch

timer

timer

And in words, the idea is whenever the magnet passes the Hall Effect switch, the following things happen:

  1. the number of timer ticks since that last happened, divided by the number of radial lines to display is stored (in “DisplayCounterSet”)
  2. DisplayCounter is reset (to DsiplayCounterSet)
  3. The radial line to display is reset to zero
  4. The zero radial line is displayed

The timer is counting down DisplayCounter, and when it reaches zero, the DisplayCounter is reset to DisplayCounterSet and a new line gets displayed.

Because the wheel rotation speed is changing (reasonably) slowly, this scheme uses the last rotation speed to guess where to display each radial line. If we didn’t do this, he orientation of the displayed image would drift, unless the wheel was going at the exactly correct speed (which would also be dependent on battery voltage and temperature).

Final Breadboard

With the code working, this can be implemented on a breadboard. It’s the same breadboard as used before, just with the addition of the magnetic switch onto pin 4 of the PIC. (Pin 4 is the input only pin of the PIC12f675 so it makes sense to use it as the only input.) For aliveness testing I also added an LED driven by pin 3 and an additional line into the Hall Effect routine to toggle the GPIO so I could check that a) the PIC was doing something and b) all magnet passes were identified.

And it works!

Video here: http://www.youtube.com/watch?v=nfqQzUZzInU

You can see in the video that there is a fast pattern for the first 3 seconds, and then I pass a magnet near the Hall Effect sensor (which is on the bottom right of the board). The pattern then repeats after the next pass at 7 seconds. The pattern certainly repeats.

The pattern is hardcoded to 64 lines. It intends to say “CYCLING ROCKS”. The font is hand designed to fit into the 64 lines to be 8×4 sets, to look like this:

Excel produced image

Excel produced of message

The circuit board (as seen in the video) was actually built a couple of years ago for a 16 pin PIC. Fortunately, the power connections for different PICs are presumably deliberately pin 1 and the last numbered pin, so a 8 pin PIC can be put into the same socket. After wrapping with some duct tape, I then mounted on the front of wheel of my daughter’s bike. (Smallest bike to get into the kitchen work area).

Breadboard on the bike

Breadboard on the bike

The magnet was duct-taped to the fork, and with the lights off, can be tested properly, as can be seen below:

running

This was stable for different rotation speeds. So apart from senses of letters, this can probably be declared a success!

Next steps are to try this on a bike that we can actually cycle along to see what it looks like to a random passersby before going for a full up 24 LED version. (Still slightly worried about fitting all the data into the PIC…)

Bike Spoke Images: Code release

As intended, I’ve setup a github account and repository. The clone url is: https://github.com/astrospanner/pov_project.git

All the code used for the demos so far is on there. Because it was setup after I wrote and debugged most of the code, there’s little history that you would normally associate with a proper version control system.

From now, this is now the public facing repository for all project work that this blog will document.

It’s worth pointing out that I’m using TortiseGit (https://code.google.com/p/tortoisegit/) as a Windows 7 shell extension to help with the commits and pushing. The Dancing Monkeys blog had an excellent easy to follow instruction blog post that I followed to get everything setup. Linky: http://dancingmonkeysaccelerated.blogspot.co.uk/2012/03/git-for-windows-with-tortoisegit-and.html

Enjoy the code! If you think it can be improved; comment, or send me a patch!

Licensing…

I’m going to release the code for the Bike Spoke images. But which license should I use? http://choosealicense.com/ gives a handy guide, and I quickly decided on the MIT License. (http://choosealicense.com/licenses/mit/)

Why? That’s a question with two levels.

Firstly, I want to distribute the code so that others can learn from it, use it, and tweak it to add things to adapt it to their use cases. (For example, running with less LEDs, or changing the image, or, even, providing a memory card containing the image on the fly…) An open source license allows this.

Secondly, I want some attribution (or as some might say, blame) for my code. But if it blows up your toaster or makes your cat sick on the rug (it won’t), I don’t want to be liable. If someone invents a wizzy method for something that builds on my code, and manages to license/sell it, great for them. This means further use of my code, which goes back to the original reason for building stuff; to make something that might outlast you.

The MIT license fits with these goals, and is not an enormous long legalistic document that no-one will read (c.f. GPL v2 or v3). So my default license will be the MIT license. And I see this work plastered all over a youtube video as a how-to (with attribution) I will be happy.

 

Bike Spoke Images; timer interrupt woes

Interrupts are wonderful things for programmers, both for embedded system programmers using PICs, but also for PCs. Their utility comes from the fact that the processor is an inherently serial device[1]; it processes one instruction, and then another, and then another. And for the large part, that’s how we write code; one statement following another, following another.

Clock ticks

Imagine that you were writing a piece of code to tell the time, and that you didn’t have a seperate “clock unit”[1]. You know how fast the instruction clock is, and how many cycles each instruction takes, and so you could count how many cycles have gone since the last “time increment”. But you’d have to do that by hand, based on the source code. Could be do-able for a RISC chip like a PIC; the instructions all take 2 cycles (if I remember correctly). But for a complex instruction set (CISC) beastie like the long-in-the-tooth 8086 chip, different addressing modes would change the number of clock cycles from 6 to 12 [reference: http://zsmith.co/intel.html#clock]. Impossible.

Interrupts to the rescue! Interrupts literally interrupt the processor in what its doing, and say “go do this bit now”, where “this bit” is a separate piece of code stored at a a specific location. There’s what’s called a context switch first; basically a bookmark placed in the code (along with register contents) so that it can come back to it later; the interrupt routine is then free to do its job, and at the end of that says “that’s it, done”, and the processer does another context switch back to the pre-running code.

An historical aside

MS-DOS programmers had an meaning for “interrupt”, because the 8086 allowed you call interrupts with a “INT xx” command. Microsoft provided an API on INT 21, and the PC hardware would provide API on lower INT numbers. The wonderful Ralf Brown Interrupt List (http://www.ctyme.com/rbrown.htm) detailed them all. Sharp eyed readers will note that some viruses add their own install checks in there as well! I still remember the lever arch file full of the printout that I used back in the day.

Interrupt sources

For a PIC, interrupts can be generate from internal or external events. (No handy API for PIC programmers!). External events can be a peripheral[2] wanting attention (eg UART for RS232 comms[3], ADC finished it’s conversion), or an externally applied voltage going high, or internal, which is really just one of the timers.

The externally applied voltage we’re going to use for the output from the Hall Effect switch.

The timer we should use to do the timing to ensure that the relative timing works.

Testing timers

According to the documentation, an interrupt will be generated if

  1. The ToIE bit (bit 5 of INTCON register) is set, and
  2. The clock counter TMR0 overflows (i.e. goes from 255 to 0), and
  3. Interrupts are enabled.

Again, according to the docs, software should clear the interrupt.

So I wrote some initalization code that does this, and a C code interrupt handler:

void interrupt general_ISR(void) {
 // interrupt service routine. 
 if (INTCON & 0b00100100 == 0b00100100) { 
    // if bit 2 and 5 set, interrupt called
    counter++;
    INTCON = INTCON & 0b11111011; // clear bit 2
 }

}

This did not work for me. Neither in hardware, nor in the MPLAB provided simulator[4]. But reading the supplied lessons (!) showed that the following should work:

void interrupt general_ISR(void) {
 // interrupt service routine. 
 // two interrupts to check; GPIO and timer0 overflow...
 if (T0IE && T0IF) { //are TMR0 interupts enable and is TMR0 interrupt set?
    T0IF = 0; // clear in software
    counter++;
 }
}

Success! It works! I can only assume that something subtle  is happening in the compile process, but playing with the debugger shows that this is now called, and after a quick code change to light the LED, it works in hardware as well. Phew! It’s worth saying that this took 2 evenings of fiddling/reading/recompiling/head-wall interfacing to try alternatives/read docs/swear loudly… But now it works, and we can move on…

[1] I have a project in mind that will use a Real Time Clock chip.

[2] The PIC team have an odd idea about peripherals. For me, a peripheral is an external device. For the PIC team, a peripheral is an internal piece of circuitry that can be disabled; eg the ADC unit.

[3]  Not a feature of the PIC I’m using here, but a previous work related PIC project has used serial comms from a PC, and the UART takes all the pain out. Don’t do USB or RS232 comms in software; let the hardware handle it!

[4] Which I’d not played with before. I’ve used PICkit3, with its in circuit debugger[5], and PICkit1 (which I have at home) does have that, so I thought I was restricted to staring at the code and thinking hard. But one of the debugger tools in MPLAB is MPLAB SIM which is a full up simulator of the PIC device. And for a situation like this with no complicated external circuits, it was easy to show that my code never actually ran.

[5] Fantastic bit of kit. Single step through some PIC code whilst all the external hardware is attached? Yes please; great for debugging.

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…

 

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…