oPossum 1,083 Posted June 20, 2012 Share Posted June 20, 2012 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); // } gordon, Rickta59, kff2 and 3 others 6 Quote Link to post Share on other sites
Rickta59 589 Posted June 20, 2012 Share Posted June 20, 2012 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 bluehash 1 Quote Link to post Share on other sites
gordon 229 Posted June 20, 2012 Share Posted June 20, 2012 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: The crystal is completely optional (and I doubt it would work properly in that spot, but anyway). Completely untested. shutter.zip polymeris, bluehash and oPossum 3 Quote Link to post Share on other sites
polymeris 0 Posted June 21, 2012 Share Posted June 21, 2012 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). Quote Link to post Share on other sites
polymeris 0 Posted June 22, 2012 Share Posted June 22, 2012 So, I moved the circuit to its own board and made an enclosure. This is the schematic I ended up using: Sadly, the reach is only about 1.5 meters. I may have to experiment with the output stage. Quote Link to post Share on other sites
gordon 229 Posted June 22, 2012 Share Posted June 22, 2012 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): polymeris 1 Quote Link to post Share on other sites
polymeris 0 Posted June 22, 2012 Share Posted June 22, 2012 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. Quote Link to post Share on other sites
gordon 229 Posted June 22, 2012 Share Posted June 22, 2012 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. 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 . Quote Link to post Share on other sites
polymeris 0 Posted June 22, 2012 Share Posted June 22, 2012 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? Quote Link to post Share on other sites
gordon 229 Posted June 23, 2012 Share Posted June 23, 2012 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. oPossum, polymeris and GeekDoc 3 Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.