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.
Und hier etwas von dem Geklimper drumrum: Umrechnen in Kapazität, Messbereich auswählen, Kalibrierung, etcCode:#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_); }
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







Zitieren

Lesezeichen