Er, it's been a while, but I think I multiplied by 1000 to turn µs into ns and divided by 16 because the clock was 16 MHz and not 1 MHz.
Well, as of late last night, the basic capacitor measurement function was working. Whew! Converting Nicks code to work on the Micro turned out to be a bit of a chore. Getting all the registers on the Micro correct took lots of reading and double checking the datasheet for the ATmega16U4/ATmega32U4.
I do have a question, it's not pressing but I don't see any reason in my code for the first reading taken will always be about .....well, let's just say wrong! and I can't blame it on contact bounce because upon reset with a cap already connected, the first is still wrong. (normally too large).
Next I have to order the precision resistors so I can set up all four ranges but in the mean time, here is what I have so far. Both code and hook up have changed.
/*
Tested and working on Arduino Micro
Keshka Kotera 8 Feb 2016
*/
#include <Math.h>
#define Charge_pin4 12 // pin to charge caps
#define CapPositive_pin 7 // pin used by comparator for rising voltage across the capacitor
#define Analog_pin A0 // analog pin for reading current charge level
char message[80];
volatile unsigned long Total_counts; //volatile- for vars used in AND out of ISR's (interupt service routines)
volatile unsigned long Overflow_counts;
volatile boolean Triggered;
volatile boolean Active;
unsigned int Timer1_counts;
float Resistance_value = 330;
unsigned long Previous_millis = 0;
int times;
int Apin_value;
void setup()
{
pinMode(Analog_pin, INPUT); // set Analog_pin to input, will be pulled high by the current Charge_pin if no cap
pinMode(A1, INPUT); // set A1 (our AIN- later) to input
digitalWrite(A1, LOW); // make sure pull-up resistor is off so as not to load the 3.3v ref
pinMode(CapPositive_pin, INPUT); // AIN0 (PE6) the + input on D7 on the Micro cap to test here.
digitalWrite(CapPositive_pin, LOW); // make sure pull-up resistor is off
Active = false; // we have no capacitor to test
Serial.begin(19200);
Previous_millis = millis();
pinMode(Charge_pin4, OUTPUT); // set Charge_pin to output for range 4
digitalWrite(Charge_pin4, HIGH); // set ready for testing
delay(2000);
}
void loop()
{
if(!Active) // we are NOT testing a cap
{
Apin_value = analogRead(Analog_pin);
if(Apin_value < 1020) // we have a cap to test!
{
Active = true; // don't come in here again until triggered is finished
discharge_cap(); // discharge our cap and leave Charge_pin low
noInterrupts ();
// prepare comparator
ACSR &= ~bit (ADC); // Analog Comparator Disable (ADC) set to 0 for comparator on
ACSR &= ~bit (ACBG); // Analog Comparator BandGap (ACBG) set to 0 to connect to AIN0 the AIN+ on D7
ACSR &= ~bit (ACO); // Analog Comparator Output (ACO) sync the AC to the output..? says if you do causes a couple clock cycle delay
ACSR |= bit (ACI); // (Clear) Analog Comparator Interrupt Flag ...write a one to clear
ACSR |= bit (ACIE); // Analog Comparator Interrupt Enable set to one
ACSR |= bit (ACIC); // Analog Comparator Input Capture Enable bit (ACIC) set to one to enable input capture for Timer1
ACSR |= bit (ACIS0); // ACIS1, ACIS0: Analog Comparator Interrupt Mode Select (trigger on rising edge)
ACSR |= bit (ACIS1);
// prepare timer
ADCSRB |= bit (ACME); // (Disable) ACME: Analog Comparator Multiplexer Enable, set bit 6 to 1
ADCSRA &= ~bit (ADEN); // (Disable) ADEN: Analoge digital converteret disable (ADC), set bit 7 to 0
PRR0 &= ~bit(PRADC); // make sure power reduction is not on so A2D MUX still works and can set A1
ADMUX = B00000110; // set the AIN- to ADC6 (A1 on the Micro) for our reference voltage
TCCR1A = 0; // reset Timer 1
TCCR1B = 0; // reset Timer 1
TIFR1 = bit (ICF1); // *clear* ICF1
TCNT1 = 0; // Counter to zero
TIMSK1 = bit (TOIE1) | bit (ICIE1); // set bits in timer/counter1 (TIMSK1) register for interrupt on Timer 1 overflow (TOIE1) and input capture (ICIE1)
TCCR1B = bit (CS10) | bit (ICES1); // start Timer 1, no prescaler plus Input Capture Edge Select
interrupts (); // enable interupts
digitalWrite (Charge_pin4, HIGH); // start charging capacitor
}
if(millis() - Previous_millis > 5000) // only update every 5 seconds
{
Serial.print("analog pin = ");
Serial.println(Apin_value);
Previous_millis = millis();
if(times++ == 2) // my auto start for testing when cap is already charged
{
discharge_cap();
}
}
}
if (Triggered)
{
char Flt_str[20];
float Ov_shift;
float Micro_sec;
float Capacitance;
pinMode(Charge_pin4, INPUT); // stop charging/discharging cap
digitalWrite(Charge_pin4, LOW); // set to high impedance
Ov_shift = (Overflow_counts << 16);
dtostrf((((Ov_shift + Timer1_counts) * 1000L) / (F_CPU / 1000L)), 12,2,Flt_str);
sprintf(message,"Number of microseconds %s",Flt_str);
Serial.println(message);
Micro_sec = (((Ov_shift + Timer1_counts) * 1000L) / (F_CPU / 1000L));
Capacitance = -(Micro_sec/(Resistance_value*log(1-(3.3/5))));
dtostrf(Capacitance, 8, 2, Flt_str);
sprintf(message,"Capacitance is %s uF",Flt_str);
Serial.println(message);
ADCSRB &= ~bit (ACME); // Enable) ACME: Analog Comparator Multiplexer Enable, set bit 6 to 0
ADCSRA |= bit (ADEN); // (Enable) ADEN: Analoge digital converteret disable (ADC), set bit 7 to 1
pinMode(Charge_pin4, OUTPUT); // set Charge_pin to output for range 4
discharge_cap(); // drain the cap. get ready for next read
delay(10000); // display value for ten seconds
digitalWrite(Charge_pin4, HIGH); // set to high so we can check for next cap to read
Triggered = false;
Active = false;
Apin_value = 0;
Overflow_counts = 0;
}
}
ISR (TIMER1_OVF_vect)
{
++Overflow_counts; // count number of Counter 1 overflows
}
ISR (TIMER1_CAPT_vect)
{
TCCR1B = 0; // stop the timer
Timer1_counts = ICR1; // grab timer count, see datasheet, page 117 (accessing 16-bit registers)
if (Active) // did we finish?
{
if ((TIFR1 & bit (TOV1)) && Timer1_counts < 0x7FFF) // if just missed an overflow
{
Overflow_counts++;
}
Total_counts = (Overflow_counts << 16) + Timer1_counts; //calculate total count, each overflow is 65536 more
Triggered = true;
}
}
ISR (ANALOG_COMP_vect) // hangs if this ISR does not exist
{
}
void discharge_cap()
{
digitalWrite(Charge_pin4, LOW); // set it to LOW
while(analogRead(Analog_pin) > 0); // wait until capacitor is completely discharged
}