IR interfacing with Capsense Button

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Esteem_123
Level 2
Level 2
50 sign-ins 25 sign-ins 10 replies posted

Hello all,

I want to turn on and turn off LED using IR receiver which connected to My cy8c4245axi-483. I am using IR IRM-3638, Modulation frequency of 38 kHz. LED should turn On and turn off by both the ways, i.e. by capsense button and by remote also. how could i do this? i have already completed through On/Off by Capsense. I have gone through example which is given here.  PSoC 4 Pioneer Kit Community Project#091 – RC-5... | element14 | Cypress Kits.

@MotooTanaka 

Thanks & Regards,

Prem KB

 

0 Likes
1 Solution
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I posted the following sample

https://community.cypress.com/t5/Code-Examples/An-experiment-of-RC5-remote-receiver-CY8CKIT-042-with...

Some notes:

  1. You need to test if the timing is OK with your RC5 remote
  2. You need to test the address and command of the button you'd like to use to toggle the LED
  3. In the main loop of the receiver program, check if the address and command matches with what you expected and if both matches, toggle LED

I hope this could be some hints.

moto

View solution in original post

0 Likes
16 Replies
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

 Hi Prem, 

 

Can you share your project and let us know where you are facing issues? Were you able to get the signals from the remote to the PSoC?

 

Best regards, 
Hari

BragadeeshV
Moderator
Moderator
Moderator
First question asked 1000 replies posted 750 replies posted

Hi @Esteem_123 ,

Does your IR receiver follow the NEC protocol. If yes, can you check this thread that has IR receiver (NEC protocol) implemented in PSoC 4 device.

https://community.cypress.com/t5/PSoC-4-MCU/How-to-make-an-IR-pulse-distance-decoder-on-psoc4/m-p/17... 

Regards,
Bragadeesh
0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

The sample you are specifying is using PSoC as a transceiver (remote controller),

but your description sounds like a receiver (controlled by a remote controller or remote IR light).

It would be helpful if you can specify with what kind of IR light/signal you want to switch the LED connected to the PSoC board or if you want to control a remote device from PSoC 4.

moto

0 Likes
lock attach
Attachments are accessible only for community members.

Hi @Hari @MotooTanaka 

Let me clear what actually I wanted to do. I have one IR receiver which is connected to one pin of MCU. I have separate remote to send signals to this IR receiver. Now I have to control one LED connected to other pin of MCU. When I press button of IR remote that LED should turn on. Again when I press button LED should turn off. Turn on and off LED by using Capsense I have already completed. But I don't know how on/off LED with Remote. Note that my remote using RC5 protocol. I have attached IR receiver details.

https://www.google.com/url?sa=t&source=web&rct=j&url=http://www.everlight.com/file/ProductFile/IRM-3...

 

Thanks,

Prem KB

 

 

 

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @Esteem_123 

 

Were you able to interface the IR to PSoC? Can you get an interrupt or a gpio signal when you press the button on the remote? If so, then the remaining process is extremely simple. You can generate an interrupt and in the ISR, you can toggle the pin. 

 

I cannot see the datasheet that you have shared, I get a 404 error...

 

Best regards, 
Hari

0 Likes
lock attach
Attachments are accessible only for community members.

Hi @Hari @MotooTanaka @BragadeeshV

I found one project example on IR receiver with PSoC 4 with Sony protocol. I wanted to do same with RC5 protocol. This code is working for me but when I press any button on remote LED gets toggled. I wanted to assign a particular remote switch for particular button. Can you please look in to it? I don't want LED char displayed in this project instead of I want to print in UART it self.

 

Thanks & Regards,

Prem KB

0 Likes
Hari
Moderator
Moderator
Moderator
750 replies posted 500 replies posted 250 solutions authored

Hi @Esteem_123 

 

You can easily port the LCD functionality to UART by using the SCB or software transmit UART components. You can take a look at CE195366 and CE195379.

Are you using a kit for the project or is it a custom PCB? Note that the 042 kit requires an external connection for UART to kitprog.

Best regards, 
Hari

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

 This code is working for me but when I press any button on remote LED gets toggled.

Seeing the attached project, I could not figure out how it can receive the data sent in the RC5 protocol.

 

But assuming that it is working, then you should get some value sent from the remote

and according to the value you should decide if flip the LED.

 

If the received value is theValue  and the value of button which will toggle LED is expectedButtonValue

then you could modify the code something like

	if (theValue == expectedButtonValue) {		    
		ledstatus = Pin_RedLED_Read();
		if (ledstatus == 0) {
			ledstatus = 1;
		} else {
			ledstatus = 0;
		}
		Pin_RedLED_Write(ledstatus);
	}

 moto

 

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

I posted the following sample

https://community.cypress.com/t5/Code-Examples/An-experiment-of-RC5-remote-receiver-CY8CKIT-042-with...

Some notes:

  1. You need to test if the timing is OK with your RC5 remote
  2. You need to test the address and command of the button you'd like to use to toggle the LED
  3. In the main loop of the receiver program, check if the address and command matches with what you expected and if both matches, toggle LED

I hope this could be some hints.

moto

0 Likes

Respected sir,

thank you for sharing this project. it has solved my problem. it is working fine.

Thanks,

 Prem KB

lock attach
Attachments are accessible only for community members.
Esteem_123
Level 2
Level 2
50 sign-ins 25 sign-ins 10 replies posted

Hello @MotooTanaka @BragadeeshV @Hari,

i have made modification to NEC receiver project which i have found Cypress community. i am trying to operate LED with both Remote and Capsense. i can able to operate it with remote but it is not working with Capsense. C code i have attached here. I know i have put Capsense inside if(framereceived),so that capsense is not working. But if i put after frame received then only capsense is working not NEC receiver. Please give me suggestions.

 

#include "project.h"
#include "stdio.h"
#define TIMER_FREQUENCY 1000000UL
#define ADDRESS_SIZE    16U
#define DATA_SIZE       16U
volatile uint16_t timeStart;
volatile uint16_t timeEnd;
uint32_t pulseWidth;
volatile uint16_t pulseReceived;
volatile uint16_t overflow;
uint32_t timeDiff;
/******************************/
uint8_t startFrameFlag = 0;
uint8_t addressCount = 0;
uint8_t dataCount = 0;
uint16_t address_temp;
uint8_t address_temp2;
uint8_t address;
uint8_t address_inv;
uint16_t data_temp;
uint8_t data;
uint8_t data_inv;
uint8_t frameReceived;
unsigned char status=0;
unsigned char flag[10];
/*****************************/
typedef enum 
{
    IDLE,
    ADDRESS_FRAME,
    DATA_FRAME,
}state;
state nec_state;
/* CountFlag is 0 only once or during the start of the frame */
volatile uint16_t countFlag;
uint16_t timerPeriod;
asm (".global _printf_float");
/* For GCC compiler revise _write() function for printf functionality */
int _write(int file, char *ptr, int len)
{
    (void) file;
    int i;
    for (i = 0; i < len; i++)
    {
        UART_UartPutChar(*ptr++);
    }
    return(len);
}
void Pin_ISR();
void Timer_ISR();
void DecodeProcotol(uint16_t pulseWidth);
int main(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    CapSense_Start();
    OF_8_Write(1);
    CapSense_InitializeAllBaselines();
    Pin_Interrupt_StartEx(Pin_ISR);
    Timer_Interrupt_StartEx(Timer_ISR);
    UART_Start();
    UART_UartPutString("Working\r\n");
    nec_state = IDLE;
    Timer_Start();
    timerPeriod = Timer_ReadPeriod();
    /* Place your initialization/startup code here (e.g. MyInst_Start()) */
    for(;;)
    {
        CapSense_ProcessAllWidgets();
        CapSense_ScanAllWidgets();
        if(pulseReceived)
        {
            if(timeEnd > timeStart)
            {
                timeDiff = (overflow * timerPeriod) + (timeEnd - timeStart);
            }
            else
            {
                timeDiff = (overflow * timerPeriod) - (timeStart - timeEnd);
            }
            timeStart = timeEnd;
            overflow = 0;
            pulseReceived = 0;
            pulseWidth = timeDiff; //in uS
            //printf("%u uS\r\n", pulseWidth);
            DecodeProcotol(pulseWidth);
        }
        if(frameReceived)
        {
            address_inv = address_temp >> 8;
            address = address_temp & 0x00FF;
            data_inv = data_temp >> 8;
            data = data_temp & 0x00FF;
                if((uint8_t)(~data) == data_inv)
                {
                    //printf("Data received: %u\r\n", data_temp);
                    printf("Data received: %u\r\n", data);
                }
                else
                {
                    printf("Data corrupted\n\r");
                }
            //ResetFlags
            countFlag = 0;
            timeEnd = 0;
            timeStart = 0;
            frameReceived = 0;
            address_temp = 0;
            data_temp = 0;
            address_inv = 0;
            address = 0;
            data_inv = 0;
           status=CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID);
           if(status || data==6)
            {
           if(flag[8]==0)  
                    {flag[8]=1;OF_8_Write(0);
                    
                    }
            else
                    {flag[8]=0;OF_8_Write(1);
                    
                    }
            while(status)
            {
                CapSense_ProcessAllWidgets();
                while(CapSense_IsBusy()); 
                CapSense_ScanAllWidgets();   
                status = CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID);
            }
        }
        }
    }
}
CY_ISR(Pin_ISR)
{
    uint8 intrSrc;
    intrsrc=NEC_IN_ClearInterrupt();
    if(intrSrc != 0u)
    {
        if(countFlag == 0)
        {   
            timeStart = Timer_ReadCounter();
            countFlag = 1;
        }
        else
        {
            timeEnd = Timer_ReadCounter();
            pulseReceived = 1;
        }
    }
}
CY_ISR(Timer_ISR)
{
    if((Timer_GetInterruptSourceMasked() & Timer_INTR_MASK_TC ) != 0)
    {
        if(countFlag != 0)
        overflow++;
        Timer_ClearInterrupt(Timer_INTR_MASK_TC);
    }
}
void DecodeProcotol(uint16_t pulseWidth)
{
    uint8_t bit = 0;
    switch(nec_state)
    {
        case IDLE://Checks for start of frame
        {
            if(pulseWidth > 12000 && pulseWidth < 15000)
            {
                nec_state = ADDRESS_FRAME;
                startFrameFlag = 1;
            }
            else
            {
                //Invalid Frame received
                nec_state = IDLE;
            }
        
            break;
        }
        case ADDRESS_FRAME:
        {
            if(pulseWidth > 1100 && pulseWidth < 1160)
            {
                bit = 0;
            }
            else if(pulseWidth > 2200 && pulseWidth < 2300)
            {
                 bit = 1;
            }
            address_temp |= ( bit << addressCount);
            addressCount++;
            if(addressCount >= ADDRESS_SIZE)
            {
               addressCount = 0; 
               nec_state = DATA_FRAME;
            }
            break;
        }
        case DATA_FRAME:
        {
            if(pulseWidth > 1100 && pulseWidth < 1160)
            {
                bit = 0;
            }
            else if(pulseWidth > 2200 && pulseWidth < 2300)
            {
                bit = 1;
            }
           data_temp |= ( bit << dataCount);
           dataCount++;
            if(dataCount >= DATA_SIZE)
            {
               dataCount = 0; 
               nec_state = IDLE;
               frameReceived = 1;
            }
            break;
        }
    }
}


Thanks && Regards,

Prem KB 

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

As the nature of the question is different from the original question,

it may be better to ask this question in a newly created question,

so that more people will notice/look into your new question.

 

Having written that, following is my short opinion.

As you have 2 asynchronous operation in the main loop,

basically you should not have "while()" wait inside.

So I would try some thing like below

    unsigned char prev_status = 0 ; // after the line of status=0

... in main()

    CapSense_ProcessAllWidgets();
    CapSense_ScanAllWidgets();    

    for(;;) {
        if (pulseReceived) {
           // do process for pulse received
        }
        if (frameReceived) {
           // do process for frame received
        }
        if (!CapSense_IsBusy()) {
            CapSense_ScanAllWidgets();   
            status = CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID);
            if (!prev_status && status) {
              // do process for CapSense Activated edge
            }
            prev_status = status ;
            CapSense_ProcessAllWidgets();
        }
     }

 

moto

0 Likes

hello Sir,

i have modified as per you have suggested. LED should operate by both ways capsense and Remote. but it is not working.

if (!CapSense_IsBusy()) {
            CapSense_ScanAllWidgets();   
            status = CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID) ||(data==18);
            if (status && !prev_status)
              // do process for CapSense Activated edge
                {
                    if(flag[8]==0)  
                            {flag[8]=1;OF_8_Write(0);}
                    else
                            {flag[8]=0;OF_8_Write(1);}
                }
                prev_status = status ;
                CapSense_ProcessAllWidgets();
        }

 

Thanks,

Prem KB 

0 Likes
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

First of all, it was my bad that the sequence of

CapSense_ProcessAllWidgets()

and

CapSense_ScanAllWidgets()

in my previous code snippet was wrong,

it should have been something like

 

        if (CapSense_NOT_BUSY == CapSense_IsBusy()) {   
            /* Process data for all widgets */
            CapSense_ProcessAllWidgets();     
            
            status  = CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID);         
            
            if (status && !prev_status) {
                // do process for CapSense Activated edge
            }
            
            prev_status = status ;

            /* Initiate new scan for all widgets */
            CapSense_ScanAllWidgets();                      
        }

 

Meantime, I think that the LED on/off by IR Remote should be taken care of outside of

if (CapSense_NOT_BUSY == CapSense_IsBusy()) {

block, to make CapSense and IR Remote independent.

 

And please debug and make sure both methods are working individually

by comment out the other method in the main loop.

As I don't know about the NEC protocol stuff,

I'm not paying attention about IR part this time.

moto

 

0 Likes

hello sir,

it is working with capsense properly.  but at a same time if i pressed remote button to make it toggle, it won't work with remote or capsense. Please have look in this video.https://www.mediafire.com/file/jov256zx09qyr8n/WhatsApp+Video+2021-04-08+at+10.22.35+PM.mp4/file 

 

Thanks for your quick response,

Prem KB

0 Likes
lock attach
Attachments are accessible only for community members.
MotooTanaka
Level 9
Level 9
Distributor - Marubun (Japan)
First comment on blog Beta tester First comment on KBA

Hi,

So I added a CapSense to my RC5 receiver sample.

 

Schematic

And I assigned the Green LED on CY8CKIT-042 as LED

P1.1 as button08

P1.5 as button07

003-schematic.JPG

Pins

004-Pins.JPG

 

As I tested, I noticed that when IR signal is being detected,

CapSense needed to be stopped.

And it needed to be started again after RC5 timer process completed.

I assigned the RC5 address 3 to MY_IR_ADDRESS

command 7 to MY_IR_COMMAND.

You need to test your remote controller and get the address and command number

which you'd like to use to turn on/off the LED.

So I modified the main.c as

#include "project.h"
#include "stdio.h"
#include "tty_utils.h"

#define IR_ST_IDLE       0
#define IR_ST_START_BIT  1
#define IR_ST_TOGGLE     2
#define IR_ST_ADDRESS    3
#define IR_ST_COMMAND    4
#define IR_ST_DATA_READY 5

#define IR_ADDRESS_WIDTH 5
#define IR_COMMAND_WIDTH 6

#define MY_IR_ADDRESS    3
#define MY_IR_COMMAND    7

volatile int ir_status = IR_ST_IDLE ;
volatile int ir_address_bit = 0 ; /* 5bit */
volatile int ir_command_bit = 0 ; /* 6bit */
volatile int ir_toggle      = 0 ;
volatile int ir_address     = 0 ;
volatile int ir_command     = 0 ;
volatile int capsense_running = 0 ;

CY_ISR_PROTO(timer_isr) ;

CY_ISR(ir_isr)
{
    isr_ir_ClearPending() ;
    
    if (ir_status == IR_ST_IDLE) {
        if (capsense_running) {
            CapSense_Stop() ;
            capsense_running = 0 ;
        }
        ir_status = IR_ST_START_BIT ;
        isr_ir_Disable() ;
        isr_ir_ClearPending() ;
        isr_bit_ClearPending() ;
        isr_bit_StartEx(timer_isr) ;
        bit_timer_ClearInterrupt(bit_timer_INTR_MASK_CC_MATCH) ;
        bit_timer_WriteCounter(0) ;
        bit_timer_Enable() ;
    }
}

CY_ISR(timer_isr)
{
    int ir_in ;
    
    bit_timer_ClearInterrupt(bit_timer_INTR_MASK_CC_MATCH) ;
    ir_in = IR_input_Read() ;
    
    switch(ir_status) {
    case IR_ST_IDLE: // should not come here
        break ;
    case IR_ST_START_BIT:
        if (ir_in == 1) {
            ir_status = IR_ST_TOGGLE ;
        } else {
            ir_status = IR_ST_IDLE ;
        }
        break ;
    case IR_ST_TOGGLE:
        ir_toggle = ir_in ;
        ir_status = IR_ST_ADDRESS ;
        break ;
    case IR_ST_ADDRESS:
        ir_address <<= 1 ;
        ir_address |= ir_in ;
        if (++ir_address_bit >= IR_ADDRESS_WIDTH) {
            ir_status = IR_ST_COMMAND ;
        }
        break ;
    case IR_ST_COMMAND:
        ir_command <<= 1 ;
        ir_command |= ir_in ;
        if (++ir_command_bit >= IR_COMMAND_WIDTH) {
            ir_status = IR_ST_DATA_READY ;
            isr_bit_Disable() ;
            isr_bit_ClearPending() ;
            bit_timer_Stop() ;
        }
        break ;
    case IR_ST_DATA_READY: // should not come here
    default:               // should not come here
        break ;
    }
}

void clear_data(void)
{
    ir_toggle = 0 ;
    ir_address = 0 ;
    ir_address_bit = 0 ;
    ir_command = 0 ;
    ir_command_bit = 0 ;
}

void init_hardware(void)
{
    CyGlobalIntEnable; /* Enable global interrupts. */
    
    tty_init() ;
    
    splash("RC5 Test") ;
    
    isr_ir_ClearPending() ;
    isr_ir_StartEx(ir_isr) ;
    
    isr_bit_ClearPending() ;
    isr_bit_StartEx(timer_isr) ;
    
    bit_timer_Init() ;
    
    capsense_running = 1 ;
    CapSense_Start() ;
    CapSense_ScanAllWidgets() ;
}

int main(void)
{   
    uint8_t status, prev_status ;
    int my_ir_address = MY_IR_ADDRESS ;
    int my_ir_command = MY_IR_COMMAND ;
    int toggle_led_flag = 0 ;
    
    init_hardware() ;

    for(;;)
    {
        if (ir_status == IR_ST_DATA_READY) {
            snprintf(str, STR_BUF_LEN, "toggle: %d address %d: command %d\n\r", 
                ir_toggle, ir_address, ir_command) ;
            print(str) ;
            if ((ir_address == MY_IR_ADDRESS) && (ir_command == MY_IR_COMMAND)) {
                print("IR Command Hit!\n\r") ;
                toggle_led_flag = 1 ;
            }

            if (capsense_running == 0) {
                capsense_running = 1 ;
                CapSense_Start() ;
                CapSense_ScanAllWidgets() ;
            }
            
            clear_data() ;
            ir_status = IR_ST_IDLE ;
            isr_ir_ClearPending() ;
            isr_ir_StartEx(ir_isr) ;
            // isr_ir_Enable() ;
        }
        if (capsense_running && (CapSense_NOT_BUSY == CapSense_IsBusy())) {
            CapSense_ProcessAllWidgets() ;
            status = CapSense_IsWidgetActive(CapSense_BUTTON08_WDGT_ID) ;
            if (status && !prev_status) { /* CapSense Activated Edge */
                print("CapSense Button08 Touched!\n\r") ;
                toggle_led_flag = 1 ;
            }
            prev_status = status ;
            CapSense_ScanAllWidgets() ;
        }
        if (toggle_led_flag) {
            toggle_led_flag = 0 ;
            print("LED: ") ;
            if (LED_Read()) {
                LED_Write(0) ;
                print("ON\n\r") ;
            } else {
                LED_Write(1) ;
                print("OFF\n\r") ;
            }
        }
    }
}

Now when the serial output of CY8CKIT-042 was

002-rc_test_log.JPG

After starting, 

(1) I touched the button, LED turned ON

(2) I touched the button, LED turned OFF

(3) I sent 0 0 0 from the emulator on CY8CKIT-044

received 0 0 0

(4) I sent 0 1 2  received 0 1 0

(5) I sent 0 3 7 received 0 3 0

(6) I sent 0 3 7 received 0 3 6

(7) I sent 0 3 7 received  0 3 7 (command matched) LED turned ON

(8) I sent 0 3 7 received 0 3 7 (command matched) LED turned OFF

(9) I touched the button, LED turned ON

(10) I touched the button, LED turned OFF

(11) I sent 0 3 7 received 0 3 7 (command matched) LED ON

(12) I sent 0 3 7 received 0 3 7 (command matched) LED OFF

(13)  I touched the button, LED turned ON

(14) I sent 0 3 7 received 0 3 7 (command matched) LED OFF

(15) I sent 0 3 7 received 0 7 0 

(16) I sent 0 3 7 received 0 3 7 (command matched) LED ON

(17) I touched the button, LED turned OFF

 

So basically, both RC5 signal and CapSense are working,

but with my program, sometimes the receiver fails to receive correct RC5 value(s),

this may be cause by the accuracy of the clock

or CapSense interrupt and/or some other system level interrupts are

causing the inaccuracy of the timer value.

 

Although I could have spent much more time,  I decided to stop here.

 

moto

0 Likes