-
        

Ergebnis 1 bis 9 von 9

Thema: C-Messung

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    08.09.2005
    Beiträge
    28

    C-Messung

    Anzeige

    SMARTPHONES & TABLETS-bis zu 77% RABATT-Kostenlose Lieferung-Aktuell | Cool | Unentbehrlich
    Habe vor die sich ändernde Kapazität eines Kondensators zu messen, etwa über den sich ändernden Strom oder Phasenwinkel und Suche hierfür einen IC der mir, wenn möglich, über Ausgangspegel mitteilt ob C einen bestimmten Wert erreicht hat.

    Gibr es IC's in dieser Art?

  2. #2
    Super-Moderator Lebende Robotik Legende Avatar von Manf
    Registriert seit
    30.01.2004
    Ort
    München
    Alter
    64
    Beiträge
    12.366
    So ungefähr, immerhin genau für den Zweck gebaut.
    Manfred

    Der UTI von Smartec ist ein universeller Messinterface Baustein der Kapazitäten im Bereich von 0-2 oder 0-12pF auch bis 300pF misst. Er ist auch für viele weitere Anwendungen wie für Widerstandsmessbrücken einsetzbar. ...
    http://www.roboternetz.de/phpBB2/zei...?p=22772#22772

  3. #3
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Hab ich mal mit einem Atmel AT90S2313 gemach, da reicht ein analog-Komparator aus. Die 3 Messbereiche reichen von 1pF bis ca 1µF.
    Und das geht so (Die zu messende Kapazität ist C1)
    1. C1 wird über R4 auf Vcc aufgeladen. Dazu wird AIN0 als OUT geschaltet und auf HIGH gelegt.
    2. Ein paar ms warten.
    3. AIN0 wird als hochohmiger IN geschaltet und gleichzeitig
    4. Timer1 wird auf 0 gesetzt, gestartet und die CapturCompare-Einheit des 2313 aktiviert. Input von CapCom ist der AnalogComparaton AIN0/AIN1.
    5. C1 entlädt sich über R5, R6 oder R7.
    6. Wenn der Wert an AIN0 (=C1+) unter den Wert an AIN1 (=Vcc/2) fällt, wird der Wert von Timer1 automatisch gesichert.
    7. Die gemessene Zeit ist proportional zur Kapazität C.
    8. Ist Timer1 übergelaufen, weil die Kapazität zu groß ist, dann wird via Reed-Relais ein anderer Widerstand zum Entladen gewählt. Gehe dann zu 1.
    9. Umrechnen der Zeit in die Kapazität und anzeige am Display.

    Das Messen wird per Taster ausgelöst.
    Kurzer Tastendruck --> Messen
    Langer Tastendruck --> Messen und Wert merken zum Kalibrieren des Messgerätes, weil Leitungen schon Kapazitäten im pF-Bereich haben. Das wird später wieder rausgerechnet, damit parasitäre Effekte nicht das Messergebnis verfälschen.
    Miniaturansichten angehängter Grafiken Miniaturansichten angehängter Grafiken capacity.png  
    Disclaimer: none. Sue me.

  4. #4
    Erfahrener Benutzer Begeisterter Techniker Avatar von H.A.R.R.Y.
    Registriert seit
    15.09.2005
    Beiträge
    306
    Wie bekommst Du den Wert eines 1pF Kondensators reproduzierbar hin? Bei meinen Aufbauten dieser Empfindlichkeitsstufe langt es meist schon mit der Hand bis auf 10cm ranzukommen - der Wert driftet dadurch um etliche pF weg! Kapazitive Näherungssensoren nutzen solche Effekte gezielt aus.

    Gruß René
    a) Es gibt keine dummen Fragen, nur dumme Antworten
    b) Fehler macht man um aus ihnen zu lernen
    c) Jeder IO-Port kennt drei mögliche Zustände: Input, Output, Kaputt

  5. #5
    Neuer Benutzer Öfters hier
    Registriert seit
    08.09.2005
    Beiträge
    28
    Danke erstmal für die Mühe!
    Es hat sich jedoch ein neues Problem ergeben.
    Ich beabsichtige Regen kapazitiv festzustellen, hierzu benutze ich 2 Alubleche die nebeneinander angebracht werden C beträgt ca. 14pF.
    Beim Berechnen der C Änderung bei aufgebrachtem Wasser (ca. 100mm³) erhalte ich eine Änderung von C in der Femto Gegend.
    Die aktualisierte Frage lautet also wie lässt sich die C Änderung erhöhen?

    Es wäre natürlich auch denkbar einen Kondensator mit Femto F zu bauen, jedoch wäre die Messung den wohl etwas empfindlich.

  6. #6
    Super-Moderator Lebende Robotik Legende Avatar von Manf
    Registriert seit
    30.01.2004
    Ort
    München
    Alter
    64
    Beiträge
    12.366
    Es gibt es hygroskopische Materialien die die Luftfeuchte konzentrieren. So ist sie in Luftfeuchtesensoren leichter zu messen.

    Bei Regen hat man das Problem ja eigentlich nicht. Man kann ja das Wasser aufsammeln das herunterfällt, in einen Gefäß, dass sich automatisch in einem Kippvorgang entleert.
    (shishi odoshi) http://www.roboternetz.de/phpBB2/viewtopic.php?t=10940
    Manfred

  7. #7
    Gast
    @Sprinter:
    Kannst Du dein Programm mal hier zur V erfügung stellen, es muß ja nicht jeder das Rad neu erfinden ??

    felack

  8. #8
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    Zitat Zitat von felack
    @Sprinter:
    Kannst Du dein Programm mal hier zur V erfügung stellen, es muß ja nicht jeder das Rad neu erfinden ??
    Jo, bei Gelegenheit kram ich das Zeugs mal wieder raus und poste die Quelle des entsprechenden Moduls. Ist in C für avr-gcc.

    Zitat Zitat von H.A.R.R.Y.
    Wie bekommst Du den Wert eines 1pF Kondensators reproduzierbar hin? Bei meinen Aufbauten dieser Empfindlichkeitsstufe langt es meist schon mit der Hand bis auf 10cm ranzukommen - der Wert driftet dadurch um etliche pF weg!
    Wie gesagt, der Messbereich fängt bei 1pF an, nicht die Messgenauigkeit. Dazu kommen noch Ungenauigkeiten durch Rundungsfehler. Der kleinste C, den ich hab, ist ein 6.8pF und da werden brav 7+-1 pF angezeigt. Sooo genau brauch ich's auch nicht. Für nen Feuchtigkeitssensor reichts aber IMHO nicht aus, da muss wohl ein Schwingkreis her?

    Messung/Kalibrieren wird gestartet über Taster, und beim Start hab ich die Hand ja immer an der selben Stelle. Das hab ich nur mal probeweise gebaut, weil an vielen C die Größe nicht mehr lesbar ist. Ging dann ganz gut.

    Als Anzeige ist ein VFD dran, das zur Messung abgeschaltet werden muss.

    Die Bereichsumschaltung hab ich mit Reed gemacht. Mit Transen ging das nicht so wie geplant.

    Messprobleme gibt es eher mit grösseren Kapazitäten, speziell bei Elkos. Die Ladung scheint langsam zu wachsen. Ein nicht-vollständiges Entladen kann dafür kaum verantwortlich sein, denn dann wäre der Effekt ab der dritten Messung nicht mehr zu beobachten. Liegt wohl an dielektrischer Absorption (memory-Effekt, auch 'recovery voltage').
    Disclaimer: none. Sue me.

  9. #9
    Erfahrener Benutzer Robotik Einstein Avatar von SprinterSB
    Registriert seit
    09.06.2005
    Ort
    An der Saar
    Beiträge
    2.801
    So, hier die versprochenen Code-Schnippsel.
    Das ganze ist eher als Anregung gedacht und eigentlich nur Pseudo-Code, weil nicht alle Haeder dabei sind. Es sind nur die relevanten stellen, die für ne C-Messung gebraucht wurden. Der Code ist recht antik, undokumentiert und war auch nicht für's breite Publikum gedacht...

    Das ganze drumrum hab ich weggelassen wie Taster abfragen, VFD-Routinen, etc

    Laufen tut das auf einem AT90S2313 mit 8MHz Keramik.

    Hier wird nur der C geladen und die Zeit in Ticks gemessen.

    Code:
    #include "capacity.h"
    //#include "morse.h"
    
    extern void ioinit(); 
    extern void wait_10ms (const byte);
    
    // Multiplikator:
    // k = (ny * R * ln 2)^{-1}
    // mit ny = 8MHz und R = 10k:
    
    // k = 18pF / Inkrement
    
    word measure_time (byte loadTime)
    {
    	// Load capacity via AIN+ push-pull
    	SET (PORT_AIN_POS); MAKE_OUT (PORT_AIN_POS);
    	wait_10ms (loadTime);
    
    	// disable all interrupts
    	cli();
    	
    	// stop timer1
    	TCCR1B = 0;
    	
    	// enable AC (ACD = 0)
    	// AC Input Capture on -> connect to Input Capture of Timer/Counter1
    	// AC Interrupt on Falling Output Edge
    	ACSR = _BV(ACIC) | _BV (ACIS1);
    	
    	// disconnect timer1 from output pin OC, no PWM
    	TCCR1A = 0;
    	
    	// reset timer1 to 0
    	TCNT1 = 0;
    	
    	// clear Timer1 Overflow and InputCapture Flags
    	TIFR = _BV (TOV1) | _BV (ICF1);
    	
    	// start timer 1 at full speed
    	// no clear on compare match
    	// no noise cancel
    	// input capture edge = falling
    	TCCR1B = _BV (CS10);
    
    	// here we go! 
    	// start discharging via external resistor
    	// AIN+ to high Z
    	MAKE_IN (PORT_AIN_POS); CLR (PORT_AIN_POS); 
    	
    	byte flag;
    	
    	do
    	{
    		flag = TIFR & (_BV (TOV1) | _BV (ICF1));
    	} while (flag == 0);
    	
    	if (flag & _BV (TOV1))
    		return 0xffff;
    		
    	return ICR1;
    	
    	// restore status of machine
    //	ioinit();
    	
    //		morse (_O_);
    //	if (flag & _BV (ICF1))
    		
    //		morse_dec (capture-4);
    //		morse (_FRAGE_);
    }
    Und hier etwas von dem Geklimper drumrum: Umrechnen in Kapazität, Messbereich auswählen, Kalibrierung, etc
    Code:
    #include "ports.h"
    #include "main.h"
    #include "util.h"
    #include "taster.h"
    #include "timer.h"
    
    #include "vfd.h"
    #include "capacity.h"
    
    extern void ioinit(); 
    
    static unsigned long mul_ww (word, word);
    static void measureC (byte doCallibrate);
    static void put_decimal (byte pos, word val, byte dot);
    static word callibra[3] = {3, 3, 3};
    
    enum
    {
    	OHM_1M = 0,
    	OHM_47K = 1,
    	OHM_1K5 = 2
    };
    
    
    #define	CONST_1M   687995.        /* 0M993    */
    #define	CONST_47K   32140.        /*    46K8  */ 
    #define	CONST_1K5     759.5       /*     1K49 */
    
    // doCallibrate == 0: C bestimmen und anzeigen
    // doCallibrate != 0: C bestimmen und callibrate[] damit besetzen
    void measureC (byte doCallibrate)
    {
    	word capval;
    
    	char dim;
    	char toobig;
    	byte ohm;
    	word const_R;
    	byte loadTime;
    	byte dot;
    
    	ioinit();
    #if VFD	
    	vfd_reset (1);
    #endif	
    	vfd_clear();
    	vfd.bright = 0;
    	vfd.cursor_on = 0;
    	vfd.cursor_blink = 0;
    	vfd_init ();
    
    	for (ohm = OHM_1M; ohm <= OHM_1K5; ohm++)
    	{
    		switch (ohm)
    		{
    			default:
    			case OHM_1M:
    				MAKE_IN (PORT_RELAIS1); CLR (PORT_RELAIS1);
    				MAKE_IN (PORT_RELAIS2); CLR (PORT_RELAIS2);
    				const_R = (word) (1.01*1e12*65536./(XTAL_PHI * CONST_1M)); // 1pF
    				loadTime = 20;
    				dot = 0;
    				dim = 'p';
    				break;
    			case OHM_47K:
    				MAKE_OUT (PORT_RELAIS1); SET (PORT_RELAIS1);
    				MAKE_IN  (PORT_RELAIS2); CLR (PORT_RELAIS2);
    				const_R = (word) (1.01*1e10*65536./(XTAL_PHI * CONST_47K)); // 100pF
    				loadTime = 40;
    				dot = 1;
    				dim = 'n';
    				break;
    			case OHM_1K5:
    				MAKE_OUT (PORT_RELAIS1); SET (PORT_RELAIS1);
    				MAKE_OUT (PORT_RELAIS2); SET (PORT_RELAIS2);
    				const_R = (word) (1.17*1e9*65536./(XTAL_PHI * CONST_1K5)); // 1nF
    				loadTime = 150;
    				dot = 0;
    				dim = 'n';
    				break;
    		}
    	
    		wait_10ms (10);
    		
    		capval = measure_time (loadTime);
    		
    		toobig = (0xffff == capval);
    		
    		if (doCallibrate)
    		{
    			if (toobig)
    				break;
    			callibra[ohm] = capval-3;
    		}
    		else
    		{
    			if (!toobig)
    			{
    				capval -= callibra[ohm];
    				capval = (word) (mul_ww (const_R, capval) >> 16);
    				break;
    			}
    		}
    			
    		ioinit();
    	}
    	ioinit();		
    	
    	vfd.bright = 4;
    	vfd_init ();
    		
    	if (toobig)
    	{
    		static const prog_char STR_C_ZU_GROSS[] = "C zu groß";
    		if (doCallibrate)
    		{
    			vfd_pos_string_P (0x03, STR_C_ZU_GROSS);
    			vfd_pos_string_P (0x40, PSTR("zum kalibrieren"));
    		}
    		else
    			vfd_pos_string_P (0x43, STR_C_ZU_GROSS);
    			
    		return;
    	}
    
    	if (doCallibrate)
    	{
    		vfd_pos_string_P (0x03, PSTR("Kalibriert"));
    		return;
    	}
    	
    	if (ohm == OHM_1K5)
    	{
    		if (capval > 1000)
    		{
    			capval = (word) (mul_ww (capval, (word) (65536./10.)) >> 16);
    			dim = 0xe4; // my
    			dot = 2;
    		}
    	}
    	if (ohm == OHM_1M)
    	{
    		if (capval > 1000)
    		{
    			dim = 'n';
    			dot = 3;
    		}
    	}
    	vfd_pos_char (0x40, '0'+ohm);
    	put_decimal (0x48, capval, dot);
    	vfd_pos_char (0x4a, dim);
    	vfd_pos_char (0x4b, 'F');
    }
    
    void put_decimal (byte pos, word val, byte dot)
    {
    	byte i = 0;
    	do
    	{
    		word r,d;
    		divmod10 (d, r, val);
    		vfd_pos_char (pos--, '0' + (byte) r);
    		val = d;
    		i++;
    		if (i == dot)
    			vfd_pos_char (pos--, '.');
    	} while (val);
    }
    
    #if 1
    //	return (a*b) >> 16
    unsigned long mul_ww (word _a, word b)
    {
    	unsigned long ab = 0;
    	unsigned long a = _a;
    	
    	while (1)
    	{
    		if (b & 1)
    			ab += a;
    			
    		b >>= 1;
    		if (b==0)
    			return ab;
    		a <<= 1;
    	}
    }
    #endif
    Disclaimer: none. Sue me.

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •