Controller Calibration of sensors



  • This may well have already been talked about but if it has I couldn't find it so thought I'd ask

    I am aiming to create a multisensor to place in all rooms in my house. As I'm very new to the arduino I thought it would be easier to get one working then just clone it. So I made a sensor with relays, motion, and temp/humidity (DHT11).

    The problem was that the DHT11s had varying accuracy/calibration and e.g. if I put two nodes in the same room they would report wildly different temps. Rather than hard coding the calibration I added a dummy dimmer switch sensor then used the recieved value (a value between 0 and 100%) to adjust the value that the DHT11 was reporting.

    This is the code I made (probably very inefficient but it works)

    int TempOffset = 50; // initial offset is zero when first loaded
    
    //Now divides temp offset by 10 & subtracts 5.  
    //then e.g. 10% received from domoticz gives a temp offset of -4 degrees.  
    //Allows dht offset to be +/- 5 degrees
    float ActualTempOffset = (TempOffset/10)-5;
    
    MyMessage msgTempOffset(CHILD_ID_TEMP_OFFSET, V_PERCENTAGE);
    
    void presentation
    {
     ...other sensors here
    present(CHILD_ID_TEMP_OFFSET, S_DIMMER);
    }
    void receive(const MyMessage &message)
    {
    	... relay stuff here
    	}
        else if (message.type==V_PERCENTAGE)  {
        int TempOffset = atoi(message.data);
        ActualTempOffset = (TempOffset/10)-5;
        Serial.print("New Temp Offset: ");
        Serial.println(ActualTempOffset);
    
        }  
        
    	
    }
    
    
    

    One thing that I would like it to do is to save the calibration state in EEPROM and report it Domoticz on boot to save calibrating each time.

    Can anyone help?


  • Mod

    @Ben-Andrewes you can probably look at how the relay example handles state. It does not report to the controller on startup but to do that you just invoke the send function at the end of setup(). It is also possible to request the last known value from the controller if you prefer that.

    See the API for more details on saveState, loadState, receive and request.

    Note that save/loadState can only store one byte (0-255 in decimal) at a time, so either you need to fit the offset into one byte or you need to split the data when saving.


  • Mod

    Get a more accurate temp humidity sensor like sht31 and you are good to go. Dht sensors are a pain.



  • @gohan said in Controller Calibration of sensors:

    sht31

    Unfortunately as I'm intending to make over 10 of the same sensor cost becomes a consideration - I think the sht31 are about £4 more than the DHTs... My wife only allows me so much pocket money :)

    (I also bought a load of DHT11s before I really had any idea of what I was doing so need to use them up)



  • @mfalkvidd that worked for me (I had tried it but was saving the data to a different part of the eeprom than I thought).

    Cheers


  • Mod

    Great work!

    Today I noticed that Domoticz seems to have some sort of built-in offset support:
    0_1500837575136_upload-3396fb5d-13b6-422e-9fd9-692edd4face6
    I haven't tried it though, and your solution is more versatile since it works regardless of controller.


  • Mod

    @Ben-Andrewes consider a Dallas temperature sensor as it is cheap and more reliable than a dht11. There are also dht22 that is still cheap but better than dht11



  • @mfalkvidd Damn - I hadn't noticed that - would've saved some time! Oh well, I learnt a bit about programming whilst I was doing it... :)

    @gohan I have a dallas sensor so might try that, and they are cheap. I think I got a bit carried away with he idea that the DHT would do humidity as well - not that I really know why I want to know the humidity...!

    If it is of any interest, I'm thinking of adding gesture recognition and reporting to the sensor using an APDS-9960 - I've seen a sketch that uses the APDS-9960, is this a good bit of kit or should I try to use something else?

    I sort of have an idea of a sensor which has a couple of relays on that I can control from Domoticz, and also reports temp/hum, presence via PIR, and gesture controls to Domoticz which will then handle the logic.....


  • Mod

    @Ben-Andrewes the apds-9960 is fun. I did a project a while back (check the videos), but I only used the distance meter, not the gesture recognition.



  • @mfalkvidd That looks very cool, great work.

    Unfortunately, I'm having trouble with the code for the apds9960 and I think that the interrupt isn't working properly - it seems to fire once then the interrupt is stuck low. I've now tried a test sketch from Sparkfun (official example sketch) without any mysensors stuff and added some serial prints to read the state of the interrupt pin every 5 secs and it always returns 0. Any idea why this might be? Do I need to send a message to the sensor to reset the interrupt back to high after it runs the interruptRoutine?

    #include <Wire.h>
    #include <SparkFun_APDS9960.h>
    
    // Pins
    #define APDS9960_INT    3  // Needs to be an interrupt pin
    
    // Constants
    
    // Global Variables
    SparkFun_APDS9960 apds = SparkFun_APDS9960();
    volatile int isr_flag = 0;
    
    unsigned long SLEEP_TIME = 5000; // Sleep time between reads (in milliseconds)
    unsigned long lastRefreshTime = 0; // Use this to implement a non-blocking delay function
    void interruptRoutine();
    void handleGesture();
    
    void setup() {
    
      // Set interrupt pin as input
      pinMode(APDS9960_INT, INPUT);
        Serial.println("Pin state is:");
        Serial.println(digitalRead(APDS9960_INT));
      // Initialize Serial port
      Serial.begin(9600);
      Serial.println();
      Serial.println(F("--------------------------------"));
      Serial.println(F("SparkFun APDS-9960 - GestureTest"));
      Serial.println(F("--------------------------------"));
    
      //define sensitivty
      apds.setGestureGain( 0 );
    
        // Initialize interrupt service routine
      
      attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
    
    
      // Initialize APDS-9960 (configure I2C and initial values)
      if ( apds.init() ) {
        Serial.println(F("APDS-9960 initialization complete"));
      } else {
        Serial.println(F("Something went wrong during APDS-9960 init!"));
      }
      
      // Start running the APDS-9960 gesture sensor engine
      if ( apds.enableGestureSensor(true) ) {
        Serial.println(F("Gesture sensor is now running"));
      } else {
        Serial.println(F("Something went wrong during gesture sensor init!"));
      }
    
    }
    
    void loop() {
    
      boolean needRefresh = (millis() - lastRefreshTime) > SLEEP_TIME;
      if (needRefresh)
      {
        lastRefreshTime = millis();
        Serial.println("I'm Alive");
        Serial.println("Pin state is:");
        Serial.println(digitalRead(APDS9960_INT));
    
      }  
      if( isr_flag == 1 ) {
        Serial.println("Interrupt");
        detachInterrupt(digitalPinToInterrupt(APDS9960_INT));
        handleGesture();
        Serial.print("returned from handling gesture");
        isr_flag = 0;
        Serial.println(isr_flag);
        attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
        Serial.println("attachInterrupt executed");
      }
    }
    
    void interruptRoutine() {
      Serial.println("Interrupt Routine started");
      isr_flag = 1;
    }
    
    void handleGesture() {
      Serial.println("Handling gesture");
        //if ( apds.isGestureAvailable() ) {
          //Serial.println("apds.isGestureAvailable() has returned true");
    /****************
        switch ( apds.readGesture() ) {
          case DIR_UP:
            Serial.println("UP");
            break;
          case DIR_DOWN:
            Serial.println("DOWN");
            break;
          case DIR_LEFT:
            Serial.println("LEFT");
            break;
          case DIR_RIGHT:
            Serial.println("RIGHT");
            break;
          case DIR_NEAR:
            Serial.println("NEAR");
            break;
          case DIR_FAR:
            Serial.println("FAR");
            break;
          default:
            Serial.println("NONE");
        }
        *******************/
      // }
      
    }
    

  • Mod

    @Ben-Andrewes maybe the interrups doesn't get cleared until you read the sensor?

    A side note: Doing Serial prints from an interrupt routine can result in strange results. Remove it to make sure you're not chasing ghosts.


  • Mod

    From the datasheet:

    Gesture Interrupts flags: GINT, GVALID, and GFLVL are cleared by emptying e. all data has been read).



  • Thanks @mfalkvidd - you're right, the interrupt would never be cleared until the code read the gesture. I uncommented the readGesture only to find that the code hanged at that point (think that was why I commented it out before - I'd had a beer or two).

    I think I really need to spend a bit of time learning about the Arduino programming language, and libraries etc as my programming knowledge is based on BASIC 30yrs ago and a bit of VBA at work. At the moment my arduino programming is just hacking stuff together and seeing if it works...

    Anyway I found that it was the library that IDE installed was wrong and I needed to get the library direct from Sparkfun... Now it works fine so I just need to MySensorise it...


Log in to reply
 

Looks like your connection to MySensors Forum was lost, please wait while we try to reconnect.