Capmeter
Zipdatei enthält:
-
eagle (Schematic/Board)
-
qt creator + binaries (32bit/64bit linux)
-
mathcad (some simple calcs)
-
octave (some simple calcs)
-
arduino micro pro (avrstudio ATE Avr Template Express)
Measuring Cap's
Cheap and simple Capacitance Meter.
Principle: Count the time from start of loading to a reaching a reference voltage.
Auto Range: If loading time too short-> switch to higher load resistor
Problem: for very large Caps charge/discharge currents too high → use external transistor.


Attention: parts are placed on top layer, so soldering arduino pico pro's pins is difficult (see image below) – could be improved by 2 layer layout (or omit large cap C3 and place parts at bottom (new layout needed).


Software
Arduino
/*
* Main.cpp
*
* incomplete – open zip file attached
*/
#include <Arduino.h>
#define TIMER_START TCCR1B = (1<<CS10)
#define TIMER_STOP TCCR1B = 0
#define ANALOG_COMP_INT_DISABLE ACSR &= ~(1 << ACIE);
#define INPUT_HIGHER_THAN_REFERENCE (ACSR & (1<<ACO))
#define THRESHOLD 5 //D10 ADC13
#define CHARGE 5 //Arduino Pin numbers
#define CHARGELONG 6
#define SENSE 4
#define DISCHARGE 3
#define TESTPIN 2 //just for debugging - with LED
volatile int timeroverflows = 0;
volatile bool timeout = false;
int speed = 1; //fastest
unsigned long timePhase1;
unsigned int senseVoltage;
void sendSerial(); //output data to serial port
void dischargeC(); //discharge the cap
void restart(); //start new conversion
void chargeC(uint8_t speed1){
pinMode(DISCHARGE,INPUT);
pinMode(SENSE,INPUT);
if (speed1==3){
pinMode(CHARGE,INPUT);
pinMode(CHARGELONG,OUTPUT);
digitalWrite(CHARGELONG,HIGH);
}
else if (speed1==2){
pinMode(CHARGELONG,INPUT);
pinMode(CHARGE,OUTPUT);
digitalWrite(CHARGE,HIGH);
}
else{
pinMode(CHARGELONG,INPUT);
pinMode(CHARGE,INPUT);
pinMode(DISCHARGE,OUTPUT); //fastest pin: discharge
digitalWrite(DISCHARGE,HIGH);
speed=1;
}
}
uint16_t threshold;
uint16_t resistorHigh;
uint16_t resistorLow;
void setup()
{
pinMode(TESTPIN,OUTPUT);
Serial.begin(115200UL);
getThresholdAndResistorinfo();
// Analog Multiplexer: Enabled high bit for Mux 8..15
ADCSRB = (1 << ACME)|(1<<MUX5);
ADCSRA &= ~(1<<ADEN);//ADEN disabled for Analog Mux to work
ADMUX = THRESHOLD; // 5 ... ADC13
//ACSR &= ~((1<<ACD)|(1<<ACBG));
// Disable digital input (preserves power consumption)
DIDR1 |= (1<<AIN0D);
TCCR1A = 0;
TCCR1B = 0;
TIMSK1 = (1<<TOIE1);
TIMER_STOP;
speed = 1;
}
uint16_t nr =0;
#define TIMEOUT 1500
void loop()
{
restart();
TCNT1=0;
if (timeout){
speed--; //shorten time constant
digitalWrite(TESTPIN,HIGH);
}
if (timePhase1<100){
speed++;
digitalWrite(TESTPIN,HIGH);
}
timeroverflows=0;
timeout=false;
chargeC(speed);
digitalWrite(TESTPIN,LOW);
TIMER_START;
while((!INPUT_HIGHER_THAN_REFERENCE) &&(!timeout)); //wait for ACO
TIMER_STOP;
timePhase1=timeroverflows*0x10000+TCNT1;
if (!timeout) sendSerial();
else {
Serial.print("Timeout:");
Serial.println(speed);
}
}
ISR(TIMER1_OVF_vect){
timeroverflows++;
if (timeroverflows>TIMEOUT) timeout=true;
}
void dischargeC(){
pinMode(DISCHARGE,OUTPUT);
digitalWrite(DISCHARGE,LOW);
pinMode(SENSE,OUTPUT);
digitalWrite(SENSE,LOW);
pinMode(CHARGE,OUTPUT);
digitalWrite(CHARGE,LOW);
pinMode(CHARGELONG,OUTPUT);
digitalWrite(CHARGELONG,LOW);
}
void restart(){
dischargeC();
ADCSRA |= (1<<ADEN); //turn ADC on
senseVoltage = 100;
while (senseVoltage > 0) //wait for cap to discharge
{
delay(1);
senseVoltage = analogRead(A6);
}
ADCSRA &= ~(1<<ADEN); //turn ADC off so Analog Mux can work
ADMUX = THRESHOLD;
delay(50);
}Qt Creator
programming C++ and using Qt allows development for win/linux/android;
calculates capacitance and smooths results by means of FIFO (QQueue)
do the calculations on the pc side
QString processData(QByteArray data){
QQueue<double> filter;
int oldspeed=0;
QString s = data;
QStringList sl = s.split("/");
if (sl.size()!=5) return ""; //there may be broken lines
int speed=sl[0].toInt();
if (speed<1 || speed>3) return "";
int x2=sl[1].toInt();
int x3=sl[2].toInt();
int x4=sl[3].toInt();
int timer1=sl[4].toInt();
double T=1/16E6; //Period @ 16MHz
double Vthreshold=1.6;
double Resistors[] = {150,200,2E3,200E3};
int corrections[]={0, 6, 6, 68};
double R = Resistors[speed];
//double timer1korr=timer1-68; //some pF for the equipment
double timer1korr = timer1-corrections[speed];
double t=timer1korr*T;
double Cx=-t/(R*log(1-Vthreshold/5));
if (speed != oldspeed) filter.clear();
filter.enqueue(Cx);
if (filter.size() > 10) filter.dequeue();
double sum=0;
for(int i=0; i<filter.size(); i++){
sum += filter.at(i);
}
double Cy = sum/filter.size();
Cxs = eng(Cx,2,0);
QString Cys = eng(Cy,2,0);
qDebug() << Cxs << " (" << Cys << ")";
oldspeed=speed;
// }
return Cys;
}







