My project is and RTISR (Real Time Instant Signal Recognizer). I'm sampling a signal from PIN A0 in the Arduino, and I have 6 types of Signals which I compare with (using squared cross correlation to avoid using sqrt() function).
Any way, to avoid killing my SRAM I wanted to burn the data of the 6 known signals in the Flash memory. I wanted to put there the signal, its Mean value, and its variance, which I calculate in advanced (with a function).
there is the code:
#include <avr/pgmspace.h>
#include <math.h>
#define T1_PS_L 5 //Timer1_Prescalers_Length
#define MAIN_CLK_FREQ 16000000
#define TIMER1_REG_CAPACITY 65536
#define NUM_OF_SAMPLES 64
#define SAMPLING_FREQUENCY 100
#define ANALOG_INPUT_PIN A0
#define WAVE_1 1 //PORTB PIN 8
#define WAVE_2 2 //PORTB PIN 9
#define WAVE_3 4 //PORTB PIN 10
#define WAVE_4 8 //PORTB PIN 11
#define WAVE_5 16 //PORTB PIN 12
#define WAVE_6 32 //PORTB PIN 13
#define NUM_OF_ETALONS 6
const short timer1_prescalers[] PROGMEM = {1, 8, 64, 256, 1024};
void SetTimer1CTCforFreq(float freq);
long get_prescaler_timer(float freq, char *ref_pres_indx);
double CrossCorrelation(const double x[], volatile double y[], int len, int delay);
double Variance(double arr[], int len);
double Mean(double arr[], int len);
/*-------------- ETALON SIGNALS ---------------------*/
const double sinWave1[NUM_OF_SAMPLES] PROGMEM = {0.0, 0.0980171403295606, 0.19509032201612825, 0.29028467725446233,
0.3826834323650898, 0.47139673682599764, 0.5555702330196022, 0.6343932841636455,
0.7071067811865475, 0.773010453362737, 0.8314696123025452, 0.8819212643483549,
0.9238795325112867, 0.9569403357322089, 0.9807852804032304, 0.9951847266721968, 1.0,
0.9951847266721969, 0.9807852804032304, 0.9569403357322089, 0.9238795325112867,
0.881921264348355, 0.8314696123025455, 0.7730104533627371, 0.7071067811865476,
0.6343932841636455, 0.5555702330196022, 0.47139673682599786, 0.3826834323650899,
0.2902846772544624, 0.1950903220161286, 0.09801714032956083, 1.2246467991473532e-16,
-0.09801714032956059, -0.19509032201612836, -0.2902846772544621, -0.38268343236508967,
-0.47139673682599764, -0.555570233019602, -0.6343932841636453, -0.7071067811865475,
-0.7730104533627367, -0.8314696123025452, -0.8819212643483549, -0.9238795325112865,
-0.9569403357322088, -0.9807852804032303, -0.9951847266721969, -1.0, -0.9951847266721969,
-0.9807852804032304, -0.9569403357322089, -0.9238795325112866, -0.881921264348355,
-0.8314696123025455, -0.7730104533627369, -0.7071067811865477, -0.6343932841636459,
-0.5555702330196022, -0.4713967368259979, -0.3826834323650904, -0.2902846772544625,
-0.19509032201612872, -0.0980171403295605};
const double sinWave2[NUM_OF_SAMPLES] PROGMEM = {0.0, 0.19509032201612825, 0.3826834323650898, 0.5555702330196022,
0.7071067811865475, 0.8314696123025452, 0.9238795325112867, 0.9807852804032304,
1.0, 0.9807852804032304, 0.9238795325112867, 0.8314696123025455,
0.7071067811865476, 0.5555702330196022, 0.3826834323650899, 0.1950903220161286,
1.2246467991473532e-16, -0.19509032201612836, -0.38268343236508967,
-0.555570233019602, -0.7071067811865475, -0.8314696123025452,
-0.9238795325112865, -0.9807852804032303, -1.0, -0.9807852804032304,
-0.9238795325112866, -0.8314696123025455, -0.7071067811865477,
-0.5555702330196022, -0.3826834323650904, -0.19509032201612872,
-2.4492935982947064e-16, 0.19509032201612825, 0.38268343236508995,
0.5555702330196018, 0.7071067811865474, 0.8314696123025452,
0.9238795325112865, 0.9807852804032303, 1.0, 0.9807852804032307,
0.9238795325112867, 0.8314696123025456, 0.7071067811865483,
0.5555702330196023, 0.3826834323650905, 0.19509032201612797,
3.6739403974420594e-16, -0.19509032201612725, -0.38268343236508984,
-0.5555702330196017, -0.7071067811865479, -0.8314696123025451,
-0.9238795325112864, -0.9807852804032305, -1.0, -0.9807852804032307,
-0.9238795325112867, -0.8314696123025456, -0.7071067811865485,
-0.5555702330196024, -0.3826834323650906, -0.19509032201612808};
const double sinWave3[NUM_OF_SAMPLES] PROGMEM = {0.0, 0.29028467725446233, 0.5555702330196022, 0.773010453362737,
0.9238795325112867, 0.9951847266721968, 0.9807852804032304, 0.881921264348355,
0.7071067811865476, 0.47139673682599786, 0.1950903220161286,
-0.09801714032956059, -0.38268343236508967, -0.6343932841636453,
-0.8314696123025452, -0.9569403357322088, -1.0, -0.9569403357322089,
-0.8314696123025455, -0.6343932841636459, -0.3826834323650904,
-0.0980171403295605, 0.19509032201612825, 0.47139673682599753,
0.7071067811865474, 0.8819212643483548, 0.9807852804032303,
0.9951847266721969, 0.9238795325112867, 0.7730104533627375,
0.5555702330196023, 0.29028467725446344, 3.6739403974420594e-16,
-0.2902846772544628, -0.5555702330196017, -0.7730104533627371,
-0.9238795325112864, -0.9951847266721969, -0.9807852804032307,
-0.8819212643483552, -0.7071067811865485, -0.47139673682599814,
-0.19509032201612808, 0.09801714032955978, 0.3826834323650897,
0.6343932841636447, 0.831469612302545, 0.9569403357322085, 1.0,
0.9569403357322088, 0.8314696123025457, 0.6343932841636455,
0.3826834323650907, 0.09801714032956088, -0.195090322016127,
-0.47139673682599564, -0.7071067811865477, -0.8819212643483547,
-0.9807852804032301, -0.9951847266721968, -0.9238795325112868,
-0.7730104533627378, -0.5555702330196041, -0.2902846772544621};
const double rectWave4[NUM_OF_SAMPLES] PROGMEM = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1};
const double rectWave5[NUM_OF_SAMPLES] PROGMEM = {-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
const double triWave6[NUM_OF_SAMPLES] PROGMEM = {0.0, 0.0625, 0.125, 0.1875, 0.25, 0.3125, 0.375, 0.4375, 0.5,
0.5625, 0.625, 0.6875, 0.75, 0.8125, 0.875, 0.9375, 1.0, 0.9375,
0.875, 0.8125, 0.75, 0.6875, 0.625, 0.5625, 0.5, 0.4375, 0.375,
0.3125, 0.25, 0.1875, 0.125, 0.0625, 0.0, -0.0625, -0.125, -0.1875,
-0.25, -0.3125, -0.375, -0.4375, -0.5, -0.5625, -0.625, -0.6875,
-0.75, -0.8125, -0.875, -0.9375, -1.0, -0.9375, -0.875, -0.8125,
-0.75, -0.6875, -0.625, -0.5625, -0.5, -0.4375, -0.375, -0.3125,
-0.25, -0.1875, -0.125, -0.0625};
const double sinWaveMean1 PROGMEM = (const double)Mean((double*)sinWave1, NUM_OF_SAMPLES);
const double sinWaveMean2 PROGMEM = (const double)Mean((double*)sinWave2, NUM_OF_SAMPLES);
const double sinWaveMean3 PROGMEM = (const double)Mean((double*)sinWave3, NUM_OF_SAMPLES);
const double rectWaveMean4 PROGMEM = (const double)Mean((double*)rectWave4, NUM_OF_SAMPLES);
const double rectWaveMean5 PROGMEM = (const double)Mean((double*)rectWave5, NUM_OF_SAMPLES);
const double triWaveMean6 PROGMEM = (const double)Mean((double*)triWave6, NUM_OF_SAMPLES);
const double sinWaveVariance1 PROGMEM = Variance((double*)sinWave1, NUM_OF_SAMPLES);
const double sinWaveVariance2 PROGMEM = Variance((double*)sinWave2, NUM_OF_SAMPLES);
const double sinWaveVariance3 PROGMEM = Variance((double*)sinWave3, NUM_OF_SAMPLES);
const double rectWaveVariance4 PROGMEM = Variance((double*)rectWave4, NUM_OF_SAMPLES);
const double rectWaveVariance5 PROGMEM = Variance((double*)rectWave5, NUM_OF_SAMPLES);
const double triWaveVariance6 PROGMEM = Variance((double*)triWave6, NUM_OF_SAMPLES);
const double* const Etalon_Signals[NUM_OF_ETALONS] PROGMEM = {sinWave1, sinWave2, sinWave3, rectWave4, rectWave5, triWave6};
const double Etalon_Signals_Mean[NUM_OF_ETALONS] PROGMEM = {sinWaveMean1, sinWaveMean2, sinWaveMean3, rectWaveMean4, rectWaveMean5, triWaveMean6};
const double Etalon_Signals_Variance[NUM_OF_ETALONS] PROGMEM = {sinWaveVariance1, sinWaveVariance2, sinWaveVariance3, rectWaveVariance4, rectWaveVariance5, triWaveVariance6};
/*-------------- SAMPLED SIGNAL ---------------------*/
volatile double signal_samples[NUM_OF_SAMPLES];
volatile int idx = 0;
/*-------------- CORRELATION VARS -------------------*/
volatile int counter = 0;
volatile double correlation = 0, MostSimillarCorrVal = 0, LocalMaxCorr = 0, maxCorrWave = 0;
volatile double SignalSamplesVar = 0, yMean = 0;
double EtalonSignalVal, EtalonMeanVal, EtalonVarianceVal, SignalSamplesVarTemp;
void setup()
{
SetTimer1CTCforFreq(SAMPLING_FREQUENCY);
DDRB = WAVE_1 | WAVE_2 | WAVE_3 | WAVE_4 | WAVE_5 | WAVE_6;
pinMode(A0, INPUT);
Serial.begin(115200);
}
void loop()
{
Serial.println("hi");
}
ISR(TIMER1_COMPA_vect)
{
signal_samples[idx] = analogRead(ANALOG_INPUT_PIN);
Serial.println(signal_samples[idx]);
for(int k = 0; k < NUM_OF_ETALONS; k++)
{
EtalonMeanVal = pgm_read_float(&Etalon_Signals_Mean[k]);
EtalonVarianceVal = pgm_read_float(&Etalon_Signals_Variance[k]);
Serial.println(EtalonVarianceVal);
Serial.println(EtalonMeanVal);
for(int delay = -NUM_OF_SAMPLES; delay < NUM_OF_SAMPLES; delay++)
{
counter = 0;
while(counter < NUM_OF_SAMPLES)
{
SignalSamplesVarTemp = (signal_samples[(idx + counter - delay)%NUM_OF_SAMPLES] - yMean) * (signal_samples[(idx + counter - delay)%NUM_OF_SAMPLES] - yMean);
SignalSamplesVar += SignalSamplesVarTemp;
correlation += EtalonVarianceVal*SignalSamplesVarTemp;
counter++;
}
correlation /= SignalSamplesVar * EtalonVarianceVal;
LocalMaxCorr = LocalMaxCorr < correlation ? correlation : LocalMaxCorr;
}
if(MostSimillarCorrVal < LocalMaxCorr)
{
MostSimillarCorrVal = LocalMaxCorr;
maxCorrWave = 1<<(k+1); // num of wave is 1 shifted left k+1 times.
}
}
PORTB = maxCorrWave;
idx = (idx+1)%NUM_OF_SAMPLES;
}
/*
x - first signal.
y - second signal.
len - length of both of signals (or the max{LEN_x, LEN_y}).
*/
double CrossCorrelation(double x[], double y[], int len, int delay)
{
double corr = 0, xVar = Variance(x, len), SignalSamplesVar = 0;
double xMean = Mean(x, len), yMean = Mean(y, len);
for (int i = 0; i < len; i++)
{
if ((i - delay) >= 0 && (i - delay) < len)
{
SignalSamplesVar += (y[i - delay] - yMean) * (y[i - delay] - yMean);
corr += (x[i] - xMean) * (y[i - delay] - yMean) * (x[i] - xMean) * (y[i - delay] - yMean);
}
}
double denominator = SignalSamplesVar * xVar;
if (!denominator)
return 0;
else
corr /= denominator;
return corr;
}
double Variance(double arr[], int len)
{
double mean = Mean(arr, len);
double variance = 0;
for (int i = 0; i < len; i++)
variance += (arr[i] - mean) * (arr[i] - mean);
return variance;
}
double Mean(double arr[], int len)
{
double sum = 0;
for (int i = 0; i < len; i++)
sum += arr[i];
return (sum / len);
}
long get_prescaler_timer(float freq, char *ref_pres_indx)
{
bool loop_runs = true;
float count_f = 0;
long count_l = 0;
char index = 0;
long first_count_to_work = 0;
char first_idx_to_work = 0;
for (index = 0; index < T1_PS_L && loop_runs; index++)
{
count_f = MAIN_CLK_FREQ / (freq * timer1_prescalers[index]) - 1;
count_l = (long)count_f;
loop_runs = ((count_f - count_l) != 0 || count_l > TIMER1_REG_CAPACITY);
first_count_to_work += count_l * (count_f < TIMER1_REG_CAPACITY && first_count_to_work == 0);
first_idx_to_work += index * (first_count_to_work != 0 && first_idx_to_work == 0);
}
*ref_pres_indx = index;
if (loop_runs) // if we didnt finish the loop succesfuly.
{
*ref_pres_indx = first_idx_to_work;
count_l = first_count_to_work;
}
return count_l;
}
void SetTimer1CTCforFreq(float freq)
{
char mask = 1;
char pres_indx = 0;
cli(); //stop interrupts
TCCR1A = 0; // set entire TCCR1A register to 0
TCCR1B = 0; // same for TCCR1B
TCNT1 = 0; // initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = get_prescaler_timer(freq, &pres_indx); // = (16*10^6) / (1[HZ]*1024[prescaler]) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS10 and CS12 bits for 1024 prescaler
do
{
TCCR1B |= mask * (pres_indx % 2); // in datasheet, values can be 1 - 5.
pres_indx /= 2;
mask = mask << 1;
} while (pres_indx);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei(); //allow interrupts
}
I'm getting the Error: "variable 'Etalon_Signals_Mean' with dynamic initialization put into program memory area" and it marks the line:
const double Etalon_Signals_Mean[NUM_OF_ETALONS] PROGMEM = {sinWaveMean1, sinWaveMean2, sinWaveMean3, rectWaveMean4, rectWaveMean5, triWaveMean6};
which are somewhere at the beggining (line 116). I dont understand why. My guess is that the compiler sees the "Mean" values which are a result of a function, and functions are "dynamic". But those values are getting into a const variable, so I don't get it. Please help.