Hi all,
I seem to have issues using the PROGMEM declaration for a 2D array. My project has to do with intelligent lighting so in my code, I have a function called void calcRefLight() which calculates the reference light source for a given CCT(Correlated Color Temperature) of a test light source based on the equations within the function.
The input to void calcRefLight() is CCT and the final result is stored in the variable refLight[]. I have another function getMaxValue() which simply finds the maximum value of an array and returns it. This maximum value will be used to normalize the final refLight[] output.
I run the following code and get the corresponding output. Note that I have not declared D_vector[][] under PROGMEM.
#include <avr/pgmspace.h>
#define RES 81
//Daylight vector for calculating CIE Standard D Illuminant
double D_vector[][4] = {{380, 63.4, 38.5, 3},
{385, 64.6, 36.75, 2.1},
{390, 65.8, 35, 1.2},
{395, 80.3, 39.2, 0.05},
{400, 94.8, 43.4, -1.1},
{405, 99.8, 44.85, -0.8},
{410, 104.8, 46.3, -0.5},
{415, 105.35, 45.1, -0.6},
{420, 105.9, 43.9, -0.7},
{425, 101.35, 40.5, -0.95},
{430, 96.8, 37.1, -1.2},
{435, 105.35, 36.9, -1.9},
{440, 113.9 , 36.7, -2.6},
{445, 119.75, 36.3, -2.75},
{450, 125.6, 35.9, -2.9},
{455, 125.55, 34.25, -2.85},
{460, 125.5, 32.6, -2.8},
{465, 123.4, 30.25, -2.7},
{470, 121.3, 27.9, -2.6},
{475, 121.3, 26.1, -2.6},
{480, 121.3, 24.3, -2.6},
{485, 117.4, 22.2, -2.2},
{490, 113.5, 20.1, -1.8},
{495, 113.3, 18.15, -1.65},
{500, 113.1, 16.2, -1.5},
{505, 111.95, 14.7, -1.4},
{510, 110.8, 13.2, -1.3},
{515, 108.65, 10.9, -1.25},
{520, 106.5, 8.6, -1.2},
{525, 107.65, 7.35, -1.1},
{530, 108.8, 6.1, -1},
{535, 107.05, 5.15, -0.75},
{540, 105.3, 4.2, -0.5},
{545, 104.85, 3.05, -0.4},
{550, 104.4, 1.9, -0.3},
{555, 102.2, 0.95, -0.15},
{560, 100, 0, 0},
{565, 98, -0.8, 0.1},
{570, 96, -1.6, 0.2},
{575, 95.55, -2.55, 0.35},
{580, 95.1, -3.5, 0.5},
{585, 92.1, -3.5, 1.3},
{590, 89.1, -3.5, 2.1},
{595, 89.8, -4.65, 2.65},
{600, 90.5, -5.8, 3.2},
{605, 90.4, -6.5, 3.65},
{610, 90.3, -7.2, 4.1},
{615, 89.35, -7.9, 4.4},
{620, 88.4, -8.6, 4.7},
{625, 86.2, -9.05, 4.9},
{630, 84, -9.5, 5.1},
{635, 84.55, -10.2, 5.9},
{640, 85.1, -10.9, 6.7},
{645, 83.5, -10.8, 7},
{650, 81.9, -10.7, 7.3},
{655, 82.25, -11.35, 7.95},
{660, 82.6, -12, 8.6},
{665, 83.75, -13, 9.2},
{670, 84.9, -14, 9.8},
{675, 83.1, -13.8, 10},
{680, 81.3, -13.6, 10.2},
{685, 76.6, -12.8, 9.25},
{690, 71.9, -12, 8.3},
{695, 73.1, -12.65, 8.95},
{700, 74.3, -13.3, 9.6},
{705, 75.35, -13.1, 9.05},
{710, 76.4, -12.9, 8.5},
{715, 69.85, -11.75, 7.75},
{720, 63.3, -10.6, 7},
{725, 67.5, -11.1, 7.3},
{730, 71.7, -11.6, 7.6},
{735, 74.35, -11.9, 7.8},
{740, 77, -12.2, 8},
{745, 71.1, -11.2, 7.35},
{750, 65.2, -10.2, 6.7},
{755, 56.45, -9, 5.95},
{760, 47.7, -7.8, 5.2},
{765, 58.15, -9.5, 6.3},
{770, 68.6, -11.2, 7.4},
{775, 66.8, -10.8, 7.1},
{780, 65, -10.4, 6.8}
};
//Global variables
double refLight[RES];
double CCT;
int i;
void setup()
{
Serial.begin(9600);
Serial.println("Initializing...");
CCT = 3500;
calcRefLight(CCT, refLight);
}
void loop()
{
}
//This function calculates the reference source light based on the CCT of the test source
void calcRefLight(double CCT, double refLight[])
{
double xD, yD;
double M1, M2;
double tempMax;
//if CCT < 5000 --> Planckian radiator used as reference source
//if 5000>CCT<7000 --> Daylight used as reference source
if (CCT < 5000)
{
Serial.println("Planckian radiator used as reference source");
for (i = 0; i < RES; i++)
{
refLight[i] = (pow((D_vector[i][0] * 1e-9), -5)) / exp((0.014388 / ((D_vector[i][0] * 1e-9) * CCT)) - 1);
//Serial.print(PlanckLaw[i]);
}
tempMax = getMaxValue(refLight, RES);
Serial.println("Normalized Reference source");
for (i = 0; i < RES; i++)
{
refLight[i] = refLight[i] / tempMax; //normalized reference light
Serial.println(refLight[i]);
}
}
else if (CCT <= 7000)
{
Serial.println("Daylight used as reference");
xD = (-4.6070e9 / (pow(CCT, 3))) + (2.9678e6 / (pow(CCT, 2))) + (0.9911e3 / CCT) + 0.244063;
yD = (-3.000 * (pow(xD, 2))) + (2.870 * xD) - 0.275;
M1 = (-1.3515 - 1.7703 * xD + 5.9114 * yD) / (0.0241 + 0.2562 * xD - 0.7341 * yD);
M2 = (0.03 - 31.4424 * xD + 30.0717 * yD) / (0.0241 + 0.2562 * xD - 0.7341 * yD);
for (i = 0; i < RES; i++)
{
refLight[i] = D_vector[i][1] + (M1 * D_vector[i][2]) + (M2 * D_vector[i][3]);
//Serial.println(dayLight[i]);
}
tempMax = getMaxValue(refLight, RES);
Serial.println("Normalized Reference source");
for (i = 0; i < RES; i++)
{
refLight[i] = refLight[i] / tempMax;
Serial.println(refLight[i]);
}
}
else //7000<CCT<25000
{
xD = (-2.0064e9 / (pow(CCT, 3))) + (1.9018e6 / (pow(CCT, 2))) + (0.24748e3 / CCT) + 0.237040;
yD = (-3.000 * (pow(xD, 2))) + (2.870 * xD) - 0.275;
M1 = (-1.3515 - 1.7703 * xD + 5.9114 * yD) / (0.0241 + 0.2562 * xD - 0.7341 * yD);
M2 = (0.03 - 31.4424 * xD + 30.0717 * yD) / (0.0241 + 0.2562 * xD - 0.7341 * yD);
Serial.println("Daylight used as reference");
for (i = 0; i < RES; i++)
{
refLight[i] = D_vector[i][1] + (M1 * D_vector[i][2]) + (M2 * D_vector[i][3]);
//Serial.println(dayLight[i]);
}
tempMax = getMaxValue(refLight, RES);
Serial.println("Normalized Reference source");
for (i = 0; i < RES; i++)
{
refLight[i] = refLight[i] / tempMax;
Serial.println(refLight[i]);
}
}
}
//find max value and its index of an array
double getMaxValue(double array[], int n)
{
int maxIndex = 0;
double maxValue = array[maxIndex];
for (int i = 0; i < n; i++)
{
if (maxValue < array[i])
{
maxValue = array[i];
maxIndex = i;
}
}
return maxValue;
}
OUTPUT:Initializing...
Planckian radiator used as reference source
Normalized Reference source
0.14
0.15
0.16
0.18
0.19
0.20
0.21
0.23
0.24
0.26
0.27
0.28
0.30
0.31
0.33
0.34
0.36
0.37
0.39
0.40
0.42
0.44
0.45
0.47
0.48
0.50
0.51
0.53
0.54
0.56
0.57
0.59
0.60
0.62
0.63
0.65
0.66
0.67
0.69
0.70
0.71
0.73
0.74
0.75
0.76
0.78
0.79
0.80
0.81
0.82
0.83
0.84
0.85
0.86
0.87
0.88
0.88
0.89
0.90
0.91
0.91
0.92
0.93
0.93
0.94
0.95
0.95
0.96
0.96
0.97
0.97
0.97
0.98
0.98
0.99
0.99
0.99
0.99
1.00
1.00
1.00
Result of output is as expected. Now, the only change I have made is the declaration of D_vector[][] under PROGMEM and get the following output.
const double D_vector[][4] PROGMEM ={};
OUTPUT:
Initializing...
Planckian radiator used as reference source
Normalized Reference source
inf
inf
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
nan
inf
inf
nan
nan
inf
inf
inf
nan
nan
nan
inf
nan
inf
nan
nan
nan
inf
inf
inf
nan
nan
inf
inf
nan
nan
inf
inf
inf
Can anyone explain this behavior when using PROGMEM? I need to use PROGMEM due to memory issues. Am I going wrong somewhere?
I'm using Arduino IDE 1.6.5 with Arduino MEGA 2560. Any help is much appreciated.
Cheers