How to read out the output of 'ezPyro SMD I2C Pyroelectric Infrared Sensor' via I2C command?



  • Hi There,

    I'm a newbie in the micro-controller world. I have started with Pycom Expansion board and LoPY4.
    I have been reading the docs from the Pycom website and trying to understand how to 'Talk' to a connected sensor.
    I have a little bit of experience with micro-controller & sensor stuffs but it was on PIC18 and the language was C. Python is something new for me, still I'm trying to learn how to program and make it work on Pycom.
    So far what I have understood about I2C communication is, I'll have to create the I2C object and initialize it with Pins and Type i.e. Master. Then I will have to set the sensor's I2C address from where the output of the sensor would be read. And then I can assign this value to a variable and get it printed. Below is the code I got from the Pycom website and I rearranged it as below:

    from machine import I2C
    i2c = I2C(0, I2C.MASTER, baudrate=100000)
    value=i2c.readfrom(address of the sensor's I2C,)
    print ("value")
    

    Is it that simple or I'm just totally wrong?
    The sensor I'm using is a gas sensor. The sensor's output is current. I need to measure that current value to convert it into another measurement. The datasheet exceeds the maximum upload limit. Hence, I have inserted the images of the I2C section below for the reference.
    I2C.PNG
    I2C_2.PNG
    I2C_3.PNG
    I2C_4.PNG
    So please guide and enlighten me how can I get it done. Your help is much appreciated.

    Regards



  • @Oridroo said in How to read out the output of 'ezPyro SMD I2C Pyroelectric Infrared Sensor' via I2C command?:

    Would you please explain a bit how you did this calculation, like why you divided it by 4 and then right shifted?

    No, not and but OR, shift a binary number to left is equal to multiply this number by 2, shift a binary number to rigth is equal to divide this number by 2. This work for all power of 2 value.

    My question is, why we are shifting the bits to get the decimal value?

    Your sensor compute a value between 0 and (2^24-1), then we need to transfer this value by i2c bus, but i2c bus can only transport bytes by bytes. So manufacturer say in datasheet the sensors send the on i2c 3 bytes, the first byte is [23..16] bits of this number, the next is [15..8] bits of this value and the last is [7..0] of this value. So we have a byte array[3] of 8 bit after reading on i2c. To compute this in decimal we have to shift the first byte of array by 16 bits (or multiply by 65536 it's same result), the second byte as to be shifted by 8 bits (or multiply by 256 it's same result) and the last byte is added to the value.

    For the time being, my current working code is as below. I was getting continuous "OSError: I2C bus error" until I added one delay in between print("Analogue:", analog) & ana_sett = i2c.writeto_mem(0x65, 0x14, analog)
    The code was executing till printing 'Analogue' and then showing that I2C error. Please suggest me if you have any recommendation for the programme.

    No idea why you have this, but for me it's mean that the sensors doesn't be ready to anwser to the command.
    You can use smaller delay if you use time.sleep(0.1) you have 100 ms delay



  • @Eric73 , Once again, Thanks a lot for the explanation.

    My Wipy's firmware is:

    Firmware: (sysname='WiPy', nodename='WiPy', release='1.20.0.rc13', version='v1.9.4-94bb382 on 2019-08-22', machine='WiPy with ESP32')

    Would you please explain a bit how you did this calculation, like why you divided it by 4 and then right shifted?

    "0x29/4 == 0xA the fifo clear command (x/4 == x>>2) , 0x29 & 0x3==1 so answer is command ok"

    Actually I tried to read a bit about bit shifting but couldn't fully understand how it is happening to convert the binary to decimal (in the code below).

    What I understood is, Left bit shifting is like multiplying by 2 and right bit shifting is division by 2. As we shifted to left by 16 and 8 bits respectively, those two bytes got multiplied by 2^16 (65536) & 2^8 (256) respectively. And we didn't shift the last bit, hence 2^0 = 1.

    My question is, why we are shifting the bits to get the decimal value?

    Ch1_value=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]
    

    For the time being, my current working code is as below. I was getting continuous "OSError: I2C bus error" until I added one delay in between print("Analogue:", analog) & ana_sett = i2c.writeto_mem(0x65, 0x14, analog)
    The code was executing till printing 'Analogue' and then showing that I2C error. Please suggest me if you have any recommendation for the programme.
    Regards

    from machine import I2C, Timer
    import time
    import ubinascii
    import os
    print("Firmware:",os.uname())
    
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    wake_up = i2c.readfrom_mem(0x65, 0x22, 1)
    print("Wake_UP:", wake_up)
    time.sleep(1)
    
    FIFO_status = i2c.readfrom_mem(0x65, 0x04, 1)
    print("FIFO_Status:", FIFO_status)
    time.sleep(1)
    
    buf = bytes([0x00, 0x07, 0x07, 0x07, 0x07])
    print("Buffer:", buf)
    
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, buf)
    print("Channel Control:", chnl_ctr)
    time.sleep(1)
    
    analog = bytes([0x00, 0x09])
    print("Analogue:", analog)
    time.sleep(1)
    ana_sett = i2c.writeto_mem(0x65, 0x14, analog)
    print("Analog Settings:", ana_sett)
    time.sleep(1)
    ana_read = i2c.readfrom_mem(0x65, 0x12, 4)
    print("Analog Read:", ana_read)
    time.sleep(1)
    
    
    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    print("fifo_read_active:", fifo_read_active)
    hex = ubinascii.hexlify(fifo_read_active)
    print("FIFO_Read_Active_Chnl:",hex)
    time.sleep(1)
    
    # fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    # print("FIFO_Read_All_Chnl:", fifo_read_full)
    
    # frame_count_MSB = fifo_read_active[15]
    # frame_count_LSB = fifo_read_active[16]
    
    #print("Frame Count MSB:", frame_count_MSB)
    #print("Frame Count LSB:", frame_count_LSB)
    
    #print("Individual Channel Bytes: 3, 4, 5, 6, 7, 8 :--- ",fifo_read_active[3],fifo_read_active[4],fifo_read_active[5],fifo_read_active[6],fifo_read_active[7],fifo_read_active[8] )
    
    #print("Individual Channel Bytes: 9,10,11,12,13,14,15,16 :--- ",fifo_read_active[9],fifo_read_active[10],fifo_read_active[11],fifo_read_active[12],fifo_read_active[13],fifo_read_active[14],fifo_read_active[15],fifo_read_active[16] )
    
    USB = fifo_read_active[3]
    MSB = fifo_read_active[4]
    LSB = fifo_read_active[5]
    Ch1_value=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]
    Ch1_value=Ch1_value/1000
    print("Channel_1:", Ch1_value)
    
    # Ch1_value_BS=((USB<<16) + (MSB<<8) + LSB)         #Using bit shifting to convert binary to decimal
    # print("Channel_1_BS:", Ch1_value_BS)
    
    Ch2_value=fifo_read_active[6]*65536+fifo_read_active[7]*256+fifo_read_active[8]
    Ch2_value=Ch2_value/1000
    print("Channel_2:", Ch2_value)
    
    Ch3_value=fifo_read_active[9]*65536+fifo_read_active[10]*256+fifo_read_active[11]
    Ch3_value=Ch3_value/1000
    print("Channel_3:", Ch3_value)
    
    Ch4_value=fifo_read_active[12]*65536+fifo_read_active[13]*256+fifo_read_active[14]
    Ch4_value=Ch4_value/1000
    print("Channel_4:", Ch4_value)
    
    FIFO_clear = i2c.readfrom_mem(0x65, 0x0A, 1)
    print("FIFO_Clear:", FIFO_clear)
    time.sleep(1)
    
    FIFO_reset = i2c.readfrom_mem(0x65, 0x0C, 1)
    print("FIFO_Reset:", FIFO_reset)
    time.sleep(1)
    
    FIFO_status = i2c.readfrom_mem(0x65, 0x04, 1)
    print("FIFO_Status:", FIFO_status)
    time.sleep(1)
    
    

    Output:

    >>> 
    >>> 
    Firmware: (sysname='WiPy', nodename='WiPy', release='1.20.0.rc13', version='v1.9.4-94bb382 on 2019-08-22', machine='WiPy with ESP32')
    I2C Address [101]
    Wake_UP: b'\x89'
    FIFO_Status: b'='
    Buffer: b'\x00\x07\x07\x07\x07'
    Channel Control: 5
    Analogue: b'\x00\t'
    Analog Settings: 2
    Analog Read: b'\x00\t\t\t'
    fifo_read_active: b'\x00\x1e2\x00!\xad\x00 \x83\x00#\x113\xd23\xd23'
    FIFO_Read_Active_Chnl: b'001e320021ad00208300231133d233d233'
    Channel_1: 8.621
    Channel_2: 8.323
    Channel_3: 8.977
    Channel_4: 3396.147
    FIFO_Clear: b')'
    FIFO_Reset: b'1'
    FIFO_Status: b'='
    >
    Pycom MicroPython 1.20.0.rc13 [v1.9.4-94bb382] on 2019-08-22; WiPy with ESP32
    Type "help()" for more information.
    


  • @Oridroo said in How to read out the output of 'ezPyro SMD I2C Pyroelectric Infrared Sensor' via I2C command?:

    b')' and b'='

    Look at hex value of this character, 0x29 and 0x3D

    0x29/4 == 0xA the fifo clear command (x/4 == x>>2) , 0x29 & 0x3==1 so answer is command ok as explain in DS 13.3, if 0x29 &0x3==2 it's mean command failed.(& sign is AND boolean bit operator)

    0x3D is answer to fifo status (as DS 13.3.3 ) in binary 00111101
    WakeDetect :0
    Error0 and 1 : 01 (read when fifo empty or write when fifo full)
    FifoCount : 1110 so 14 data packet is present in memory

    You can do a fifo_reset to clear all fifo value, and then read fresh value after waiting some time.

    About the value read i have no idea what the sensor value mean or if it's a normal or anormal result, sorry i have no technical knowledge about this. The sensor manufacturer is better to answer about this.

    It seem (but i am not sure) that channel 4 and frame count is WRONG VALUE, Error0 and Error1 seem show that the host (your pycom device are you using the latest firmware ? ) have aborted the read (not read the 17 byte as requested).

    I SUGGEST : Add pull-up on i2c line AND/OR try low baudrate for testing this

    i2c = I2C(0, I2C.MASTER,pins=('P10','P9'),baudrate=20000)
    


  • Hi @Eric73 , Thanks a lot for your guidelines. I am getting some outputs now, although not so sure how accurate they are. Below is the code I'm using now. I tried to use FIFO_Clear and FIFO_Status commands but none of them worked. I sent the command same as Wake-Up command but getting b')' and b'=' as output!

    I tried to Frame Count (MSB & LSB) command as well and getting some outputs although not so sure what do they indicate?

    Another thing is, out of 4 active channels, the output of Channel_2 and Channel_3 is more or less same for every execution (~8000-9000). On the other hand, Channel_1's output varies in the range of 5000~12000 in normal condition (sensor kept in open air inside the room). But if I blow my breath around it, the value becomes way higher. And Channel_4's output is something always high in most of the cases. Please see the image below. So, I'm wondering how accurate are they. As I'm getting change in channel_1, so I'm thinking of taking it as standard/reference to calculate the change in gas ppm. Please share your valuable opinion.

    Channel.PNG

    from machine import I2C, Timer
    import time
    import ubinascii
    
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    wake_up = i2c.readfrom_mem(0x65, 0x22, 1)
    print("Wake_UP:", wake_up)
    time.sleep(1)
    
    FIFO_status = i2c.readfrom_mem(0x65, 0x04, 1)
    print("FIFO_Status:", FIFO_status)
    time.sleep(1)
    
    buf = bytes([0x00, 0x07, 0x07, 0x07, 0x07])
    print("Buffer:", buf)
    
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, buf)
    print("Channel Control:", chnl_ctr)
    time.sleep(1)
    
    analog = bytes([0x00, 0x09])
    print("Analogue:", analog)
    ana_sett = i2c.writeto_mem(0x65, 0x14, analog)
    print("Analog Settings:", ana_sett)
    time.sleep(2)
    ana_read = i2c.readfrom_mem(0x65, 0x12, 4)
    print("Analog Read:", ana_read)
    time.sleep(2)
    
    
    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    print("fifo_read_active:", fifo_read_active)
    hex = ubinascii.hexlify(fifo_read_active)
    print("FIFO_Read_Active_Chnl:",hex)
    time.sleep(1)
    fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    print("FIFO_Read_All_Chnl:", fifo_read_full)
    
    frame_count_MSB = fifo_read_active[15]
    frame_count_LSB = fifo_read_active[16]
    
    print("Frame Count MSB:", frame_count_MSB)
    print("Frame Count LSB:", frame_count_LSB)
    
    print("Individual Channel Bytes: 3, 4, 5, 6, 7, 8 :--- ",fifo_read_active[3],fifo_read_active[4],fifo_read_active[5],fifo_read_active[6],fifo_read_active[7],fifo_read_active[8] )
    
    print("Individual Channel Bytes: 9,10,11,12,13,14,15,16 :--- ",fifo_read_active[9],fifo_read_active[10],fifo_read_active[11],fifo_read_active[12],fifo_read_active[13],fifo_read_active[14],fifo_read_active[15],fifo_read_active[16] )
    
    USB = fifo_read_active[3]
    MSB = fifo_read_active[4]
    LSB = fifo_read_active[5]
    Ch1_value=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]
    print("Channel_1:", Ch1_value)
    
    Ch1_value_BS=((USB<<16) + (MSB<<8) + LSB)
    print("Channel_1_BS:", Ch1_value_BS)
    
    Ch2_value=fifo_read_active[6]*65536+fifo_read_active[7]*256+fifo_read_active[8]
    print("Channel_2:", Ch2_value)
    
    Ch3_value=fifo_read_active[9]*65536+fifo_read_active[10]*256+fifo_read_active[11]
    print("Channel_3:", Ch3_value)
    
    Ch4_value=fifo_read_active[12]*65536+fifo_read_active[13]*256+fifo_read_active[14]
    print("Channel_4:", Ch4_value)
    
    FIFO_clear = i2c.readfrom_mem(0x65, 0x0A, 1)
    print("FIFO_Clear:", FIFO_clear)
    time.sleep(1)
    
    FIFO_status = i2c.readfrom_mem(0x65, 0x04, 1)
    print("FIFO_Status:", FIFO_status)
    time.sleep(1)
    
    

    Output

    I2C Address [101]
    Wake_UP: b'\x89'
    FIFO_Status: b'='
    Buffer: b'\x00\x07\x07\x07\x07'
    Channel Control: 5
    Analogue: b'\x00\t'
    Analog Settings: 2
    Analog Read: b'\x00\t\t\t'
    fifo_read_active: b'\x00\x1d\xbf\x000z\x00 5\x00"\xdd\xe9\x83\xe9\x83\xe9'
    FIFO_Read_Active_Chnl: b'001dbf00307a0020350022dde983e983e9'
    FIFO_Read_All_Chnl: b'\x00\x1d\xbf\x000z\x00 5\x00"\xdd\xe9\x83\xe9\x83\xe9'
    Frame Count MSB: 131
    Frame Count LSB: 233
    Individual Channel Bytes: 3, 4, 5, 6, 7, 8 :---  0 48 122 0 32 53
    Individual Channel Bytes: 9,10,11,12,13,14,15,16 :---  0 34 221 233 131 233 131 233
    Channel_1: 12410
    Channel_1_BS: 12410
    Channel_2: 8245
    Channel_3: 8925
    Channel_4: 15303657
    FIFO_Clear: b')'
    FIFO_Status: b'='
    
    Regards


  • @Oridroo

    Here, [3], [4], [5] which array they are indicating?

    Well, it's from your code

    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    

    i2c.readfrom return a bytes array that contain the bytes read on i2c bus. So index [0,1,2] is for channel 0 and index [3,4,5] is for channel 1 as explain in DS 13.3.10 (and so on)

    And can you please show me how would I convert thw FIFO output byte into Decimal in micropython? I found few examples for python but didn't workout.

    That's exactly what this line do

    ValCh1=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]
    

    So you have to compute ValCh2 with 6,7,8 and so on for all channel



  • @Eric73 here is the rest of the code:

    
    /*********************************************************************************
     * Channel Control Packet (CCP) Modification 
     *********************************************************************************/
        if (keyboard_buffer == "PX1") {                   // Single Pixel Sensor
          ezPyro_Pixel = 1;
          Read_CCP();                                     // Read the CCP
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("Single Pixel Sensor Set"));
          Read_CCP();                                     // Read the CCP
        }
    
        if (keyboard_buffer == "PX4") {                   // 2x2 Pixel Sensor
          ezPyro_Pixel = 4;
          Read_CCP();                                     // Read the CCP
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("2x2 Pixel Sensor Set"));
          Read_CCP();                                     // Read the CCP
        }
    
        if (keyboard_buffer == "HPF1") {                  // HPF Freq= 1Hz
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xCF;         // &1100 1111 clr HPF 
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_HP_FILTER_1 ;
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("High Pass Frequency Filter set to 1Hz"));
          Read_CCP();                                     // Read the CCP
        }
        
        if (keyboard_buffer == "HPF2") {                  // HPF Freq= 2Hz
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xCF;         // &1100 1111 clr HPF Freq
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_HP_FILTER_2 ;
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("High Pass Frequency Filter set to 2Hz"));
          Read_CCP();                                     // Read the CCP
        }
    
        if (keyboard_buffer == "HPF4") {                  // HPF Freq= 4Hz
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xCF;         // &1100 1111 clr HPF Freq
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_HP_FILTER_4 ;
          set_CCP();
          Write_CCP();                                    // Write CCP  
          Serial.println(F("High Pass Frequency Filter set to 4Hz"));
          Read_CCP();                                     // Read the CCP
        }
    
        if (keyboard_buffer == "HPF8") {                  // HPF Freq= 8Hz
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xCF;         // &1100 1111 clr HPF Freq
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_HP_FILTER_8 ;
          set_CCP();         
          Write_CCP();                                    // Write CCP
          Serial.println(F("High Pass Frequency Filter set to 8Hz"));
          Read_CCP();                                     // Read the CCP
        }
     
        if (keyboard_buffer == "T120") {                  // Transconductance = 1.2T
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0x3F;         // &0011 1111 clr Transcnd
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_TRANS_120T ;
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("Transconductance set to 1.2T"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If T120
    
        if (keyboard_buffer == "T060") {                  // Transconductance = 0.6T
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0x3F;         // &0011 1111 clr Transcnd
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_TRANS_060T ;
          set_CCP();         
          Write_CCP();                                    // Write CCP
          Serial.println(F("Transconductance set to 0.6T"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If T060
    
        if (keyboard_buffer == "T030") {                  // Transconductance = 0.3T
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0x3F;         // &0011 1111 clr Transcnd
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_TRANS_030T ;
          set_CCP();         
          Write_CCP();                                    // Write CCP
          Serial.println(F("Transconductance set to 0.3T"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If T030
    
        if (keyboard_buffer == "T015") {                  // Transconductance = 0.15T
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0x3F;         // &0011 1111 clr Transcnd
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_TRANS_015T ;
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("Transconductance set to 0.15T"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If T015
        
        if (keyboard_buffer == "X1"){                     // Amplification = 1x
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;         // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_01x ;
          set_CCP();
          Write_CCP();                                    // Write CCP  
          Serial.println(F("Amplification set to 1x"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If X1
        
        if (keyboard_buffer == "X2"){                     // Amplification = 2x
          Read_CCP();                                    // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;        // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_02x ;
          set_CCP();
          Write_CCP();                                   // Write CCP
          Serial.println(F("Amplification set to 2x"));
          Read_CCP();                                    // Read the CCP
        }                                                // End If X2
        
        if (keyboard_buffer == "X4"){                    // Amplification = 4x
          Read_CCP();                                    // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;        // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_04x ;
          set_CCP();
          Write_CCP();                                   // Write CCP
          Serial.println(F("Amplification set to 4x"));
          Read_CCP();                                    // Read the CCP
        }                                                // End If X4
    
        if (keyboard_buffer == "X8"){                    // Amplification = 8x
          Read_CCP();                                    // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;        // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_08x ;
          set_CCP();
          Write_CCP();                                   // Write CCP
          Serial.println(F("Amplification set to 8x"));
          Read_CCP();                                    // Read the CCP
        }                                                // End If X8
    
        if (keyboard_buffer == "X16"){                    // Amplification = 16x
          Read_CCP();                                    // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;        // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_16x ;
          set_CCP();
          Write_CCP();                                   // Write CCP
          Serial.println(F("Amplification set to 16x"));
          Read_CCP();                                    // Read the CCP
        }                                                // End If X16
    
        if (keyboard_buffer == "X32"){                    // Amplification = 32x
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;         // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_32x ; 
          set_CCP();
          Write_CCP();                                    // Write CCP
          Serial.println(F("Amplification set to 32x"));
          Read_CCP();                                     // Read the CCP
        }                                                 // End If X32
    
        if (keyboard_buffer == "X64"){                    // Amplification = 64x
          Read_CCP();                                     // Read the CCP
          ezPyro_FIFO[2] = ezPyro_FIFO[2] & 0xF1;        // &1111 0001 clr Amp
          ezPyro_FIFO[2] = ezPyro_FIFO[2] | ezPyro_CCP_AMP_64x;
          set_CCP();
          Write_CCP();                                   // Write CCP
          Serial.println(F("Amplification set to 64x"));
          Read_CCP();                                    // Read the CCP
        }                                                // End If X64
      }
      keyboard_buffer ="";
    } // End Serial Port Read
    
    /*********************************************************************************
     * Start_ASIC function
     * Setup & Start the ASIC
    **********************************************************************************/
    void Start_ASIC(void) {
      Wire.begin();                                                 // Start up the Soft i2c bus
      Wire.beginTransmission(ezPyro_i2c);                           // Check the device is on the i2C bus at 0x65
      error = Wire.endTransmission();
      Serial.println();
      Serial.print(F("Tx simple toggle : "));
      check_error();
    
      if (!readI2C(ezPyro_i2c, ezPyro_VERSION, 1)) {                // Read the chip Version 
        Serial.println(F("Read Version Error"));
        while (1);
      }
      Serial.print(F("ASIC Version = , "));
      Serial.println(ezPyro_FIFO[0]);
    
      // ***** Write the Analog Front End Packet 
      // Byte 0 is the Sampling Rate. Sample Rate = 1000 / (N + 1)
      // N =   0, Rate = 1000.00
      // N =   1, Rate =  500.00
      // :
      // N = 255, Rate =    3.92
      //
      // Note that when you use this, the number of readings (N+1) get added together
      // so the full 23 bits of the data packet get used ... 
      ezPyro_Clock_Divider = 10;
      ezPyro_FIFO[0] = (ezPyro_Clock_Divider - 1);
      // Set AFE Byte 1
      ezPyro_FIFO[1] = ezPyro_INT_ENABLE;                           // En Interrupts
      ezPyro_FIFO[1] |= ezPyro_TEMP_ENABLE;                         // En Temp Monitor
      ezPyro_FIFO[1] |= ezPyro_LO_PASS_FREQ_022_5;                  // LPF
      ezPyro_FIFO[1] |= ezPyro_HI_PASS_FILTER_ON;                   // HPF on
      //ezPyro_FIFO[1] |= ezPyro_LOW_POWER_MODE;                    // Low Power Mode
      
      Write_AFE();                                                  // Write AFE
      Read_AFE();                                                   // Read AFE
      
      // ***** Write the Channel Control Packet
      // Set up CCP
      // Activate Channel 2
      ezPyro_FIFO[2] |= ezPyro_CCP_ACTIVE ;
      ezPyro_FIFO[2] |= ezPyro_CCP_TRANS_015T;                      // Transcond 0.15T
      ezPyro_FIFO[2] |= ezPyro_CCP_HP_FILTER_8;                     // Set HPF to 8 Hz
    
      if(ezPyro_Pixel == 1){
        ezPyro_FIFO[2] |= ezPyro_CCP_AMP_01x ;                      // Fb Cap 3200= 1x Amp
        ezPyro_FIFO[0] = ezPyro_FIFO[2];                            // Ch0 is temp- Activate ch
      } else{
        ezPyro_FIFO[2] |= ezPyro_CCP_AMP_16x ;  
        ezPyro_FIFO[0] = ezPyro_FIFO[2];                            // Ch0 is temp- Activate ch
        ezPyro_FIFO[1] = ezPyro_FIFO[2];                            // Channel 1 Activated 
        ezPyro_FIFO[3] = ezPyro_FIFO[2];                            // Channel 3 Activated
        ezPyro_FIFO[4] = ezPyro_FIFO[2];                            // Channel 4 Activated
      }
      
      set_CCP();
      Write_CCP();                                                  // Write CCP
      Read_CCP();                                                   // Read CCP
    
      ezPyro_FIFO[0] = 0x65 << 1;                                   // Shift 7 LSB to 7 MSB
      if (!writeI2C(ezPyro_i2c, ezPyro_ADDR_WRITE, 1)) {            // Change the Address 
        Serial.println(F("Write Set Addr Error"));
        while (1);
      }
      
      Serial.print(F("Addr Written = 0x"));
      ezPyro_i2c = ezPyro_FIFO[0] >> 1;                             // Shift 7 MSB to 7 LSB
      Serial.println(ezPyro_i2c, HEX);
    
      if (!writeI2C(ezPyro_i2c, ezPyro_FIFO_RESET, 0)) {            // Reset the full FIFO
        Serial.println(F("Reset FIFO Error"));
        while (1);
      }
      Serial.println();
    }
    
    /*********************************************************************************
     * readI2C function
     * Standard READ routine
     *********************************************************************************/
    boolean readI2C(byte addr, byte command, byte data_count) {
    
      Wire.beginTransmission(addr);
      Wire.write(command);
      if (Wire.endTransmission(false) != 0) return false;
      Wire.requestFrom(ezPyro_i2c, data_count);
      for (i = 0 ; i < data_count ; i++){
        ezPyro_FIFO[i] = Wire.read();
      }
      return true;
    } // End of Read I2C
    
    /*********************************************************************************
     * function
     * Standard WRITE routine
     *********************************************************************************/
    boolean writeI2C(byte addr, byte command, byte data_count) {
      Wire.beginTransmission(addr);
      Wire.write(command);
      for (i = 0 ; i < data_count ; i++){
        Wire.write(ezPyro_FIFO[i]);
      }
      return true;
    } // End of Write I2C
    
    /*********************************************************************************
     * function
     * Put the AFE to screen
     *********************************************************************************/
    void display_AFE(){
      Serial.print(F("AFE ="));  
      for (i = 0 ; i < 2 ; i++){
        Serial.print(F(" , "));  
        Serial.print(ezPyro_FIFO[i]);
      }
      Serial.println();
    } // End of Display AFE
    
    /*********************************************************************************
     * function
     * Put the CCP to screen
     *********************************************************************************/
    void display_CCP(){
      Serial.print(F("CCP ="));  
      for (i = 0 ; i < 5 ; i++){
        Serial.print(F(" , "));  
        Serial.print(ezPyro_FIFO[i]);
      }
      Serial.println();
    } // End of Display CCP
    
    /*********************************************************************************
     * set_CCP function
     * Set the CCP depending on single or 2x2 sensor
     * Activate Channel 1 , 2, 3 , 4 (4-pixel device)
     *********************************************************************************/
    void set_CCP(){
      ezPyro_FIFO[0] = ezPyro_FIFO[2] ;
      ezPyro_FIFO[1] = ezPyro_FIFO[2] ;
      ezPyro_FIFO[3] = ezPyro_FIFO[2] ;
      ezPyro_FIFO[4] = ezPyro_FIFO[2] ;
    
      if(ezPyro_Pixel != 4){  
        ezPyro_FIFO[1] = ezPyro_CCP_DISABLE ;
        ezPyro_FIFO[3] = ezPyro_CCP_DISABLE ;
        ezPyro_FIFO[4] = ezPyro_CCP_DISABLE ;
      }
    } // End of Set CCP
    
    /*********************************************************************************
     * check_error function
     * Error Codes from I2C bus communication
     * byte, which indicates the status of the transmission:
     * 0: success
     * 1: data too long to fit in transmit buffer
     * 2: received NACK on transmit of address
     * 3: received NACK on transmit of data
     * 4: other error
     *********************************************************************************/
    void check_error(){
      Serial.println();
      if (error == ERR_OK) {
        Serial.print(F("Good Tx to addr 0x")); // 'F' puts string in flash 
      } else if (error == ERR_LONG_DATA) {
        Serial.print(F("Data too long to fit in tx buffer at addr 0x"));
      } else if (error == ERR_NAK_ADDR) {
        Serial.print(F("Rxed NACK on tx of addr at addr 0x"));
      } else if (error == ERR_NAK_DATA) {
        Serial.print(F("Rxed NACK on tx of data at addr 0x"));
      } else if (error == ERR_UNKNOWN){
        Serial.print(F("Unknow error1 at addr 0x"));
      } else{
        Serial.print(F("Unknown error2- "));
        Serial.print(error);
        Serial.print(F(" at addr 0x"));
      }
      Serial.println(ezPyro_i2c,HEX);
    } // End of Error Checking
    
    
    /*********************************************************************************
     * Read_AFE function
     * AFE= Analogue Front End
     *********************************************************************************/
    void Read_AFE(void) {
      if (!readI2C(ezPyro_i2c, ezPyro_AFE_READ, ezPyro_AFE_SIZE)) {     // Read AFE
        Serial.println(F("Read AFE Error"));
        while (1);
      }
      display_AFE();
    }
    
    /*********************************************************************************
     * Write_AFE function
     *********************************************************************************/
    void Write_AFE(void){
      if (!writeI2C(ezPyro_i2c, ezPyro_AFE_WRITE, ezPyro_AFE_SIZE)) {   // Write AFE
        Serial.println(F("Write AFE Error"));
        while (1);
      }
    }
    
    /*********************************************************************************
     * Read_CCP function
     * CCP= Channel Control Packet
     *********************************************************************************/
    void Read_CCP(void){
      if (!readI2C(ezPyro_i2c, ezPyro_CCP_READ, ezPyro_CCP_SIZE)) {   // Read the CCP 
        Serial.println(F("Read CCP Error"));
        while (1);
      }
      display_CCP();
    }
    
    /*********************************************************************************
     * Write_CCP function
     *********************************************************************************/
    void Write_CCP(void){
      if (!writeI2C(ezPyro_i2c, ezPyro_CCP_WRITE, ezPyro_CCP_SIZE)) { // Write the CCP
        Serial.println(F("Write CCP Error"));
        while (1);
      }
    }
    /*********************************************************************************
     * Align Number
     * padds spaces, so numbers are decimal point aligned. up to 99,999.
     *********************************************************************************/
    void alignNumber(unsigned int num2align){
    
      if (num2align<10000){
        Serial.print(" ");
        if (num2align<1000){
          Serial.print(" ");
          if (num2align<100){
            Serial.print(" ");
            if (num2align<10){
              Serial.print(" ");
            }
          }
        }
      }
    }
      
    


  • @Eric73 , below is the first portion of the .ino file:

    // ******************************************************
    // ezPyro_SoftWire_Backplane_V4.0
    //
    // V1.0,          Original version of SoftI2C code ... works OK but basic
    // V2.0, 08/02/17 Cleaned up the code from V.1.0 - it works but was messy
    // V2.1, 17/02/17 Takes Input from Serial Console for live re-configuration
    //                Also counts uSecs between measures rather than ms accumulated
    // V3.0, 21/02/17 Added the RTC module, RTC & ASIC Temperature Monitoring.
    // V4.0  01/05/19 DD Take over code base and rewrite
    //
    String Revision_Info = "ezPyro SoftWire Backplane V4.0 With Serial I/P & Temp";
    
    // ******************************************************
    // Started with "I2C" library as the ezPyro i2c protocol does not work
    // with "Wire". Allows re-mapping of SDA/ SCL to any i/o pin on any AVR Mega MCU
    // NB Commented out SoftWire.h setClock() prototype in ln 56 top remove warning DD
    // ******************************************************
    // ezPyro Breakout Board header (PYB-266)
    //                               /----+
    // Vdd 3.3V MAX, NOT 5V       1 | o o | 2  Unassigned
    // SCL (12C)Digital I/O       3 | o o | 4  SDA (12C)Digital I/O
    // CS needs start-up sequence 5  ]o o | 6  INT (Optional)
    // SYNC (Optional)            7 | o o | 8  CLK (Optional)
    // Unassigned                 9 | o o | 10 Gnd
    //                              +-----+
    // ******************************************************
    // ezPyro to MCU interface board (PYB-269REV_A&B)
    // ******************************************************
    //   PYB-269 Left           Nano        PYB-269 Right
    //  ----------------------  ----------- -------------------------
    //  Rev B,diff Rev A        Left  Right Rev A         Rev B,diff
    //  ---------  -----------  ----  ----- --------      -----------
    //  N/C        INT_Sensor_2 TX1   VIN   VIN 
    //  N/C        INT_Sensor_3 RX0   GND   GND all sensors
    //             N/C          RST   RST   N/C
    //             N/C          GND   5.0v  N/C
    //             BT_2         D2    A7    INT_Sensor_4  N/C
    //             Emit_Sync    D3    A6    BT_5          INT_Sensor_4
    //             SDA          D4    A5    BT_4          INT_Sensor_3
    //             SCL          D5    A4    BT_3          INT_Sensor_2
    //             CS_1         D6    A3    INT_Sensor_1
    //             Sync_microC  D7    A2    N/C
    //             CLK_microC   D8    A1    LED_Ready
    //             BT_0         D9    A0    LED_Running
    //             BT_1         D10   REF   N/C
    //             CS_2         D11   3.3v  VDD all sensors
    //             CS_3         D12   D13   CS_4
    //
    // ******************************************************
    // The default Address for the ezPyro device is 0x65
    // this is shifted 1 bit to 11001010b; LSB =0, Wr =1, Rd 
    //
    // There are 5 24-bit A-D's (Channels 00 - 04)
    // On single pixel ezPyro, data on Channel 2
    // On 2 x 2 pixel ezPyro, data on Channel 1-4
    //
    // Soft I2C library - allows SCL / SDA pin remapping
    // https://github.com/felias-fogg/SoftI2CMaster
    //
    // You can also define the following I2C constants
    // - I2C_FASTMODE = 1, I2C bus up to 400 kHz
    // - I2C_SLOWMODE = 1, I2C bus up to 25 kHz 
    // Table of I2C bus speed in kbit/sec:
    // CPU clock:           1MHz   2MHz    4MHz   8MHz   16MHz   20MHz
    // Fast I2C mode          40     80     150    300     400     400
    // Standard I2C mode      40     80     100    100     100     100
    // Slow I2C mode          25     25      25     25      25      25  
    
    #define I2C_FASTMODE 1
    //#define ezPyro_i2c  0x65        // ezPyro I2C default address
    byte ezPyro_i2c = 0x65;           // ezPyro I2C default address
    
    #include "ezPyro.h"               // Include ezPyro Header
    #include <SoftWire.h>             // Assembly is in "softI2CMaster.h", included by SoftWire.h
    
    // Global Variables
    byte ezPyro_FIFO[17] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; // Data FIFO
    byte ezPyro_STATUS = 0xFF;
        
    int i = 0 ;                       // data loop General use counter 1
    unsigned long j = 0 ;             // data loop General use counter 2
    
    unsigned long time_1;             // Timing Monitoring counters
    unsigned long time_2;
    int dataCounter = 0;
    byte serial_byte;
      
    unsigned long USB;                // Upper Byte ezPyro Sensor data
    unsigned long MSB;                // Middle Byte
    unsigned long LSB;                // Lower Byte
    
    // Sensor Data & counters
    byte ezPyro_Clock_Divider = 0;
    byte ezPyro_Pixel = 1;
    byte sensor_0_OS;   
    byte sensor_1_OS; 
    byte sensor_2_OS; 
    byte sensor_3_OS; 
    byte sensor_4_OS;   
    unsigned long sensor_0;
    unsigned long sensor_1;
    unsigned long sensor_2; 
    unsigned long sensor_3;
    unsigned long sensor_4;
    unsigned long sensor_sign;
    unsigned int frame_count;
    byte temp_on = 1; 
    float sensor_Temperature;
    
    // General Variables
    byte error;
    byte CPU_divider ;
    //float Seconds_Passed; // not used
    String keyboard_buffer;
    
    SoftWire Wire = SoftWire();       // Create the Softwire Instance
    
    /*******************************************************************************
     * Simple LED control routines
     *******************************************************************************/
    #define RUNNING_LED_ON   digitalWrite(ezPyro_LED_Running, LOW)
    #define RUNNING_LED_OFF  digitalWrite(ezPyro_LED_Running, HIGH)
    #define READY_LED_ON     digitalWrite(ezPyro_LED_Ready, LOW)
    #define READY_LED_OFF    digitalWrite(ezPyro_LED_Ready, HIGH)
    
    /********************************************************************************
     * Setup function
     ********************************************************************************/
    void setup(void) {
      time_1 = micros();                      // Start the timer counter
    
      // Configure the Arduino I/O to talk to the ezPyro Breakout Board Backplane
      pinMode(ezPyro_LED_Running, OUTPUT);    // Set the "Running" LED
      pinMode(ezPyro_LED_Ready,OUTPUT);
      pinMode(ezPyro_CS_1, OUTPUT);           // CS is on D6
      pinMode(ezPyro_CS_2, OUTPUT);           //
      pinMode(ezPyro_CS_3, OUTPUT);           //
      pinMode(ezPyro_CS_4, OUTPUT);           // 
    
      pinMode(ezPyro_INT_1, INPUT_PULLUP);    // Interrupt (INT) is on A3
        
      digitalWrite(ezPyro_CS_1, HIGH);        // CS1
      digitalWrite(ezPyro_CS_2, HIGH);        // CS2
      digitalWrite(ezPyro_CS_3, HIGH);        // CS3
      digitalWrite(ezPyro_CS_4, HIGH);        // CS4
    
      RUNNING_LED_OFF;
      READY_LED_OFF;
    
      // Chip Sellect Start-up Scenario - CS toggling.
      // The CS line controls both power and reset at the same time, 
      // then some of the internal register will not be reset properly. 
      // The CS sequence should be:
      //  - CS high, wait at least 5us for 1.8v regulator to come up
      //  - CS low, wait 0.10us - 10us. The low pulse can be as short as 0.05us. 
      //    If CS low >100us (... we found ~155us) the power supply will drop. 
      //    Then restart the sequence again.
      //  - CS high to complete the reset.
    
      time_2 = micros();
      while(micros() - time_2 < 10){}  // Force 10 us Hi to ensure stable start - Have gone as low as 5us and still OK
      
      // Force the smallest possible Low (Lo/Hi on Chip Select) for stable reset
      // these are the timings for the Arduino digitalWrite toggle
      // Div 2^0 @ 16MHz = 4.122us - Pass (76,800 baud)
      // Div 2^1 @ 8MHz = 8.375us - Pass (38,400 baud)
      // Div 2^2 @ 4MHz = 16.75us - Pass (19,200 baud)
      // Div 2^3 @ 2MHz = 33.5us - Pass (9,600 baud)
      // Div 2^4 @ 1 MHz = 67.0us - Pass (4,800 baud)
      // Div 2^5 @ 500kHz = 134us - Pass (2,400 baud)
      // Div 2^6 @ 250kHz = 268us - Fail (1,200 baud)
      // Div 2^7 @ 125kHz = 536us - Fail (600 baud)
      // Div 2^8 @ 67.5kHz = 1072us - Fail (300 baud)
    
      // Force the smallest possible Low (Lo/Hi on Chip Select) for stable rst ... 
      // these are the timings for the True C toggle
      // Div 2^0 @ 16MHz = 0.125us - Pass (76,800 baud)
      // Div 2^1 @ 8MHz = 0.250us - Pass (38,400 baud)
      // Div 2^2 @ 4MHz = 0.500us - Pass (19,200 baud)
      // Div 2^3 @ 2MHz = 1.0us - Pass (9,600 baud)
      // Div 2^4 @ 1 MHz = 2.0us - Pass (4,800 baud)
      // Div 2^5 @ 500kHz = 4.0us - Pass (2,400 baud)
      // Div 2^6 @ 250kHz = 8.0us - Pass (1,200 baud)
      // Div 2^7 @ 125kHz = 16.0us - Pass (600 baud)
      // Div 2^8 @ 67.5kHz = 32.0us - Pass (300 baud)
    
      PORTD |=  _BV(PD6);                     // toggle CS_1,D6/ PD6, 38x speed of Arduino Code
      PORTD &= ~_BV(PD6);                     // Arduino toggle is 4.75us, True C toggle is 0.125us
      PORTD |=  _BV(PD6);
        
      // adjusting the AVR CPU speed
      CLKPR = 0x80;                           // Tell the AtMega we want to change the system clock
      CLKPR = 0x00;                           // eg 2^5= 1/32 prescaler= 0.5MHz for a 16MHz crystal
      CPU_divider = 1;                        // for(i=0 ; i< 0 ; i++){CPU_divider = CPU_divider * 2;}
    
      RUNNING_LED_ON;
      Serial.begin(115200);                   // NB With 1/32 clk (2^5), console is 2,400(0.5 MHz)
      Serial.println();Serial.println();Serial.println();
      Serial.println(Revision_Info);
      Serial.println(F("============================================================"));
      Serial.println();
      Start_ASIC();
    
      printTitleBar();
      RUNNING_LED_OFF;
    } // End of Set Up
    
    /*********************************************************************************
     * Main loop function
     *********************************************************************************/
    void loop(void){
    
      while (Serial.available() > 0) {        // Check for Serial Input
        Serial.print("Avail= "); Serial.println(Serial.available());
        Serial.println();
        Serial.println("data in i/p buffer");
        keyboard_buffer = Serial.readString();// Read the keyboard string
        keyboard_buffer.toUpperCase();
        Serial.print("Buff1= "); Serial.println(keyboard_buffer);
        processCommand();
        Serial.print("Buff2= "); Serial.println(keyboard_buffer);
      }
      // *****************************************************************************
      // Read part of the FIFO & speed things up ? 
      // (fastest read cycle is 7.42 ms ... sould be able to get to 1ms)
      // Make a new Version (4.0 ?) for this using FIFO_READ_ACTIVE.
      //
      // FIFO_READ_ACTIVE
      // e.g. if 2 Active Channels (0 & 2) , 8 bytes.
      // Byte 0 = channel 0 bits 23:16
      // Byte 1 = channel 0 bits 15:8
      // Byte 2 = channel 0 bits 7:0
      // Byte 3 = channel 2 bits 23:16
      // Byte 4 = channel 2 bits 15:8
      // Byte 5 = channel 2 bits 7:0
      // Byte 6 = frame count MSB
      // Byte 7 = frame count LSB
      // *****************************************************************************
        
      // Read the Full 17 byte FIFO
      if (!readI2C(ezPyro_i2c, ezPyro_FIFO_READ_FULL, ezPyro_FIFO_SIZE)) {
        // Loop til data in FIFO - triggered by the ASIC Interrupt going Low
      } else{
        /* ****** FIFO Structure
        FIFO_DPF  Data
        Byte 0  channel 0 bits 23-16   Byte 1  channel 0 bits 15-8  Byte 2  channel 0 bits 7-0
        Byte 3  channel 1 bits 23-16   Byte 4  channel 1 bits 15-8  Byte 5  channel 1 bits 7-0
        Byte 6  channel 2 bits 23-16   Byte 7  channel 2 bits 15-8  Byte 8  channel 2 bits 7-0
        Byte 9  channel 3 bits 23-16   Byte 10 channel 3 bits 15-8  Byte 11 channel 3 bits 7-0
        Byte 12 channel 4 bits 23-16   Byte 13 channel 4 bits 15-8  Byte 14 channel 4 bits 7-0
        Byte 15 frame count MSB        Byte 16 frame count LSB
        */
        RUNNING_LED_OFF;
       if(!temp_on){                          // Temp or Dark Pixel
         sensor_0_OS = 0;                     // Over Range Flag
         if(ezPyro_FIFO[0] > 0x7F){
           sensor_0_OS = 1;
         }
         sensor_0 = ((long)(ezPyro_FIFO[0]&0x7f)<<16) | ((long)ezPyro_FIFO[1]<<8) | ezPyro_FIFO[2];
       } else {
         sensor_0 = ((long)ezPyro_FIFO[1]* 256) + ezPyro_FIFO[2];
         sensor_Temperature = -0.026 * sensor_0 + 422;         
       }
          
    // Sensor 1, 3 bytes
       sensor_1_OS = 0;                                  // Over Range Flag
    
       if (ezPyro_FIFO[3] > 0x7F){
         sensor_1_OS = 1;
       }
       sensor_1 = ((long)(ezPyro_FIFO[0]&0x7f)<<16) | ((long)ezPyro_FIFO[1]<<8) | ezPyro_FIFO[2];
    // end of prototype replacement
    
       USB = ezPyro_FIFO[0];                             // Sensor 0= 3 bytes
       MSB = ezPyro_FIFO[1];
       LSB = ezPyro_FIFO[2];
       if(!temp_on){                                     // Temp or Dark Pixel
         sensor_0_OS = 0;                                // Over Range Flag
         if(ezPyro_FIFO[0] > 0x7F){
           sensor_0_OS = 1;
           USB = USB &0x7F;          // DD isnt this be USB &= 0x7f BITWISE&
         }
         sensor_0 = (USB<<16) + (MSB<<8) + LSB;
       } else {
         sensor_0 = (MSB * 256) + LSB;
         sensor_Temperature = -0.026 * sensor_0 + 422;         
       }
       
       USB = ezPyro_FIFO[3];                             // Sensor 1, 3 bytes
       MSB = ezPyro_FIFO[4];
       LSB = ezPyro_FIFO[5];
       sensor_1_OS = 0;                                  // Over Range Flag
       if (ezPyro_FIFO[3] > 0x7F){
         sensor_1_OS = 1;
         USB = USB &0x7F;
       }
       sensor_1 = (USB<<16) + (MSB<<8) + LSB;
    
       USB = ezPyro_FIFO[6];                             // Sensor 2, 3 bytes
       MSB = ezPyro_FIFO[7];
       LSB = ezPyro_FIFO[8];
       sensor_2_OS = 0;                                  // Over Range Flag
    
       if(USB > 0x7F){
         sensor_2_OS = 1;
         USB = USB &0x7F;
       }
       sensor_2 = (USB<<16) + (MSB<<8) + LSB;
    
       USB = ezPyro_FIFO[9];                             // Sensor 3, 3 bytes
       MSB = ezPyro_FIFO[10];
       LSB = ezPyro_FIFO[11];
       sensor_3_OS = 0;                                  // Over Range Flag
       if(USB > 0x7F){
         sensor_3_OS = 1;
         USB = USB &0x7F;
       }
       sensor_3 = (USB<<16) + (MSB<<8) + LSB;
            
       USB = ezPyro_FIFO[12];                            // Sensor 4, 3 bytes
       MSB = ezPyro_FIFO[13];
       LSB = ezPyro_FIFO[14];
       sensor_4_OS = 0;                                  // Over Range Flag
       if(USB > 0x7F){
         sensor_4_OS = 1;
         USB = USB &0x7F;
       }
       sensor_4 = (USB<<16) + (MSB<<8) + LSB;
    
       USB = ezPyro_FIFO[15];                            // Frame Count, 2 bytes
       LSB = ezPyro_FIFO[16];
       frame_count = (USB*256) + LSB;
    
       // Display the data. It takes ~0.15ms / line to print to screen
       Serial.print(j++);        
       Serial.print("\t    ");
       if(temp_on){
         if (sensor_Temperature <100){
           Serial.print(" ");
             if (sensor_Temperature <10){
                Serial.print(" ");
             }
          }
          Serial.print(sensor_Temperature, 3);
        } else{
          Serial.print(sensor_0 / ezPyro_Clock_Divider);
        }
        Serial.print("\t");
        alignNumber((unsigned int)(sensor_1 / ezPyro_Clock_Divider));
        Serial.print(sensor_1 / ezPyro_Clock_Divider);
        Serial.print("\t");
        alignNumber((unsigned int)(sensor_2 / ezPyro_Clock_Divider));
        Serial.print(sensor_2 / ezPyro_Clock_Divider);
        Serial.print("\t");
        alignNumber((unsigned int)(sensor_3 / ezPyro_Clock_Divider));
        Serial.print(sensor_3 / ezPyro_Clock_Divider);
        Serial.print("\t");
        alignNumber((unsigned int)(sensor_4 / ezPyro_Clock_Divider)); 
        Serial.print(sensor_4 / ezPyro_Clock_Divider);
    
        Serial.print("\t      ");
        alignNumber((unsigned int)frame_count);
        Serial.print(frame_count);
        Serial.print("\t     ");
        time_2 = micros();
        alignNumber((unsigned int)((time_2 - time_1) * CPU_divider));
        Serial.print((time_2 - time_1) * CPU_divider);
        time_1 = micros();
        if(sensor_1_OS || sensor_2_OS || sensor_3_OS || sensor_4_OS){
          Serial.print(F("\tOver Scale\t  "));
        } else{
          Serial.print(F("\tOK        \t  "));
        }
        Serial.println("");
        if (!writeI2C(ezPyro_i2c, ezPyro_FIFO_RESET, 0)) {// Rst Full FIFO 
          Serial.println(F("Reset FIFO Error"));        // for next data set
          while (1);
        }
        RUNNING_LED_OFF;
      }   
    }         // End of Main Loop **************************************************************
    
    /*********************************************************************************
     * printTitleBar function
     *********************************************************************************/
    void printTitleBar(void){
    //  Serial.println("\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT\tT");      // Aid to aligning tab stops
      Serial.print(F("#\tezPyro Temp\tSen 1\tSen 2\tSen 3\tSen 4\tFrame Count\tT Delta/uS\tOver Scale"));
      Serial.println();
      Serial.print(F("=================================================================================================="));
      Serial.println();
    }
    
    /*********************************************************************************
     * processCommand function
     * This routine acts upon the keyboard input
     *********************************************************************************/
    void processCommand(void){
    
      static char fullReset=0;              // ASIC is started in startup function
      
      if (keyboard_buffer == "GO"){         // Config & Start ASIC & Sensor
    //  Serial.println("Go received");
        Start_ASIC();
        fullReset=0;                        // Enable commands, once ASIC has been started
    
        Serial.println(F("Sensor Started ..."));
        printTitleBar();
      }
      if (0==fullReset){                        // Disable commands, until ASIC has been started
    //  Serial.println(F("waiting for ezPyro to be ready for keyboard command"));
        while(!readI2C(ezPyro_i2c, ezPyro_FIFO_READ_FULL, ezPyro_FIFO_SIZE)) {Serial.print("ez.");}    // Loop til ezPyro is ready to take cmd
    
        if (keyboard_buffer == "P"){    // Pause the serial port until any keypress 
          while (!Serial.available()){}
    //    keyboard_buffer = Serial.readString();         
        }
        
        if (keyboard_buffer == "CLR"){              // Clear & Reset serial comms- only works on terminal, not Arduino monitor ...
          Serial.write(27);                         // ESC
          Serial.print("[2J");                      // clear screen
          Serial.write(27);                         // ESC
          Serial.print("[H");                       // cursor home
          Serial.println(F("Serial Reset ..."));  
        }
        if (keyboard_buffer == "RST F"){            // Full Reset the ASIC
          if (!writeI2C(ezPyro_i2c, ezPyro_RESET_FULL, 0)) { // Send a full Reset
            Serial.println(F("Write Full Reset Error"));
            while (1);
          }
          fullReset=1;                                // Disable commands, until ASIC has been restarted
          Serial.println(F("Full Reset ..."));  
        }
    
        if (keyboard_buffer == "RST S"){                    // Soft Reset the ASIC
          if (!writeI2C(ezPyro_i2c, ezPyro_RESET_SOFT, 0)){ // Send a Soft Reset
            Serial.println(F("Write Soft Reset Error"));
            while (1);
          }
          Serial.println(F("Soft Reset ..."));  
        }
    
    /*********************************************************************************
     * Analog Front End Modification
     * *******************************************************************************/
        if (keyboard_buffer == "TEMP OFF") {                // Temp Monitoring Off
          Read_AFE();                                       // Read Analogue Front End
          temp_on = 0;
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xFD;           // &1111 1101 rst TEMP to 0
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_TEMP_DISABLE ;
          Write_AFE();                                      // Write Analogue Front End
          Serial.println(F("Temperature Monitorring Off"));
          Read_AFE();                                       // Read Analogue Front End 
        }
        
        if (keyboard_buffer == "TEMP ON") {                 // Set the Temperature Monitoring On
          Read_AFE();                                       // Read Analogue Front End 
          temp_on = 1;
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xFD;           // &1111 1101 rst TEMP to 0      ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_TEMP_ENABLE ;
          Write_AFE();                                      // Write Analogue Front End   
          Serial.println(F("Temperature Monitorring On"));
          Read_AFE();                                       // Read Analogue Front End 
        }
    
        if (keyboard_buffer.charAt(0) == 'S'){              // set the sample rate  
          Serial.print("Clock Divider was = ");
          Serial.println(ezPyro_Clock_Divider);      
          keyboard_buffer.remove(0, 1);                     // Remove the 'S'
          ezPyro_Clock_Divider = keyboard_buffer.toInt();   // Convert String to Int
          Serial.print("Clock Divider is now = ");
          Serial.println(ezPyro_Clock_Divider);
          Read_AFE();                                       // Read Analogue Front End 
          ezPyro_FIFO[0] = (ezPyro_Clock_Divider - 1);      // set the sample rate        
          Write_AFE();                                      // Write Analogue Front End 
          Serial.println(F("Sample Rate Set"));
          Read_AFE();                                       // Read Analogue Front End 
        } // End If "Sample Rate"
    
        if (keyboard_buffer == "HPF ON") {                  // Enable High Pass Filter  
          Read_AFE();                                       // Read Analogue Front End
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xBF;           // &1011 1111 clr En HPF
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_HI_PASS_FILTER_ON ; //0x40 DD above?
          Write_AFE();                                      // Write Analogue Front End
          Serial.println(F("High Pass Frequency Filter Enabled"));
          Read_AFE();                                       // Read Analogue Front End
        }
          
        if (keyboard_buffer == "HPF OFF") {                 // Disable High Pass Filter
          Read_AFE();                                       // Read Analogue Front End
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xBF;           // &1011 1111 clr En HPF 
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_HI_PASS_FILTER_OFF ;
          Write_AFE();                                      // Write Analogue Front End
          Serial.println(F("High Pass Frequency Filter Disabled"));
          Read_AFE();                                       // Read Analogue Front End
        }
    
        if (keyboard_buffer == "PWR HI") {                // ezPyro Standard (High) Power Mode  
          Read_AFE();                                     // Read Analogue Front End
            
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0x7F;         //&0111 1111 clr LoPow Mode
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_STANDARD_POWER_MODE ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Power Mode Disabled"));
          Read_AFE();                                     // Read Analogue Front End        
        }
    
        if (keyboard_buffer == "PWR LO") {                // ezPyro Low Power Mode  
          Read_AFE();                                     // Read Analogue Front End 
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0x7F;         // &0111 1111 clr LoPow Mode 
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_LOW_POWER_MODE ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Power Mode Enabled"));
          Read_AFE();                                     // Read Analogue Front End
        }
    
        if (keyboard_buffer == "LPF22.5") {               // Set LPF Freq to 22.5Hz
          Read_AFE();                                     // Read Analogue Front End 
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xCF;         // &1100 1111 clr LPF Freq
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_LO_PASS_FREQ_022_5 ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Pass Frequency Filter set to 22.5Hz"));
          Read_AFE();                                     // Read the Analogue Front End
        }
    
        if (keyboard_buffer == "LPF45") {                 // Set LPF Freq to 45Hz
          Read_AFE();                                     // Read Analogue Front End
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xCF;         // &1100 1111 clr LPF Freq
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_LO_PASS_FREQ_045 ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Pass Frequency Filter set to 45Hz"));
          Read_AFE();                                     // Read the Analogue Front End
        }
    
        if (keyboard_buffer == "LPF90") {                 // Set LPF Freq to 90Hz
          Read_AFE();                                     // Read Analogue Front End
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xCF;         // &1100 1111 clr LPF Freq
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_LO_PASS_FREQ_090 ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Pass Frequency Filter set to 90Hz"));
          Read_AFE();                                     // Read Analogue Front End
        }
    
        if (keyboard_buffer == "LPF180") {                // Set LPF Freq to 180Hz
          Read_AFE();                                     // Read Analog Front End
          ezPyro_FIFO[1] = ezPyro_FIFO[1] & 0xCF;         // &1100 1111 clr LPF Freq
          ezPyro_FIFO[1] = ezPyro_FIFO[1] | ezPyro_LO_PASS_FREQ_180 ;
          Write_AFE();                                    // Write Analogue Front End
          Serial.println(F("Low Pass Frequency Filter set to 180Hz"));
          Read_AFE();                                     //  Read the Analogue Front End
        }
    


  • [0_1585827494564_ezPyro_h.txt](Uploading 100%) @Eric73 , I have contacted the manufacturer as well regarding this issue. They couldn't help me out directly with micropython code but they have provided the Arduino C code and log file along with I2C library.
    I don't have any experience with Arduino as of now. Hence, I have attached the header file below if it can be of any use. I can't upload the other files as it's not supported here.

    // ************************************
    // * ezPyro Header 
    // ************************************
    //#include <ezPyro.h>
    // ezPyro.h
    //
    // Version 1.0 17-Jan-2016
    // 
    // Standard datasets & commands for ezPyro product
    // Default Address for the ezPyro device is 0x65h
    //  (Note ... is this shifted 1 bit to 11001010b / 202d / 0xCA)
    //
    //  There are 5 24-bit A-D's (Channels 00 - 04)
    //  On single pixel exPyro, the data comes in on Channel 2
    //  On 2 x 2 pixel ezPyro, the data comes in on Channel 0-3
    //
    // Channel 0 is the Dark Pixel on the Sensor or the Temperature Sensor on the ASIC
    // depending on the Configuration Setup
    //
    // ezPyro i2c commands available
    #define ezPyro_TEST                 0x00
    #define ezPyro_VERSION              0x02
    #define ezPyro_FIFO_STATUS          0x04
    #define ezPyro_FIFO_READ_FULL       0x06
    #define ezPyro_FIFO_READ_ACTIVE     0x08
    #define ezPyro_FIFO_CLEAR           0x0A
    #define ezPyro_FIFO_RESET           0x0C
    #define ezPyro_CCP_READ             0x0E
    #define ezPyro_CCP_WRITE            0x10
    #define ezPyro_AFE_READ             0x12
    #define ezPyro_AFE_WRITE            0x14
    #define ezPyro_WUP_READ             0x16
    #define ezPyro_WUP_WRITE            0x18
    #define ezPyro_ENG_READ             0x1A
    #define ezPyro_ENG_WRITE            0x1C
    #define ezPyro_ADDR_WRITE           0x1E
    #define ezPyro_GO_TO_SLEEP          0x20
    #define ezPyro_WAKE_UP              0x22
    #define ezPyro_RESET_SOFT           0x24
    #define ezPyro_RESET_FULL           0x26
    #define ezPyro_MEMTEST_ON           0x28
    #define ezPyro_MEMTEST_OFF          0x2A
    #define ezPyro_MEMTEST_WR_SAME      0x2C
    #define ezPyro_MEMTEST_WR_ALT       0x2E
    #define ezPyro_MEMTEST_RD           0x30
    
    // I2C Error & State Flags
    #define ERR_OK                      0
    #define ERR_LONG_DATA               1
    #define ERR_NAK_ADDR                2
    #define ERR_NAK_DATA                3
    #define ERR_UNKNOWN                 4
    #define ON                          1
    #define OFF                         0
    
    // Data Set Package Definitions
    #define ezPyro_FIFO_SIZE            17
    #define ezPyro_CCP_SIZE             5
    #define ezPyro_AFE_SIZE             2
    #define ezPyro_WUP_SIZE             6
    
    // Channel Control Packet
    // **** Switch on Channel 2 only (Single Sensor) *****
    #define ezPyro_CCP_DISABLE          0x00
    #define ezPyro_CCP_ACTIVE           0x01
    #define ezPyro_CCP_AMP_01x          0x0C
    #define ezPyro_CCP_AMP_02x          0x0A
    #define ezPyro_CCP_AMP_04x          0x08
    #define ezPyro_CCP_AMP_08x          0x06
    #define ezPyro_CCP_AMP_16x          0x04
    #define ezPyro_CCP_AMP_32x          0x02
    #define ezPyro_CCP_AMP_64x          0x00
    #define ezPyro_CCP_HP_FILTER_1      0x00
    #define ezPyro_CCP_HP_FILTER_2      0x10
    #define ezPyro_CCP_HP_FILTER_4      0x20  
    #define ezPyro_CCP_HP_FILTER_8      0x30
    #define ezPyro_CCP_TRANS_120T       0x00
    #define ezPyro_CCP_TRANS_060T       0x80  
    #define ezPyro_CCP_TRANS_030T       0xA0  
    #define ezPyro_CCP_TRANS_015T       0xC0
      
    // Analog Front End Packet
    #define ezPyro_INT_DISABLE          0x00
    #define ezPyro_INT_ENABLE           0x01
    #define ezPyro_TEMP_DISABLE         0x00
    #define ezPyro_TEMP_ENABLE          0x02
    #define ezPyro_SYNC_MASTER          0x00
    #define ezPyro_SYNC_SLAVE           0x04
    #define ezPyro_CLK_OUT_DISABLE      0x00
    #define ezPyro_CLK_OUT_ENABLE       0x08
    #define ezPyro_LO_PASS_FREQ_180     0x00
    #define ezPyro_LO_PASS_FREQ_090     0x10
    #define ezPyro_LO_PASS_FREQ_045     0x20
    #define ezPyro_LO_PASS_FREQ_022_5   0x30
    #define ezPyro_HI_PASS_FILTER_OFF   0x00
    #define ezPyro_HI_PASS_FILTER_ON    0x40
    #define ezPyro_STANDARD_POWER_MODE  0x00
    #define ezPyro_LOW_POWER_MODE       0x80
    
    // Define the I2C I/O pins
    #define SDA_PORT                    PORTD  
    #define SDA_PIN                     4              // SDA = D4
    #define SCL_PORT                    PORTD          // SCL = D5
    #define SCL_PIN                     5
    
    // Define all the pin assignments for the Pyreos Backplane Board
    #define ezPyro_LED_Running          A0
    #define ezPyro_LED_Ready            A1
    #define ezPyro_CS_1                 6
    #define ezPyro_CS_2                 11
    #define ezPyro_CS_3                 12
    #define ezPyro_CS_4                 13
    #define ezPyro_INT_1                A3
    #define ezPyro_INT_2                A4
    #define ezPyro_INT_3                A5
    #define ezPyro_INT_4                A6
    
    

    Regards



  • @Eric73 Thanks a lot for the correction.

    No, I haven't added any Pull-up resistor yet.

    I haven't understood the calculation you showed for channel 1 value at the end.

    Val=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]
    

    Here, [3], [4], [5] which array they are indicating?
    And can you please show me how would I convert thw FIFO output byte into Decimal in micropython? I found few examples for python but didn't workout.

    Regards



  • @Oridroo said in How to read out the output of 'ezPyro SMD I2C Pyroelectric Infrared Sensor' via I2C command?:

    buf = bytes([0x00, 0x07, 0x07, 0x07, 0x07])
    print("Buffer:", buf)

    chnl_ctr = i2c.writeto_mem(0x65, 0x10, buf)

    As you have set all channel it's logical that Fifo_Read_Active and Fifo_Read_All return same resultat as all channel are actived.

    b'001e170020c10020310022f730e730e730'

    Is not a number, it's a byte array that must be decoded according to DS 13.3.10 , for next value you have to send a fifo_clear before reading again.

    So the result is
    001e17 CH0
    0020c1 CH1
    002031 CH2
    0022f7 CH3
    30e730 CH4
    e730 Frame count (?) Strange value, have you add pull-up on i2c line ?
    CH1=0x20C1 so 8385 decimal adc points

    Exemple : For CH1 value
    Val=fifo_read_active[3]*65536+fifo_read_active[4]*256+fifo_read_active[5]



  • @Eric73 Once again, Thanks a lot for the guidelines.

    Things are better than before. Now the 'Wake-up' command works, although I don't see any difference in the FIFO output with and without wake-up function.

    I tried to follow your instructions and set the channel control and left the analogue settings as default.
    The code is now as below:

    from machine import I2C, Timer
    import time
    import ubinascii
    
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    wake_up = i2c.readfrom_mem(0x65, 0x22, 1)
    print("Wake_UP:", wake_up)
    time.sleep(1)
    
    buf = bytes([0x00, 0x07, 0x07, 0x07, 0x07])
    print("Buffer:", buf)
    
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, buf)
    print("Channel Control:", chnl_ctr)
    time.sleep(1)
    
    analog = bytes([0x00, 0x09])
    print("Analogue:", analog)
    ana_sett = i2c.writeto_mem(0x65, 0x14, analog)
    print("Analog Settings:", ana_sett)
    time.sleep(2)
    ana_read = i2c.readfrom_mem(0x65, 0x12, 4)
    print("Analog Read:", ana_read)
    time.sleep(2)
    
    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    hex = ubinascii.hexlify(fifo_read_active)
    print("FIFO_Read_Active_Chnl:",hex)
    time.sleep(1)
    fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    print("FIFO_Read_All_Chnl:", fifo_read_full)
    

    One bizarre thing is, at first I was trying to print with the command you suggested

    print("FIFO_Read_Active_Chnl:"+str(ubinascii.hexlify(fifo_read_active)))
    

    but it was showing error again and again. Then I removed the '+str' and it worked. Now, a while ago I tried with '+str' again and it's working. And I'm getting identical outputs for both the commands like below:

    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    print("FIFO_Read_Active_Chnl:"+str(ubinascii.hexlify(fifo_read_active)))
    hex = ubinascii.hexlify(fifo_read_active)
    print("FIFO_Read_Active_Chnl:",hex)
    

    Output

    FIFO_Read_Active_Chnl:b'001e23001fbb0020470022df1e9d1e9d1e'
    FIFO_Read_Active_Chnl: b'001e23001fbb0020470022df1e9d1e9d1e'
    

    Another thing is, I'm getting the same output for both the FIFO Active Channel Output and All Channel Output:

    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    hex = ubinascii.hexlify(fifo_read_active)
    print("FIFO_Read_Active_Chnl:",hex)
    time.sleep(1)
    fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    hex_2 = ubinascii.hexlify(fifo_read_full)
    print("FIFO_Read_All_Chnl:", hex_2)
    

    Output

    FIFO_Read_Active_Chnl: b'001e170020c10020310022f730e730e730'
    FIFO_Read_All_Chnl: b'001e170020c10020310022f730e730e730'
    

    And the output I'm getting out of the FIFO buffer is a Huge number! According to DS, there would be 17 bytes of data in every frame. Is this why the output number is so big?
    In decimal, it's ranging in between (2.5-4.5)x10^37
    I tried to scale it down but couldn't find any micropython code to do that.

    Also, from the DS, what I learnt is that each frame is containing the ADC data from all 5 channels (12.6). So, is the FIFO output (17 bytes number) is representing the output of the sensor? The manufacturer says the output of the sensor is 'Current'. I am not understanding how to interpret/convert this huge number into relevant current output? Or is this huge number is something realistic/logical for this sensor's characteristics?

    Please enlighten me. I'm totally stuck at this point. If I can't get a reliable output, I won't be able to proceed to the next stage which is testing with gas.

    Regards



  • @Oridroo
    Ok, first before all, you need to setup correctly your sensor before trying understood what you have when you read it's fifo.

    You can use someting like this
    Buf=bytes([0x00, 0x31, 0x31,0x31,0x31])
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, Buf)

    Buf is an object of type bytes with a length of 5, just pass it to i2c.writeto_mem it will compute the length to send

    To send a simple command like wakeup you have to send a i2c_read (see ds 12.6.5) and not a i2c_write

    wake_up = i2c.readfrom_mem(0x65, 0x22, 1)
    print("Wake_UP:", wake_up)
    

    Expected value is 0x89 (0x22<<2+1=OK)
    CLK_OUT, SYNC, or interrupt dont change default value this time. You will change it later

    For simple read of fifo value please do something like this

    import ubinascii
    ...
    print("FIFO_Read_Active_Chnl:"+str(ubinascii.hexlify(fifo_read_active))
    


  • @Eric73 Thank you so much for the heads up.

    Unfortunately, I have been scratching my head all day long!

    As per your instruction, I wrote the below code, but it shows 'OSError: I2C bus error'. I connected 'CS' to Vss (3.3V, continuous supply) as well but still got this error.

    from machine import I2C, Timer
    import time
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    wake_up = i2c.writeto_mem(0x65, 0x22, 1)
    print("Wake_UP:", wake_up)
    
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, 5)
    print("Channel Control:", chnl_ctr)
    time.sleep(1)
    ana_sett = i2c.writeto_mem(0x65, 0x14, 0x05)
    print("Analog Settings:", ana_sett)
    time.sleep(2)
    ana_read = i2c.readfrom_mem(0x65, 0x12, 4)
    print("Analog Read:", ana_read)
    time.sleep(2)
    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    print("FIFO_Read_Active_Chnl:", fifo_read_active)
    time.sleep(2)
    fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    print("FIFO_Read_All_Chnl:", fifo_read_full)
    

    Then I ran the code without 'Wake-up' command and got the below output:

    from machine import I2C, Timer
    import time
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    
    chnl_ctr = i2c.writeto_mem(0x65, 0x10, 5)
    print("Channel Control:", chnl_ctr)
    time.sleep(1)
    ana_sett = i2c.writeto_mem(0x65, 0x14, 0x05)
    print("Analog Settings:", ana_sett)
    time.sleep(2)
    ana_read = i2c.readfrom_mem(0x65, 0x12, 4)
    print("Analog Read:", ana_read)
    time.sleep(2)
    fifo_read_active = i2c.readfrom_mem(0x65, 0x08, 17)
    print("FIFO_Read_Active_Chnl:", fifo_read_active)
    time.sleep(2)
    fifo_read_full = i2c.readfrom_mem(0x65, 0x06, 17)
    print("FIFO_Read_All_Chnl:", fifo_read_full)
    

    Output:

    I2C Address [101]
    Channel Control: 1
    Analog Settings: 1
    Analog Read: b'\x05\t\t\t'
    FIFO_Read_Active_Chnl: b'\x80\x02P\x00\x01\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
    FIFO_Read_All_Chnl: b'\x80\x02P\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01'
    

    Now, I am certain that I couldn't configure both the 'Analogue Settings' and 'Channel Settings' required for the sensor. And I couldn't convert the FIFO Read outputs to a suitable, readable number as well.

    I tried to understand the 'Channel Control Packet-13.3.5' and 'Analogue Front End Packet-13.3.6' from the datasheet and below is what I understood so far:

    CCP.PNG
    CCP_2.PNG

    The 'Channel Control Packet' command will be containing 5 bytes in it and each byte is associated with a single channel. From the datasheet, byte-0 is associated with Channel-0 . similarly byte-1 to channel-1 and so on. Now, I can configure 'Channel Status', Feedback Capacitor' 'HP Signal Filter Frequency' and 'Front End Trans-conductance' of each channel by changing the bit sequences.
    I did something like this:

    bit:7 -- bit:6 -- bit:5 -- bit:4 -- bit:3 -- bit:2 -- bit:1 -- bit:0
    0 0 1 1 0 0 0 1

    But I couldn't figure it out what setting would be appropriate and would this setting be same for all four channels (Ch4:Ch1, except Ch0 as the datasheet says: "Note that channel 0 is currently used for internal test purposes only.") ?

    And how to send this configuration to the sensor?

    chnl_ctr = i2c.writeto_mem(0x65, 0x10, 5)
    

    Here, '0x65' is the I2C address, '0x10' is the 'COM Code' (the address of the channel?) provided in the datasheet for 'Ch-write' and 5 is the number of bytes passed to that address. So, how can I send the configuration to channel via this instruction?

    I am confused about the Analogue settings as well.

    AFP.PNG

    From the datasheet what I understood is, the 'Byte 0' will be '0x00' if we are following the
    Sampling Rate = 1000/(N+1).

    And the 'Byte 1' can be:
    bit:7 -- bit:6 -- bit:5 -- bit:4 -- bit:3 -- bit:2 -- bit:1 -- bit:0
    0 1 0 0 0 1 0 0

    Here, do I need to use 'High Pass' filter? Should I disable 'CLK_OUT' (internal clock output)? Would 'SYNC' be '1' as our I2C is slave? 'Bit 1' is by default set as 0. Shall I enable the 'interrupt'?

    The 'FIFO' read output (both for Active and Full channel) are changing every time I run the code for the same settings like below:

    I2C Address [101]
    Channel Control: 1
    Analog Settings: 1
    Analog Read: b'\x05\t\t\t'
    FIFO_Read_Active_Chnl: b'\x00\xd8\x11&m&m&&&&&&&&&&'
    FIFO_Read_All_Chnl: b'\x00\xd8\x11\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&m'
    
    I2C Address [101]
    Channel Control: 1
    Analog Settings: 1
    Analog Read: b'\x05\t\t\t'
    FIFO_Read_Active_Chnl: b'\x00\xdc\x88msmsmmmmmmmmmm'
    FIFO_Read_All_Chnl: b'\x00\xdc\x88\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00ms'
    
    I2C Address [101]
    Channel Control: 1
    Analog Settings: 1
    Analog Read: b'\x05\t\t\t'
    FIFO_Read_Active_Chnl: b'\x00\xbf\xc7\x7f\x1b\x7f\x1b\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f\x7f'
    FIFO_Read_All_Chnl: b'\x00\xbf\xc7\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x7f\x1b'
    

    I ran it consecutively within a minute.

    I know I have asked too many basic questions and just hope that it doesn't annoy you but I badly need these basic understandings, otherwise I'm feeling really frustrated. Please help me to learn the mistakes I'm making in understanding the datasheet and programming.

    Looking forward to your kind guidelines.

    Regards



  • @Oridroo

    So, here I'm getting the Current output as '0' means nothing is there although as a 'Methane' sensor, it should show some values as methane is present in the open air.

    No you dont read 'methane value', 0x12 command, ANA_READ return analog settings 'datasheet 13.3.6' (not analog value). In this case you read b'0x00\t', that mean 0x00,0x09 and it's default analog setting so your i2c communication seem correct.

    Once your device is posered up, it will start in low power mode. You have to wake up it(Wake up command), then send Channel configuration (13.3.5) and Analog setting (13.3.6) , after that wait some time and read from fifo the expected value.

    P.S. I haven't used any pull-up resistor in the I2C bus.

    Not a good think, how have you set the CS signal of your sensor ? If not connected to +3.3V your sensor cannot be waked up.

    Regards



  • @Eric73 Thanks for the suggestion.

    I tried something like this:

    from machine import I2C
    
    i2c = I2C(0, I2C.MASTER)
    i2c = I2C(0, pins=('P10','P9'))
    print("I2C Address", i2c.scan())
    
    value = i2c.readfrom_mem(0x65, 0x12, 2)
    
    print("Current:", value)
    

    After running it, I'm getting output as:

    I2C Address [101]
    Current: b'\x00\t'
    

    So, here I'm getting the Current output as '0' means nothing is there although as a 'Methane' sensor, it should show some values as methane is present in the open air.

    I tried to go through the datasheet but couldn't figure out anything. Would you please have a look into the datasheet and my code and guide me?

    P.S. I haven't used any pull-up resistor in the I2C bus.

    Regards



  • @Oridroo

    Could you please stretch a bit about how to set up the sensor correctly?

    Well at least you have to set sampling clock, irq setting, digital filter and so on as a lot of other sensor. Datasheet show 18 command you can send to it, so at least you need send some command to perform your need.

    Do I need to add external pull-up resistors at the sensor end?

    As good practice, alway have some 4.7K pull-up resistor on I2C bus. You just have to check your low power requierment if you want to do very low power consumption when putting esp32 in deep sleep.



  • @Eric73 Thanks a lot for your reply.

    WARNING : Be sure that your sensor doesn't need I2C clock stretching because as far i know, it's not supported by firmware (https://forum.pycom.io/topic/331/i2c-clock-stretching )

    I couldn't find any mention about 'Clock Stretching' in the sensor datasheet. I have attached the datasheet here (Sensor_Datasheet-min (3).pdf). Although the images are blur as I had to compress it extremely to upload here.

    But you still have to read and understand your datasheet sensor to set it up correctly to have your correct value.

    Could you please stretch a bit about how to set up the sensor correctly? Did you mean the physical connections from sensor to pycom? The I2C connectivity described in the datasheet is as below:

    I2C Connectivity.PNG

    (and don't forget the pull-up on both line SCL,SDA)

    Doesn't Pycom has internarl pull-up resistors? Do I need to add external pull-up resistors at the sensor end?

    Sorry too many novice questions but your answers will help me to learn and understand.

    Regards



  • @Oridroo said in How to read out the output of 'ezPyro SMD I2C Pyroelectric Infrared Sensor' via I2C command?:

    Is it that simple or I'm just totally wrong?

    Yes it is simple and correct.[That's why i like python for none business job]
    R/W, ACK,NACK,START,STOP and other I2C stuff is not at your charge (low level driver do it for you). WARNING : Be sure that your sensor doesn't need I2C clock stretching because as far i know, it's not supported by firmware (https://forum.pycom.io/topic/331/i2c-clock-stretching )

    But you still have to read and understand your datasheet sensor to set it up correctly to have your correct value.

    Before starting your application code, i suggest you to start by a code with i2c.scan() to check if you have correctly set i2c wire (and don't forget the pull-up on both line SCL,SDA)


Log in to reply
 

Pycom on Twitter