I need to recognize a signal from an IR remote, not to use a library for working with IR remotes/receivers. How can when the button is clicked to display its name. I have PIC12F615 microcontroller with this code: code and 5 buttons connected to him and I need recognise which button pressed. Why NEC IR remote control decoder does not work,
Schema in Proteus:
pulseLengthLastUs
is always false in this condition: pulseLengthLastUs > 8000 && pulseLengthLastUs < 10000
on any button press.
Code:
volatile boolean nec_ok = 0;
byte command, inv_command;
volatile byte nec_state = 0 ;
unsigned int address;
volatile unsigned long nec_code;
volatile uint32_t errFlag = 0 ;
volatile uint32_t decodeStartAtMs = 0 ;
void setup() {
Serial.begin(9600);
pinMode( 2, INPUT_PULLUP ) ;
attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Enable external interrupt (INT0)
}
void remote_read() {
static byte i = 0 ;
static bool wasSpace;
static unsigned long enteredAtUs = 0 ;
static unsigned long pulseLengthLastUs ;
wasSpace = ! digitalRead( 2 ) ;
pulseLengthLastUs = micros() - enteredAtUs; // Calculate pulse length
enteredAtUs = micros(); // Store current time for next entry
switch (nec_state) {
case 0 : // Wait here until 9ms pulse found )
if ( pulseLengthLastUs > 8000 && pulseLengthLastUs < 10000 ) { // got a 9ms pulse
decodeStartAtMs = millis() ; // for timeout
nec_state = 1 ;
nec_code = 0 ;
i = 0 ;
}
break;
case 1 : // handle 4.5ms space
if ((pulseLengthLastUs > 5500) || (pulseLengthLastUs < 3500)) {
errFlag = 10000000 + pulseLengthLastUs ;
nec_state = 0; // Reset decoding process
}
else
nec_state = 2; // Next state: end of 562µs pulse (start of 562µs or 1687µs space)
break;
case 2 : // handle 562µs or 1687µs space
if ((pulseLengthLastUs > 1900) || (pulseLengthLastUs < 400)) { // Time interval invalid ==> stop decoding
errFlag = 20000000 + pulseLengthLastUs ;
nec_state = 0; // Reset decoding process
break;
}
if ( wasSpace ) {
// we are interested only in the space length
if ( pulseLengthLastUs > 1000) // If space width > 1ms (short space)
bitSet(nec_code, (31 - i)); // Write 1 to bit (31 - i)
else // If space width < 1ms (long space)
bitClear(nec_code, (31 - i)); // Write 0 to bit (31 - i)
i++;
if (i > 31) { // If all bits are received
i = 0 ;
nec_ok = 1; // Decoding process OK
detachInterrupt(0); // Disable external interrupt (INT0)
}
}
break;
}
}
void loop() {
if ( errFlag > 0 ) {
Serial.print( "Error: " ) ;
Serial.println( errFlag ) ;
errFlag = 0 ;
}
if ( nec_state > 0 && millis() - decodeStartAtMs > 90 ) {
Serial.println( "Timeout" ) ;
nec_state = 0 ;
}
if (nec_ok) {
Serial.print( "Code received = " ) ;
Serial.println( nec_code, HEX ) ;
address = (nec_code >> 16) & 0xFF; // Extract address from received code
inv_command = (nec_code >> 8) & 0xFF; // Extract inverted command from received code
command = nec_code & 0xFF; // Extract command from received code
if (command == ((~inv_command) & 0xFF)) { // Verify command validity
Serial.print("Received valid NEC code: ");
Serial.print(address, HEX); Serial.print(", ");
Serial.print(command, HEX); Serial.print(", ");
Serial.println(inv_command, HEX);
}
else {
Serial.println("Received invalid NEC code!");
}
nec_ok = 0; // Reset decoding process
nec_state = 0; // Reset decoding state
attachInterrupt(digitalPinToInterrupt(2), remote_read, CHANGE); // Re-enable external interrupt (INT0)
}
}
