Input Capture

Hey Guys,

Would Just like to know if anyone can spot any errors in my code:

I am first using timer1 to count up to 9000ticks with a clock of 16Mhz and prescalar of 1024.

during this time I am integrating an unknown voltage.

After 9000 ticks. I thereafter switch off the unknown voltage and switch on a negative reference voltage and de-integrate it

this is the dual slope integration method for ADC.

I run the output of the comparator of the dual slope ADC to the ICP pin 8 on arduino board and monitor for falling edge upon which i save time from ICR1.

I am getting incorrect results.

code:

 /*
* ----------------------------------------------------------------------------
* ALPHATRONICS POWER METER 
* DUAL SLOPE INTEGRATING ANALOG-DIGITAL CONVERTER
* REFERENCE VOLTAGE DE-INTEGRATION 
* ----------------------------------------------------------------------------
*/

//INCLUDES
  #include <avr/io.h>
  #include <util/delay.h>
  #include <avr/interrupt.h>
  #include <math.h>

/***********/
/* DEFINITIONS */
/***********/
  
  //Reference S-R variables
  #define ICP_Pin 8
  #define Vref_Control_1 9
  #define Vref_Control_2 12
 
  //Input S-R Variables : Allocation of Control Pins for Each ADC
  #define Vin_Control_1 10
 
  
  //Discharge S-R 
  #define Discharge_Pin 11
  
/********************/
/* Global variables */
/********************/

  //Reference S-R Variables
  double period_high = 0.00;
  double period_low = 0.00;
  double period = 0.00;

/*************************/
/* SYSTEM INITIALIZATION */
/*************************/

void setup()
{
  
  Serial.begin(9600);
/**********************/
/* I/O INITIALIZATION */
/**********************/

// OUTPUTS

  pinMode(ICP_Pin,INPUT);//ICP1 as INPUT
  pinMode(Vref_Control_1,OUTPUT);
  pinMode(Vref_Control_2,OUTPUT);
  
  pinMode(Vin_Control_1, OUTPUT); //Defining control pin 1 as an output
  
  pinMode(Discharge_Pin, OUTPUT);// initialize the digital pin as an output.
  digitalWrite(Discharge_Pin, HIGH);    // turn the LED off by making the voltage LOW
  digitalWrite(Vref_Control_1, HIGH);    // turn the LED off by making the voltage LOW
  digitalWrite(Vin_Control_1, HIGH);    // turn the LED off by making the voltage LOW
  
  
  
  /******************************/
  /* Initialization of the code */
  /******************************/
  // Global enable interrupts
  sei();
}

/******************/
/* MAIN CODE LOOP */
/******************/
void loop()
{
  
  Discharge();
  
  Timer1_Input_SR();
  
  Timer1_Reference();
  
  Serial.print(period);
  Serial.print(" ");
  Serial.print(ICR1);
  Serial.print(" ");
  Serial.print(ICR1L);
  Serial.print(" ");
  Serial.print(ICR1H);
  Serial.print(" ");
  Serial.println(" ");
  
  
  
  
  delay(1000);
}
/***********************/
/* INTERRUPT FUNCTIONS */
/***********************/

 //Timer1 Ouput COmpare Match Interrupt Subroutine
 //Responsible for switching of Inpput Voltage control pins of each ADC
   ISR(TIMER1_COMPB_vect)
   {
      digitalWrite(Vin_Control_1, HIGH);//Output a low to Control Pin 1 To switch OFF the Input Voltage for the 1st and 2nd ADC
      
      Serial.println(TCNT1);

   }

  // Timer 1 input capture interrupt service routine
  ISR(TIMER1_CAPT_vect)
  {
      /*period_high = ICR1H;
      period_low = ICR1L;*/
     
      digitalWrite(Vref_Control_1, HIGH); //Output a Low to Control Pin 1 to switch OFF the reference Voltage for the 1st ADC
      digitalWrite(Vref_Control_2, HIGH); //Output a Low to Control Pin 2 to switch OFF the reference Voltage for the 2nd ADC
      period = ICR1;
      
      
  }

/***********************/
/* OTHER FUNCTIONS */
/***********************/

//Discharge Capacitor
void Discharge()
{
  digitalWrite(Discharge_Pin, LOW);   // turn the LED on (HIGH is the voltage level)
  delay(3000);               // wait for a second
  digitalWrite(Discharge_Pin, HIGH);    // turn the LED off by making the voltage LOW
}

 // Initialize Timer1
void Timer1_Input_SR(){
    cli();          // disable global interrupts
    
    TCCR1A = 0;     // set entire TCCR1A register to 0
    TCCR1B = 0;     // set entire TCCR1A register to 0
    TCNT1 = 0;
   
   /*Serial.print("INIT ");
   Serial.print(TCNT1);
   Serial.println(" ");*/
   digitalWrite(Vin_Control_1, LOW); //Output a High to Control Pin 1 to switch ON the Input Voltage for the 1st and 2nd ADC
   
   
  // set compare match register to desired timer count: to account for 0.036s of Integration Time
   OCR1B = 9000;
   
   // Timer1 Starts counting in CTC mode:
   TCCR1B |= (1 << WGM12);
   
  // Set CS10 and CS12 bits in TCCR1B for 1024 prescaler:
   TCCR1B |= (1 << CS10);
   TCCR1B |= (1 << CS12);
   
  // enable timer compare interrupt:
   TIMSK1 |= (1 << OCIE1B);
   
  
  // enable global interrupts:
   sei();
}

void Timer1_Reference()
{
  cli();
  
  digitalWrite(Vref_Control_1, LOW); //Output a High to Control Pin 1 to switch ON the reference Voltage for the 1st ADC
  digitalWrite(Vref_Control_2, LOW); //Output a High to Control Pin 2 to switch ON the reference Voltage for the 2nd ADC
  
  // Timer/Counter 1 initialization
  // Clock source: System Clock
  // Prescalar 1024
  // Mode: Normal
  // OC1A output: Discon.
  // OC1B output: Discon.
  // OC1C output: Discon.
  // Noise Canceler: Off
  // Input Capture on Falling Edge
  // Timer 1 Overflow Interrupt: Off
  // Input Capture Interrupt: Onn
  // Compare A Match Interrupt: Off
  // Compare B Match Interrupt: Off
  // Compare C Match Interrupt: Off
    TCCR1A = 0x00;
    TCCR1B = 0x05;
    TCNT1H = 0x00;
    TCNT1L = 0x00;
    ICR1H = 0x00;
    ICR1L = 0x00;
  
  // Timer(s)/Counter(s) Interrupt(s) initialization
    TIMSK1 |= 0x20;
    TIFR1 |= 0x20;
    sei();
}

Note the switch activates for a digital low and deactivates for a digital high.

It may seem contradictory in some places with the comments, but this is how it operates.

The switch is a DG201

After 9000 ticks. I thereafter switch off the unknown voltage and switch on a negative reference voltage and de-integrate it

Are you really feeding a negative voltage into the Arduino? Are you trying to kill it?

I admit I didn't understand much of the sketch, but what caught my eye is that Serial.println() inside an ISR. Not wise, IMHO.

My 0.05 cents.

@Paul, no I am not. The only thing the arduino does is generate a high signal which turns on an analogue switch that outputs a positive 9Volts which goes to an Inverter and is inverted to 9V. to arduino is completely isolated from the analogue circuit.

is it wise to save the value from ICR1. or should i read from ICR1L and then ICR1H ?