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; }