IR Sensor only reading every other button press



  • Hi,

    I am trying to pass IR data from my TV remote to my controller (Home Assistant) for later processing.

    I am using a TSOP38238 receiver connected to D3 on an arduino pro mini. The pro mini is using two other sensors (lux and temp/humidity) connected via i2c which are pulled every 90 seconds by the arduino. For brevity I'll omit their code, let me know if you need to see it anyway.

    The arduino sleeps and is woken up by an interrupt if the IR-sensor receives data. The weird thing is though: The arduino wakes up on every signal from the TV remote (LG TV) but only receives every other signal.

    Here is the output of the serial monitor:

    20:20:55.561 ->  
    20:20:55.561 ->  __  __       ____
    20:20:55.595 -> |  \/  |_   _/ ___|  ___ _ __  ___  ___  _ __ ___
    20:20:55.595 -> | |\/| | | | \___ \ / _ \ `_ \/ __|/ _ \| `__/ __|
    20:20:55.595 -> | |  | | |_| |___| |  __/ | | \__ \  _  | |  \__ \
    20:20:55.595 -> |_|  |_|\__, |____/ \___|_| |_|___/\___/|_|  |___/
    20:20:55.595 ->         |___/                      2.4.0-alpha
    20:20:55.595 -> 
    20:21:01.036 -> Tempsensor started
    20:21:01.036 -> UPDATE_INTERVAL:90000
    20:21:06.079 -> wake_reason=1
    20:21:06.079 -> IR Processing done--------------------
    20:21:08.369 -> wake_reason=1
    20:21:08.369 -> 20DF4EB
    20:21:08.468 -> IR Processing done--------------------
    20:21:10.525 -> wake_reason=1
    20:21:10.525 -> IR Processing done--------------------
    20:21:11.686 -> wake_reason=1
    20:21:11.686 -> 20DF8E7
    20:21:11.819 -> IR Processing done--------------------
    20:21:13.379 -> wake_reason=1
    20:21:13.379 -> IR Processing done--------------------
    20:21:14.607 -> wake_reason=1
    20:21:14.607 -> 20DFC63
    20:21:14.706 -> IR Processing done--------------------
    20:21:16.033 -> wake_reason=1
    20:21:16.033 -> IR Processing done--------------------
    20:21:16.929 -> wake_reason=1
    20:21:16.929 -> 20DF867
    20:21:17.029 -> IR Processing done--------------------
    
    

    I pressed four different buttons on the remote, each one twice.

    Here is the code, please let me know what I am doing wrong:

    /**
     * The MySensors Arduino library handles the wireless radio link and protocol
     * between your home built sensors/actuators and HA controller of choice.
     * The sensors forms a self healing radio network with optional repeaters. Each
     * repeater and gateway builds a routing tables in EEPROM which keeps track of the
     * network topology allowing messages to be routed to nodes.
     *
     * Created by Henrik Ekblad <henrik.ekblad@mysensors.org>
     * Copyright (C) 2013-2015 Sensnology AB
     * Full contributor list: https://github.com/mysensors/Arduino/graphs/contributors
     *
     * Documentation: http://www.mysensors.org
     * Support Forum: http://forum.mysensors.org
     *
     * This program is free software; you can redistribute it and/or
     * modify it under the terms of the GNU General Public License
     * version 2 as published by the Free Software Foundation.
     *
     *******************************
     *
     * REVISION HISTORY
     * Version 1.0: Yveaux
     * 
     * DESCRIPTION
     * This sketch provides an example of how to implement a humidity/temperature
     * sensor using a Si7021 sensor.
     *  
     * For more information, please visit:
     * http://www.mysensors.org/build/humiditySi7021
     * 
     */
    
    // Enable debug prints
    //#define MY_DEBUG
    
    #define MY_OWN_DEBUG
    
    #ifndef MY_OWN_DEBUG //disable serial in production compile, potentially saves few uA in sleep mode
         #define MY_DISABLED_SERIAL
    #endif
    
    
    // Enable and select radio type attached
    #define MY_RADIO_RFM69
    #define MY_IS_RFM69HW
    #define MY_RFM69_NEW_DRIVER
    
    
    #define MY_NODE_ID 3
    #include <MySensors.h>
    
    // IR specific setup  
    #include <IRremote.h>
    int RECV_PIN     = 3;
    IRrecv            irrecv(RECV_PIN);
    decode_results    ircode;
    const char * TYPE2STRING[] = {
        "UNKONWN",
        "RC5",
        "RC6",
        "NEC",
        "Sony",
        "Panasonic",
        "JVC",
        "SAMSUNG",
        "Whynter",
        "AIWA RC T501",
        "LG",
        "Sanyo",
        "Mitsubishi",
        "Dish",
        "Sharp",
        "Denon"
    };
    #define Type2String(x)   TYPE2STRING[x < 0 ? 0 : x]
    #define AddrTxt          F(" addres: 0x")
    #define ValueTxt         F(" value: 0x")
    #define NATxt            F(" - not implemented/found")
    unsigned long last_value;
    // IR specific setup end
    
    #define CHILD_ID_HUM  0
    #define CHILD_ID_TEMP 1
    #define CHILD_ID_LUX  2
    #define CHILD_ID_IR 3
    
    #define SKETCH_NAME "mysensors_wohnzimmer_main"
    #define SKETCH_MAJOR_VER "1"
    #define SKETCH_MINOR_VER "0"
    
    static bool metric = true;
    
    int BATTERY_SENSE_PIN = A0;  // select the input pin for the battery sense point
    int oldBatteryPcnt = 0;
    
    float lastHum = 0;
    float lastTemp = 0;
    int lastLux = 0;
    
    
    // Sleep time between sensor updates (in milliseconds)
    static const unsigned long UPDATE_INTERVAL = 90000;
    
    #include <SI7021.h>
    #include <BH1750.h>
    
    static SI7021 tempsensor;
    BH1750 lightmeter;
    
    
    // Change to V_LIGHT if you use S_LIGHT in presentation below
    MyMessage msgHum(CHILD_ID_HUM, V_HUM);
    MyMessage msgTemp(CHILD_ID_TEMP, V_TEMP);
    MyMessage msgLux(CHILD_ID_LUX, V_LEVEL);
    MyMessage msgIrRecord(CHILD_ID_IR, V_IR_RECEIVE); 
    
    
    
    void presentation()  
    { 
     // Send the sketch version information to the gateway and Controller
      sendSketchInfo(SKETCH_NAME, SKETCH_MAJOR_VER "." SKETCH_MINOR_VER);
    
      present(CHILD_ID_HUM, S_HUM);
       present(CHILD_ID_TEMP, S_TEMP);
      present(CHILD_ID_LUX, S_LIGHT_LEVEL);
      present(CHILD_ID_IR, S_IR);
    }
    
    void setup()
    {
      //Serial.begin(9600);
      //Serial.print("Starting: ");
      while (not tempsensor.begin())
      {
        Serial.println(F("Temperaturesensor not detected!"));
        delay(5000);
      }
        #ifdef MY_OWN_DEBUG
        Serial.println("Tempsensor started");
      #endif
      lightmeter.begin();
      #ifdef MY_OWN_DEBUG
        Serial.print("UPDATE_INTERVAL:");Serial.println(UPDATE_INTERVAL);
      #endif
      irrecv.enableIRIn();
    }
    
    
    void loop(){
      int8_t wake_reason;
      sleep_bod_disable();//disable BOD  - saves~ 15uA
      wake_reason = smartSleep(RECV_PIN-2, CHANGE, UPDATE_INTERVAL);
      #ifdef MY_OWN_DEBUG
      Serial.print("wake_reason=");Serial.println(wake_reason);
      #endif
      if (wake_reason == 1){
        //woken up by interrupt on d3
        ir_received();
      }
      else{
        //woken by update_interval
        update_interval();
      }
    
    
    }
    
    void ir_received(){
        if (irrecv.decode(&ircode)) {
    
          unsigned long ir_value = ircode.value;
          if (ir_value == REPEAT) //if repeat-code: send last code
          {
             ir_value = last_value;
          }
          else{ //if not: save new value as last value
            last_value = ir_value;
          }
          Serial.println(ir_value,HEX);
          delay(100);
          send(msgIrRecord.set(ir_value));
          irrecv.resume(); // Receive the next value
        }
        Serial.println("IR Processing done--------------------");
    }
    
    void update_interval()      
    {  
      //removed for brevity
    }
    
    
    


  • @kiesel Did you learn the codes yourself?

    Some remotes (panasonic for example) will send a different code each time the button is pressed. They do this by having 2 codes for each button.

    First time you press a button it sends code from the 'A' set and the next press of the button sends the 'B' set.

    So it may be the same for the remote you have. If so you need to learn both sets of IR code and then implement a check in your sketch (a simple if comparison should be enough).....

    I have also found that replacing irrecv.resume(); with irrecv.enableIRIn(); might help. Also to stop the reveive function when you have got a code, send a dummy ir message and then re-enable the ir reveiver as I just suggested.



  • @skywatch

    I used the sketch "IRrecvDump" from the IRremote library to verify that only one code is sent per button press, so I don't think that's the problem.

    With that sketch the same code is written to the serial monitor every time I press the same button.

    The issue is that code uses polling and I want the arduino to sleep because it is a battery powered node.

    /edit: irrecv.enableIRIn(); didn't make a difference unfortunately.



  • I think this is solved: It appears that the interrupt wakes the arduino who then queries the sensor before the full code is received. I added a

    delay(100); 
    

    to give it a bit more time to read the data.

    void ir_received(){
      delay(100);
        if (irrecv.decode(&ircode)) {
          //#ifdef MY_OWN_DEBUG
          //dump(&ircode);
          //#endif
          unsigned long ir_value = ircode.value;
          if (ir_value == REPEAT) //if repeat-code: send last code
          {
             ir_value = last_value;
          }
          else{ //if not: save new value as last value
            last_value = ir_value;
          }
          Serial.println(ir_value,HEX);
          
          send(msgIrRecord.set(ir_value));
          
        }
        //delay(100);
        irrecv.resume(); // Receive the next value
    
        Serial.println("IR Processing done--------------------");
    }
    

    If anybody has a better idea please let me know.



  • @kiesel Good work on finding the issue. Delay will block the cpu from performing other tasks (maybe that is what you want). Usually in mysensors we use wait(100); instead.

    I have just finished my first IR send and receive node and have another 2 to build this weekend (hopefully).....



  • @skywatch

    I didn't know that delay blocked, good to know, thanks. I have nothing that's supposed to run in the background so delay works for the time being 🙂

    Congrats on the node! Is the code available somewhere? I'd like to take a look. Always good to learn new stuff.



  • @kiesel You are welcome! - We are all here to learn! 🙂

    As to my code, here is the thread with the problems I had and how I fixed them....

    https://forum.mysensors.org/topic/10936/vs838-ir-receiver-led-anyone-got-it-working-with-mys?_=1582743282787

    I am still tinkering around the edges and I expect a final version to be about a week away. It is mostly getting it all the way I want it now! 😉


Log in to reply
 

Suggested Topics

  • 6
  • 5
  • 55
  • 6
  • 9
  • 21
  • 5
  • 8

2
Online

9.5k
Users

10.1k
Topics

105.0k
Posts