I already have readings from several components
Program:
/*
Version 4.4 (12/05/2024)
Copyright 2024 Picuino
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
IN THE SOFTWARE.
*/
#include <stdint.h>
#define CLK_BOARD 16000000
#define UART_BAUDS 115200
#define MEASURE_TIME 1.0
#define PIN_SIGNAL_OUT 3
#define PIN_DEBUG_OUT 5
#define PIN_ANALOG A6
#define PIN_ANALOG_MUX 6
#define PIN_SCK 13
#define PIN_SDI 12
#define PIN_CNV 10
#define SAMPLES_16
#ifdef SAMPLES_32
#define SAMPLES_PER_WAVE 32
#define ADC_PRESCALER (0b110)
#define TIMER2_PERIOD 220
#define TIMER2_FREQ (CLK_BOARD / ((TIMER2_PERIOD + 1) * 64 * 2))
#define TIMER0_PERIOD (110 - 1)
#define TIMER0_PHASE_ADJUST (0.40)
#define TIMER0_FREQ (CLK_BOARD / ((TIMER0_PERIOD + 1) * 8))
#define SAMPLES_PER_MEASURE (SAMPLES_PER_WAVE * (long) ((MEASURE_TIME) * (TIMER0_FREQ) / SAMPLES_PER_WAVE))
const float BOARD_CALIBRATION = 0.2520 / (SAMPLES_PER_MEASURE); // Converts measure to milliohms
const float BOARD_PHASE_ADJUST = -0.1074; // Radians adjust
const float BOARD_ADDED_RESISTOR = 0.0; // Substract board probes resistor. Sistematic Error
const int16_t SIN_INTEGER[SAMPLES_PER_WAVE + SAMPLES_PER_WAVE / 4] = {
5, 14, 23, 31, 38, 43, 47, 49,
49, 47, 43, 38, 31, 23, 14, 5,
-5, -14, -23, -31, -38, -43, -47, -49,
-49, -47, -43, -38, -31, -23, -14, -5,
5, 14, 23, 31, 38, 43, 47, 49,
};
#endif
#ifdef SAMPLES_16
#define SAMPLES_PER_WAVE 16
#define ADC_PRESCALER (0b111)
#define TIMER2_PERIOD 220
#define TIMER2_FREQ (CLK_BOARD / ((TIMER2_PERIOD + 1) * 64 * 2))
#define TIMER0_PERIOD (220 - 1)
#define TIMER0_PHASE_ADJUST (0.4)
#define TIMER0_FREQ (CLK_BOARD / ((TIMER0_PERIOD + 1) * 8))
#define SAMPLES_PER_MEASURE (SAMPLES_PER_WAVE * (long) ((MEASURE_TIME) * (TIMER0_FREQ) / SAMPLES_PER_WAVE))
const float BOARD_CALIBRATION = 0.2512 / (SAMPLES_PER_MEASURE); // Converts measure to milliohms
const float BOARD_PHASE_ADJUST = +0.1074; // Radians adjust
const float BOARD_ADDED_RESISTOR = 69.0; // Substract board probes resistor. Sistematic Error
const int16_t SIN_INTEGER[SAMPLES_PER_WAVE + SAMPLES_PER_WAVE / 4] = {
9, 26, 39, 46,
46, 39, 26, 9,
-9, -26, -39, -46,
-46, -39, -26, -9,
9, 26, 39, 46,
};
#endif
volatile int32_t adc_acc_inphase;
volatile int32_t adc_acc_quadrature;
volatile int32_t adc_samples;
volatile uint8_t adc_measuring;
volatile uint8_t level_state;
volatile uint8_t level_state_old;
float impedance_inphase;
float impedance_quadrature;
float impedance_sign;
void setup() {
Serial.begin(UART_BAUDS);
// Set up output reference signal pin
pinMode(PIN_SIGNAL_OUT, OUTPUT);
pinMode(PIN_DEBUG_OUT, OUTPUT);
// Print initial info
print_info();
// Set up peripherals
timer0_setup();
timer2_setup();
timer_synchronize();
adc_setup();
// Inits measure
measure_init();
while (adc_measuring == 1);
measure_init();
}
void loop() {
// Main Loop
while (1) {
if (adc_measuring == 0) {
read_float_values();
phase_adjust();
print_values();
measure_init();
}
}
}
void read_float_values(void) {
// Read accumulator values
impedance_inphase = -adc_acc_inphase;
impedance_quadrature = -adc_acc_quadrature;
// Rescale values
impedance_inphase *= BOARD_CALIBRATION;
impedance_quadrature *= BOARD_CALIBRATION;
}
void phase_adjust(void) {
// Get impedance sign
if (impedance_quadrature > 0) {
impedance_sign = 1;
}
else {
impedance_sign = -1;
}
impedance_quadrature = abs(impedance_quadrature);
// Phase adjust
float module = sqrt(impedance_inphase * impedance_inphase + impedance_quadrature * impedance_quadrature);
float phase;
if (abs(impedance_inphase) < 0.1) {
phase = 90;
}
else {
phase = atan(impedance_quadrature / impedance_inphase);
}
phase *= impedance_sign;
phase += BOARD_PHASE_ADJUST;
impedance_inphase = module * cos(phase);
impedance_quadrature = module * sin(phase);
// Get new impedance sign
if (impedance_quadrature > 0) {
impedance_sign = 1;
}
else {
impedance_sign = -1;
}
impedance_quadrature = abs(impedance_quadrature);
// Substract board resistance (sistematic error)
impedance_inphase -= BOARD_ADDED_RESISTOR;
}
void print_info(void) {
Serial.println();
Serial.print("SAMPLE_FREQUENCY = ");
Serial.print(1.0 * TIMER0_FREQ);
Serial.println(" Hz");
Serial.print("MEASURE_SIGNAL_FREQUENCY = ");
Serial.print(1.0 * TIMER2_FREQ);
Serial.println(" Hz");
Serial.print("SAMPLE_TIME = ");
Serial.print(1.0 * SAMPLES_PER_MEASURE / TIMER0_FREQ);
Serial.println(" s");
}
void print_values(void) {
Serial.print(impedance_inphase, 1);
Serial.print("\tmOhm R \t");
if (impedance_sign > 0) {
Serial.print(impedance_quadrature, 1);
Serial.print("\tmOhm Z_L \t");
if (impedance_quadrature > 5.0) {
Serial.print(impedance_quadrature * 1000.0 / (TIMER2_FREQ * 2.0 * 3.1415927));
Serial.println("\tuHenrys");
}
else {
Serial.println();
}
}
else {
Serial.print(impedance_quadrature, 1);
Serial.print("\tmOhm Z_C \t");
if (impedance_quadrature > 5.0) {
Serial.print(1000000000.0 / (impedance_quadrature * TIMER2_FREQ * 2.0 * 3.1415927));
Serial.println("\tuFarads");
}
else {
Serial.println();
}
}
}
void adc_setup(void) {
analogRead(PIN_ANALOG);
cli(); // Stop interrupts
ADMUX = (1 << 6) |
(0 << ADLAR) |
(PIN_ANALOG_MUX << 0);
ADCSRA = (1 << ADEN) |
(0 << ADSC) |
(0 << ADATE) |
(0 << ADIE) |
(ADC_PRESCALER); // Division factor
ADCSRB = 0x00;
sei(); // Allow interrupts
}
void measure_init(void) {
delayMicroseconds(1000);
cli();
adc_acc_inphase = 0;
adc_acc_quadrature = 0;
level_state = SAMPLES_PER_WAVE * 0.25;
level_state_old = 0;
adc_samples = 0;
ADCW = 0;
sei();
while ((PIND & (1 << PIN_SIGNAL_OUT)) != 0);
while ((PIND & (1 << PIN_SIGNAL_OUT)) == 0);
adc_measuring = 1;
}
void timer0_setup(void) {
cli(); // Stop interrupts
// set compare match register
TCCR0A = (0 << 6) | // OOM0A. 0=OC0A disconnected. 1=Toggle OC0A on compare match (p.84)
(0 << 4) | // COM0B. 0=OC0B disconnected. 1=Toggle OC0B on compare match (p.85)
(2 << 0); // WGM0. PWM mode. 1=phase correct 2=CTC (p.86)
TCCR0B = (0 << 7) | // FOC0A.
(0 << 6) | // FOC0B.
(0 << 3) | // WGM02.
(2 << 0); // CLOCK source.
OCR0A = TIMER0_PERIOD;
OCR0B = TIMER0_PERIOD / 2;
TIMSK0 = (0 << 2) | // OCIE0B. Match B Interrupt Enable
(1 << 1) | // OCIE0A. Match A Interrupt Enable
(0 << 0); // TOIE0. Overflow Interrupt Enable
TIFR0 = 0;
TCNT0 = 0; // Initialize Timer0 counter
sei(); // Allow interrupts
}
void timer2_setup(void) {
cli(); // Stop interrupts
TCCR2A = (1 << 6) | // OOM2A. 0=OC2A disconnected. 1=Toggle OC2A on compare match (p.128)
(2 << 4) | // COM2B. 2=Clear OC2B on compare match (p.129)
(1 << 0); // WGM2. PWM mode. 1=phase correct (p.130)
TCCR2B = (0 << 7) | // FOC2A.
(0 << 6) | // FOC2B.
(1 << 3) | // WGM22.
(4 << 0); // CLOCK source.
OCR2A = TIMER2_PERIOD;
OCR2B = TIMER2_PERIOD / 2;
TIMSK2 = (0 << 2) | // OCIE2B. Match B Interrupt Enable
(0 << 1) | // OCIE2A. Match A Interrupt Enable
(0 << 0); // TOIE2. Overflow Interrupt Enable
TIFR2 = 0;
TCNT2 = 0; // Initialize Timer2 counter
sei(); // Allow interrupts
}
void timer_synchronize(void) {
cli(); // Stop interrupts
GTCCR = (1 << TSM) | (1 << PSRASY) | (1 << PSRSYNC); // halt all timers
TCNT0 = 0; // Initialize Timer0 counter
TCNT2 = 0; // Initialize Timer2 counter
GTCCR = 0; // release all timers
sei(); // Allow interrupts
while ((PIND & (1 << PIN_SIGNAL_OUT)) != 0);
while ((PIND & (1 << PIN_SIGNAL_OUT)) == 0);
TCNT0 = TIMER0_PERIOD * TIMER0_PHASE_ADJUST; // Initialize Timer0 counter
}
// Timer0 interrupt handler
ISR(TIMER0_COMPA_vect) {
int16_t adc_value;
if (adc_measuring == 1) {
// ADC Start Conversion
ADCSRA |= (1 << ADSC);
// Read last conversion
adc_value = ADCW;
// Accumulate values (10us)
adc_acc_inphase += (int32_t) adc_value * SIN_INTEGER[level_state_old];
adc_acc_quadrature += (int32_t) adc_value * SIN_INTEGER[level_state_old + SAMPLES_PER_WAVE / 4];
// Update next state
level_state_old = level_state;
level_state++;
if (level_state >= SAMPLES_PER_WAVE)
level_state = 0;
adc_samples++;
if (adc_samples > SAMPLES_PER_MEASURE) {
adc_measuring = 0;
}
}
}
// Timer2 interrupt handler
ISR(TIMER2_COMPA_vect) {
}
void debug_pin_pulse(void) {
PORTD |= (1 << PIN_DEBUG_OUT);
delayMicroseconds(4);
PORTD &= ~(1 << PIN_DEBUG_OUT);
}
Resistor 1 ohm 5% (I have calibrated the board so that this component gives an accurate value):
SAMPLE_FREQUENCY = 9090.00 Hz
MEASURE_SIGNAL_FREQUENCY = 565.00 Hz
SAMPLE_TIME = 1.00 s
1001.3 mOhm R 0.4 mOhm Z_C
1001.3 mOhm R 0.5 mOhm Z_C
1001.4 mOhm R 0.4 mOhm Z_C
1001.2 mOhm R 0.3 mOhm Z_C
1001.2 mOhm R 0.4 mOhm Z_C
1001.3 mOhm R 0.4 mOhm Z_C
1001.3 mOhm R 0.4 mOhm Z_C
1001.2 mOhm R 0.4 mOhm Z_C
1001.1 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.4 mOhm Z_C
1001.0 mOhm R 0.4 mOhm Z_C
1001.0 mOhm R 0.4 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.4 mOhm Z_C
1001.0 mOhm R 0.4 mOhm Z_C
1000.7 mOhm R 0.4 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.6 mOhm R 0.2 mOhm Z_C
1000.9 mOhm R 0.2 mOhm Z_C
1000.7 mOhm R 0.1 mOhm Z_C
1000.9 mOhm R 0.2 mOhm Z_C
1000.7 mOhm R 0.2 mOhm Z_C
1000.8 mOhm R 0.2 mOhm Z_C
1000.8 mOhm R 0.2 mOhm Z_C
1000.8 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.4 mOhm Z_C
1001.0 mOhm R 0.3 mOhm Z_C
1000.7 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.3 mOhm Z_C
1000.7 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.4 mOhm Z_C
1000.9 mOhm R 0.2 mOhm Z_C
1000.7 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.9 mOhm R 0.3 mOhm Z_C
1000.6 mOhm R 0.3 mOhm Z_C
1000.8 mOhm R 0.4 mOhm Z_C
1000.7 mOhm R 0.3 mOhm Z_C
Capacitor 1000uF 16V 20%:
-0.7 mOhm R 310.7 mOhm Z_C 906.69 uFarads
-0.8 mOhm R 310.3 mOhm Z_C 907.67 uFarads
-0.8 mOhm R 310.6 mOhm Z_C 906.91 uFarads
-1.0 mOhm R 310.3 mOhm Z_C 907.80 uFarads
-1.1 mOhm R 310.3 mOhm Z_C 907.90 uFarads
-1.2 mOhm R 310.2 mOhm Z_C 908.01 uFarads
-1.2 mOhm R 310.4 mOhm Z_C 907.49 uFarads
-1.2 mOhm R 310.3 mOhm Z_C 907.87 uFarads
-1.4 mOhm R 310.3 mOhm Z_C 907.79 uFarads
-1.3 mOhm R 310.4 mOhm Z_C 907.46 uFarads
-1.3 mOhm R 310.3 mOhm Z_C 907.76 uFarads
-1.4 mOhm R 310.3 mOhm Z_C 907.71 uFarads
-1.2 mOhm R 310.3 mOhm Z_C 907.75 uFarads
-1.3 mOhm R 310.3 mOhm Z_C 907.92 uFarads
-1.4 mOhm R 310.2 mOhm Z_C 908.22 uFarads
-1.3 mOhm R 310.3 mOhm Z_C 907.94 uFarads
-1.3 mOhm R 310.1 mOhm Z_C 908.40 uFarads
-1.5 mOhm R 310.3 mOhm Z_C 907.85 uFarads
-1.4 mOhm R 310.2 mOhm Z_C 908.20 uFarads
-1.4 mOhm R 310.2 mOhm Z_C 908.20 uFarads
-1.4 mOhm R 310.2 mOhm Z_C 907.98 uFarads
-1.5 mOhm R 310.5 mOhm Z_C 907.36 uFarads
-1.4 mOhm R 310.3 mOhm Z_C 907.77 uFarads
-1.4 mOhm R 310.3 mOhm Z_C 907.85 uFarads
-1.4 mOhm R 310.2 mOhm Z_C 908.01 uFarads
Inductance 68uH 20%:
35.0 mOhm R 171.1 mOhm Z_L 48.20 uHenrys
35.1 mOhm R 171.1 mOhm Z_L 48.20 uHenrys
34.8 mOhm R 170.5 mOhm Z_L 48.03 uHenrys
34.7 mOhm R 170.6 mOhm Z_L 48.04 uHenrys
35.0 mOhm R 171.0 mOhm Z_L 48.17 uHenrys
34.8 mOhm R 171.0 mOhm Z_L 48.18 uHenrys
34.8 mOhm R 170.8 mOhm Z_L 48.11 uHenrys
34.8 mOhm R 170.7 mOhm Z_L 48.08 uHenrys
34.4 mOhm R 170.2 mOhm Z_L 47.95 uHenrys
34.5 mOhm R 169.9 mOhm Z_L 47.85 uHenrys
34.1 mOhm R 169.7 mOhm Z_L 47.80 uHenrys
34.2 mOhm R 169.8 mOhm Z_L 47.83 uHenrys
34.1 mOhm R 169.7 mOhm Z_L 47.79 uHenrys
34.2 mOhm R 170.0 mOhm Z_L 47.87 uHenrys
34.1 mOhm R 169.9 mOhm Z_L 47.87 uHenrys
34.1 mOhm R 170.0 mOhm Z_L 47.88 uHenrys
34.2 mOhm R 169.9 mOhm Z_L 47.87 uHenrys
34.1 mOhm R 170.0 mOhm Z_L 47.89 uHenrys
33.9 mOhm R 170.0 mOhm Z_L 47.88 uHenrys
34.1 mOhm R 170.1 mOhm Z_L 47.90 uHenrys
34.3 mOhm R 170.1 mOhm Z_L 47.90 uHenrys
Obviously I have to calibrate the board resistor better so that the capacitor shows its ESR.
But I like the preliminary results very much.