2011年6月6日月曜日

arduinoでLCメータを妄想してみる

morecat_labさんのtwitterでaruduinoの周波数カウンタのライブラリを知りました。
精度、安定度は不明ですが周波数から逆算するLCメータが作れるのでは? なんて考えました。
基本的考え方はtiny2313vでLCメータと同じでソフト部分だけ妄想してみました。

実数を使うとどれくらいメモリーを消費するか調べるために基本部分だけです。
コンパイルサイズは
Binary sketch size: 6406 bytes (of a 32256 byte maximum)
なので余裕です。

ハード部分は後日tiny2313vでLCメータを分解して再利用予定。

/*
  Martin Nawrath KHM LAB3
  Kunsthochschule f¸r Medien Kˆln
  Academy of Media Arts
  http://www.khm.de
  http://interface.khm.de/index.php/labor/experimente/
 */
/*
  Masahiko KANETAKA
  kane4d@gmail.com
  http://kane4d.blogspot.com/
 
  Port MAP
  D0   I  RX
  D1   O  TX
  D2
  D3   I  LC Mode SW (High: C, Low: L)
  D4   I  Zero Adjust Botton
  D5   I  Wave(Frequency)
  D6   O  LCD d7
  D7   O  LCD d6
  D8   O  LCD d5
  D9   O  LCD d4
  D10  O  LCD enable
  D11  O  LCD rs
  D12  O  Relay drive
  D13  O  LED
*/
#define USE_SERIAL
#define USE_LCD
#include <FreqCounter.h>
#ifdef USE_LCD
#include <LiquidCrystal.h>
#endif
double getfreq(unsigned int f_comp = 10, int gateTime = 100);
#ifdef USE_LCD
LiquidCrystal lcd(11, 10, 9, 8, 7, 6);
#endif

double frq1_r = 0.0F, frq2_r = 0.0F, frq3_r = 0.0F;
double val_r;
int cnt;
bool cal_bool = false;
#define pinLed (13)
#define pinRelay (12)
#define pinZeroAdjBtn (4)
// High: C, Low: L
#define pinLCModeSW (3)
#define DEFAULT_TRY_COUNT (3)
//1000pF + 100uH
#define CAL_CAP (1000.0F)
double getfreq(unsigned int f_comp, int gateTime)
{
  double _frq_r = 0.0F;
  FreqCounter::f_comp = f_comp;   // Cal Value / Calibrate with professional Freq Counter
  for(int i = 0; i < DEFAULT_TRY_COUNT; ++i){
    FreqCounter::start(gateTime);  // 100 ms Gate Time
    while (FreqCounter::f_ready == 0) ;
    _frq_r += FreqCounter::f_freq;
  }
  return _frq_r / DEFAULT_TRY_COUNT;
}
void setup() {
  pinMode(pinLed, OUTPUT);
  pinMode(pinRelay, OUTPUT);
  pinMode(pinZeroAdjBtn, INPUT);
  pinMode(pinLCModeSW, INPUT); // High: C, Low: L
#ifdef USE_SERIAL
  Serial.begin(9600);        // connect to the serial port
  Serial.println("LC Meter v0.1");
#endif
#ifdef USE_LCD
  lcd.clear();
#endif
  //frq1_r = frq2_r = frq3_r = 0.0F;
}
void loop() {
  if ( ! digitalRead(pinZeroAdjBtn) && ! cal_bool ){
    //zero cal
    digitalWrite(pinRelay, false);
    delay(30);
    frq1_r = getfreq();
    digitalWrite(pinRelay, true);
    delay(30);
    frq2_r = getfreq();   
    digitalWrite(pinRelay, false);
    cal_bool = true;
  }else{
    cal_bool = false;
    if ( frq1_r > 0.0 && frq2_r > 0.0 ){
      digitalWrite(pinRelay, false);
      delay(30);
      frq3_r = getfreq();
      if (digitalRead(pinLCModeSW)){
        //CALC_C
        //val_r = CAL_CAP * ( (frq1_r / frq3_r) ^ 2 - 1.0 ) / ( (frq1_r / frq2_r) ^ 2 - 1.0 );
        val_r = (frq1_r + frq3_r) / frq3_r;
        val_r *= (frq1_r - frq3_r) / frq3_r;
        val_r *= frq2_r / (frq1_r + frq2_r) ;
        val_r *= frq2_r / (frq1_r - frq2_r) ;
        val_r *= CAL_CAP;
      }else{
        //CALC_L
        //val_r = CAL_C * ( (frq1_r / frq3_r) ^ 2 - 1.0 ) * ( (frq1_r / frq2_r) ^ 2 - 1.0 ) / CAL_CAP /( (2 * M_PI frq1_r)^2 );
        val_r = (frq1_r + frq3_r) / frq3_r;
        val_r *= (frq1_r - frq3_r) / frq3_r;
        val_r *= (frq1_r + frq2_r) / frq2_r;
        val_r *= (frq1_r - frq2_r) / frq2_r;
        val_r /= CAL_CAP;
        val_r /= 4 * M_PI * M_PI * frq1_r * frq1_r;
      }
#ifdef USE_SERIAL     
      Serial.println(val_r);
#endif
#ifdef USE_SERIAL     
      lcd.println(val_r);
#endif
    }
   
  }
  digitalWrite(pinLed,!digitalRead(pinLed));  // blink Led
 
}

0 件のコメント:

コメントを投稿