//コイルインダクタンスメーター //OLEDバージョン // #include #include #include #include #if 0 #define DEBUG true #endif typedef unsigned long ulong; U8GLIB_SSD1306_128X32 u8g(U8G_I2C_OPT_NONE); // Just for 0.91 h(128*32) //0x3c #define GATETIME (100) //Start counting with gatetime(ms) #define GATEPSEC (1000/GATETIME) //gatetime par second //AVR hardware Pin #define CCAL_PIN 7 //D7: Digital I/O 7 #define ZSET_PIN 8 //D8: Digital I/O 8 //インダクタンス計算用の各値 //Arduino Unoのdouble型はfloat型と同一の実装で精度は向上しないのでfloatを使用 #ifndef PI const float PI = 3.14159265; #endif static ulong f1 = 0; //基本校正時の周波数(Hz)774,874Hz前後 static ulong f2 = 0; //Ccal校正時の周波数(Hz)438,293Hz前後 static ulong f3 = 0; //コンデンサ測定時の周波数(Hz)[未使用] static ulong f4 = 0; //コイル測定時の周波数(Hz) const float Ccal = 1000e-12; //固定値(1000pF) static float C1 = 0; //f1, f2から算出(F) static float L1 = 0; //f1, f2から算出(H) static float Cx = 0; //コンデンサ値(F)[未使用] static float Lx = 0; //コイル値(H) //状態表示用フラグ static bool f1_lflg = false; static bool f2_lflg = false; static bool f1_blink = false; static bool f2_blink = false; //校正時の周波数(パーツは固定なので同じような値になる) #define F1_MIN 750000 #define F1_MAX 800000 #define F2_MIN 400000 #define F2_MAX 450000 #define F4_MIN 1000 #define F4_MAX f1 //単位指数値 // 整数部(Integer part) // 少数部(Decimal part) #define INT 0 //無 整数 #define MILLI 3 //m 10e-3 #define MICRO 6 //μ 10e-6 #define NANO 9 //n 10e-9 #define PICO 12 //p 10e-12 void setup(void) { Serial.begin(9600); //connect to the serial port Serial.println("MSG: Coil inductance meter"); //ボタンピンの内部プルアップ pinMode(CCAL_PIN, INPUT_PULLUP); pinMode(ZSET_PIN, INPUT_PULLUP); //プルアップを解除内部 Wire.begin(); digitalWrite(SDA, 0); digitalWrite(SCL, 0); //OLEDセットアップ u8g.begin(); // assign default color value switch(u8g.getMode()) { case U8G_MODE_R3G3B2: u8g.setColorIndex(255); //white break; case U8G_MODE_GRAY2BIT: u8g.setColorIndex(3); //max intensity break; case U8G_MODE_BW: u8g.setColorIndex(1); //pixel on break; case U8G_MODE_HICOLOR: u8g.setHiColorByRGB(255,255,255); break; } // u8g.setFont(u8g_font_helvB08); // u8g.setFont(u8g_font_fub20); // u8g.setFont(u8g_font_fub14); // u8g.setFont(u8g_font_fub17); } //周波数をTRYCOUNT回カウントして平均値を出す #define TRYCOUNT 2 static ulong getFreq(void) { ulong freq = 0; FreqCounter::f_comp = 8; //Set compensation to 12 for(int n = 0; n < TRYCOUNT; n++) { FreqCounter::start(GATETIME); while(FreqCounter::f_ready == 0); //wait until counter ready freq += FreqCounter::f_freq; //read result } freq /= TRYCOUNT; freq *= GATEPSEC; return(freq); } void loop(void) { char lxStr[32], stStr[32]; ulong freq; if(digitalRead(ZSET_PIN) == LOW) { //校正ボタン押下中 if(digitalRead(CCAL_PIN) == HIGH) { //Ccalなし(基本校正) Serial.println("MSG: standard calibration"); delay(50); //少し待つ if((freq = getFreq()) > F1_MIN && freq < F1_MAX) { f1 = freq; } if(f1 != 0) { sprintf(lxStr, "%lu Hz", f1); } else { sprintf(lxStr, "Wait as it is "); } f1_blink = true; } else { //Ccalあり(Ccal校正) Serial.println("MSG: Ccal calibration"); delay(50); //少し待つ if((freq = getFreq()) > F2_MIN && freq < F2_MAX) { f2 = freq; } if(f2 != 0) { sprintf(lxStr, "%lu Hz", f2); } else { sprintf(lxStr, "Wait as it is "); } f2_blink = true; } if(f1 != 0 && f2 != 0) { //C1, L1算出 C1 = pow(f2, 2) / (pow(f1, 2) - pow(f2, 2)) * Ccal; L1 = 1 / (4 * pow(PI, 2) * pow(f1, 2) * C1); } } else { if(C1 != 0 && L1 != 0) { if(digitalRead(CCAL_PIN) == HIGH) { //対象計測 f4 = getFreq(); if(f4 > F4_MIN && f4 < F4_MAX) { Lx = (pow(f1, 2) / pow(f4, 2) - 1) * L1; //print frequency //Serial.print(f4); //Serial.println(" Hz"); //剰余演算子(%)はfloat型に対しては機能しない //また結果がfloat型になる int iPrt = 0; int dPrt = 0; //print インダクタンス if(Lx < 1000e-12) { //PICO(pH) iPrt = (int)(Lx * pow(10, PICO)); dPrt = (int)(Lx * pow(10, PICO + 1)) % 10; sprintf(lxStr, "%d.%d pH", iPrt, dPrt); } else if(Lx < 1000e-9) { //NANO(nH) iPrt = (int)(Lx * pow(10, NANO)); dPrt = (int)(Lx * pow(10, NANO + 1)) % 10; sprintf(lxStr, "%d.%d nH", iPrt, dPrt); } else if(Lx < 1000e-6) { //MICRO(uH) iPrt = (int)(Lx * pow(10, MICRO)); dPrt = (int)(Lx * pow(10, MICRO + 1)) % 10; sprintf(lxStr, "%d.%d uH", iPrt, dPrt); } else if(Lx < 1000e-3) { //MILLI(mH) iPrt = (int)(Lx * pow(10, MILLI)); dPrt = (int)(Lx * pow(10, MILLI + 1)) % 10; sprintf(lxStr, "%d.%d mH", iPrt, dPrt); } else { //INT(H) iPrt = (int)(Lx); dPrt = (int)(Lx * 10) % 10; sprintf(lxStr, "%d.%d H", iPrt, dPrt); } #ifdef DEBUG Serial.print("DBG: iPrt = "); Serial.print(iPrt); Serial.print(", "); Serial.print("dPrt = "); Serial.println(dPrt); #endif Serial.println(lxStr); } else { strcpy(lxStr, "no coil"); } } else { //CcalスイッチがONなのでOFFメッセージ Serial.println("MSG: turn off Ccal switch"); strcpy(lxStr, "turn off SW"); } } f1_blink = f2_blink = false; } #ifdef DEBUG Serial.print("DBG: f1 = "); Serial.print(f1); Serial.print("Hz, "); Serial.print("f2 = "); Serial.print(f2); Serial.print("Hz, "); Serial.print("f4 = "); Serial.print(f4); Serial.println("Hz"); Serial.print("DBG: C1 = "); Serial.print(C1); Serial.print(", "); Serial.print("L1 = "); Serial.print(L1); Serial.print(", "); Serial.print("Lx = "); Serial.print(Lx); Serial.println("H"); #endif //status string if(f1_blink) { //F1校正時 if(f1_lflg) { strcpy(stStr, "F1 "); f1_lflg = false; } else { strcpy(stStr, " "); f1_lflg = true; } } else if(f2_blink) { //F2校正時 if(f2_lflg) { strcpy(stStr, " F2"); f2_lflg = false; } else { strcpy(stStr, " "); f2_lflg = true; } } else { //計測モード時 if(f1 != 0 && f2 != 0) { strcpy(stStr, "F1 F2"); } else { if(f1 == 0 && f2 == 0) { //校正が行われていない if(f1_lflg) { strcpy(stStr, "F1 F2"); f1_lflg = f2_lflg = false; } else { strcpy(stStr, " "); f1_lflg = f2_lflg = true; } Serial.println("MSG: no initial calibration"); } else if(f1 == 0) { //基本校正されていない if(f1_lflg) { strcpy(stStr, "F1 F2"); f1_lflg = false; } else { strcpy(stStr, " F2"); f1_lflg = true; } Serial.println("MSG: no standard calibration"); } else { //Ccal校正されていない if(f2_lflg) { strcpy(stStr, "F1 F2"); f2_lflg = false; } else { strcpy(stStr, "F1 "); f2_lflg = true; } Serial.println("MSG: no Ccal calibration"); } strcpy(lxStr, "no calibrate"); } } // picture loop u8g.firstPage(); do { u8g.setFont(u8g_font_helvB08); u8g.setPrintPos(0, 16); u8g.print(stStr); u8g.setFont(u8g_font_fub14); u8g.setPrintPos(0, 32); //was 28 u8g.print(lxStr); } while(u8g.nextPage()); delay(500); }