CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

12F1822 IR Remote Receiver
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Mar 18, 2021 2:02 am     Reply with quote

I was able to make it work. First I ordered this very cheap IR remote
and sensor set from Amazon. It's even cheaper from China on EBAY
but I didn't want to wait:
https://www.amazon.com/dp/B07S67SFSF/

Then I connected one of the IR sensors to the Microchip Low Pin Count
board, running at +5 volts. I also connected Vcc and Gnd for the sensor.

1. I moved the IR sensor pin to pin A2 on the PIC. He originally had it
on pin A3. That's the MCLR pin, so he had to use the NOMCLR fuse.
I personally like to use the MCLR pin as MCLR. I have a 10K
pullup on it.

2. I did not use pin A0 or A1 for anything because those are the ICSP
pins for the Pickit3, and I don't want anything on them.

3. I got rid of #use fast_io(A). I don't like fast io. I let the compiler
handle the TRIS.

4. I added a software RS-232 transmit on pin A4. I like to see what I'm
doing, and print results on TeraTerm on my PC.

5. I got rid of the #fuses statement. For this little test program I went with
the default fuses that the compiler assigns. They can be reviewed at the
end of the .LST file.

6. I let the compiler handle setting up the clock by using:
#use delay(internal=32M)
I dropped all the zeros after the 32 because it's way easier to read this way.

7. Most important, I did not try to make his program work as is.
I cut out his if() statements for his codes. Instead I went diagnostic
and used printf to display the codes that I'm actually getting.

In short, I went for speed of editing the program and for reliability.
Also, after I made these changes, it worked immediately.

On the little remote, if I press a key, I get these codes:
Press 1: 00ff30cf

press 2: 00ff18e7

press CH: 00ff629d

These correspond exactly with the codes listed on this website in a table:
https://www.circuitbasics.com/arduino-ir-remote-receiver-tutorial/
Scroll down to the part where he shows a terminal window for:
Quote:
COM 7 (Arduino / Genuino Uno)

Just below that image, he has a table of the codes. He's using the
same remote as sold on Amazon and EBAY. This remote is tiny.
It's 3.4 inches long by 1.6 inches wide (8.6cm x 4.0cm).

The original code (same as used by Denny) comes from the receiver
code on this webpage:
http://ccspicc.blogspot.com/2016/09/nec-ir-transmitter-receiver-circuit-pic-c-code.html

Here is the modified code I used to test the hardware (with CCS vs. 5.103):
Code:
// Extended NEC protocol IR remote control decoder using PIC12F1822 CCS PIC C code
// http://ccspicc.blogspot.com/
// [email protected]
// Use at your own risk

#include <12F1822.h>
#use delay(internal=32M)
#use rs232(baud=9600, xmit=PIN_A4)

//#use fast_io(A)

#define IR_Sensor PIN_A2

unsigned int32 ir_code;
 
short nec_remote_read()
{
  unsigned int16 count = 0;
  unsigned int8 i;
  // Check 9ms pulse (remote control sends logic high)
  SET_TIMER1(0);
  while(!input(IR_Sensor) && (count < 9500))
    count = GET_TIMER1();
  if( (count > 9499) || (count < 8500))
    return FALSE;
  // Check 4.5ms space (remote control sends logic low)
  SET_TIMER1(0);
  count = 0;
  while((input(IR_Sensor)) && (count < 5000))
    count = GET_TIMER1();
  if( (count > 4999) || (count < 4000))
    return FALSE;
  // Read message (32 bits)
  for(i = 0; i < 32; i++){
    SET_TIMER1(0);
    count = 0;
    while(!input(IR_Sensor) && (count < 650))
      count = GET_TIMER1();
    if( (count > 649) || (count < 500))
      return FALSE;
    count = 0;
    SET_TIMER1(0);
    while((input(IR_Sensor)) && (count < 1800))
      count = GET_TIMER1();
    if( (count > 1799) || (count < 400))
      return FALSE;
    if( count > 1000)                                 // If space width > 1ms
      bit_set(ir_code, (31 - i));                     // Write 1 to bit (31 - i)
    else                                              // If space width < 1ms
      bit_clear(ir_code, (31 - i));                   // Write 0 to bit (31 - i)
  }
  return TRUE;
}

//===============================
void main()
{
//  setup_oscillator(OSC_8MHZ | OSC_PLL_ON);  // Set internal oscillator to 32MHz (8MHz and PLL)
//  output_a(0);
//  set_tris_a(8);
  SETUP_TIMER_1(T1_INTERNAL | T1_DIV_BY_8);

  while(TRUE)
    {
     while(input(IR_Sensor));    // Wait until IR_Sensor pin falls
     nec_remote_read();
     printf("%lx\n\r", ir_code);
    }
}
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Thu Mar 18, 2021 4:31 am     Reply with quote

Thanks PCM, I purchased the same remote package on Amazon, to originally test and it looks as if the codes are different than the one’s the original author had in Their source code. That would explain a lot, and appreciate the time and effort you’ve put into this, I’ve learned a lot!

It would really help if I build a decoder first, so that I know the exact hexadecimal codes to use. I have a 1602 LCD screen in my stash, so I may do that first.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Thu Mar 18, 2021 6:07 am     Reply with quote

PCM, do you see a problem migrating this code to a 16F1823? I want to have access to a few more pins, because I like your idea of not using the MCLR pin for an I/O.

Last edited by Denny9167 on Thu Mar 18, 2021 8:08 am; edited 2 times in total
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Thu Mar 18, 2021 7:30 am     Reply with quote

I'd say 'no problem'. They are close relatives. However if I was doing that
I'd say go to the 1824. More ROM is always useful as well as the extra
pins. The 1829 is still from the same family, and has even more pins and
EEPROM etc.. Very Happy
dexta64



Joined: 19 Feb 2019
Posts: 11

View user's profile Send private message

Clock must be selected in the oscillator setting.
PostPosted: Fri Mar 19, 2021 12:23 am     Reply with quote

in this row you must select the internal clock.
Code:

setup_oscillator(OSC_8MHZ | OSC_PLL_ON | OSC_INTRC);
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Mar 19, 2021 3:15 am     Reply with quote

With CCS vs. 5.103, you don't need that line. The compiler will set it up
to use the PLL and the correct #fuses for the 12F1822, based on this line:
Code:
#use delay(internal=32M)
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Fri Mar 19, 2021 9:21 am     Reply with quote

I’m going to re-build the code with the new hexadecimal commands that PCM
Pointed out in a earlier post, and see if that doesn’t get this going.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Fri Mar 19, 2021 3:41 pm     Reply with quote

Works great!! With the right command codes!

I have a question for the experts, i don’t want two of the LED’s to latch, but only remain high as long as the switch is pressed. A “while” instead of “if” statement on the specific output pins possibly?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Mar 20, 2021 1:05 am     Reply with quote

Here's a quick way to do it, as shown in bold below. Anytime it receives
the IR code, it will turn on the LED for 200 ms. This delay can potentially
cause problems, because it blocks anything else from happening during
the delay time.
This delay could be done with a timer interrupt, but again, you'd have
interrupts potentially occurring when the PIC should be receiving data.
Try this, see if it solves your problem. You need to copy that code for
each LED.
Quote:
if(nec_remote_read())
{
if(ir_code == 0x40BF00FF)
{
output_high(PIN_A0);
delay_ms(200);
output_low(PIN_A0);
}

if(ir_code == 0x40BF807F)
output_toggle(PIN_A1);
if(ir_code == 0x40BF40BF)
output_toggle(PIN_A2);
if(ir_code == 0x40BF20DF)
output_toggle(PIN_A4);
if(ir_code == 0x40BFA05F)
output_toggle(PIN_A5);
}
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 20, 2021 3:59 am     Reply with quote

PCM programmer wrote:
Here's a quick way to do it, as shown in bold below. Anytime it receives
the IR code, it will turn on the LED for 200 ms. This delay can potentially
cause problems, because it blocks anything else from happening during
the delay time.
This delay could be done with a timer interrupt, but again, you'd have
interrupts potentially occurring when the PIC should be receiving data.
Try this, see if it solves your problem. You need to copy that code for
each LED.
Quote:
if(nec_remote_read())
{
if(ir_code == 0x40BF00FF)
{
output_high(PIN_A0);
delay_ms(200);
output_low(PIN_A0);
}

if(ir_code == 0x40BF807F)
output_toggle(PIN_A1);
if(ir_code == 0x40BF40BF)
output_toggle(PIN_A2);
if(ir_code == 0x40BF20DF)
output_toggle(PIN_A4);
if(ir_code == 0x40BFA05F)
output_toggle(PIN_A5);
}


I will try that, I won’t be able to use this Amazon remote because I
believe it transmits a different code when any button remains pressed, but I’m
Still working on the Transmitter that goes with this. I just need it for 2 pins the others will be used to initiate relays, and they will need to remain latched.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 20, 2021 4:09 am     Reply with quote

I have another project that I’ve used where
one can change the action of the relays from latched to momentary.
But it’s written in assembly code, I’m sure something similar can be done
In C.

https://picprojects.org/projects/ir/sirc10f/index.htm
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 20, 2021 5:37 am     Reply with quote

PCM programmer wrote:
Here's a quick way to do it, as shown in bold below. Anytime it receives
the IR code, it will turn on the LED for 200 ms. This delay can potentially
cause problems, because it blocks anything else from happening during
the delay time.
This delay could be done with a timer interrupt, but again, you'd have
interrupts potentially occurring when the PIC should be receiving data.
Try this, see if it solves your problem. You need to copy that code for
each LED.
Quote:
if(nec_remote_read())
{
if(ir_code == 0x40BF00FF)
{
output_high(PIN_A0);
delay_ms(200);
output_low(PIN_A0);
}

if(ir_code == 0x40BF807F)
output_toggle(PIN_A1);
if(ir_code == 0x40BF40BF)
output_toggle(PIN_A2);
if(ir_code == 0x40BF20DF)
output_toggle(PIN_A4);
if(ir_code == 0x40BFA05F)
output_toggle(PIN_A5);
}


It seems to be working, I did away with the “#use fast_io” directive also.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 20, 2021 7:52 am     Reply with quote

One more question, is it possible to have only one PiN engaged at a time? Meaning each time a command is sent, it engages one PIN at a time, and whenever another command is sent, it engages another pin and turns off the others.
Ttelmah



Joined: 11 Mar 2010
Posts: 19545

View user's profile Send private message

PostPosted: Sat Mar 20, 2021 8:49 am     Reply with quote

Of course it is.

If you just have the code for button 1 turn on it's pin, and turn the others
off, then button 2 does the same, 3 etc. etc..
Then if you push 1, this pin will go on, and all others off. Staying on
till another button is pressed.
Denny9167



Joined: 15 Feb 2021
Posts: 49

View user's profile Send private message Send e-mail

PostPosted: Sat Mar 20, 2021 10:02 am     Reply with quote

PCM programmer wrote:
Here's a quick way to do it, as shown in bold below. Anytime it receives
the IR code, it will turn on the LED for 200 ms. This delay can potentially
cause problems, because it blocks anything else from happening during
the delay time.
This delay could be done with a timer interrupt, but again, you'd have
interrupts potentially occurring when the PIC should be receiving data.
Try this, see if it solves your problem. You need to copy that code for
each LED.
Quote:
if(nec_remote_read())
{
if(ir_code == 0x40BF00FF)
{
output_high(PIN_A0);
delay_ms(200);
output_low(PIN_A0);
}

if(ir_code == 0x40BF807F)
output_toggle(PIN_A1);
if(ir_code == 0x40BF40BF)
output_toggle(PIN_A2);
if(ir_code == 0x40BF20DF)
output_toggle(PIN_A4);
if(ir_code == 0x40BFA05F)
output_toggle(PIN_A5);
}


Instead of the delay, which only works with the initial command, how would the statement be worded to keep the output high so long as the command is being received and then go low when it’s not(button release on transmitter).
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group