Jump to content
43oh

Pronto IR code transmission


Recommended Posts

Pronto CIR codes have become a de facto standard for CIR code exchange. They where originally used by the Philips Pronto series of universal remotes, but are now supported by many universal remotes and PC CIR software. There is a database of codes at Remote Central.

 

This MSP430 firmware will send most type 0 pronto codes - that is the most common type. It can run at 1 MHz, so it can be used with the G2231 and G2211 chips that came with the rev 1.4 and earlier Launchpad.

 

The pronto codes have the timing in units of the IR carrier frequency. This characteristic allows the firmware to work with only one Timer A unit. It is used for both carrier generation with hardware PWM and for timing with an ISR.

 

 

/*

   Copyright (C) 2012  Kevin Timmerman

   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program.  If not, see .


Pronto code format
http://www.remotecentral.com/features/irdisp2.htm

Pronto code database
http://www.remotecentral.com/cgi-bin/codes/

*/

#include 


static const unsigned pentax[] = {                  // - Pentax camera IR code in Pronto format
                                                   // http://img811.imageshack.us/img811/6074/pentaxprotocol.jpg
   0,                                              // Modulated code
   109,                                            // Carrier period - 4,145,152 / 38 kHz = 109 
   8,                                              // Number of one time pairs
   0,                                              // Number of repeat pairs
   500, 115,                                       // 13 ms on, 3 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39,                                         // 1 ms on, 1 ms off
   38, 39                                          // 1 ms on, 1 ms off
};

                                                   // - Canon camera IR code in Pronto format 
                                                   // http://www.doc-diy.net/photo/rc-1_hacked/index.php
static const unsigned canon_immed[] = {             // Immediate shutter release
   0,                                              // Modulated code
   127,                                            // 32.768 kHz
   16,                                             // Number of one time pairs
   0,                                              // Number of repeat pairs
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240,                                        // 488 us on, 7332 us off 
   16, 240                                         // 488 us on, 7332 us off 
};                                                  //
static const unsigned canon_delay[] = {             // Delayed shutter release
   0,                                              // Modulated code
   127,                                            // 32.768 kHz
   16,                                             // Number of one time pairs
   0,                                              // Number of repeat pairs
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176,                                        // 488 us on, 5372 us off 
   16, 176                                         // 488 us on, 5372 us off 
};

static volatile int cycle_count;                    // IR carrier cycle count

#pragma vector = TIMERA0_VECTOR                     // Timer A Capture/Compare 0 interrupt
__interrupt void timera0_isr(void)                  // This ISR must be very simple because there may
                                                   // be as few as 16 cycles available for it to complete
{                                                   //
   if(--cycle_count == 0)                          // Decrement cycle count
       __bic_SR_register_on_exit(LPM0_bits);       // Wakeup main code when count reaches 0
}                                                   //

inline void send_chunk(const unsigned *code, unsigned len)
{
   do {                                            // Do all pairs
       __bis_SR_register(LPM0_bits + GIE);         // Sleep until cycle count is zero
       TACCTL1 = OUTMOD_7;                         // Turn on IR
       cycle_count += *code++;                     // Set on cycle count
       __bis_SR_register(LPM0_bits + GIE);         // Sleep until cycle count is zero
       TACCTL1 = OUTMOD_0;                         // Turn off IR
       cycle_count += *code++;                     // Set off cycle count                                                  
   } while(--len);                                 // Decrement pair count, do next pair if not zero
}

void send_code(const unsigned *code, unsigned repeat)
{
   if(*code++) return;                             // First word must be 0 (0 = Modulated code)
                                                   // Pronto carrier freq == 4,145,152 / N
                                                   // ( 4,145,152 == 32,768 * 506 / 4 )
                                                   // 1,000,000 / 4,145,152 == 0.241246
                                                   // 0.241246 << 16 == 15,810
   const unsigned period = (((unsigned long)*code++ * 15810) + 7905) >> 16; // For 1 MHz MPU clock
   //const unsigned period = *code++;              // For 4.145152 MHz MPU clock
   const unsigned one_len = *code++;               // One time length
   const unsigned repeat_len = *code++;            // Repeat length
                                                   //
   TACCR0 = period - 1 ;                           // Set timer period
   TACCR1 = TACCR0 >> 1;                           // Set timer on duration - 50% duty cycle
   cycle_count = 16;                               // Setup some initial IR off lead in
   TACCTL0 = CCIE;                                 // Enable Timer A CC0 interrupt
                                                   //
   if(one_len) send_chunk(code, one_len);          // Send one time chunk
                                                   //
   if(repeat_len) {                                // Send repeat chunk
       code += (one_len << 1);                     // Move pointer to repeat chunk
       while(repeat) {                             // Do it repeat times
           send_chunk(code, repeat_len);           // Send it
           --repeat;                               // Decrement repeat count
       }                                           //
   }                                               //
                                                   //
   __bis_SR_register(LPM0_bits + GIE);             // Sleep until cycle count is zero
   TACCTL0 = 0;                                    // Turn off Timer A CC0 interrupt
}

void main(void)
{
   WDTCTL = WDTPW | WDTHOLD;                       // Disable watchdog reset
   DCOCTL = 0;                                     // Run at 1 MHz
   BCSCTL1 = CALBC1_1MHZ;                          // Note: The ideal clock freq for this code
   DCOCTL = CALDCO_1MHZ;                           //  is 4.145152 MHz - calibrate the DCO for
                                                   //  that freq for optimal timing - the second
                                                   //  word of the pronto code can then be used
                                                   //  without scaling
   P1OUT = 0;                                      //
   P1DIR = BIT6;                                   // Enable PWM output on P1.6
   P1SEL = BIT6;                                   //
                                                   //                                                  
   TACTL = TASSEL_2 | MC_1;                        // Timer A config: SMCLK, count up
   TACCTL1 = OUTMOD_0;                             // Make sure IR is off
                                                   //
   _enable_interrupts();                           // Enable global interrupts
                                                   //
   send_code(pentax, 1);                           // Send Pentax IR code
//  send_code(canon_immed, 1);                      //
//  send_code(canon_delay, 1);                      //
}

Link to post
Share on other sites

Nice stuff! That code is a great example of how to best use the built-in features of the msp430. Attached is a picture taken remotely by my Canon EOS Rebel XT (AKA 350D) of the launchpad and the IR LED. You can see my finger in the picture pushing the reset button. The IR-LED comes from a dollar store remote. I just chewed it off the pcb with pliers and soldered on some jumper wires.

 

* msp430g2231

* launchpad

* 2n2222 transistor

* IR LED from dollar store remote pcb

* resistors 1k base, 100ohm between 5V and collector

* cap 100uF

* 5 volt power stolen from usb

 

Thanks!

 

-rick

post-1984-135135553175_thumb.jpg

Link to post
Share on other sites

There was this guy on IRC yesterday whose questions started all this goodness :). He left with a couple of his questions unanswered due to temporal inactivity. I only assume he came from here, so if you are reading this, try this one for solving your range/directionality/power problems. The board is part TH part SMD (but huge parts and lots of clearance so you can assemble it even if you have no SMD-soldering experience) and is designed to be glued on top of a 2xAA battery holder, not unlike this one:

 

post-2505-135135553453_thumb.jpg

 

post-2505-135135553463_thumb.png

 

The crystal is completely optional (and I doubt it would work properly in that spot, but anyway).

 

post-2505-135135553481_thumb.png

 

Completely untested.

shutter.zip

Link to post
Share on other sites
I only assume he came from here, so if you are reading this, try this one for solving your range/directionality/power problems. The board is part TH part SMD (...)

 

I am not from here but your post intrigued me, so I just signed up to see the pics. Not sure how active I will be, I am already subscribed to too many forums, but I promise to at least watch this thread.

 

The board you suggest looks interesting, but I am relatively new to electronic stuff (this is actually my first practical project), and my solder-fu is weak (someday I'll have to work on that!).

In the meanwhile, I think I'll just see what some simple circuit (1 transistor or so) can do for power/reach. I would be happy with 3 or 4 meters.

 

 

My current code is at the HNrhvgDH pastebin. (Sorry, 43oh won't let me post links)Includes an intervalometer mode, and thinking of adding a light trigger (for photographing lightning).

Link to post
Share on other sites

What transistor have you used? Can it carry enough current? Can your power supply supply enough current (fast enough)? Are you sure you are switching the transistor on fully (2K seems a bit high, whatever transistor that is)?

 

Seriously, just give this method a try, also read oPossum's stuff at http://forums.adafruit.com/viewtopic.php?p=22714 (many good things about how and why this works):

 

post-2505-135135553807_thumb.png

Link to post
Share on other sites
What transistor have you used? Can it carry enough current? Can your power supply supply enough current (fast enough)? Are you sure you are switching the transistor on fully (2K seems a bit high, whatever transistor that is)?

 

My method for picking both transistor and resistor values consisted of "use whatever I found first in the spares bin*". This because I have almost no knowledge about the theory behind all this stuff (I am not an engineer, only had some passive circuit analysis course in uni once). The transistor happens to be a "C9018" -- I downloaded the datasheet and it says: I_C = -I_E = 20mA. Is this the figure I should be looking at? It seems low. There are, of course, a lot of other specs that I have no idea how to interpret, yet alone how to figure out what resistor values I should be using.

 

Thanks a lot for the link and that schematic, I guess I have a lot of reading to do.

 

I don't have any PN2222As. How can I figure out which of the things I have will do the job? Components are hard to find around here and very expensive, so I tend to recylce old stuff or order online, which takes 1 or 2 months.

 

Sorry for the annoyingly basic questions, and again, thanks a lot.

 

* spares bin= stuff I have ripped out of old electronics

 

EDIT: I replaced the C9018 by a 2N4401, and the 2k2 by a 220 resistor like we discussed on IRC and the results are much better! I get about 2 meters reach, maybe slightly more. Still, not enough, cuadratic light falloff and all that. So, next, I will wire the circuit you posted. Oh, and probably replace the debounce cap with a smaller value. It tends to go into interval mode to easily.

Link to post
Share on other sites

You can put multiple LEDs in parallel like in the first schematic.

 

Edit: just to make it clear, the result is a third transistor switching the two other stages, not simply just stages in parallel.

 

post-2505-135135553882_thumb.png

 

Also, I just noticed that you have (what looks to be) a 100R on the collector of your transistor. It will limit the LED current to 30mA, which is not enough for range. In a remote control application, the LEDs are typically driven near their peak ratings (they can work under these conditions for the brief period of time the LED is actually on during the transmission of a code), which generally speaking is around 1A (I assume we can't know what LED you actually have, but 600mA should be OK anyway). You can leave that 100R out and observe magic -- what the rest does and how it is safe in this kind of application is detailed in the Adafruit posts I linked above.

 

Just don't leave the transmitter on :).

Link to post
Share on other sites
You can leave that 100R out and observe magic -- what the rest does and how it is safe in this kind of application is detailed in the Adafruit posts I linked above.

 

 

I didn't dare to just leave it out, but tried replacing it with a 10R, and the IR LED will glow visibly red. I first thought I even saw some red when the pin (1.6) was off, but I think I was mistaken, I might have shorted something. The range has increased enourmously.

It is ok to leave the mcu on or will it still drain the battery faster with this resistor?

 

BTW, I was afraid the resistor would blow, it being only 1/4 watt. Could that happen?

Link to post
Share on other sites

10R will result in 300mA through your LED, which is starting to get OK :) :).

 

Some visible red glow is not necessarily bad. I am guessing the LED's peak wavelength is in the 850nm-ish range, that may very well mean that when overdriven, it will emit some light even in the visible red (750-780nm-ish) range (if you look at a webcam or some of these cheap-ish CCD cameras that have "night vision mode", you will probably see them doing this too). CIR applications usually operate in the 940nm-ish wavelength, which doesn't mean others won't work, just that the range and sensitivity will decrease. If that apparently 850-ish works for you, all the better, but you can achieve better results if you match your LEDs to the receiver in your camera (harvest some from old remotes and try). I am not familiar with cameras as such, dig the intertubes for info on what wavelength yours expects, someone must have figured it out already :).

 

You can safely leave the MCU on, just don't leave the pin that is controlling the transistor on (in other terms, do not try to use this setup for continuous infrared illumination) -- that would burn the LED out on short notice. Again, it is perfectly safe for remote control (short bursts with plenty of dead periods in between them).

 

The 0.25W resistor is also OK, since it only has to cope with 300mA for very short time periods, it simply doesn't have time to overheat.

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...