Fibonacci Sequence Counter

imagesThe Fibonacci Sequence Counter is a small device based on a PIC12F683 microcontroller that computes and displays Fibonacci numbers with 16 bit accuracy . The project was created as an exercise in assembly language for PIC microcontrollers.
The assembly code should be useful for anyone wanting to learn how to deal with a PIC's special function registers, 16bit addition, and outputting clocked serial data to a device such as a shift register.

For information on the Fibonacci Sequence look here: http://en.wikipedia.org/wiki/Fibonacci_number
(simply put, any number in the sequence is made by adding the previous two numbers, for example 0, 1, 1, 2, 3, 5, 8, 13, etc....)

If you have any questions or comments about this project or PIC's and electronics in general, please email me at cybrown@cp-tel.net

More projects can be found at http://www.pasqualy.com

 

Operation

The unit has 16 LED's to display the Fibonacci numbers in binary. In the image above the MSB is on the right, and the LSB is on the left.
The Overflow LED lets the user know when the 16bit number space has been reached. At this point all operations stop and the last good Fibonacci number is left on the display.

There are two buttons on the device:
Reset: Resets the device and starts with the LED's cleared.
Next: This button tells the PIC to calculate the next Fibonacci number in the sequence and display it on the LEDs. The device starts with the first two numbers 0 and 1 assumed, so the first number to be displayed will be 1 (0+1=1).

As a side note, this project makes a pretty decent random bit pattern after the first 20 or so iterations if you set it to run over a delay instead of button presses. Once it is past the small numbers that can be represented with 16 bits you can get a nice light show by letting the program run past the overflow point. You can get an idea of how random the distribution is by setting the operation to run at a high rate and observing if all the LED's appear to have the same brightness. If one is dim, it means its not getting the same on time as the others over time.

 

Code

The entire project was written in assembly and compiled using MPLAB from microchip. I did test the circuit beforehand by using a simple test program written in PICBasic so that I could concentrate on debugging my code instead of debugging the code and hardware at the same time.
Most of the code came from adapting examples found on the web and some helpful advice from the SparkFun forums.

The program consists 4 major parts:

Setup: This includes setup of the PIC's special function registers at startup such as turning off the analog devices and setting the appropriate pins to inputs/outputs etc. This part actually frustrated me for quite a while because I was getting the ANSEL and CMCON0 registers confused, luckily I didn't burn anything up in the process.
For anyone working with a PIC that has built in analog functions including comparators:
ANSEL needs to be 00H to set all ports as digital I/O
CMCON0 needs to be 07H to turn off the comparator
Double check the data sheet for your PIC since some may have different settings!

Button Polling: This was a simple repeating check to see if the user had pressed the button, and then a hold to make sure the device didn't compute and display several numbers in one button press. I debounced the Next button with a small capacitor.

Fibonacci Calculation: A simple addition of two 16 bit integers, and then moving those integers down the line in the sequence to prepare for the next computation. If this addition results in an overflow the program breaks to a final function that turns on the Overflow LED and then sets the PIC to sleep.
Getting the overflow flag right for the high bytes was tricky for me at first but with some advice I found a good solution (a much better one than my original idea.)
When the two low bytes are added, and they generate a carry, you have to add that carry to one of the high bytes. The problem is if the high byte you add it to is already FFh. This would flip it to 00h with a carry, but when you add this modified first high byte to the second high byte, you get whatever that second high byte is as an answer, but the carry is lost because 0 + A = A with no carry.
The solution is:

movf   byte0hi,w      ;move one of the high bytes into W
btfsc   STATUS,C   ;if there is a carry from the low byte operation then...
     incfsz   byte1hi,f  ;increment the first high byte, skip next if zero since there is no need to add to 0
addwf   byte1hi,w    ;add the second high byte to W, store in W
movwf   bytefinalhi   ;move the final answer into the desired register


Display: The numbers are displayed on LEDs driven by two 8 bit shift registers (since the PIC12F683 only has 6 I/O pins!). The display code shifts out the two bytes to the two cascaded shift registers. If you use this code please keep in mind that there are little or no delays in between bit changes on the serial output and clockouts etc to the shift registers. They were not needed for this project since the shift registers had response times of pico seconds and the PIC's instructions are one microsecond each (with a 4Mhz clock).

The output works by setting the serial data out pin to the MSB of the desired byte to be output, setting the clock line high, then shifting the output byte to the left and setting the clock line low. This is repeated 7 more times to shift out an entire byte. The shifting is done between the clockout's high and low so that these instructions act as a sort of delay to make sure the shift registers have time to handle the input. As noted above your application might need more of a delay depending on what devices you are using etc.
Both bytes of the 16 bit number are shifted out on the same line and the serial out pin on one register is connected to the serial in of the second. Once both bytes have been shifted out, the data is latched to the LED's with a high pulse on the RCK line of the registers.

 

fibmakerfinal.asm - Assembly code
fibmakerfinal.HEX - HEX file as compiled by MPLAB

 

Circuit and Design

The circuit uses a PIC12F683 which has 6 I/0 lines.
Next Button: Lets the user display the next Fibonacci number
Reset Button: Resets the device and clears the display
Serial Data Out: Data line for the shift registers
Data Clock: Data clock for the shift registers
Latch Clock: Latch control for the shift registers
OverFlow LED: LED to indicate that the 16bit space cannot hold the next Fibonacci number

The registers were TPIC6B595 8 bit shift registers that I picked up from sparkfun. I simply cascaded them so that they would share the same Serial Data, Data Clock, and Latch Clock lines.

Click on the image for a larger version.

 

Images and Video

Fibonacci Counter: Since this was just a simple exercise to get better with assembly for the PIC, I probably won't move it past the breadboard.
The green LED at the top left is just a power on indicator, the lower left LED is the overflow LED.
The multicolored rows are the Fibonacci number in binary, MSB on the right. They are multicolored because I used scrap LED's from a grab bag from Jameco.
The two buttons are Next and Reset.

(click image to enlarge)