July 11, 2010
by Keyster
|
ok guys, i have no questions today. i just completed a sample project i have been working on and wanted to post the code here for others to use. i used a simple infrared LED i purchased from Radio Shack (276-143) years ago for another project i was working on. this code only controls the Volume Up on my TV but is the "proof of concept" i was looking for. the code is also overly bloated to make it visually easy to see what is happening at the LED level. in the control string a "1" is used to send an ON burst and a "0" is used to send an OFF burst. here are some links i used for this project:
knowedge base on different protocols
some codes for samsung TV
cool page on how the IR works
i will put the code in the next post.
--Bryan |
July 11, 2010
by Keyster
|
//
// Infrared NEC Protocol Transmitter by Bryan Key
// my attempt at the NEC Protocol for IR remote controls
//
// Samsung uses 38kHz carrier wave
// IR LED is connected at PB1
// visible LED is connected at PB2 (for visual aid during testing)
//
// set processor speed
#define F_CPU 14745600
// set how many pulses are in each burst
// 19->23 Works
#define _BURSTWIDTH 21
#include <stdio.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/pgmspace.h>
//#include <string.h>
#include <inttypes.h>
#include "../libnerdkits/delay.h"
#include "../libnerdkits/lcd.h"
#include "../libnerdkits/uart.h"
// prescale 8 & 102 counter = 18070.588 Hz
// prescale 8 & 51 counter = 36141.176 Hz (~36kHz)
// prescale 8 & 48 counter = 38400 Hz (~38kHz)
// prescale 8 & 25 counter = 73728 Hz (.01356 ms)
// prescale 8 & 24 counter = 76800 Hz (~38hz * 2) (.01302 ms)
// i uses 76800 because there is one cycle with LED on and one cycle with the LED off
// hince making one complete LED cycle at ~38kHz
volatile uint8_t indx = 0;
volatile int8_t toggle = 0, HighLow = 0;
volatile uint16_t BurstWidth;
volatile uint8_t buffer[210];
//
// each interrupt fire is 0.01302ms
//
ISR(TIMER0_COMPA_vect)
{ int8_t data;
if (toggle)
{ PORTB |= (HighLow<<PB1); // if HighLow is 1 then turn on PB1
PORTB |= (HighLow<<PB2); // PB2 is a "test" LED (visible light)
}
else
{ PORTB &= ~(1<<PB1); // turn off PB1
PORTB &= ~(1<<PB2); // turn off PB2 (test LED)
BurstWidth--; //each burst change is 0.02604ms
}
toggle ^= 1; //toggle the toggle
if (!BurstWidth) //if BurstWidth == 0
{ BurstWidth = _BURSTWIDTH; // reset BurstWidth counter
data = '-';
while (data == '-') // skip dashes, i put the dashes in for visual aid when creating strings
data = buffer[indx++]; // grab the next byte in string
if (data == 0x39) // look for a "9", 9 is "end-of-string"
{ indx = 0; // reset index back to zero
HighLow = 0; // turn pulse off
}
if (data == 0x38) // "8" = insert a pause of 46.716ms
{ HighLow = 0; // this is the "filler" at the end of the command to make it 110ms
BurstWidth = 1794;
}
if (data == 0x37) // "7" = insert a pause of 96.192ms
{ HighLow = 0; // "filler" at the end of a "repeat" command if needed
BurstWidth = 3694;
}
if (data == 0x31)
HighLow = 1; // a "1" turns the pulse on
if (data == 0x30)
HighLow = 0; // a "0" turns the pulse off
}
}
int main()
{
cli(); //make sure interrups are disabled during setup
TCCR0A = (1<<WGM01); //CTC (Clear Timer on Compare Match)
TCCR0B = (1<<CS01); // set prescaler to 8
OCR0A = 23; //24 is 76800 interrupts per second (38kHz * 2)
DDRB |= (1<<DDB1) | (1<<DDB2); // set pin for Output
TIMSK0 = 2; // set the bit mask to enable interrupt - Timer 0 Compare Match A
toggle = 1;
HighLow = 1;
BurstWidth = _BURSTWIDTH; //set the number of pulses in each burst
//Samsung 52 inch LCD TV, also works on my 19 inch Samsung
// Volume Up 0xE0E0-E01F
memcpy_P((void*)buffer, PSTR("11111111-00000000--1000-1000-1000-10-10-10-10-10--1000-1000-1000-10-10-10-10-10--1000-1000-1000-10-10-10-10-10--10-10-10-1000-1000-1000-1000-1000--189-------------"),160);
// Power 0xE0E0-40BF
//memcpy_P((void*)buffer, PSTR("11111111-00000000--1000-1000-1000-10-10-10-10-10--1000-1000-1000-10-10-10-10-10--10-1000-10-10-10-10-10-10--1000-10-1000-1000-1000-1000-1000-1000--189--------"),155);
sei(); //start the interrupts
while (1)
{ // just do nothing, let the interrupt do all the work
}
}
//
// 11111111-00000000 is the AGC pulse (header/Automatic Gain Control)
// 1000 is a "1"
// 10 is a "0"
// 189 is - 1 stop bit (single ON burst) - pause for filler (~46ms) - end string/start over
// keep in mind the "-" in the string is only for visual aid, it has no bearing on the output
// each byte is .54684ms (547 microseconds)
|
July 12, 2010
by lcruz007
|
What a coincidence. I am working on a 'similar' project as well.
I will post my project in the next few weeks :)
Very nice project by the way!! :) |