Challenger2011
Member
Hello,
I am making a teensy4.1 capacitance meter running the adc at 12 bits. My code is posted below for one of my two code snippets, the one below is for small capacitors which is simply being charged and discharged via two analog pins.
I am in need of the 4.1's internal I/O pin equivalent schematic. I am unsure about how to interpret this for the teensy in contrast to the Arduino. In the ATMEGA user manual, there is an equivalent schematic with resistance values. For me to be able to charge and measure the capacitor, I need the internal pull up resistance and also the internal capacitance of the chip (which, I calculated by using a capacitor I measured with a keithly for its real value, placed it in my circuit, and did the math to solve for the unknown capacitance - image attached of this arithmetic).
Below is my code, please notice the const float r_pullup var I need to be accurate for this to work. Let me know if there are any ways you think I can improve the accuracy if you may - The measurement is accurate at some capcitances but for others it isnt (e.g. 22pf measures at 23.6 pf, 68pf measures at 50pf...). Thanks in advance!
I am making a teensy4.1 capacitance meter running the adc at 12 bits. My code is posted below for one of my two code snippets, the one below is for small capacitors which is simply being charged and discharged via two analog pins.
I am in need of the 4.1's internal I/O pin equivalent schematic. I am unsure about how to interpret this for the teensy in contrast to the Arduino. In the ATMEGA user manual, there is an equivalent schematic with resistance values. For me to be able to charge and measure the capacitor, I need the internal pull up resistance and also the internal capacitance of the chip (which, I calculated by using a capacitor I measured with a keithly for its real value, placed it in my circuit, and did the math to solve for the unknown capacitance - image attached of this arithmetic).
Below is my code, please notice the const float r_pullup var I need to be accurate for this to work. Let me know if there are any ways you think I can improve the accuracy if you may - The measurement is accurate at some capcitances but for others it isnt (e.g. 22pf measures at 23.6 pf, 68pf measures at 50pf...). Thanks in advance!
Code:
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ADC.h>
// Pin definitions for Teensy 4.1
const int OUT_PIN = 16; // Analog pin A2 on Teensy 4.1
const int IN_PIN = 14; // Analog pin A0 on Teensy 4.1
LiquidCrystal_I2C lcd(0x27, 20, 4); // LCD address and dimensions
const float IN_STRAY_CAP_TO_GND = 14.59; // Adjusted value for your setup
const float IN_CAP_TO_GND = IN_STRAY_CAP_TO_GND;
const float R_PULLUP = 22000.0; // Pull-up resistor value in Ohms
const int MAX_ADC_VALUE = 4095; // Teensy 4.1 ADC max value for 12-bit resolution
ADC *adc = new ADC(); // Create an ADC object
void setup() {
pinMode(OUT_PIN, OUTPUT);
pinMode(IN_PIN, OUTPUT);
lcd.init();
lcd.backlight();
// Set up ADC
adc->adc0->setAveraging(16); // Set number of averages
adc->adc0->setResolution(12); // Set resolution to 12 bits
adc->adc0->setConversionSpeed(ADC_CONVERSION_SPEED::HIGH_SPEED); // Set conversion speed
adc->adc0->setSamplingSpeed(ADC_SAMPLING_SPEED::HIGH_SPEED); // Set sampling speed
}
void loop() {
pinMode(IN_PIN, INPUT);
digitalWrite(OUT_PIN, HIGH);
int val = adc->adc0->analogRead(IN_PIN);
digitalWrite(OUT_PIN, LOW);
lcd.setCursor(0, 0);
lcd.print("ADC Value: ");
lcd.print(val);
if (val < (MAX_ADC_VALUE * 0.9)) { // Adjust threshold if needed
pinMode(IN_PIN, OUTPUT);
float capacitance = (float)val * IN_CAP_TO_GND / (float)(MAX_ADC_VALUE - val);
lcd.setCursor(0, 1);
if (capacitance > 1000.0) {
lcd.print(capacitance / 1000.0, 3);
lcd.print(" nF");
} else {
lcd.print(capacitance, 3);
lcd.print(" pF");
}
} else {
pinMode(IN_PIN, OUTPUT);
delay(1);
pinMode(OUT_PIN, INPUT_PULLUP);
unsigned long u1 = micros();
unsigned long t;
int digVal;
do {
digVal = digitalRead(OUT_PIN);
unsigned long u2 = micros();
t = u2 > u1 ? u2 - u1 : u1 - u2;
} while ((digVal < 1) && (t < 400000UL)); // Ensure correct type for UL
pinMode(OUT_PIN, INPUT);
val = adc->adc0->analogRead(OUT_PIN);
digitalWrite(IN_PIN, HIGH);
int dischargeTime = (int)(t / 1000UL) * 5; // Ensure correct type for UL
delay(dischargeTime);
pinMode(OUT_PIN, OUTPUT);
digitalWrite(OUT_PIN, LOW);
digitalWrite(IN_PIN, LOW);
float capacitance = -(float)t / R_PULLUP / log(1.0 - (float)val / (float)MAX_ADC_VALUE);
lcd.setCursor(0, 1);
if (capacitance > 1e6) {
lcd.print(capacitance / 1e6, 3);
lcd.print(" uF");
} else if (capacitance > 1000.0) {
lcd.print(capacitance / 1000.0, 3);
lcd.print(" nF");
} else {
lcd.print(capacitance, 3);
lcd.print(" pF");
}
}
while (micros() % 1000 != 0);
}