Why NEC IR remote control decoder does not work

Thread Starter

philipsusers

Joined May 7, 2023
1
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, 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)
  }

}
Schema in Proteus:a0adee3382000794d06951c16499e6de00ec273b.jpeg
 
Top