Runway with PIC18F2550
A few months ago I came across microchip's PIC18-series. One in particular got my attention: the PIC18F2550. Nice features: build in USB support, lots of I/O, A/D conversion, etc. etc. I thought that's a nice device to build a simple cheap oscilloscope.
But before you get to the point of developing an oscilloscope, you first need to understand the this device is working.The best way to learn stuff is to break down the problem in smaller problems and solve each smaller problem one by one.
So I cut my "Continuous capture input signal, send it via USB to PC"-problem into smaller problems:
continuous capture data, display converted 10 bit value on series of 10 leds send DATA via USB
The first problem was still to big to handle at once. So "continuous capture data, display converted 10 bit value on series of 10 leds" became:
do single capture use 16 bit timer and interrupts drive series of 10 leds
While playing with the 16 bit timer, interrupt and the 10 leds I at once had a running light. When I showed this to my children, they said: "wow, can you build a toy for us as well?". After answering "yes", I had to keep my word. Children have a good memory. So, first I had find out "what can I build within a month, in my spare time". The answer: a miniature runway. That's how this story started.
runway schema (gEDA)
The schema is quite simple:
a voltage regulator 7805 for converting the 9V DC to 5V DC a diode for protecting from incorrect battery connection a PIC18F2550, the heart of the device a 20Mhz crystal a 5 pins print header for connecting the programmer K8076 and of course some leds, resistor and capacitors
In the schema you only see 10 leds instead of 20(plus one, power-on indicator). The reason for this is that I paired the leds and only need 2 connections per pair on the PCB.
paired leds
The PCB was quite a challenge for me. This was my first one with an SMD-component. When I ordered the PIC18F2550, the image on the side showed an SDIP package, but when I received it, it turned out to be an SO28-package. I should have read the small letters on the site telling me that the image can differ from the real device. But in the end I managed to create the PCB as shown below. It's a two layer PCB, but I only etched one side and the few connections on the component side, had to be wired manually.
PCB image (gEDA)
In the mean while I created from MDF the physical runway. Drill holes a little bit smaller than the 5mm led-heads.
MDF: the physical runway
PCB: final result
backside of the mdf, wiring the paired-leds
After mounting all the components, I checked and double checked all the soldering connections. Especially the ones connected to the PIC. After that, I connected the programming device the K8076 and kept my fingers crossed. Would it recognize the controller? Yes it did. So now I could upload the HEX-file with all the programming and control logic. Below you can see the assembly file. It hasn't been optimized what so ever.
#include<P18F2550.inc>
CONFIG XINST = ON ;Instruction set extension and Indexed Addressing mode enabled
CONFIG DEBUG = OFF ;Background debugger disabled, RB6 and RB7 are gen. purp. I/O pins
CONFIG BORV = 0 ;
CONFIG BOR = ON ;Brown-out Reset enabled in hardware only (SBOREN is disabled)
CONFIG FCMEN = ON ;Fail-Safe Clock Monitor enabled
CONFIG IESO = ON ;Oscillator Switchover mode enabled
CONFIG PWRT = OFF ;PWRT disabled
CONFIG VREGEN = OFF ;USB voltage regulator disabled
CONFIG WDT = OFF ;HW Disabled - SW Controlled
CONFIG WDTPS = 32768 ;1:32768
CONFIG MCLRE = OFF ;RE3 input pin enabled; MCLR disabled
CONFIG LPT1OSC = OFF ;Timer1 configured for higher power operation
CONFIG PBADEN = OFF ;PORTB<4:0> pins are configured as digital I/O on Reset
CONFIG CCP2MX = OFF ;CCP2 input/output is multiplexed with RB3
CONFIG STVREN = OFF ;Stack full/underflow will not cause Reset
CONFIG LVP = OFF ;Single-Supply ICSP disabled
CONFIG CP0 = OFF ;Block 0 (000800-001FFFh) not code-protected
CONFIG CP1 = OFF ;Block 1 (002000-003FFFh) not code-protected
CONFIG CP2 = OFF ;Block 2 (004000-005FFFh) not code-protected
CONFIG CP3 = OFF ;Block 3 (006000-007FFFh) not code-protected
CONFIG CPB = OFF ;Boot block (000000-0007FFh) not code-protected
CONFIG CPD = OFF ;Data EEPROM not code-protected
CONFIG WRT0 = OFF ;Block 0 (000800-001FFFh) not write-protected
CONFIG WRT1 = OFF ;Block 1 (002000-003FFFh) not write-protected
CONFIG WRT2 = OFF ;Block 2 (004000-005FFFh) not write-protected
CONFIG WRT3 = OFF ;Block 3 (006000-007FFFh) not write-protected
CONFIG WRTB = OFF ;Boot block (000000-0007FFh) not write-protected
CONFIG WRTC = OFF ;Configuration registers (300000-3000FFh) not write-protected
CONFIG WRTD = OFF ;Data EEPROM not write-protected
CONFIG EBTR0 = OFF ;Block 0 not protected from table reads executed in other blocks
CONFIG EBTR1 = OFF ;Block 1 not protected from table reads executed in other blocks
CONFIG EBTR2 = OFF ;Block 2 not protected from table reads executed in other blocks
CONFIG EBTR3 = OFF ;Block 3 not protected from table reads executed in other blocks
CONFIG EBTRB = OFF ;Boot block not protected from table reads executed in other blocks
CONFIG PLLDIV = 5 ;Divide by 5 (20 MHz oscillator input)
CONFIG CPUDIV = OSC2_PLL3 ;[OSC1/OSC2 Src: /2][96 MHz PLL Src: /3]
CONFIG USBDIV = 2 ;USB clock source comes from the 96 MHz PLL divided by 2
CONFIG FOSC = HSPLL_HS ;HS oscillator, PLL enabled, HS used by USB
constant CNT0 = 00h
constant CNT1 = 01h
constant CNT2 = 02h
constant CNT3 = 03h
constant CNT4 = 04h
constant CNT5 = 05h
constant CNT6 = 06h
constant CNT7 = 07h
constant CNT8 = 08h
constant CNT9 = 09h
org 0x0000
goto MAIN_INIT
org 0x0008
GOTO INT_HIGH
org 0x0018
GOTO INT_LOW
MAIN_INIT:
BCF T0CON, TMR0ON; stop timer 0
CLRF PORTA
CLRF LATA
CLRF PORTB ; Initialize PORTB by clearing output data latches
CLRF LATB ; Alternate method to clear output data latches
CLRF PORTC ; Initialize PORTB by clearing output data latches
CLRF LATC ; Alternate method to clear output data latches
MOVLW b'1111' ;All digital ports
MOVWF ADCON1 ; digital I/O pins (required if config bit PBADEN is set)
MOVLW 00h ; Value used to initialize data direction
MOVWF TRISB ;
MOVWF TRISC ;
BCF PORTB,RB0 ;
BCF PORTB,RB1 ;
BCF PORTB,RB2 ;
BCF PORTB,RB3 ;
BCF PORTB,RB4 ;
BCF PORTB,RB5 ;
BCF PORTB,RB6 ;
BCF PORTB,RB7 ;
BCF PORTC,RB6 ;
BCF PORTC,RB7 ;
CLRF CNT0
CLRF CNT1
CLRF CNT2
CLRF CNT3
CLRF CNT4
CLRF CNT5
CLRF CNT6
CLRF CNT7
CLRF CNT8
CLRF CNT9
MOVLW 0x00
ADDWF CNT0,1
MOVLW 0x19
ADDWF CNT1,1
MOVLW 0x32
ADDWF CNT2,1
MOVLW 0x4b
ADDWF CNT3,1
MOVLW 0x64
ADDWF CNT4,1
MOVLW 0x7d
ADDWF CNT5,1
MOVLW 0x96
ADDWF CNT6,1
MOVLW 0xaf
ADDWF CNT7,1
MOVLW 0xc8
ADDWF CNT8,1
MOVLW 0xe1
ADDWF CNT9,1
CLRF INTCON; disable all interrupts
MOVLW b'01000111';stop timer0, 16bits, (CLKO), low2high, prescalar assigned, 1:256
MOVWF T0CON;
BSF INTCON, TMR0IE; overflow interrupt enable
BCF INTCON, RBIE;
BSF INTCON, PEIE; enable interupts from peripherals
BSF INTCON, GIE; global enable interrupts
BSF T0CON, TMR0ON; start timer 0
MAIN:
NOP
NOP
NOP
NOP
GOTO MAIN
INT_LOW:
BTFSC INTCON, TMR0IF; Skip next instruction if clear
GOTO ALT_SUB1
BTFSC INTCON, RBIF; Skip next instruction if clear
GOTO ALT_RBIF
BSF PORTB,RB4 ;
BSF PORTB,RB5 ;
BSF PORTB,RB6 ;
RETFIE;return from interrupt
INT_HIGH:
BTFSC INTCON, TMR0IF; Skip next instruction if clear
GOTO ALT_SUB1
BTFSC INTCON, RBIF; Skip next instruction if clear
GOTO ALT_RBIF
BSF PORTB,RB4 ;
BSF PORTB,RB5 ;
BSF PORTB,RB6 ;
RETFIE;return from interrupt
ALT_SUB1:
INFSNZ CNT0
BTG PORTC,RB6 ;
INFSNZ CNT1
BTG PORTC,RB7 ;
INFSNZ CNT2
BTG PORTB,RB0 ;
INFSNZ CNT3
BTG PORTB,RB1 ;
INFSNZ CNT4
BTG PORTB,RB2 ;
INFSNZ CNT5
BTG PORTB,RB3 ;
INFSNZ CNT6
BTG PORTB,RB4 ;
INFSNZ CNT7
BTG PORTB,RB5 ;
INFSNZ CNT8
BTG PORTB,RB6 ;
INFSNZ CNT9
BTG PORTB,RC7 ;
BCF INTCON, TMR0IF
RETFIE;return from interrupt
ALT_RBIF:
NOP;
NOP;
NOP;
BCF INTCON, RBIF
NOP;
RETFIE;return from interrupt
end
runway under construction
runway under construction (2)
Next thing I did was adding a LEGO-interface. After a little help of super construction kit, a lot of pressure on the LEGO-part and some patience (not mine).
The runway was ready and officially declared open.
Airport "Vriescheloo" 2012