| Need
an 8-bit infrared remote control IC that can function as the
encoder or the decoder, has latching or momentary
outputs, up to 25mA drive capacity per output pin, can operate from 3 to 5
VDC, and it's incredibly simple to use..?
Look no further.
We'll show you how to roll-your-own infrared remote control encoder &
decoder IC's. All you need is the
PicBasic Pro compiler, a couple of
PIC16F628 microcontrollers, and a few simple
support components. The source
code compiles to only 495 words so you can use the 16F627, 16F628, and both of the newer "A" revisions. The code has been tested on all versions.
The key to this projects code is the simple Pulse routine.
You can drop this small section of code into your next PBP application to
send infrared data modulated at ~40kHz and change it to work on any I/O-pin.
I won't go into great detail here so you're on your own
discovering just how & why these work. That's part of the fun anyhow. The
code is a stripped down version of the same code we use for our new IR-DX8
remote control encoder/decoder IC's shown in this schematic
HERE, We've just
stripped out a few auto-tuning routines used in our commercial versions, and
made part of the core code available here for y-o-u to experiment with.
The logic applied to
the L/M pin selects latching or momentary output modes when the PIC is
configured for decode mode. By simply connecting the MODE & L/M pins to the
appropriate logic levels before applying power to the PIC, you select encode
or decode modes + latching or momentary decoder operation. You have a single
IC you can now use for your IR encoder or decoder. Pretty simple stuff, but
tons of fun.
Note: I
recommend you download & print the schematics at the link above. These are
much better quality than the screen captured graphics below, and show an
optional High-Power IR LED driver circuit for considerably longer range
operation. Replace the NPN Darlington with a logic level MOSFET for even
better results.
I won't ramble
on any longer. If you're like me you prefer to just dive right on in - so
here's the schematics for both transmitter & receiver + the raw PBP source
code. Enjoy....;o]
The IR Decoder / Receiver Circuit:

Example Decoder / Receiver Circuit
Decode Mode / Latching Outputs:
MODE = Vdd (Decode Function Selected)
L/M = Vdd (Latching Outputs Selected)
R/T = Receives IR Signal From Detector
A0-A4 = 5-Bit Address Inputs
D0-D7 = 8-Bit Latching Outputs
Decode Mode / Momentary Outputs:
MODE = Vdd (Decode Function Selected)
L/M = Ground (Momentary Outputs Selected)
R/T = Receives IR Signal From Detector
A0-A4 = 5-Bit Address Inputs
D0-D7 = 8-Bit Momentary Outputs

The IR Encoder / Transmitter
Circuit:

Example Encoder / Transmitter Circuit
Encode Mode:
MODE = Ground (Encode Function Selected)
L/M = Ground or Vdd (Used Only by Decoder)
R/T = 40kHz Transmit Output For IR LED
A0-A4 = 5-Bit Address Inputs
D0-D7 = 8-Bit Data Input (Button Inputs)

The PIC16F628 Code:
'****************************************************************
'* Name : IR-Chips.bas *
'* Author : Bruce Reynolds http://www.rentron.com *
'* Notes : Infrared decoder & encoder IC *
'* : For PIC16F62x & A version using 4MHz INTRC *
'* modified : Same PIC functions as IR encoder or decoder *
'* version : PM assembler. Compile size = 495 words. *
'****************************************************************
@ DEVICE MCLR_OFF, INTRC_OSC, WDT_OFF, LVP_OFF, BOD_OFF, PWRT_ON, PROTECT_OFF
DEFINE PULSIN_MAX 3000 '// MAX wait time for pulsin
DEFINE NO_CLRWDT '// Saves 17 words code space
'// RA.6 = MODE select. 1 = decode function. 0 = encode function
'// RA.7 = LED drive or IR receive input configured by MODE
'// RA.0 = LM Latched = 1, Momentary = 0 (used only in decode mode)
'// RA.1 to RA.5 = Hardware address inputs (set same on encoder as decoder)
'// For PIC16F62x & A versions
CMCON = 7 '// Comparators Off
VRCON = 0 '// Vref Off
TRISA.6 = 1 '// Set for input. 1 = Decode ; 0 = Encode
'// Setup IR bit widths / carrier cycle times
Header CON 96 '// Header = (96 * 25uS) = 2.4mS burst
Zero CON 24 '// Zero = (24 * 25uS) = 0.6mS burst
One CON 48 '// One = (48 * 25uS) = 1.2mS burst
'// Define variables
LM VAR PORTA.0 '// Latched or Momentary mode select for decode only
Cycles VAR BYTE '// Holds number of 40KHz carrier cycles
Loops VAR BYTE '// Loop counter
Index VAR BYTE '// Index counter
IR_PULSE VAR BYTE(13) '// 13-bytes. 8 data ; 5 address
PULSE_IN VAR WORD '// Raw pulsin value
DBYTE VAR BYTE '// Holds 8-bit data byte
ABYTE VAR BYTE '// Holds 5-bit hardware address
ABYTE1 VAR BYTE '// 2nd address byte storage for verification
DBYTE1 VAR BYTE '// 2nd data byte storage for verification
H_Add VAR BYTE '// Holds "Hardware" address
X VAR BYTE '// Bit pointer for loop
'// Test for encode or decode function & configure I/O
PAUSE 10 '// Stabilize on power-up
IF PORTA.6 = 1 THEN '// Is Decode MODE selected..?
TRISA = $FF '// Yes. PORTA = inputs for 5-bit address & IR input
PORTB = 0 '// All outputs = 0 (off)
TRISB = 0 '// PORTB all outputs (8-bit data output)
OPTION_REG.7 = 1 '// PORTB pull-ups off
GOTO Decode '// GOTO Decode routine
ENDIF '// Else encode function selected
TRISB = $FF '// PORTB = 8-bit switch inputs
OPTION_REG.7 = 0 '// PORTB internal pull-ups = on
'// IRLED 170
PORTA.7 = 0 '// Transmitter IR LED = off RA.7 ----|>|----/\/\/\---gnd
'// Note: RA.7 can drive an NPN transistor for longer range
TRISA = %01111111 '// PORTA.7 = output LED drive. Rest inputs for address
GOTO Encode '// Mode = Encode, jump over sub to Encode routine
Pulse: '// Emits # of 40kHz bursts held in variable Cycles
ASM ;// with auto delay between bursts
bsf porta, 7 ;// 1uS, LED=on [need 25uS total
goto $+1 ;// 3uS (2uS per goto $+1)
goto $+1 ;// 5uS
goto $+1 ;// 7uS
goto $+1 ;// 9uS
goto $+1 ;// 11uS
goto $+1 ;// 13uS
bcf porta, 7 ;// 14uS, LED=off
goto $+1 ;// 16uS
goto $+1 ;// 18uS
goto $+1 ;// 20uS
goto $+1 ;// 22uS
decfsz _Cycles,F ;// 23uS
goto _Pulse ;// 25us
ENDASM
PAUSEUS 500 '// 500uS delay between each data bit
RETURN '// Return to Main
'// Send header pulse + 13-bit data/address packet on keypress
Send:
Cycles = Header '// Load header pulse time
CALL Pulse '// Send 2.4mS header/synch pulse
'// Header sent, now send 8 data bits
FOR Index = 0 TO 7 '// Loop for 8 bits data
IF DBYTE.0[Index] = 0 THEN '// Get polarity of each data bit to send
Cycles = Zero '// Pulse time = 0.6mS for a "0" data bit
ELSE
Cycles = One '// Pulse time = 1.2mS for a "1" data bit
ENDIF
CALL Pulse '// Send Zero or One data bit/burst
NEXT Index '// Loop until 8 data-bits sent
'// 8 data bits sent, now send 5-bit address
'// Shift RA.0 out, RA.1,2,3,4,5=address, mask "zero" upper 3-bits
ABYTE = (PORTA >> 1) & %00011111 '// ABYTE = address from RA.1 to RA.5
FOR Index = 0 TO 4 '// Loop for 5-bits to complete address code
IF ABYTE.0[Index] = 0 THEN '// Get polarity of each address bit to send
Cycles = Zero '// Pulse time = 0.6mS for a "0" address bit
ELSE
Cycles = One '// Pulse time = 1.2mS for a "1" address bit
ENDIF
CALL Pulse '// Send bit
NEXT Index '// Loop until 5-bits sent
PAUSE 25 '// 25mS delay between packets (40kHz bursts)
Encode:
IF PORTB != $FF THEN '// Loop until key-press
DBYTE = PORTB
GOTO Send
ENDIF
GOTO Encode
Decode: '// Shift right to remove bit RA.0
H_Add = (PORTA >> 1) & %00011111 '// AND with %00011111 to mask upper 3-bits
'// RA.1 to RA.5 = 5-bit hardware address
Decode2:
PULSIN PORTA.7,0,PULSE_IN '// Read-in start pulse
IF (PULSE_IN < 200) OR (PULSE_IN = 0) THEN '// Less than Start pulse, then keep looking
Loops = 0 '// Reset Loops on idle or key release
IF LM = 1 THEN Decode '// If mode = latching, don't change outputs.
PORTB = 0 '// Mode = momentary. Key = released or idle
GOTO Decode '// so clear outputs & return.
ENDIF
Verify: '// Read, Decode, then verify data
FOR Index = 0 TO 12 '// Setup to read-in 13 pulses
PULSIN PORTA.7,0,IR_PULSE[Index] '// Read 13 low-going pulses on RA.7
NEXT Index '// Loop x times
DBYTE = $FF '// Start with all 1's and find each 0
FOR Index = 0 TO 7 '// Get 8 "data" bits
IF IR_PULSE[Index] < 100 THEN DBYTE.0[Index]=0 '// Less than 1mS = 0
NEXT Index
ABYTE = $FF '// Start with all 1's and find each 0 in pattern
X=0 '// Initialize address bit index pointer to bit 0
FOR Index = 8 TO 12 '// Get 5 address bits from IR_PULSE bits 8-12
IF IR_PULSE[Index] < 100 THEN ABYTE.0[X]=0
X = X + 1 '// Increment address bit index pointer
NEXT Index
ABYTE = ABYTE & %00011111 '// Mask out upper 3-bits. Result = 5-bit address.
'// Loops is multi-purpose.
'// If Loops = 1, store 1st data & address bytes for comparison on the next
'// pass. Loops is cleared on key release or during idle periods, and is used
'// in the toggle function to determine if a key was released, an idle period
'// occured, or if a key is being held down. If Loops (NOT = 2) on entry to
'// Latch, outputs will not be changed.
Loops = Loops + 1 '// Increment loop counter
IF Loops = 1 THEN '// Record data & address bytes only on 1st pass
DBYTE1 = DBYTE '// Load 1st data byte into verify register
ABYTE1 = ABYTE '// Load 1st address byte into verify register
GOTO Decode2 '// Get 2nd readings for comparison with 1st two
ENDIF
IF Loops = 255 THEN Loops = 3 '// Prevent roll-overs from 255 to 0 & make sure Loops
'// can never be 2 again until the key is released
'// or an idle period
IF ABYTE != (H_Add & ABYTE1) THEN Decode2 '// Does address match?
IF LM = 1 THEN Latch '// Is latch mode selected?
'// In momentary mode, any combination of key-presses are
'// allowed simultaneously
Momentary:
PORTB = ~DBYTE '// Momentary mode set so invert & place data on PORTB
GOTO Decode2
'// Latch mode requires each key to be released before it will toggle
'// the port pin a 2nd time. In Latch mode, only single key-presses
'// are allowed.
Latch:
IF Loops != 2 THEN Decode2 '// Has key been released?
IF DBYTE != DBYTE1 THEN Decode2 '// Do both data bytes match?
FOR Index = 0 TO 7 '// Yes. Now extract data bits
IF DBYTE.0[Index] = 0 THEN
PORTB.0[Index] = PORTB.0[Index] ^ 1 '// XOR port bits to toggle port pins
ENDIF
NEXT Index
GOTO Decode2
END

That's it..! Now you're ready to drop
your own custom IR encoder & decoder IC's into your next project. See
if you can create your own IR protocols or change the transmitter code to
control other IR gear in your home.
If you're new to all this, and don't own
the PicBasic Pro Compiler, click
HERE to purchase
PicBasic Compilers - and hardware. Visit the link
HERE to return to our
PicBasic projects section. If you need items like IR detectors & IR LEDs, we
have them right
HERE too.
Until the next project - have fun - and
don't blow anything up...;o]
Regards,
-Bruce

Back to the PicBasic Projects
Section


Copyright
© 1999-2008 Reynolds Electronics
|
Contact
Information |

 |