Thermal cam with PROGMEM

Dear all,

I am working with an amg88xx sensor on an MEGA arduino board attached to an ILI9341 shell. The original sample code provided by the arduino IDE, with interpolation, was changed from TFT to UTFT. The system works perfectly. However, I would like to insert the camColors constant into PROGMEM. This will be necessary for me in the future to save arduino memory. All my attempts to insert PROGMEM are failing. I don’t know if I’m reading the constant by the wrong way. The fact is that when using PROGMEM the scan speed seems to reduce significantly and the color map changes completely with each scan. My latest version is attached.
Obviously I’m doing some thing wrong and I need some help. Thank for any help with this code.

Cesar

      #include <Wire.h>
      #include <ITDB02_Touch.h>
      #include <memorysaver.h>
      #include <UTFT_Buttons_ITDB.h>

      //Declare which fonts we will be using
      extern uint8_t SmallFont[];
      extern uint8_t BigFont[];
      extern uint8_t SevenSegNumFont[];
      extern unsigned char TinyFont[];
    
      int x, y;    
      #define YAXIS 0 //Axis of the TFT sceen
      #define XAXIS 1
      #define PRESSDELAY 200 //Delay between touch screen readings
      // Set the pins to the correct ones for your development shield
      UTFT myGLCD(ILI9341_16,38,39,40,41);

      #define BLACK   0x0000

      #include <Adafruit_AMG88xx.h>                                                                                                                           
      //low range of the sensor (this will be blue on the screen)
      #define MINTEMP 20
      //high range of the sensor (this will be red on the screen)
      #define MAXTEMP 28

      #include <avr/pgmspace.h>                                                                     
      byte b;
      unsigned int displayInt;
                                                                         
      //the colors we will be using
      const PROGMEM uint16_t camColors[] = {0x480F,
      0x400F,0x400F,0x400F,0x4010,0x3810,0x3810,0x3810,0x3810,0x3010,0x3010,
      0x3010,0x2810,0x2810,0x2810,0x2810,0x2010,0x2010,0x2010,0x1810,0x1810,
      0x1811,0x1811,0x1011,0x1011,0x1011,0x0811,0x0811,0x0811,0x0011,0x0011,
      0x0011,0x0011,0x0011,0x0031,0x0031,0x0051,0x0072,0x0072,0x0092,0x00B2,
      0x00B2,0x00D2,0x00F2,0x00F2,0x0112,0x0132,0x0152,0x0152,0x0172,0x0192,
      0x0192,0x01B2,0x01D2,0x01F3,0x01F3,0x0213,0x0233,0x0253,0x0253,0x0273,
      0x0293,0x02B3,0x02D3,0x02D3,0x02F3,0x0313,0x0333,0x0333,0x0353,0x0373,
      0x0394,0x03B4,0x03D4,0x03D4,0x03F4,0x0414,0x0434,0x0454,0x0474,0x0474,
      0x0494,0x04B4,0x04D4,0x04F4,0x0514,0x0534,0x0534,0x0554,0x0554,0x0574,
      0x0574,0x0573,0x0573,0x0573,0x0572,0x0572,0x0572,0x0571,0x0591,0x0591,
      0x0590,0x0590,0x058F,0x058F,0x058F,0x058E,0x05AE,0x05AE,0x05AD,0x05AD,
      0x05AD,0x05AC,0x05AC,0x05AB,0x05CB,0x05CB,0x05CA,0x05CA,0x05CA,0x05C9,
      0x05C9,0x05C8,0x05E8,0x05E8,0x05E7,0x05E7,0x05E6,0x05E6,0x05E6,0x05E5,
      0x05E5,0x0604,0x0604,0x0604,0x0603,0x0603,0x0602,0x0602,0x0601,0x0621,
      0x0621,0x0620,0x0620,0x0620,0x0620,0x0E20,0x0E20,0x0E40,0x1640,0x1640,
      0x1E40,0x1E40,0x2640,0x2640,0x2E40,0x2E60,0x3660,0x3660,0x3E60,0x3E60,
      0x3E60,0x4660,0x4660,0x4E60,0x4E80,0x5680,0x5680,0x5E80,0x5E80,0x6680,
      0x6680,0x6E80,0x6EA0,0x76A0,0x76A0,0x7EA0,0x7EA0,0x86A0,0x86A0,0x8EA0,
      0x8EC0,0x96C0,0x96C0,0x9EC0,0x9EC0,0xA6C0,0xAEC0,0xAEC0,0xB6E0,0xB6E0,
      0xBEE0,0xBEE0,0xC6E0,0xC6E0,0xCEE0,0xCEE0,0xD6E0,0xD700,0xDF00,0xDEE0,
      0xDEC0,0xDEA0,0xDE80,0xDE80,0xE660,0xE640,0xE620,0xE600,0xE5E0,0xE5C0,
      0xE5A0,0xE580,0xE560,0xE540,0xE520,0xE500,0xE4E0,0xE4C0,0xE4A0,0xE480,
      0xE460,0xEC40,0xEC20,0xEC00,0xEBE0,0xEBC0,0xEBA0,0xEB80,0xEB60,0xEB40,
      0xEB20,0xEB00,0xEAE0,0xEAC0,0xEAA0,0xEA80,0xEA60,0xEA40,0xF220,0xF200,
      0xF1E0,0xF1C0,0xF1A0,0xF180,0xF160,0xF140,0xF100,0xF0E0,0xF0C0,0xF0A0,
      0xF080,0xF060,0xF040,0xF020,0xF800,};

      Adafruit_AMG88xx amg;
      unsigned long delayTime;

      #define AMG_COLS 8
      #define AMG_ROWS 8
      float pixels[AMG_COLS * AMG_ROWS];

      #define INTERPOLATED_COLS 24
      #define INTERPOLATED_ROWS 24

      float get_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
      void set_point(float *p, uint8_t rows, uint8_t cols, int8_t x, int8_t y, float f);
      void get_adjacents_1d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
      void get_adjacents_2d(float *src, float *dest, uint8_t rows, uint8_t cols, int8_t x, int8_t y);
      float cubicInterpolate(float p[], float x);
      float bicubicInterpolate(float p[], float x, float y);
      void interpolate_image(float *src, uint8_t src_rows, uint8_t src_cols, 
      float *dest, uint8_t dest_rows, uint8_t dest_cols);

     
       void setup()
       {
       // Setup the LCD
       Serial.begin(9600);
       Wire.begin();
       myGLCD.InitLCD();//(oriantation:90)
       myGLCD.clrScr();
       myGLCD.setBackColor(BLACK);
            
       //Serial.println("\n\nAMG88xx Interpolated Thermal Camera!");
       if (!amg.begin()) {
       //Serial.println("Could not find a valid AMG88xx sensor, check wiring!");
       while (1) { delay(1); }                 
       }       
       }
      
  
      void loop() {       
        //read all the pixels
        amg.readPixels(pixels);       
        for(int i=1; i<=AMG88xx_PIXEL_ARRAY_SIZE; i++){
        }                
        float dest_2d[INTERPOLATED_ROWS * INTERPOLATED_COLS];
        int32_t t = millis();
        interpolate_image(pixels, AMG_ROWS, AMG_COLS, dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS);
        uint16_t boxsize = min(myGLCD.getDisplayXSize() / INTERPOLATED_COLS, myGLCD.getDisplayYSize() / INTERPOLATED_COLS);
        drawpixels(dest_2d, INTERPOLATED_ROWS, INTERPOLATED_COLS, boxsize, boxsize, false);     
      }

     //======================================================================================================Void drawpixels for Thermal Cam

      void drawpixels(float *p, uint8_t rows, uint8_t cols, uint8_t boxWidth, uint8_t boxHeight, boolean showVal) {      
        int colorTemp;
        for (int y=5; y<rows; y++) {
        for (int x=0; x<cols; x++) {
        float val = get_point(p, rows, cols, x, y);
        if(val >= MAXTEMP) colorTemp = MAXTEMP;
        else if(val <= MINTEMP) colorTemp = MINTEMP;
        else colorTemp = val;     
        uint8_t colorIndex = map(colorTemp, MINTEMP, MAXTEMP, 0, 255);
        colorIndex = constrain(colorIndex, 0, 255);
        //draw the pixels!
        uint16_t color;
        color = val * 2; 


       
              
 
        for ( byte b = 0; b < 246; b++) {
        //displayInt = pgm_read_word_near(camColors + b);
        displayInt = pgm_read_byte(camColors + b);
        //Serial.println(displayInt);               
        }
      
        
                                                                                                                                                                                                                                           
        myGLCD.setColor(camColors[colorIndex]); 
        myGLCD.fillRect(40+boxWidth * x, boxHeight * y, 40+boxWidth * x + boxWidth, boxHeight * y + boxHeight);        
        } 
       }
      }

You are storing 16 bit unsigned ints but your code is reading bytes ( uint8_t). That is a problem.

Also, you are calling

      myGLCD.setColor(camColors[colorIndex]);

but that is not accessing PROGMEM.

      colorIndex = constrain(colorIndex, 0, 255);
      colorValue = pgm_read_word_near(camColors + colorIndex);

      myGLCD.setColor(colorValue);

Yes, now I understand very clear. Make sense. It is working very well. Thank you very much for your help.

Cesar