Panasonic IR receiver with dual PWM output

This Panasonic IR receiver/decoder description holds 4 sections:

  1. The newest hardware/software version with 4 PWM outputs.
  2. The hardware/software version with 2 PWM outputs.
  3. The original version with the Panasonic IR frame decoding basics.
  4. The original version with a LCD display to shown the decoded IR frames.

1. The newest hardware/software version with 4 PWM output.

The new hardware design uses an Attiny85 to include up to 2 PWM channels and up to 4 digital outputs. One PWM channel occupies 2 digital outputs , a PWM output and a second output with the inverted PWM value. Thus, depending on the software, 3 options are available: 4 digital outputs and no PWM, 2 channels PWM and no digital outputs, 1 PWM channel and 2 digital outputs. In this version I use 2 output pins for one PWM channel and 2 digital outputs.

The new hardware adds 2 extra 12V digitals outputs:

For the software part, the state machine now deal with 5 Panasonic remote control button values: 3D, left-arrow, right-arrow, blue and yellow buttons:

The C program uses Switch-case statements in the main() function to implement the state-machine and is to be seen here: main.c

2. The hardware/software version with 2 PWM outputs. 

Made some updates to the Panasonic IR receiver module to include an PWM output to control an outdoor 12V LED lamp. The PWM duty cycle is controlled by the Panasonic remote left-arrow and right-arrow buttons.
The PWM signal is provided via hardware registers, i.e. software is only needed for initialization and for subsequent changes in frequency and/or duty cycle.
In this way, the critical IR frame receiver timing is not affected by other interrupts. A software state-event machine is now in the main function to decode specific Panasonic remote IR button sequences.
The LED lamp output pin was moved from PB3 to PB4 (OC1B) to use the PWM signal:

Shown below are the scope snapshots of min. and max. PWM duty cycles at the LIGHT output.

The Attiny25 datasheet is available here:  http://ww1.microchip.com/downloads/en/DeviceDoc/Atmel-7598_Automotive-Microcontrollers-ATtiny25-45-85_Datasheet.pdf

The state-event diagram for the state event machine inside the gcc C main() function:

The updated Attiny25 C source is here: main_c

3. The original version with the Panasonic IR frame decoding basics.

For the antenna switching circuit , I needed a piece of electronics to decode specific IR codes from Panasonic TV remotes:

The Panasonic ( Japanese ) IR protocol description is found here ( p. 56-57) : IR_Code_Analy

To measure the output of the remotes, an infrared receiver is needed. I used a Sharp GP1UX511QS 38 KHz infrared receiver, but any 38 KHz infrared receiver should do the job.
With an oscilloscope I got the following screens for the remote buttons: “TV”, “EXIT”, “eHelp” and “lastView”

The transmitted bit pattern has a syncronization part, a 16 bit address and a 32 bit of data to identify the button being pressed.
For each button two identical bit patterns are transmitted, and 3 times for the red “Power” button.
The syncronization part is the long “LOW” followed by “HIGH”:

The following 48 bits ( 16 bit address + 32 bit data ) is encoded like this:
0 : A short “LOW” followed by a short “HIGH”
1 : A short “LOW” followed by a long “HIGH”
By looking through the bit patterns for the “TV”, “EXIT” and “eHelp” buttons, I got the following data values in hexadecimal:
“TV” button: Address : 4004 data: 01400C4D
“EXIT” button: Address : 4004 data: 0100CBCA
“eHelp” button: Address : 4004 data: 01003534
“Last view” button: Address : 4004 data: 0100ECED
I decided to use an 8 pin Attiny25 microcontroller to do the decoding of the specific bit patterns. The schematic is clipped from the antenna switch project.

The free Atmel Studio 7 was used for compiling the C code. And using the AVR-ISP MKII programmer to flash the Attiny25.
The Attiny25 uses the internal clock generator at 1 MHz with the DIV8 fuse enabled.
The program to decode the bit patterns uses port interrupt at PB2 on negative going edges (INT0).

Timer 0 is set to be free running with a divide by 64 prescaler, providing timer intervals of 64 usec.:

TCCR0A = 0;
TCCR0B = 3<<CS00; // Prescaler /64 , 64 usec. timer
MCUCR |= (1<<ISC01); // Interrupt on falling edge
GIMSK |= _BV(INT0); // Enable external interrupt INT0
sei(); // enable global interrupts

Three global 16 bit variables hold address, dataHigh and DataLow.
volatile unsigned int RecdAddress;
volatile unsigned long RecdDataH;
volatile unsigned long RecdDataL;

The newFrame has a value of 1 when a new set of  address and data are received:

volatile uint8_t newFrame;

The INTO interrupt routine measures the elapsed time ( provided by Timer 0 ) from last INT0 interrupt. In case of timer overflow, the interrupt starts looking for the next syncronization pattern. When a new frame with address and data is received, the newFrame variable is set to 1.

ISR(INT0_vect) {
int BitTime = TCNT0;
int Overflow = TIFR & 1<<TOV0;
if (NextBit == 48) // looking for the Panasonic header period
{ // in between 4700 and 5700 usec.
if ((BitTime >= 73) && (BitTime <= 89) && (Overflow == 0))
{
RecdAddress = 0;
RecdDataH = 0;
RecdDataL = 0;
NextBit = 0;
} // got header, now ready to receive 48 bit data
} else
{i
f ((BitTime > 30) || (Overflow != 0))
NextBit = 48; // max bit period exceeded, restart
else
{i
f (BitTime > 15) // if bit time > “0”-time, e.g. add “1” into the bit
position
{i
f (NextBit <= 15) RecdAddress = RecdAddress | ((unsigned int)
1<<(15-NextBit));
else
{i
f ((NextBit <= 31) && (NextBit > 15)) RecdDataH = RecdDataH |
((unsigned int) 1<<(15-(NextBit-16)));
else RecdDataL = RecdDataL | ((unsigned int) 1<<(15-(NextBit-
32)));
}}
NextBit++;
if (NextBit == 48) newFrame = 1; // signal to main() to retrieve
data
}} TCNT0 =
0; // Clear counter
TIFR |= 1<<TOV0; // Clear overflow
GIFR |= 1<<INTF0; // Clear INT0 flag
}
The complete Attiny25 program is found here: main.c

4. The original version with a LCD display to shown the decoded IR frames. 

As a spin off from the Attiny25 based IR decoder, I wanted a display to show the Panasonic IR code values instead of reading and translate the code timing from an oscilloscope. The LCD display shows Panasonic TV IR codes for the address (16 bit) and data (2 * 16 bit). The hardware is the Arduino Nano v.3 and a 16*2 character LCD display with the PCF8574 port expander to provide an I2C (TWI) interface. These parts are less than 2 Euro each from AliExpress.com.

The Sharp GP1UX511QS 38 KHz infrared receiver is connected to the Atmega328P interrupt input, INT0 (PORTD2). To monitor the 9V battery voltage a 1:1 voltage divider with 2 x 4K7 resistors are added to provide 0..4.5V to the A0 ADC input.

The Atmel Studio software for this solution includes I2C and LCD libraries.
The free Atmel Studio 7 from http://www.atmel.com/Microsite/atmel-studio/ was used to compile the C code.

An AVR-ISP MKII programmer was used to flash the ATmega328P. The ATmega328P clock generator uses the external 16 MHz x-tal on the Arduino Nano board. The program to decode the bit patterns uses port interrupt at PD2 on negative going edges (INT0). Timer 0 is set to be free running with a divide by 1024 prescaler, providing timer intervals of 64 usec.

The complete source code is available here: PanaIR_I2C_LCD