Today I only want to give a small update on the function to read out the data of the temperature array of the grid-eye sensor. Until now I read out the data of one sensor pixel at once (which is 2 bytes) and then switch to the next pixel. This is a little bit unfortunate because the adressing of the sensor and the byte has to be done each time and a lot of overhead is generated.

 

It is much faster to read out as much bytes as possible at one read access. This is what I did today.

 

Therefore I used the function i2c_smbus_read_i2c_block_data. This function allows to read a block of data at once. It is limited to 32 byte because this is a restriction of the SMBus. Nevertheless this is much more than the 2 bytes I read out before and less overhead is generated. The data of the 64 pixels of the temperature sensor is stored in 128 bytes. So I have to read out 4 blocks of 32 bytes each.

 

The downside of this approach is that the source code is not as self explaining as it was before. Here is the code which does the same as in my previous blog post Stove Assistant - Bernhard - Pi Chef #3 - Connect Panasonic Grid-Eye sensor to Raspberry Pi :

 

#include <stdio.h>
#include <stdlib.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <unistd.h>
#include <opencv2/opencv.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <opencv2/contrib/contrib.hpp>


int main(void)
{
    int file;
    int addr=0x68;        // adress of AMG88xx
    int x,y;     // variables to got through the array
    signed short int internal_temp;
    signed short int pixel_temp[64];    // array for pixel temperatures
    
    int end=1;  // variable to end program
    printf("Pi Chef Stove Assistant Demo with AMG88xx\n");  // print start message
    if((file=open("/dev/i2c-1",O_RDWR))<0)    // open i2c-bus
    {
        perror("cannot open i2c-1");
        exit(1);
    }
    if(ioctl(file, I2C_SLAVE, addr)<0)    // open slave
    {
        perror("cannot open slave address");
        exit(1);
    }

    internal_temp=(signed short)(i2c_smbus_read_word_data(file, 0x0e)<<4);
    internal_temp=internal_temp/16;
    printf("Internal Temp: %f C (0x%04X = %i)\n",(float)internal_temp*0.0625,internal_temp,internal_temp);

    cv::Mat outSmall(8,8,CV_8UC1);        // create opencv mat for sensor data
    cv::Mat outSmallnorm(8,8,CV_8UC1);    // create opencv mat for normalized data
    cv::Mat outColor;    // create opencv mat for color output

    while(end==1)  // check end variable
    {
        cv::TickMeter t;
        t.start();    // start timer

        x=i2c_smbus_read_i2c_block_data(file,0x80,32,(__u8*)pixel_temp);    // read first 32 byte / 16 temperature pixels from sensor
        x=i2c_smbus_read_i2c_block_data(file,0xa0,32,(__u8*)pixel_temp+32);       // read next 32 byte / 16 temperature pixels from sensor
        x=i2c_smbus_read_i2c_block_data(file,0xc0,32,(__u8*)pixel_temp+64);       // read next 32 byte / 16 temperature pixels from sensor
        x=i2c_smbus_read_i2c_block_data(file,0xe0,32,(__u8*)pixel_temp+96);       // read last 32 byte / 16 temperature pixels from sensor

        for(x=0;x<64;x++)
        {
            pixel_temp[x]=(signed short)(pixel_temp[x]<<4)/16;    // set pixel_temp to original value
        }

        for(x=0;x<8;x++)
        {
            for(y=0;y<8;y++)
            {
                outSmall.at(x,y)=pixel_temp[x*8+y];    // copy temperature pixels into opencv mat
            }
        }
        t.stop();    // stop timer
        printf("Time: %f ms\n", (double)t.getTimeMilli() / t.getCounter());  // print result of timer

        cv::normalize(outSmall,outSmallnorm,255,0,cv::NORM_MINMAX);    // normalize Mat to values between 0 and 255
        cv::resize(outSmallnorm,outSmallnorm,cv::Size(256,256));    // resize Mat to 256 x 256 pixel
        cv::applyColorMap(outSmallnorm,outColor,cv::COLORMAP_JET);  // generate colored output with colormap
        cv::imshow("AMG88xx",outColor);  // display mat on screen
        char key = cv::waitKey(500);  // check keys for input
        if(key=='e') end=0;  // end if e was pressed
    }
    printf("ended regularly!\n");  // print end message
    close(file);
    return 0;
}

 

In the source code I also added an OpenCV timer to measure the duration of the code execution.

With my old code it took 52 ms to get the data from the sensor.

Now it takes only 20 ms.

So the new code is 2.5 times faster. Not bad for this little change.