Author Topic: NEC IR Remote using PIC  (Read 21725 times)

0 Members and 1 Guest are viewing this topic.

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
NEC IR Remote using PIC
« on: February 25, 2016, 08:52:35 pm »
i am trying to make a IR Remote using a PIC, and i will be using the NEC Protocol because thats what i want to control uses

the NEC Protocol: http://www.sbprojects.com/knowledge/ir/nec.php

i seen Dave's video about doing it with a Arduino


but i want to do it on a PIC, specifically a PIC16F628A

i recorded a command i want to send using Audacity and a IR receiver connected to the computer's microphone input, i cant see the carrier frequency of 38Khz but i can see the bits

here is what i captured

(when it goes high, the led is emitting and when it goes low, the led is off)
« Last Edit: February 25, 2016, 09:08:33 pm by luvini »
 

Offline ElectricGuy

  • Regular Contributor
  • *
  • Posts: 240
  • Country: pt
Re: NEC IR Remote using PIC
« Reply #1 on: February 25, 2016, 11:21:11 pm »
Hi Luvini;

Tha PIC Micro has PWM. Use the PWM to generate de carrier or 38Khz. Then, you just need to turn on or off the PWM mpdule, acording to the timming protocol.

--------------------------------------------------------

Caro Luvini.

Esse PIC possui PWM. Utiliza o PWM para gerar a portadora de 38Khz. Depois sempre que quiseres enviar um bit ligas o PWM de acordo com os tempos do protocolo.

« Last Edit: February 27, 2016, 07:29:07 pm by Simon »
Thank you!
Regards
ElectricGuy
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #2 on: February 26, 2016, 04:40:04 am »
i decided to use PWM, i didnt know how to make a proper PWM signal, but i guess i learned now, i even made a Excel PWM Calculator  :-+

PWM Calculator: https://docs.google.com/spreadsheets/d/1VXUw5Sm8fl1sn6Jrq0pawhZ0cFhNQzehLE0Sc8wFf2Q/edit?usp=sharing



i also decoded the signal, so RED=0 and GREEN=1



the final code i made is this, and it works, i can now control my device!

Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear

#use delay(clock=4000000)

void main()
{

setup_ccp1(ccp_pwm); //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1); //38Khz PWM using 4Mhz Osc.

delay_us (20);

//================================
// NEC PROTOCOL
//
// set_pwm1_duty(12); // START
// delay_ms(9);
// set_pwm1_duty(0);
// delay_us(4500);
//
// set_pwm1_duty(12); // 1
// delay_us(560);
// set_pwm1_duty(0);
// delay_us(1690);
//
// set_pwm1_duty(12); // 0
// delay_us(560);
// set_pwm1_duty(0);
// delay_us(560);
//
// set_pwm1_duty(12); // REPEAT
// delay_ms(9);
// set_pwm1_duty(0);
// delay_us(2250);
// set_pwm1_duty(12);
// delay_us(560);
// set_pwm1_duty(0);
// delay_us(560);
//================================

while(true)
{
if(!input(pin_a0))
{
set_pwm1_duty(12); // START
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

set_pwm1_duty(12); // 1
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);

while(!input(pin_a0))
{
set_pwm1_duty(12); // REPEAT
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
}

if(!input(pin_a1))
{

//command goes here

while(!input(pin_a1))
{
set_pwm1_duty(12); // REPEAT (NEC PROTOCOL)
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
}


set_pwm1_duty(0); //turn off IR LED while not pressing any button

}//loop
}
« Last Edit: February 27, 2016, 05:25:15 am by luvini »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #3 on: February 26, 2016, 06:16:18 am »
ok, the code worked for ONE button, so i tried to add more buttons, and it did work up to TREE buttons, why? because anything past that will be too much and wont fit into the memory... maybe theres a better way to make this code? one that use less memory?
 

Offline lapm

  • Frequent Contributor
  • **
  • Posts: 564
  • Country: fi
Re: NEC IR Remote using PIC
« Reply #4 on: February 26, 2016, 06:33:09 am »
Well those are basicly just ones and zeroes represented by infrared encoded signals. See if you can identify encoding they use...
Electronics, Linux, Programming, Science... im interested all of it...
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2276
  • Country: ca
Re: NEC IR Remote using PIC
« Reply #5 on: February 26, 2016, 03:18:58 pm »
ok, the code worked for ONE button, so i tried to add more buttons, and it did work up to TREE buttons, why? because anything past that will be too much and wont fit into the memory... maybe theres a better way to make this code? one that use less memory?
Do you see that every time you want to send a '0' bit you do exactly this:
Code: [Select]
set_pwm1_duty(12); // 0
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
And something similar for a '1' bit? Put each code block in a function, then call the function instead of repeating the same two pieces of code 32 times for each key.

Also the signal appears to be a start or preamble followed by a key code that is 16 bits long, correct? How about encoding each key as a two-byte (16 bit) data. Then you can write a function that will transmit the two bytes, one bit at a time. It will call the functions you created above (for sending a 0 or 1 bit).

Code: [Select]
// define some constants:
const char channelup = 66       // NOTE this code is fake, replace with correct data
const char channeldown = 68;    // NOTE this code is fake, replace with correct data

const char device_address = 5;    // NOTE this code is fake, replace with correct data

send_key_channelup()
{
    send_start()
    send_byte(device_address);
    send_byte(~device_address);
    send_byte(channelup);
    send_byte(~channelup);
    // optionally repeat
    ....
}

send_byte(char byte_to_send)
{
    for (char i=8, i>0, i--)    // decrementing is more efficient that incrementing
    {
        (byte_to_send & 0x1) ? send_onebit() : send_zerobit();     // the ? : is the ternary operator, works like if then else
        byte_to_send = byte_to_send>>1;
    }
}
...
I hope that gives you some ideas. There is a lot more you can do but that is a good start.
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #6 on: February 26, 2016, 10:46:48 pm »
i never used functions, but that was easy to learn, as was PWM the other day, now the code looks like this, and it only uses 20% of the chip memory, with EIGHT buttons!

Code: [Select]
#include <16F628A.h>

#fuses NOWDT      //Disable Watchdog Timer
#fuses NOPROTECT   //Disable Read/Write Protect
#FUSES NOCPD      //Disable EE protection
#fuses NOLVP      //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO      //Set CLK pins as I/O
#fuses NOMCLR      //Disable Master Clear

#use delay(clock=4000000)

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void deviceCode()
{
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
}

//================================

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(true)
{

//================================================================

if(!input(pin_a0))   //White
{
startSending();

deviceCode();

logical1();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a0))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a1))   //Red
{
startSending();

deviceCode();

logical1();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a1))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a2))   //Green
{
startSending();

deviceCode();

logical0();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a2))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a3))   //Blue
{
startSending();

deviceCode();

logical0();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a3))
{
repeatCode();
}
}

//================================================================

if(!input(pin_b0))   //OFF
{
startSending();

deviceCode();

logical0();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b0))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b1))   //ON
{
startSending();

deviceCode();

logical1();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b1))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b4))   //-Bright
{
startSending();

deviceCode();

logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b4))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b5))   //+Bright
{
startSending();

deviceCode();

logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b5))
{
repeatCode();
}
}

//================================================================

set_pwm1_duty(0);   //turn off IR LED while not pressing any button
}//loop
}

yes, i am controlling a RGB LED Lamp
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #7 on: February 27, 2016, 05:18:00 am »
tried to control my TV, and it used the NEC Protocol aswell so it was easy to do
Code: [Select]
#include <16F628A.h>

#fuses NOWDT      //Disable Watchdog Timer
#fuses NOPROTECT   //Disable Read/Write Protect
#FUSES NOCPD      //Disable EE protection
#fuses NOLVP      //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO      //Set CLK pins as I/O
#fuses NOMCLR      //Disable Master Clear

#use delay(clock=4000000)

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void deviceCode()
{
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
}

//================================

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(true)
{

//================================================================

if(!input(pin_a0))   //Power
{
startSending();

deviceCode();

logical0();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();



while(!input(pin_a0))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a1)) //inputs
{
startSending();

deviceCode();

logical1();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a1))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a2))   //Mute
{
startSending();

deviceCode();

logical1();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a2))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a3))   //OK
{
startSending();

deviceCode();

logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical1();
logical0();

logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical0();
logical1();

while(!input(pin_a3))
{
repeatCode();
}
}

//================================================================

if(!input(pin_b0))   //Right
{
startSending();

deviceCode();

logical0();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b0))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b1))   //Left
{
startSending();

deviceCode();

logical1();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b1))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b4))   //Up
{
startSending();

deviceCode();

logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical1();
logical0();

logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
logical0();
logical1();

while(!input(pin_b4))
{
repeatCode();
}
}

//================================================================
if(!input(pin_b5))   //Down
{
startSending();

deviceCode();

logical1();
logical0();
logical0();
logical0();
logical0();
logical0();
logical1();
logical0();

logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical0();
logical1();

while(!input(pin_b5))
{
repeatCode();
}
}
//================================================================
if(!input(pin_a6))   //+Volume
{
startSending();

deviceCode();

logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a6))
{
repeatCode();
}
}
//================================================================
if(!input(pin_a7))   //-Volume
{
startSending();

deviceCode();

logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a7))
{
repeatCode();
}
}
//================================================================
if(!input(pin_a4))   //Back
{
startSending();

deviceCode();

logical0();
logical0();
logical0();
logical1();
logical0();
logical1();
logical0();
logical0();

logical1();
logical1();
logical1();
logical0();
logical1();
logical0();
logical1();
logical1();

while(!input(pin_a4))
{
repeatCode();
}
}
//================================================================
if(!input(pin_b2))   //Settings
{
startSending();

deviceCode();

logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical1();
logical0();

logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical0();
logical1();

while(!input(pin_b2))
{
repeatCode();
}
}
//================================================================

set_pwm1_duty(0);   //turn off IR LED while not pressing any button
}//loop
}


i tried to make it possible to control 2 different devices, with different ids, and it worked as i just needed to make a new DeviceID function for it
Code: [Select]
#include <16F628A.h>

#fuses NOWDT      //Disable Watchdog Timer
#fuses NOPROTECT   //Disable Read/Write Protect
#FUSES NOCPD      //Disable EE protection
#fuses NOLVP      //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO      //Set CLK pins as I/O
#fuses NOMCLR      //Disable Master Clear

#use delay(clock=4000000)

//================================
//      NEC PROTOCOL

int RGBpower;

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void deviceCodeTV()
{
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
}

void deviceCodeRGB()
{
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();
}

//================================

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

RGBpower=0;

while(true)
{

//================================================================

if(!input(pin_a0))   //TV Power
{
startSending();

deviceCodeTV();

logical0();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();



while(!input(pin_a0))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a1)) //TV inputs
{
startSending();

deviceCodeTV();

logical1();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a1))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a2))   //TV +Volume
{
startSending();

deviceCodeTV();

logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a2))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a3))   //TV -Volume
{
startSending();

deviceCodeTV();

logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a3))
{
repeatCode();
}
}

//================================================================
//================================================================

if(!input(pin_b0)) //RGBpower TOGGLE
{
if(RGBpower==0) //RGB OFF
{
startSending();

deviceCodeRGB();

logical0();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
}

if(RGBpower==1) //RGB ON
{
startSending();

deviceCodeRGB();

logical1();
logical1();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();
}

RGBpower++;
if(RGBpower==2)
{
RGBpower=0;
}

delay_ms(50);

while(!input(pin_b0))
{
repeatCode();
}
}

//================================================================

if(!input(pin_b4)) //RGB White
{
startSending();

deviceCodeRGB();

logical1();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b4))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a6)) //RGB Red
{
startSending();

deviceCodeRGB();

logical1();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical0();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a6))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a7)) //RGBGreen
{
startSending();

deviceCodeRGB();

logical0();
logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a7))
{
repeatCode();
}
}

//================================================================

if(!input(pin_a4)) //RGB Blue
{
startSending();

deviceCodeRGB();

logical0();
logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();

logical1();
logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_a4))
{
repeatCode();
}
}

//================================================================

if(!input(pin_b5)) //RGB -Bright
{
startSending();

deviceCodeRGB();

logical0();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical1();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b5))
{
repeatCode();
}
}

//================================================================

if(!input(pin_b1)) //RGB +Bright
{
startSending();

deviceCodeRGB();

logical1();
logical0();
logical1();
logical0();
logical0();
logical0();
logical0();
logical0();

logical0();
logical1();
logical0();
logical1();
logical1();
logical1();
logical1();
logical1();

while(!input(pin_b1))
{
repeatCode();
}
}

//================================================================

set_pwm1_duty(0);   //turn off IR LED while not pressing any button
}//loop
}
(even added a power TOGGLE for the RGB LED Lamp, as it had 2 separate buttons for ON and OFF)


« Last Edit: February 27, 2016, 05:10:23 pm by luvini »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #8 on: February 27, 2016, 05:21:30 am »
...
Also the signal appears to be a start or preamble followed by a key code that is 16 bits long, correct? How about encoding each key as a two-byte (16 bit) data. Then you can write a function that will transmit the two bytes, one bit at a time. It will call the functions you created above (for sending a 0 or 1 bit).

Code: [Select]
// define some constants:
const char channelup = 66       // NOTE this code is fake, replace with correct data
const char channeldown = 68;    // NOTE this code is fake, replace with correct data

const char device_address = 5;    // NOTE this code is fake, replace with correct data

send_key_channelup()
{
    send_start()
    send_byte(device_address);
    send_byte(~device_address);
    send_byte(channelup);
    send_byte(~channelup);
    // optionally repeat
    ....
}

send_byte(char byte_to_send)
{
    for (char i=8, i>0, i--)    // decrementing is more efficient that incrementing
    {
        (byte_to_send & 0x1) ? send_onebit() : send_zerobit();     // the ? : is the ternary operator, works like if then else
        byte_to_send = byte_to_send>>1;
    }
}
...
I hope that gives you some ideas. There is a lot more you can do but that is a good start.

i am... not sure how does that work?
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2276
  • Country: ca
Re: NEC IR Remote using PIC
« Reply #9 on: February 28, 2016, 02:35:55 pm »
i am... not sure how does that work?
Inside the loop, the byte is bitwise ANDed with 1 (binary 00000001), which results in 1 if the first bit of the byte is 1 and 0 if it is zero. A 1 evaluates to true, so the first statement is run. A 0 is false, which means the second statement (the one after the : ) is run instead. So we call send_zero_bit() when the bit is zero and send_one_bit()  when it is one. Then we shift the byte to the right one bit, so that the next time through the loop we are working on the second bit of the byte that was passed in. The third iteration of the loop works on the third but and so on.  The loop runs 8 times for 8 bits.
 

Online pascal_sweden

  • Super Contributor
  • ***
  • Posts: 1541
  • Country: no
Re: NEC IR Remote using PIC
« Reply #10 on: February 28, 2016, 08:37:50 pm »
If you are open to use an Atmel microcontroller, then you can use an existing library, that supports a multitude of IR protocols :)

http://www.mikrocontroller.net/articles/IRSND

This library can run on different Atmel microcontrollers, and supports many IR protocols.
Next to the send library, there is also a counterpart decode library.

I have used these libraries myself, both the decode library and the send library, and everything works like a charm!

Forget Microchip. Go for Atmel. Make things easy! :)
 

Offline ElectricGuy

  • Regular Contributor
  • *
  • Posts: 240
  • Country: pt
Re: NEC IR Remote using PIC
« Reply #11 on: February 28, 2016, 08:50:13 pm »

Forget Microchip. Go for Atmel. Make things easy! :)

But there is no Atmel, only Microchip!!!  :-DD ( Just Kidding )
Thank you!
Regards
ElectricGuy
 

Online pascal_sweden

  • Super Contributor
  • ***
  • Posts: 1541
  • Country: no
Re: NEC IR Remote using PIC
« Reply #12 on: February 28, 2016, 08:52:01 pm »
I just read the news about the acquisition in another thread.
Didn't know about it until just now.

Hopefully they will keep the name Atmel, as I like it better than Microchip.

Actually I was surprised that Microchip is so much bigger than Atmel. I thought they were in the same league.

Pity, that it isn't the other way around. Atmel is a better company, and a better name as well :)
« Last Edit: February 28, 2016, 09:00:52 pm by pascal_sweden »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #13 on: February 29, 2016, 03:21:56 am »
i am... not sure how does that work?
Inside the loop, the byte is bitwise ANDed with 1 (binary 00000001), which results in 1 if the first bit of the byte is 1 and 0 if it is zero. A 1 evaluates to true, so the first statement is run. A 0 is false, which means the second statement (the one after the : ) is run instead. So we call send_zero_bit() when the bit is zero and send_one_bit()  when it is one. Then we shift the byte to the right one bit, so that the next time through the loop we are working on the second bit of the byte that was passed in. The third iteration of the loop works on the third but and so on.  The loop runs 8 times for 8 bits.
i think that makes sense, i just dont understand the function that will read each bit individually, could you explain that part?
the function would need to read, for example: ABCDEFGH, and each time it is run, it would read only a single character, if its run again, it would read only the next character, but how?


If you are open to use an Atmel microcontroller, then you can use an existing library, that supports a multitude of IR protocols :)

http://www.mikrocontroller.net/articles/IRSND

This library can run on different Atmel microcontrollers, and supports many IR protocols.
Next to the send library, there is also a counterpart decode library.

I have used these libraries myself, both the decode library and the send library, and everything works like a charm!

Forget Microchip. Go for Atmel. Make things easy! :)

i want to use a PIC16F628A for this project
« Last Edit: February 29, 2016, 03:24:58 am by luvini »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #14 on: February 29, 2016, 03:53:49 am »
made a full code, but it doesnt compile, giving error
Code: [Select]
*** Error 51 "test0002.c" Line 70(6,10): A numeric expression must appear here
*** Error 51 "test0002.c" Line 72(46,47): A numeric expression must appear here

wich happens at the "void send_byte(char byte_to_send)" and "for (char i=8, i>0, i--)"
and thats the part of the code i cannot understand...
Code: [Select]
void send_byte(char byte_to_send)
{
for (char i=8, i>0, i--)// decrementing is more efficient that incrementing
{
(byte_to_send & 0x1) ? logical1() : logical0(); // the ? : is the ternary operator, works like if then else
byte_to_send = byte_to_send>>1;
}
}

maybe this could help? http://stackoverflow.com/questions/1682996/bytes-to-binary-in-c
Code: [Select]
unsigned char byte = 49;//Decimal Number
unsigned char mask = 1; //Bit mask
unsigned char bits[8]; //8bits=1Byte

for (int i = 0; i < 8; i++)// Extract the bits
{
bits[i] = (byte & (mask << i)) != 0;//Mask each bit in the byte and store it
}


the full code is
Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear
#FUSES NOBROWNOUT //Disable Reseting On Power Loss
//#FUSES HS //Crystal With More than 4Mhz

#use delay(clock=4000000)

//=================
//DeviceID of TV
//00100000=32
//
//Code of button OK
//00100010=34
//=================

// define some constants:
//DeviceID
const char device_address = 32; //DeviceID of TV
//Buttons
const char OK = 34; //button OK

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void send_byte(char byte_to_send)
{
for (char i=8, i>0, i--)// decrementing is more efficient that incrementing
{
(byte_to_send & 0x1) ? logical1() : logical0(); // the ? : is the ternary operator, works like if then else
byte_to_send = byte_to_send>>1;
}
}

void send_key_OK() //Send button OK
{
startSending(); //Send 9ms START pulse
send_byte(device_address); //Send DeviceID
send_byte(~device_address); //Send Inverted DeviceID
send_byte(OK); //Send ButtonCode
send_byte(~OK); //Send inverted ButtonCode
}

void main()
{
while(1)
{
if(!input(pin_a0))
{
send_key_OK();
while(!input(pin_a0))
{
repeatCode();
delay_ms(110);
}
}
}
}
« Last Edit: February 29, 2016, 04:00:48 am by luvini »
 

Offline macboy

  • Super Contributor
  • ***
  • Posts: 2276
  • Country: ca
Re: NEC IR Remote using PIC
« Reply #15 on: February 29, 2016, 04:54:33 pm »
First,
Code: [Select]
for (char i=8, i>0, i--)// decrementing is more efficient that incrementingMust be:
Code: [Select]
for (char i=8; i>0; i--)// decrementing is more efficient that incrementingNote the semicolons in place of the commas. This was a typo on my part, but you could have found this.

Change:
Code: [Select]
(byte_to_send & 0x1) ? logical1() : logical0(); // the ? : is the ternary operator, works like if then else
To:
Code: [Select]
if (byte_to_send & 0x1)
        {
            logical1();
        }
        else
        {
            logical0();
        }
 

Online pascal_sweden

  • Super Contributor
  • ***
  • Posts: 1541
  • Country: no
Re: NEC IR Remote using PIC
« Reply #16 on: February 29, 2016, 07:05:45 pm »
Why do you only want to use a PIC?

Note that the library also supports some PIC microcontrollers, and not only Atmel :)
http://www.mikrocontroller.net/articles/IRSND#Unterst.C3.BCtzte_.C2.B5Cs

But really, you should consider Atmel AVR instead of PIC!
Much better software tools (Atmel Studio) and the best programmer/debugger (AVR Dragon) for only 50 EUR!

 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #17 on: February 29, 2016, 08:45:54 pm »
now the code is

Code: [Select]
void send_byte(char byte_to_send)
{

for (char i=8; i>0; i--)// decrementing is more efficient that incrementing
{

if (byte_to_send & 0x1)
{
logical1();
}

else
{
logical0();
}

byte_to_send = byte_to_send>>1;
}
}

with error
Code: [Select]
*** Error 51 "test0002.c" Line 71(6,10): A numeric expression must appear here
*** Error 12 "test0002.c" Line 71(16,17): Undefined identifier   i
*** Error 12 "test0002.c" Line 71(21,22): Undefined identifier   i
      3 Errors,  0 Warnings.

so i added a "int i;"
Code: [Select]
void send_byte(char byte_to_send)
{
int i;
for (char i=8; i>0; i--)// decrementing is more efficient that incrementing
{

if (byte_to_send & 0x1)
{
logical1();
}

else
{
logical0();
}

byte_to_send = byte_to_send>>1;
}
}

and the error is
Code: [Select]
*** Error 51 "test0002.c" Line 71(6,10): A numeric expression must appear here
*** Error 76 "test0002.c" Line 71(24,25): Expect ;
      2 Errors,  0 Warnings

at
Code: [Select]
for (char i=8; i>0; i--)

however if i remove the "char" from "for (char i=8; i>0; i--)" it does compile, but doesnt work
Code: [Select]
void send_byte(char byte_to_send)
{
int i;
for (i=8; i>0; i--)// decrementing is more efficient that incrementing
{

if (byte_to_send & 0x1)
{
logical1();
}

else
{
logical0();
}

byte_to_send = byte_to_send>>1;
}
}
Code: [Select]
>>> Warning 203 "test0002.c" Line 100(1,1): Condition always TRUE
      Memory usage:   ROM=8%      RAM=3% - 4%
      0 Errors,  1 Warnings.
« Last Edit: March 01, 2016, 02:16:33 am by luvini »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #18 on: February 29, 2016, 08:59:30 pm »
Why do you only want to use a PIC?

Note that the library also supports some PIC microcontrollers, and not only Atmel :)
http://www.mikrocontroller.net/articles/IRSND#Unterst.C3.BCtzte_.C2.B5Cs

But really, you should consider Atmel AVR instead of PIC!
Much better software tools (Atmel Studio) and the best programmer/debugger (AVR Dragon) for only 50 EUR!

50EUR is 218BRL, quite expensive when i built a PicKit2 myself under 50BRL and the PIC16F628A is just 12,50BRL

but i will try AVR someday, i think the Arduino even uses it (ATmega328), but i also dont have a Arduino ;P

the PICs supported for that library are:
-PIC12F1840 (8pins)
-PIC18F4520 (40 pins)

i want to use a small chip, but with enough pins for all the buttons, so a 8pin chip wouldn't be enough, and a 40pins would be too much, however the PIC16F628A fits what i want with 18pins
« Last Edit: February 29, 2016, 09:01:46 pm by luvini »
 

Offline differentcurrent

  • Newbie
  • Posts: 7
  • Country: il
Re: NEC IR Remote using PIC
« Reply #19 on: March 01, 2016, 09:31:50 am »
i think the compiler is confusing with "i"  try giving it another name like "j"  or "temp_looo".
when it's jumping to other functions "i"  variable is messed up

Sent from my SM-N920C using Tapatalk

 

Offline differentcurrent

  • Newbie
  • Posts: 7
  • Country: il
Re: NEC IR Remote using PIC
« Reply #20 on: March 01, 2016, 09:34:00 am »
Why do you only want to use a PIC?

Note that the library also supports some PIC microcontrollers, and not only Atmel :)
http://www.mikrocontroller.net/articles/IRSND#Unterst.C3.BCtzte_.C2.B5Cs

But really, you should consider Atmel AVR instead of PIC!
Much better software tools (Atmel Studio) and the best programmer/debugger (AVR Dragon) for only 50 EUR!
why atmel is better than microchip?
i am using pic for a couple of years and it's working fine.
i be glad if give me a good reason to try them

Sent from my SM-N920C using Tapatalk
« Last Edit: March 01, 2016, 11:43:00 am by differentcurrent »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #21 on: March 02, 2016, 01:46:04 am »
i think the compiler is confusing with "i"  try giving it another name like "j"  or "temp_looo".
when it's jumping to other functions "i"  variable is messed up

Sent from my SM-N920C using Tapatalk

changing the variable "i" to anything else gives the same error

maybe Dave's Arduino code could help: https://gist.github.com/EEVblog/6206934

i think the problem is with that "char" inside the "for(" part, because when i remove it, it compiles with no errors
but it doesn't work, but at least the compiler gives no errors

Code: [Select]
for (char i=8; i>0; i--)

i dont understand what is this "char" doing inside of the parameters for the "for" function...

//=========================
void send_byte(char byte_to_send)
{

 for (char i=8; i>0; i--)// decrementing is more efficient than incrementing
 {

  if (byte_to_send & 0x1)
  {
  logical1();
  }

  else
  {
  logical0();
  }

 byte_to_send = byte_to_send>>1;
 }
}
//=========================



can you see the image with the code above?
« Last Edit: March 02, 2016, 02:25:01 am by luvini »
 

Offline xtoffer

  • Contributor
  • Posts: 33
  • Country: se
  • A CS turned electronic hobbyist.
Re: NEC IR Remote using PIC
« Reply #22 on: March 05, 2016, 11:42:04 am »
i dont understand what is this "char" doing inside of the parameters for the "for" function...

The char is used to declare the iterative variable inside the for-loop. However this is not always allowed in all versions of C, and most likely not in your case. The solution is, as you have already figured out, to declare it right before. (Whether it is actually a char or an int is another matter. Note: char is often used as an unsigned 8-bit int for spacesaving/speed reasons.)

So the function goes through each bit and executes the appropriate output function in turn. To make it actually work you have to setup the bits in the char such that the right sequence is sent. Note that the least significant bit is always taken from what is left to send. This decides the order in which the bits are sent. (If you want to reverse the order you can instead mask with 0x80 and shift the other way.)

For example..
Code: [Select]
send_byte(0x19)..would result in the following sequence..
Code: [Select]
logical1();
logical0();
logical0();
logical1();
logical1();
logical0();
logical0();
logical0();
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #23 on: March 06, 2016, 02:08:38 am »
found why the IR LED wasnt doing anything in last version of code, forgot to activate the PWM port  :palm:
Code: [Select]
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

the expected result at the IR output when sending the code would be:


but what im getting is:


it is sending ZEROs!

current code is
Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear
#FUSES NOBROWNOUT //Disable Reseting On Power Loss
//#FUSES HS //Crystal With More than 4Mhz

#use delay(clock=4000000)

//=================
//DeviceID of TV
//00100000=32
//
//Code of button OK
//00100010=34
//=================

// define some constants:
//DeviceID
const char device_address = 32; //DeviceID of TV
//Buttons
const char OK = 34; //button OK

char i;
char byte_to_send;

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void send_byte(OK)
{
for (i=8; i>0; i--) // decrementing is more efficient than incrementing
{

if (byte_to_send & 0x1)
{
logical1();
}

else
{
logical0();
}

byte_to_send = byte_to_send>>1;
}
}

//================================

void send_key_OK() //Send button OK
{
startSending(); //Send 9ms START pulse
send_byte(device_address); //Send DeviceID
send_byte(~device_address); //Send Inverted DeviceID
send_byte(OK); //Send ButtonCode
send_byte(~OK); //Send inverted ButtonCode
}

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(1)
{
if(input(pin_a0))
{
send_key_OK();
while(input(pin_a0))
{
repeatCode(); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
delay_ms(110); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
}
}
}
}

changing "if (byte_to_send & 0x1)" to " if (byte_to_send & 1)" or " if (byte_to_send = 1)" gives the same output...


===========

some timing info: Blue channel is 0, Red is 1, Yellow is the actual IR LED output

it is actually going into the logical0() function, otherwise it wouldn't have the same timing. Something is preventing it from getting into logical1(), maybe the formula is wrong? wrong type of comparison? wrong type of data? http://www.tutorialspoint.com/cprogramming/c_operators.htm

the code for this one is
Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear
#FUSES NOBROWNOUT //Disable Reseting On Power Loss
//#FUSES HS //Crystal With More than 4Mhz

#use delay(clock=4000000)

//=================
//DeviceID of TV
//00100000=32
//
//Code of button OK
//00100010=34
//=================

// define some constants:
//DeviceID
const char device_address = 32; //DeviceID of TV
//Buttons
const char OK = 34; //button OK

char i;
char byte_to_send;

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}
//================================

void send_byte(OK)
{
for (i=8; i>0; i--) // decrementing is more efficient than incrementing
{

if (byte_to_send & 0x1)
{
output_high(pin_b1); //probe pin B1 for 1 signals
logical1();
output_low(pin_b1);
}

else
{
output_high(pin_b0); //probe pin B0 for 0 signals
logical0();
output_low(pin_b0);
}

byte_to_send = byte_to_send>>1;
}
}

//================================

void send_key_OK() //Send button OK
{++++++++++++++++++++++++++
startSending(); //Send 9ms START pulse
send_byte(device_address); //Send DeviceID
send_byte(~device_address); //Send Inverted DeviceID
send_byte(OK); //Send ButtonCode
send_byte(~OK); //Send inverted ButtonCode
}

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(1)
{
if(input(pin_a0))
{
send_key_OK();

while(input(pin_a0))
{
// repeatCode(); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
// delay_ms(110); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
}
}
}
}
« Last Edit: March 06, 2016, 02:48:33 am by luvini »
 

Offline luviniTopic starter

  • Contributor
  • Posts: 33
  • Country: br
  • PIC C programming!
Re: NEC IR Remote using PIC
« Reply #24 on: March 06, 2016, 03:23:48 am »
UPDATE


(Blue = logical0(), Red = logical1(), Yellow = PWMoutput
i got it to work 31bits!, but they are mirrored every 8 bits (1 byte)!
EDIT
fixed the inverted bytes, changed "byte_to_send = byte_to_send>>1;" to "byte_to_send = 1<<byte_to_send;"


Code: [Select]
00000100
11111011
01000100
1011101
notice the last bit is missing, its supposed to be a 1, so its not working yet...

current code
Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear
#FUSES NOBROWNOUT //Disable Reseting On Power Loss
//#FUSES HS //Crystal With More than 4Mhz

#use delay(clock=4000000)

//=================
//DeviceID of TV
//00100000=32
//
//Code of button OK
//00100010=34
//=================

// define some constants:
//DeviceID
const char device_address = 32; //DeviceID of TV
//Buttons
const char OK = 34; //button OK

char i;
char byte_to_send;

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void end_sending()
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
}

//================================

void send_byte(byte_to_send)
{
for (i=8; i>0; i--)
{

if (byte_to_send & 0x1)
{
output_high(pin_b1); //probe pin B1 for 1 signals
logical1();
output_low(pin_b1);
}

else
{
output_high(pin_b0); //probe pin B0 for 0 signals
logical0();
output_low(pin_b0);
}

byte_to_send = byte_to_send>>1;
}
}

//================================

void send_key_OK() //Send button OK
{++++++++++++++++++++++++++
startSending(); //Send 9ms START pulse
send_byte(device_address); //Send DeviceID
send_byte(~device_address); //Send Inverted DeviceID
send_byte(OK); //Send ButtonCode
send_byte(~OK); //Send inverted ButtonCode
end_sending();
}

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(1)
{
if(!input(pin_a0))
{
send_key_OK();

while(!input(pin_a0))
{
delay_ms(110); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
repeatCode(); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
}
}
}
}


and the code
Code: [Select]
#include <16F628A.h>

#fuses NOWDT //Disable Watchdog Timer
#fuses NOPROTECT //Disable Read/Write Protect
#FUSES NOCPD //Disable EE protection
#fuses NOLVP //Disable Low Voltage Programming (ICSP) ==keep low during operation if enabled to prevent entering ICSP mode==
#fuses INTRC_IO //Set CLK pins as I/O
#fuses NOMCLR //Disable Master Clear
#FUSES NOBROWNOUT //Disable Reseting On Power Loss
//#FUSES HS //Crystal With More than 4Mhz

#use delay(clock=4000000)

//=================
//DeviceID of TV
//00100000=32
//
//Code of button OK
//00100010=34
//=================

// define some constants:
//DeviceID
const char device_address = 32; //DeviceID of TV
//Buttons
const char OK = 34; //button OK

char i;
char byte_to_send;

//================================
//      NEC PROTOCOL

void startSending() // START
{
set_pwm1_duty(12);;
delay_ms(9);
set_pwm1_duty(0);
delay_us(4500);
}

void logical1() // 1
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(1690);
}

void logical0() // 0
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void repeatCode() // REPEAT
{
set_pwm1_duty(12);
delay_ms(9);
set_pwm1_duty(0);
delay_us(2250);
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
delay_us(560);
}

void end_sending()
{
set_pwm1_duty(12);
delay_us(560);
set_pwm1_duty(0);
}

//================================

void send_byte(byte_to_send)
{
for (i=0; i<8; i++)
{

if (byte_to_send & 1)
{
output_high(pin_b1); //probe pin B1 for 1 signals
logical1();
output_low(pin_b1);
}

else
{
output_high(pin_b0); //probe pin B0 for 0 signals
logical0();
output_low(pin_b0);
}

byte_to_send = 1<<byte_to_send;
}
}

//================================

void send_key_OK() //Send button OK
{++++++++++++++++++++++++++
startSending(); //Send 9ms START pulse
send_byte(device_address); //Send DeviceID
send_byte(~device_address); //Send Inverted DeviceID
send_byte(OK); //Send ButtonCode
send_byte(~OK); //Send inverted ButtonCode
end_sending();
}

void main()
{
setup_ccp1(ccp_pwm);            //CCPM1 = PIN_B3 on PIC16F628A
setup_timer_2(T2_DIV_BY_1,25, 1);   //38Khz PWM using 4Mhz Osc.
delay_us(20);

while(1)
{
if(!input(pin_a0))
{
send_key_OK();

while(!input(pin_a0))
{
delay_ms(110); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
repeatCode(); //comment this line to one-shot troubleshot on osciloscope the output of send_key_OK()
}
}
}
}
gives the output
Code: [Select]
00100001
10100001
00100001
10100001
notice the last bit is always a 1...
« Last Edit: March 06, 2016, 05:20:11 am by luvini »
 


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf