[Solved] Pysense - Light sensor shows zero after cycling through deep sleep



  • I am running 1.7.6.b1 on LoPy on a Pysense board and I have confirmed that almost all the sensors work normally and continue to work after the Pysense has been through a Deep Sleep cycle.
    However, the light sensor only works when first powered up.
    If the Pysense is put to sleep, when it wakes the board resets, runs the code but the light sensor always shows 0 for all sleep cycles after the first.

    Here is some test code that shows the effect:

    # Test script running on LoPy release 1.7.6.b1 attached to Pysense board
    from machine import Pin
    from pysense import Pysense     #Basic Pysense board settings
    from LTR329ALS01 import LTR329ALS01 #light meter
    import utime
    # escape button
    button=Pin('P14')
    
    # Set up the sensors
    BD   = Pysense()
    lightsensor= LTR329ALS01(pysense=BD)
    
    # Record some light measurements
    if button():  #Pysense button normally high - this is not pressed during the test
    	with open('/flash/mylog.log',mode='a') as f:
    		while 1:
    			# Main loop
    			(Light,dummy)= lightsensor.lux()
    			utime.sleep(1)
    			f.write(' LIGHT SENSOR '+str(Light)+'\r\n')    
    			utime.sleep(1)
    			
    			f.close()
    			BD.setup_sleep(5)# sleep in seconds 
    			BD.go_to_sleep()
    			#utime.sleep(5)
    pass
    

    The resulting Log file shows a line for each cycle:
    LIGHT SENSOR 32
    LIGHT SENSOR 0
    LIGHT SENSOR 0
    LIGHT SENSOR 0
    LIGHT SENSOR 0
    LIGHT SENSOR 0
    LIGHT SENSOR 0

    Any ideas how to reset/remove/recover the light sensor ?



  • @livius

    I am using the official library taken from here https://github.com/pycom/pycom-libraries/blob/master/shields/lib/LTR329ALS01.py which indeed as you noticed does not contain the ALS_STATUS status register reading logic.
    According to the datasheet https://www.mouser.com/datasheet/2/239/Lite-On_LTR-329ALS-01 DS_ver1.1-348647.pdf Page 22 the Device operation flow chard shows indeed kind of a loop until that status register indicate a new data is available. on Page 24 it shows a pseudo code mentioning what you are suggesting (which is checking the data readiness before performing the actual read). Page 21 it describe how to perform the check of the validity of the read.
    I can try to patch the lib according to such information and push a PR to the official repo if this is solving the problem :-).
    Keep You posted and thanks for your help!
    Stef



  • @Stefano-Ordine
    i do not see in the library reading status register
    ALS_STATUS Register (0x8C)
    maybe this is a the problem



  • @livius thanks for the reply, I implemented your idea of delaying 500ms between one read and another by coding this snippet:

    ...
    lt = LTR329ALS01(py)
    [light_blue, light_red] = (0,0)
    
    for index in range(100):
        print('index %d' % (index))
        light = lt.light()
        [light_blue, light_red] = light
        if (light_blue != 0):
            print('after %d reads I got %d' % (index, light_blue))
            break
        print('light_blue %d' % (light_blue))
        time.sleep_ms(500)
    ...
    

    it always succeed on the second reads as you can see from this output:

    
    // First light read after flashing the firmware
    rst:0x7 (TG0WDT_SYS_RESET),boot:0x1a (SPI_FAST_FLASH_BOOT)
    ...
    index 0
    after 0 reads I got 80
    
    ...
    
    // First light read after waking up from deep sleep
    rst:0x5 (DEEPSLEEP_RESET),boot:0x1a (SPI_FAST_FLASH_BOOT)
    ...
    index 0
    light_blue 0
    index 1
    after 1 reads I got 50
    
    // Second light read after waking up from deep sleep
    rst:0x5 (DEEPSLEEP_RESET),boot:0x1a (SPI_FAST_FLASH_BOOT)
    ...
    index 0
    light_blue 0
    index 1
    after 1 reads I got 87
    
    // Third light read after waking up from deep sleep
    rst:0x5 (DEEPSLEEP_RESET),boot:0x1a (SPI_FAST_FLASH_BOOT)
    ...
    index 0
    light_blue 0
    index 1
    after 1 reads I got 71
    

    Is there anything I can do for You to help solving this?



  • @Stefano-Ordine

    to test try this:

    i = 0
    while i<=100:
    	ch1low = lt.i2c.readfrom_mem(lt.ALS_I2CADDR , lt.ALS_DATA_CH1_LOW, 1)
    	ch1high = lt.i2c.readfrom_mem(lt.ALS_I2CADDR , lt.ALS_DATA_CH1_HIGH, 1)
    
    	ch0low = lt.i2c.readfrom_mem(lt.ALS_I2CADDR , lt.ALS_DATA_CH0_LOW, 1)
    	ch0high = lt.i2c.readfrom_mem(lt.ALS_I2CADDR , lt.ALS_DATA_CH0_HIGH, 1)
    
    	print(i, ch1low, ch1high, ch0low, ch0high)
    	time.sleep_ms(500)
    	i+=1
    

    and look if somewhere you got some values



  • @markN I tried to dummy read like you suggested like this:

    ...
    from pysense import Pysense
    from LTR329ALS01 import LTR329ALS01
    ...
    py = Pysense()
    ...
    lt = LTR329ALS01(py)
    dummy = lt.light()
    light = lt.light()
    ...
    pybytes.deepsleep(time_milliseconds)
    

    but still getting 0 values on waking up after deepsleeping...
    is the dummy reads mentioned in your last post to be intented as I shown? any other idea on how to solve this?

    For context I adding these additional details:
    The light function into the lib/LTR329ALS01.py is defined like this:

    class LTR329ALS01:
    ...
        def __init__(self, pysense = None, sda = 'P22', scl = 'P21', gain = ALS_GAIN_1X, integration = ALS_INT_100, rate = ALS_RATE_500):
            if pysense is not None:
                self.i2c = pysense.i2c
            else:
                self.i2c = I2C(0, mode=I2C.MASTER, pins=(sda, scl))
    
            self.gain = gain
            self.integration = integration
    
            contr = self._getContr(gain)
            self.i2c.writeto_mem(ALS_I2CADDR, ALS_CONTR_REG, bytearray([contr]))
    
            measrate = self._getMeasRate(integration, rate)
            self.i2c.writeto_mem(ALS_I2CADDR, ALS_MEAS_RATE_REG, bytearray([measrate]))
    
            time.sleep(0.01)
    
        def _getContr(self, gain):
            return ((gain & 0x07) << 2) + 0x01
    
        def _getMeasRate(self, integration, rate):
            return ((integration & 0x07) << 3) + (rate & 0x07)
    
        def _getWord(self, high, low):
            return ((high & 0xFF) << 8) + (low & 0xFF)
    
        def light(self):
            ch1low = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH1_LOW, 1)
            ch1high = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH1_HIGH, 1)
            data1 = int(self._getWord(ch1high[0], ch1low[0]))
    
            ch0low = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH0_LOW, 1)
            ch0high = self.i2c.readfrom_mem(ALS_I2CADDR , ALS_DATA_CH0_HIGH, 1)
            data0 = int(self._getWord(ch0high[0], ch0low[0]))
    
            return (data0, data1)
    ...
    


  • @markN how did You solve this problem, I am experiencing the same.
    Thanks :-)



  • @markN Please can you share your code? I have the same issue :-(



  • @markN I have now solved this. The light sensor seems to have an internal buffer that is keeping an old value. Placing a dummy read of the light sensor at the beginning of the code flushes out the old value (which is 0 if the Pysense has gone through a deep sleep cycle).



Pycom on Twitter