Transistor Gijutsu, October 2014, Special Features Chapter 7,Software of the LCRmeter トランジスタ技術2014年10月号 特集第7章のソフトウェア,サバイバルLCRメータ

Dependencies:   mbed

Revision:
0:b3e41ec91adf
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Thu Aug 28 07:09:42 2014 +0000
@@ -0,0 +1,123 @@
+//
+// Transistor Gijutu - LPC11U35 ARM Writer
+// LCR meter
+//
+#include "mbed.h"
+#include "parts.h"
+
+#include "lcd_P4bit.h"
+
+#define IPC 25 // interrupt per cycle
+#define PI 3.14159265358979
+
+int ps1k = 0;   // pre-scaler for measure freq.
+int sintable[] = { 8, 9, 11, 12, 13, 14, 14, 14, 14, 13, 12, 10, 8, 7, 5, 3, 2, 1, 1, 1, 1, 2, 3, 4, 6 };
+double Vraw[IPC], Iraw[IPC];    // AD convert data
+int VorI;
+double vcalc[IPC], icalc[IPC];  // waveform buffer for calc.
+
+Ticker f25k;    // interval timer - make sine wave and measure current and voltage
+
+DigitalOut sine0(P0_14);    // R2R DAC bit 0
+DigitalOut sine1(P0_2);     // R2R DAC bit 1
+DigitalOut sine2(P0_23);    // R2R DAC bit 2
+DigitalOut sine3(P0_17);    // R2R DAC bit 3
+DigitalOut ISRflag(P0_20);  // interrupt service routine flag
+
+AnalogIn Voltage(p20);  // Voltage ADC
+AnalogIn Current(p19);  // Current ADC
+
+// 50KHz interval interrupt
+void interval_25k() {   
+  ISRflag = 1;
+  ++ ps1k;
+  if( IPC <= ps1k ) {
+    ps1k = 0;
+    VorI = !VorI;
+  }
+  sine0 = sintable[ps1k] & 0x01;    // DAC output - each bit
+  sine1 = sintable[ps1k] & 0x02;
+  sine2 = sintable[ps1k] & 0x04;
+  sine3 = sintable[ps1k] & 0x08;
+//
+  if( VorI ) Vraw[ps1k] = Voltage.read();    // measure Voltage or Current
+  else       Iraw[ps1k] = Current.read();
+  ISRflag = 0;
+}
+
+int main() {
+  int i;
+  char s[10];
+  double vi, vq, ii, iq;    // voltage/current, in-phase,quad-phase -> vi + jvq, ii + jiq
+  double r, x;      // register, reactance -> r + jx
+  double a;     // amplitude
+  
+  // work area initialize
+  VorI = 0;
+  for( i = 0; IPC > i; i ++ ) Vraw[i] = Iraw[i] = 0.0; 
+  // LCD module initialize
+  LCD_iniz();
+  // start interval interrupt
+  f25k.attach_us( &interval_25k, FREQ / IPC );
+  // LCD test
+  LCD_cmd( 0x80 );
+  LCD_puts( "LCR Mete" );
+  LCD_cmd( 0xC0 );
+  LCD_puts( "r V0.0" );
+  // Main routine
+  for( ; ; ) {
+    // copy raw data to calc. buffer
+    for( i = 0; IPC > i; i ++ ) vcalc[i] = Vraw[i], icalc[i] = Iraw[i];
+    // calc. in-phase and quad-phase
+    vi = vq = ii = iq = 0.0;
+    for( i = 0; IPC > i; i ++ ) {
+      a = 2 * PI * (double)i / (double)IPC;
+      vi = vi + vcalc[i] * sin( a );
+      vq = vq + vcalc[i] * cos( a );
+      ii = ii - icalc[i] * sin( a );
+      iq = iq - icalc[i] * cos( a );
+    }
+    // gain calc.
+    a = ( R3 * ( R4 + R5 ) ) / ( R4 * ( R2 + R3 ) );
+    vi /= a;    // voltage real
+    vq /= a;    // voltage imaginary
+    ii /= R1;   // current real
+    iq /= R1;   // current immaginary
+    // divide : Z = v / i
+    if( 0.0 != ii || 0.0 != iq ) {
+      a = ii * ii + iq * iq;
+      r = ( ( vi * ii ) + ( vq * iq ) ) / a;
+      x = ( ( vq * ii ) - ( vi * iq ) ) / a;
+    }
+    else {
+      r = 999999.9, x = 999999.9;   // hi-Z
+    }
+    //  display R
+    if( 1000.0 > r )        sprintf( s, "R%4.1f  ", r );
+    else if( 10000.0 > r )  sprintf( s, "R%2.3fK ", r / 1000.0 );
+    else if( 100000.0 > r ) sprintf( s, "R%3.2fK ", r / 1000.0 );
+    else sprintf( s, "R ----- " );
+    LCD_cmd( 0x80 );
+    LCD_puts( s );
+    // display X
+    if( 0 < x ) {
+      // inductance
+      x = x / ( 2.0 * PI * FREQ );  // H
+      if( 1.0 > x )        sprintf( s, "L%4.1fm ", x * 1000.0 );
+      else if( 10.0 > x )  sprintf( s, "L%2.3f  ", x );
+      else if( 100.0 > x ) sprintf( s, "L%3.2f  ", x );
+      else sprintf( s, "L ----- " );
+    }
+    else {
+      // capacitance
+      x = -1000000.0 / ( x * 2.0 * PI * FREQ );    // uF
+      if( 1.0 > x )        sprintf( s, "C%4.1fn ", x * 1000.0 );
+      else if( 10.0 > x )  sprintf( s, "C%2.3fu ", x );
+      else if( 100.0 > x ) sprintf( s, "C%3.2fu ", x );
+      else sprintf( s, "C ----- " );
+    }
+    LCD_cmd( 0xC0 );
+    LCD_puts( s );
+  }
+}
+