PicBasic Pro, PicBasic, BASIC Stamp, Microchip PIC, 8051, and Remote Control Projects


Roll-Your-Own
Remote Control Encoder/Decoder IC's With PicBasic Pro

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 |