Lメータ(インダクタンスの測定器)


フランクリン発振回路周波数カウンタ(AVR使用) を付けて、 Lメータ (インダクタンスの測定器) を作ってみました。

フランクリン発振回路の発振周波数とC = 1000PF固定より、L (インダクタンス) の値を得て、 LCDに発振周波数とL (インダクタンス) の値を表示します。

インダクタンスは数百mHから数十μHまで測れるようです。
発振周波数は フランクリン発振回路 で調べたように1.5MHz以下までは実用になるようです。


Lメータの測定値
コイルの表示
(L)
Lメータの測定値(uH)
(L)
Lメータの測定値(Hz)
(f)
300mH 326965 8802
4.7mH 4733 73157
4mH 3848 71135
2mH 1933 114470
1mH 999 159256
330μH 316 283097
100μH 100 502112
10μH 10 1560550


l_meter.gif

回路図


l_meter_bb.JPG

実験風景


How to Compile (コンパイルのしかた)

プログラム
/*
 *  l_meter.c
 *  フランクリン発振回路の発振周波数とC = 1000PFよりLの値を得て、
 *  LCDに発振周波数とLの値を表示する。
 *  ATmega328P
 *
 *
 *  Fuses(システムクロック:20MHz)
 *
 *              水晶
 *  EXTENDED    0xFD
 *  HIGH        0xD9
 *  LOW         0xF7
 */

#include <stdio.h>
#include <string.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 20.0E6                /* 20 MHz */
#include <util/delay.h>

#define LCD_RS_H PORTC |= _BV(5)
#define LCD_E_H PORTC |= _BV(4)
#define LCD_RS_L PORTC &= ~_BV(5)
#define LCD_E_L PORTC &= ~_BV(4)
#define LCD_DB PORTC
typedef union tagCOUNT{
    unsigned long DWORD;
    struct{
        unsigned short lcount;
        unsigned short ucount;
    } WORD;
} COUNT;
#define PI 3.1415926535897932384626433832795
#define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))

void delay_us(unsigned short t){while(t--) _delay_us(1);}
void delay_ms(unsigned short t){while(t--) _delay_ms(1);}
void initLCD(void);
void initTIMER(void);
void clear_lcd(void);
void print_lcd(int x, int y, char *s);

unsigned long ltime;
unsigned short ucount;
COUNT freq;

int main(void)
{
    char buffer[32];
    int i;
    double freq2, lx;

    /* ATmega328P */
    DDRB = 0b00000000;      /* XTAL2 XTAL1 SCK   MISO  MOSI  ----- ----- ----- */
    DDRC = 0b00111111;      /* xxxxx RESET RS    E     DB7   DB6   DB5   DB4   */
    DDRD = 0b00000000;      /* ----- ----- T1    ----- ----- ----- ----- ----- */
    PORTB = 0b00111111;
    PORTC = 0b00000000;
    PORTD = 0b11011111;

    initLCD();
    initTIMER();
    sei();

    clear_lcd();
    print_lcd(5, 0, "START");
    delay_ms(2000);

    while(1){
        freq2 = freq.DWORD / 1.024;
        // f = 1 / (2 * Π * √L * √C)
        // f * f = 1 / (4 * Π * Π * L * C)
        // L = 1 / (f * f * 4 * Π * Π * C)
        lx = 1.0E6 / (freq2 * freq2 * 4.0 * PI * PI * 1000.0E-12);

        sprintf(buffer, "%11lu", (unsigned long)round(freq2));
        if(buffer[4] != ' '){
            for(i=0; i<3; i++)
                buffer[i] = buffer[2 + i];
            buffer[3] = ',';
            for(i=0; i<3; i++)
                buffer[4 + i] = buffer[5 + i];
            buffer[7] = ',';
        }
        else if(buffer[7] != ' '){
            for(i=0; i<3; i++)
                buffer[4 + i] = buffer[5 + i];
            buffer[7] = ',';
        }
        strcat(buffer, "Hz");
        clear_lcd();
        print_lcd(1, 0, buffer);

        sprintf(buffer, "%11lu", (unsigned long)round(lx));
        if(buffer[4] != ' '){
            for(i=0; i<3; i++)
                buffer[i] = buffer[2 + i];
            buffer[3] = ',';
            for(i=0; i<3; i++)
                buffer[4 + i] = buffer[5 + i];
            buffer[7] = ',';
        }
        else if(buffer[7] != ' '){
            for(i=0; i<3; i++)
                buffer[4 + i] = buffer[5 + i];
            buffer[7] = ',';
        }
        strcat(buffer, "uH");
        print_lcd(1, 1, buffer);

        delay_ms(1000);
    }
}

void initTIMER(void)
{
    TCCR0A = 0b00000010;    /* CTC動作 */
    TCCR0B = 0b00000101;    /* clk / 1024 */
    OCR0A = 20 - 1;         /* (1024 / 20MHz) * 20 = 1.024mS */
    TIMSK0 = 0b00000010;    /* 比較A割り込み要求有効 */

    TCCR1B = 0b00000111;    /* 外部クロックT1 (PD5)ピンの立ち上がりエッジ */
    TIMSK1 = 0b00000001;    /* オーバーフロー割り込み許可 */
}

/*
 *  TIMER0の割り込み(1.024mS)
 */
ISR(TIMER0_COMPA_vect)
{
    static unsigned long ot;

    ++ltime;

    if((unsigned long)(ltime - ot) >= 1000){
        ot = ltime;
        TCCR1B = 0b00000000;    /* カウント停止 */
        freq.WORD.lcount = TCNT1;
        TCNT1 = 0;
        TCCR1B = 0b00000111;    /* 外部クロックT1 (PD5) ピンの立ち上がりエッジ */
        freq.WORD.ucount = ucount;
        ucount = 0;
    }
}

ISR(TIMER1_OVF_vect)
{
    ++ucount;
}

/* DB:4BIT(LOWER) */
void lcd_c4(unsigned char data)
{
    unsigned char tmp;

    LCD_RS_L;                       /* RS --> L */
    LCD_E_H;                        /* E --> H */
    tmp = (unsigned char)(LCD_DB & 0xf0);
    tmp |= (unsigned char)(data & 0x0f);
    LCD_DB = tmp;
    LCD_E_L;                        /* E --> L */
    delay_us(40);
}

void lcd_c(unsigned char data)
{
    unsigned char tmp;

    LCD_RS_L;                       /* RS --> L */
    LCD_E_H;                        /* E --> H */
    tmp = (unsigned char)(LCD_DB & 0xf0);
    tmp |= (unsigned char)(data  >> 4 & 0x0f);
    LCD_DB = tmp;
    LCD_E_L;                        /* E --> L */
    delay_us(1);
    LCD_E_H;                        /* E --> H */
    tmp = (unsigned char)(LCD_DB & 0xf0);
    tmp |= (unsigned char)(data & 0x0f);
    LCD_DB = tmp;
    LCD_E_L;                        /* E --> L */
    delay_us(40);
}

/* DB:4BIT(LOWER) */
void lcd_d(unsigned char data)
{
    unsigned char tmp;

    LCD_RS_H;                       /* RS --> H */
    LCD_E_H;                        /* E --> H */
    tmp = (unsigned char)(LCD_DB & 0xf0);
    tmp |= (unsigned char)(data  >> 4 & 0x0f);
    LCD_DB = tmp;
    LCD_E_L;                        /* E --> L */
    delay_us(1);
    LCD_E_H;                        /* E --> H */
    tmp = (unsigned char)(LCD_DB & 0xf0);
    tmp |= (unsigned char)(data & 0x0f);
    LCD_DB = tmp;
    LCD_E_L;                        /* E --> L */
    delay_us(40);
}

void initLCD(void)
{
    delay_ms(15);
    lcd_c4(0x03);
    delay_ms(5);
    lcd_c4(0x03);
    delay_us(100);
    lcd_c4(0x03);
    lcd_c4(0x02);
    lcd_c(0x28);                    /* Function Set */
    lcd_c(0x08);                    /* Display OFF */
    lcd_c(0x01);                    /* Clear Display */
    delay_ms(2);
    lcd_c(0x06);                    /* Enter Mode */
    lcd_c(0x0c);                    /* Display ON */
}

void clear_lcd(void)
{
    lcd_c(0x01);                    /* Clear Display (& Cursor At Home) */
    delay_ms(2);
/// lcd_c(0x02);                    /* Cursor At Home */
/// delay_ms(2);
}

void cursor_lcd(int x, int y)
{
    lcd_c((unsigned char)(0x80 + y * 0x40 + x));
}

void print_lcd(int x, int y, char *s)
{
    cursor_lcd(x, y);

    while(*s)
        lcd_d((unsigned char)*s++);
}


真空管
戻る