pa-pa / AskSinPP

104 stars 72 forks source link

bright status in motion.h #215

Open trilu2000 opened 3 years ago

trilu2000 commented 3 years ago

I was wondering about far to high brightness values after starting the motion sensor sketch/device. The root cause for it sits in motion.h

  uint8_t status () {
    brightsens.measure();
    uint32_t bright = brightsens.brightness();
    if( bright > maxbright ) {
      maxbright = bright;
    }
    // scale to value between 0 - 255s
    return (uint8_t)(bright * 255UL / maxbright);
  }

The first bright measurement value sets the maxbright value, so that the return value will be 255 and it takes a whole day cycle to get the highest bright value for setting the maxvalue to a resonable size.

A better solution could be - assuming the followin: BH1750 measures the brightness in lux _brightness is a uint16_t TSL2561 measures the brightness in lux _brightness is a uint16_t MAX44009 measures the brightness in lux _brightness is a uint16_t

So we get in any case a 16bit integer, reflecting a lux value. Motion.h transmits an 8bit brightness value, so the challange is to scale down. In the code above it is linear and if the sensor is in an bright environment the sensitivity is reduced.

If we would replace the code with:

  uint8_t status () {
    brightsens.measure();
    uint32_t bright = brightsens.brightness();
    if( bright > 0xffff ) bright = 0xffff;
    return sqrt(bright); 
  }

sqrt will scale down the brightness with an exponent of 2, which looks like Bild1

What do you think?

pa-pa commented 3 years ago

I'm not sure - sqrt() is a big function on a 8bit CPU. It will eat up a lot of flash space. May be we add this a alternative implementation which can be enabled by a define. We could also store the maxvalue into the EEPROM. Then the value can be reused after a restart.

trilu2000 commented 3 years ago

sqrt() takes only 56 byte - but i will do some further checks. There is still a huge deviation if i compare the brightness values of an HM-Sen-MDIR and my solution with sqrt(). I will come back on this...

DarkShortie commented 3 years ago

The big question here is which range we really need to consider and report for the use case of a motion sensor.

We get a lux value which can go up to at least 40k accoridng to the datasheet of the TSL2561. 40k is direct sunshine at a real bright summer day according to what I found. The values inside a living room are 50-200 lux or 200-300 lux with general illumination. For a working desk 500-1000 lux should be targeted. So we are mainly dealing with low values compared to the maximum of the sensor on indoor usage.

In my opinion the brightness of the motion sensor is used to define when a motion should turn on the light. So if it's brighter than my desk in the room I would consider that it's bright enough that no light needs to be turned on, so higher values than 1000 lux could be already reported as 255. Maybe setting this limit a bit higher makes more sense, but I hope you get my point here in general. This will leave more room for the more useful lower values.

The current implementation takes the high possible range into account, but it doesn't make the sensors comparable. Or even if I already have a sensor and added some rules like only turn on the light if brightness > 5 and I have to change the battery or restart it for other reasons this brightness > 5 will not match anymore and I have to fine tune it again.

pa-pa commented 3 years ago

This is only a sample implementation. The important part is that is work with any light sensor out of the box. All absolute values depend from the use hardware. One open task is to store the maximal measured value into the flash. Then the battery change is no longer a problem. A this->device().getUserStorage().setData(0,maxbright) on new max value and a this->device().getUserStorage().getData(0) during initialization should do the trick. No time to do and test this. PRs are welcome.