I have a variable which changes unexpectedly

Sorry if this is a bit long, but it is probably better to have all the code rather than just some of it.

This code is meant to output a sine-wave and synchronously measure the induced voltage in a pair of secondary coils.

Because it is AC coupled I need to subtract the zero-volts ADC counts from the measured voltage. To do this I populate an array with the ADC counts of all 6 channels in the setup() function before activating the sine wave

My problem is that the first value in the array (Z[0]) doesn't stay static. In the incuded code it is Serial.print-ed and it changes just like the V[0] does when I twiddle the test-rig potentiometer.

I have checked that the setup() function isn't running continuously. I am probably missing something obvious, but I am truly baffled.

(Incidentally, I know that I am measuring 6 values and using 2, the code isn't finished)

#include "avr/pgmspace.h"

// table of 256 sine values / one sine period / stored in flash memory
PROGMEM  prog_uchar sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
PROGMEM prog_uchar arctan256[] = {
  0,0,0,1,1,1,1,2,2,2,2,2,3,3,3,3,4,4,4,4,4,5,5,5,5,6,6,6,6,6,7,7,7,7,8,8,8,8,8,9,9,9,9,10,10,10,10,10,11,11,11,11,11,12,12,12,12,13,13,13,13,13,14,14,14,14,14,15,15,15,15,16,16,16,16,16,17,17,17,17,17,
  18,18,18,18,18,19,19,19,19,19,20,20,20,20,20,21,21,21,21,21,22,22,22,22,22,22,23,23,23,23,23,24,24,24,24,24,25,25,25,25,25,25,26,26,26,26,26,27,27,27,27,27,27,28,28,28,28,28,29,29,29,29,29,29,30,30,30,30,30,30,
  31,31,31,31,31,31,32,32,32,32,32,32,32,33,33,33,33,33,33,34,34,34,34,34,34,35,35,35,35,35,35,35,36,36,36,36,36,36,36,37,37,37,37,37,37,37,38,38,38,38,38,38,38,39,39,39,39,39,39,39,39,40,40,40,40,40,40,40,
  41,41,41,41,41,41,41,41,42,42,42,42,42,42,42,42,43,43,43,43,43,43,43,43,44,44,44,44,44,44,44,44,44,45,45,45,45,45,45
};

byte EP[] = { B00, B01, B11, B10 }; // Encoder pattern

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int ledPin = 13;                 // LED pin 7
int testPin = 7;

volatile long V[5]; // Analogue values
int Z[5]; // Zero-offset values for each channel
int Q[2]; // Three Quadrature encoders
int A[2]; // Three Angles
long Cos;
long Sin;
volatile byte index; // index to current mux channel

volatile byte icnt;              // var inside interrupt

void setup()
{
  pinMode(13, OUTPUT);      // sets the digital pin as output
  Serial.begin(115200);        // connect to the serial port
  pinMode(6, OUTPUT);      // sets the digital pin as output
  pinMode(7, OUTPUT);      // sets the digital pin as output
  pinMode(11, OUTPUT);     // pin11= PWM  output / frequency output
  pinMode(2, OUTPUT);     // Encoder 0 Phase A
  pinMode(3, OUTPUT);     // Encoder 0 Phase B
  pinMode(4, OUTPUT);     // Encoder 0 Phase Z
  
  //First populate the zero-volt value for each channel
  for (int i = 0 ; i <= 5 ; i++) { // iterate through channels
    for (int j = 1 ; j<=1000 ; j++) { // 1000 samples should do
      V[i] = V[i] + analogRead(i);
    }
    Z[i] = V[i] / 1000;
    V[i] = 0;
    Serial.println(Z[i], DEC);
  }
  
  Setup_timer2();

  // disable interrupts to avoid timing distortion
  cbi (TIMSK0,TOIE0);              // disable Timer0 !!! delay() is now not available
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt
  
  SetupADC();

}
void loop()
{
  sbi (TIMSK2,TOIE2);              // enable Timer2 Interrupt 
  while(1) {
    Cos = V[0] - Z[0];
    Sin = V[1] - Z[1];
    A[0] = arctan(Cos, Sin);
    Serial.println(Z[0], DEC);
    // Count till the Quadrature counter equals the angle
    if ((Q[0] - A[0]) > 120 || (Q[0] - A[0]) < 0) 
      {
        Q[0]++ ;
      }
    else if ((A[0] - Q[0]) > 120 || (A[0] - Q[0]) < 0) 
      {
        Q[0]-- ;
      }
      
    Q[0] = Q[0] % 360 ;
    
    // Set the encoder bits accordingly
    if (Q[0] == 0) sbi(PORTD, 4);
    else cbi(PORTD,4);
    
    if (EP[Q[0] & 3] & 1) sbi(PORTD, 2);
    else cbi(PORTD,2);
    
    if (EP[Q[0] & 3] & 2) sbi(PORTD, 3);
    else cbi(PORTD,3);
  }
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM,  16000000/510 = 31372.55 Hz clock
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
  sbi (TCCR2B, CS20);
  cbi (TCCR2B, CS21);
  cbi (TCCR2B, CS22);

  // Timer2 PWM Mode set to Phase Correct PWM
  cbi (TCCR2A, COM2A0);  // clear Compare Match
  sbi (TCCR2A, COM2A1);

  sbi (TCCR2A, WGM20);  // Mode 1  / Phase Correct PWM
  cbi (TCCR2A, WGM21);
  cbi (TCCR2B, WGM22);
}

//Setup ADC
void SetupADC() {
 cbi(ADMUX, REFS1);
 sbi(ADMUX, REFS0); // Internal AREF (5V)
 cbi(ADMUX, ADLAR); // Not left-aligned
 cbi(ADMUX, MUX3);
 cbi(ADMUX, MUX2); 
 cbi(ADMUX, MUX1);
 cbi(ADMUX, MUX0); // Set the Mux to zero to begin
 
 sbi(ADCSRA, ADEN); // Enable the ADC
 cbi(ADCSRA, ADSC); // Don't start conversion yet
 cbi(ADCSRA, ADATE); // No auto-trigger
 cbi(ADCSRA, ADIF); // Not sure if that is possible or wise
 sbi(ADCSRA, ADIE); // Conversion-complete Interrupt to process data
 cbi(ADCSRA, ADPS2);
 sbi(ADCSRA, ADPS1); 
 sbi(ADCSRA, ADPS0); // Fastest possible ADC clock. Probably not ideal. 
}

//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {

  sbi(PORTD,7);          // Test / set PORTD,7 high to observe timing with a oscope

  icnt=icnt+16;     // use upper 8 bits for phase accu as frequency information
                         // read value fron ROM sine table and send to PWM DAC
  OCR2A=pgm_read_byte_near(sine256 + icnt);  

  if (icnt == 96) {
    sbi(ADCSRA, ADSC);  // Start Conversion
    sbi(PORTB,5); // LED on to show start of conversion
  }
 cbi(PORTD,7);            // reset PORTD,7
}

// ADC Conversion Complete Interrupt
ISR(ADC_vect) {
 V[index] = ADCL | ADCH<<8; //get the data
 if (++index > 5) index = 0; // increment the ADC channel number with wrap
 ADMUX = (ADMUX & B11110000) | index; // set the ADC channel 
 cbi(PORTB,5); // Reset Pin13 to show end of conversion 
}
   
int arctan(long V1, long V2) {
  //Handle the quadrants explicitly
  if (V1 < 0)
  {
    if (V2 < 0)
    {
      if (V1 < V2) // 180-225
      {
        return 180 + pgm_read_byte_near(arctan256 + 256 * V2 / V1);
      }
      else // 225-270
      {
        return 270 - pgm_read_byte_near(arctan256 + 256 * V1 / V2);
      }
    }
    else // V2 => 0
    {
      if (-V1 < V2) // 90-135
      {
        return 90 + pgm_read_byte_near(arctan256 - 256 * V2 / V1);
      }
      else // 135-180
      {
        return 180 - pgm_read_byte_near(arctan256 - 256 * V2 / V1);
      }
    }
  }
  else // V1 => 0
  {
    if (V2 < 0)
    {
      if (V1 < -V2) // 270-315
      {
        return 270 + pgm_read_byte_near(arctan256 - 256 * V1 / V2);
      }
      else // 315-360
      {
         return 360 - pgm_read_byte_near(arctan256 - 256 * V2 / V1);
      }      
    }
    else // V2 => 0
    {
      if (V1 < V2) // 45-90
      {
        return 90 - pgm_read_byte_near(arctan256 + 256 * V1 / V2);
      }
      else // 0-45
      {  
        return pgm_read_byte_near(arctan256 + 256 * V2 / V1);
      }      
    }  
  }
}

andyough,

Here is one problem:for (int i = 0 ; i <= 5 ; i++)This loop causes the program to change V[0] through V[5]. That's six elements, and the array is only dimensioned for five. Same thing for Z.

I think you want it to say:for (int i = 0 ; i < 5 ; i++)

Regards,

-Mike

Thanks, that is exactly what it was.
I suspect I am not the only one to have been caught out by this one. I am used to languages where arrays are declared in terms of the index limits rather than number of elements.