ページ移動

エントリー

2016年12月の記事は以下のとおりです。

部品が使えそうな100均ライト

部品取りに使えそうな100均のLEDライト

100円本体

少し前に購入しておいたのを忘れていたので何処で購入したのが覚えてない

横にスイッチが付いている

スイッチ電池ボックス

とりあえずコイン電池(CR2032はPCのバックアップ電池に利用されているので持っている)をセットして光度を確認

直接観てみるとそこそこ眩しい,そこで暗闇を照らしてみると

暗闇照らす

尚,32+30Wの蛍光灯下(明るさ80%)では

蛍光灯

LEDなので集光しないと明るくならないと思うが数個つかって広い範囲を照らすのに使えないか考えてみようと思う

実際はテープLEDを購入した方が安いかな?(かもしれない)

電子負荷に表示部を追加中(その5)

調整も終わったので基板化,秋月のユニバーサル基板Cタイプで部品配置を考えた

旨く配置できたかなっと自己満足,赤のジャンパーピンはバックライトの電源OFFできるように付けた

基板1

ロータリーエンコーダを付けた状態,やはり常時だと邪魔になりそうなので取り外し可能にした

基板2

裏は

裏

(2016.12.11 追加)電子負荷初版完成

電子負荷本体に実装,基板配置で隙間の高さ不足だったのでシャント抵抗を移動させた

完成

この電子負荷は「定抵抗」でしか利用できない

また,当初バッテリーの放電器として利用できないかと考えていたが,最低動作電圧が2.0V(2SJ554のVGS,実働確認1.8V)なので充電池には使えない

不足機能は次期バージョンの課題にしよう

電子負荷に表示部を追加中(その4)

Arduinoで確認できたので単独動作させるためブレッドボードで組み立て

BB

LCDの右のボタンが画面表示切替用,その右にあるのがSW付のロータリーエンコーダで電圧の微調整用(ロータリーエンコーダは常に使う訳でないので基板上では取り外し可能にする予定)

機能仕様

画面表示切替で3つの表示を切り替える

①入力電圧と負荷電流表示

②負荷電流のみ表示

③タイマーと負荷電流の表示(タイマーのリセットはタイマー表示時に画面表示切替ボタンを3秒押す)

VAATA → ①へ戻る

ロータリーエンコーダ(SW)を押すと微調整モードに切り替わる(もう1度押すと戻る)

調整画面は「入力電圧」と「負荷電流のシャント抵抗ドロップ電圧」の2つあり画面表示切替で切り替えてロータリーエンコーダを回す

電圧 ←→ 電流

調整

ブレッドボードの状態で電圧の微調整を行ってみると表示電圧が不安定であることが判明

電源の問題だろうと三端子レギュレータのパスコン等の調整を行ったが変わらない

取り付けた「S-812C33AY-B-G」の仕様を観てみると(出力電圧精度:3.3 V±2.0%)でありADCの基準電圧としては安定度が良くないようだ

そこで(出力電圧精度:3.3 V±0.5%)の「LP2950L-3.3V」(100mA)に変更

更に分圧抵抗に0.1μFのパスコンを追加することで安定した

回路図

回路図

プログラム

ロータリーエンコーダの処理はこちらを利用できたので参考にしてライブラリを使用

昔の人間なもので全て整数で処理してる

#include <EEPROM.h>
#include "MsTimer2.h"
#include "U8glib.h"
#include "rotary.h"

/*
#define REFINTERNAL        1               //内蔵基準電圧
 */
#define PIN_VOLTREG        0               //電流計測用電圧DACピン
#define PIN_VOLTM25        3               //電圧計測用DACピン
#define PIN_MAINTSW        4               //調整モードスイッチピン番号
#define PIN_SHUNTSW        7               //シャント抵抗切替スイッチピン番号
#define PIN_MODESW         8               //モード切替スイッチピン番号

#ifndef REFINTERNAL
#define REF_DEFINE        DEFAULT          //電源電圧定義
#define REF_VOLT         33               //3.3V * 10
#else
#define REF_DEFINE        INTERNAL        //内蔵基準電圧(1.1V)
#define REF_VOLT         11               //1.1V * 10
#endif

#define R1_PART            9825            //分圧抵抗1(100KΩ)
#define R2_PART            1965            //分圧抵抗2(20KΩ)
#define MAX_VOLTREG        ((long)REF_VOLT * 100 - 1)
#define MAX_VOLTM25        ((long)REF_VOLT * (R1_PART + R2_PART) / R2_PART * 100 - 1)
                                           //電圧はmV換算

#define DSP_LINE1         28               //上行表示
#define DSP_LINE2         60               //下行表示
#define DSP_LINEC         44               //中央表示

#define OP_NORMAL          0               //通常オペレーション
#define OP_MAINTENANCE     1               //メンテナンスオペレーション

#define NRD_VOLTCRNT       0               //電圧電流表示
#define NRD_CRNTONLY       1               //電流のみ表示
#define NRD_TIMECRNT       2               //タイマー電流表示
#define NRD_VERSION        3               //ソフトウェアバージョン表示

#define MNT_VOLTADJ        0               //電圧調整
#define MNT_CRNTADJ        1               //電流換算電圧調整

#define TM_SEC            20               //秒換算値(50ms)
#define TM_MINUTE        (TM_SEC * 60)     //分換算値

U8GLIB_MINI12864 u8g(10, 9);
Rotary r = Rotary(2, 3);

static boolean running = false;            //動作状態フラグ
static boolean forced;                     //強制表示フラグ

static unsigned long initTimeCount = 0;    //初期時間
static unsigned long pushTimeCount = 0;    //ボタン押下時間
static unsigned long timeCount = 0;        //時間計測

static int opState = OP_NORMAL;            //初期オペレーションモード(通常モード)
static int normalMode = NRD_VOLTCRNT;     //初期通常モード
static int maintMode = MNT_VOLTADJ;        //初期メンテナンスモード

static boolean btnOnA = false;             //ボタンA押下フラグ
static boolean btnWaitA = false;           //ボタンA押下中フラグ
static boolean btnOnB = false;             //ボタンB押下フラグ

static int adjVolt;                        //電圧調整値(EEPROM:0,1)
static int adjCrntVolt;                    //電流換算電圧調整値(EEPROM:2,3)

//調整値表示
//最小値の1は0.1%
static void displayAdjValue(int dl, int vv) {
    char str[8];
    int i = vv / 10;
    int f = vv % 10;
    if(f < 0) f *= (-1);
    if(vv < 0 && i == 0) {
        sprintf(str, "-0.%d\0", f);
    } else {
        sprintf(str, "%2d.%d\0", i, f);
    }
    u8g.setPrintPos(16, dl);
    u8g.print(str);
    u8g.setPrintPos(86, dl);
    u8g.print(" %");
}

//電圧を小数点付出力文字列に調整する
//入力電圧は1000倍された整数で下3桁が小数点以下となる
//小数点以下の表示は2桁とする
//  1000未満  0.XX
// 10000未満  N.XX
// 上記以外  NN.XX
//
static void displayVoltString(int dl, int ee) {
    char str[8];
    if(ee < 0) {
        //最大電圧超
        u8g.setPrintPos(4, dl);
        u8g.print("@OVER@");
    } else {
        int i = ee / 1000;
        int f = (ee % 1000)/10;            //小数点以下2桁にする
        if(ee < 1000) {
            sprintf(str, " 0.%02d\0", f);
        } else if(ee < 10000) {
            sprintf(str, " %d.%02d\0", i, f);
        } else {
            sprintf(str, "%2d.%02d\0", i, f);
        }
        u8g.setPrintPos(4, dl);
        u8g.print(str);
        u8g.setPrintPos(86, dl);
        u8g.print(" V");
    }
}

//電流表示(swで単位をmA/A切換え)
static void displayCrntString(int dl, int ii, int sw) {
    char str[8];
    if(sw == HIGH) {
        sprintf(str, "%4d\0", ii);
        u8g.setPrintPos(4, dl);
        u8g.print(str);
        u8g.setPrintPos(78, dl);
        u8g.print("mA");
    } else {
        int i = ii / 1000;
        int f = (ii % 1000)/10;            //小数点以下2桁にする
        if(ii < 1000) {
            sprintf(str, " 0.%02d\0", f);
        } else {
            sprintf(str, "%2d.%02d\0", i, f);
        }
        u8g.setPrintPos(4, dl);
        u8g.print(str);
        u8g.setPrintPos(86, dl);
        u8g.print(" A");
    }
}

//時間表示(HH:MM:SS)
static void displayTimeString(int dl, unsigned long tm) {
    char str[10];
    int hh = tm / ((unsigned long)60 * TM_MINUTE);
    int mm = (tm / TM_MINUTE) % 60;
    int ss = (tm % TM_MINUTE) / TM_SEC;
    sprintf(str, "%02d:%02d:%02d\0", hh, mm, ss);
    u8g.setPrintPos(2, dl);
    u8g.print(str);   
}

//電圧測定ポートから読込み
static int readVoltPort() {
    int e, val = (-1);
    if((e = analogRead(PIN_VOLTM25)) < 1023) {
        //ここでMAX_VOLTM25を補正する
        int maxvolt = (long)MAX_VOLTM25 * adjVolt / 1000 + MAX_VOLTM25;
        val = map(e, 0, 1023, 0, maxvolt);
    }
    return(val);
}

//電流測定ポートから読込み
static int readCrntPort() {
    //ここでMAX_VOLTREGを補正する
    int maxvolt = (long)MAX_VOLTREG * adjCrntVolt / 1000 + MAX_VOLTREG;
    return(map(analogRead(PIN_VOLTREG), 0, 1023, 0, maxvolt));
}

//電流読込:電流値算出
//抵抗値の電圧降下による電圧から電流値を算出する
//    D7:0.5Ω=H,5Ω=L 切替
//
static int changeCrnt(int ee, int sw) {
    int val;
    if(sw == HIGH) {
        //R = 5.00
        val = ee / 5;                    //I = E / R
    } else {
        //R = 0.5
        //val = ee * 2;                    //0.5 -> 逆数で*2
        //R = 0.52
        val = (long)ee * 192 / 100;            //1.92 = 0.52 の逆数
    }
    return(val);
}

void timeUp() {
    timeCount++;

    //メンテナンスSW処理(優先)
    int maintsw = digitalRead(PIN_MAINTSW);
    if(btnOnB) {
        //メンテナンスボタン押下後
        if(maintsw == HIGH) {
            //メンテナンスボタンが離された
            btnOnB = false;
            if(opState == OP_NORMAL) {
                //メンテナンスモードへ移行
                opState = OP_MAINTENANCE;
                maintMode = MNT_VOLTADJ;
            } else {
                //通常モードへ移行
                opState = OP_NORMAL;
                //電圧調整値書込み(EEPROMへの書き込みには3.3ミリ秒かかる)
                EEPROM.write(0, adjVolt>>8);
                EEPROM.write(1, adjVolt&0xff);
                EEPROM.write(2, adjCrntVolt>>8);
                EEPROM.write(3, adjCrntVolt&0xff);
            }
        }
    } else if(maintsw == LOW) {
        //メンテナンスボタン押下
        btnOnB = true;
    }

    //モードSW処理
    int modesw = digitalRead(PIN_MODESW);
    if(btnWaitA) {
        if(modesw == HIGH) {
            btnWaitA = btnOnA = false;    //ボタン押下終了
        }
    } else {
        if(btnOnA) {
            //ボタン押下後
            if(timeCount - pushTimeCount >= (TM_SEC * 3)) {
                btnWaitA = true;        //ボタンが離されるまで待つ
                //3秒以上の長押で操作モード変更
                //opState = (opState == OP_NORMAL)? OP_MAINTENANCE: OP_NORMAL;
                //メンテナンスモードにしたら通常モードを1にする(止め)
                //normalMode = NRD_VOLTCRNT;
                if(normalMode == NRD_TIMECRNT) {
                    //時間表示モードならリセット
                    initTimeCount = timeCount;
                    forced = true;        //強制再表示
                }
            } else if(modesw == HIGH) {
                //ボタンが離された
                btnOnA = false;            //ボタン押下終了
                //3秒未満のクリックは表示モード変更
                if(opState == OP_NORMAL) {
                    //通常オペレーション
                    switch(normalMode) {
                    case NRD_VOLTCRNT: normalMode = NRD_CRNTONLY; break;
                    case NRD_CRNTONLY: normalMode = NRD_TIMECRNT; break;
                    case NRD_TIMECRNT: normalMode = NRD_VOLTCRNT; break;
                    }
                } else {
                    //メンテナンスオペレーション
                    maintMode = (maintMode == MNT_VOLTADJ)? MNT_CRNTADJ: MNT_VOLTADJ;
                }
            }//else ボタン押下中
        } else if(modesw == LOW) {
            //ボタン押下
            btnOnA = true;
            pushTimeCount = timeCount;
        }
    }
}

ISR(PCINT2_vect) {
    if(opState == OP_MAINTENANCE) {
        unsigned char result = r.process();
        if(result) {
            //Serial.println(result == DIR_CW ? "Right" : "Left");
            int adj = (result == DIR_CW)? 1: (-1);
            if(maintMode == MNT_VOLTADJ) {
                adjVolt += adj;
            } else {
                adjCrntVolt += adj;
            }
        }
    }
}

void setup() {
    analogReference(REF_DEFINE);
    pinMode(PIN_SHUNTSW, INPUT_PULLUP);    //シャント抵抗切替スイッチの入力設定
    pinMode(PIN_MODESW, INPUT_PULLUP);    //モード切替スイッチの入力設定
    pinMode(PIN_MAINTSW, INPUT_PULLUP);    //調整モードスイッチの入力設定
    u8g.setContrast(190);
    u8g.setFont(u8g_font_helvR24);
    MsTimer2::set(1000/TM_SEC, timeUp);    //インターバルタイマー設定
    MsTimer2::start();
    //調整用ロータリーエンコーダ割込み設定
    PCICR |= (1<<PCIE2);
    PCMSK2 |= (1<<PCINT18) | (1<<PCINT19);
    //電圧調整値
    adjVolt = (EEPROM.read(0)<<8) +  EEPROM.read(1);
    adjCrntVolt = (EEPROM.read(2)<<8) +  EEPROM.read(3);
}

void loop() {
    int volt, crnt, crntvolt, shuntsw, modesw;
    int tm, st, md, mm;

    noInterrupts();
    forced = false;
    tm = timeCount / TM_SEC;
    st = opState;
    md = normalMode;
    mm = maintMode;
    interrupts();

    volt = readVoltPort();
    crntvolt = readCrntPort();
    shuntsw = digitalRead(PIN_SHUNTSW);
    crnt = changeCrnt(crntvolt, shuntsw);
    u8g.firstPage();
    do {
        if(st == OP_NORMAL) {
            //通常オペレーション
            switch(md) {
            case NRD_VOLTCRNT:
                displayVoltString(DSP_LINE1, volt);
                displayCrntString(DSP_LINE2, crnt, shuntsw);
                break;
            case NRD_CRNTONLY:
                displayCrntString(DSP_LINEC, crnt, shuntsw);
                break;
            case NRD_TIMECRNT:
                displayTimeString(DSP_LINE1, timeCount - initTimeCount);
                displayCrntString(DSP_LINE2, crnt, shuntsw);
                break;
            }
        } else {
            //メンテナンスオペレーション
            if(mm == MNT_VOLTADJ) {
                displayVoltString(DSP_LINE1, volt);
                displayAdjValue(DSP_LINE2, adjVolt);
            } else {
                displayAdjValue(DSP_LINE1, adjCrntVolt);
                displayVoltString(DSP_LINE2, crntvolt);
            }
        }
    } while(u8g.nextPage());

    while(!forced && tm == (timeCount / TM_SEC)) delay(100);
}

 

電子負荷に表示部を追加中(その3)

機能仕様とプログラムは落ち着いたので完成させるため基本データ値の計測を行う

シャント抵抗値

正確な電流値を出すため必要となるシャント抵抗(0.5Ω,5.0Ω)の正確な抵抗値を計測

先ずはテスターで計測してみる

0.55.0

4つのテスタで計測してみて結果は次のとおり

テスター名 0.5Ω 5.0Ω
sanwa PM3 0.6 5.1
kaise KU-1188 0.8 5.5
MASTECH MS8221C 0.8 5.2
Janisa PM18C 1.0 5.5

想像していたとおりで正確な抵抗値は計測できないようだ

そこで4端子法を使用して測定(4端子法の説明はこちらが判りやすい)

0.5-25.0-2

電流制限抵抗(Ω) 0.5Ω 5.0Ω 算出抵抗値(Ω)
電圧(mV) 電流(mA) 電圧(mV) 電流(mA) 0.5 5.0
330   7.8 14.86 72.5 14.66  0.52 4.95
100 25.0 48.0 231 46.0  0.52 5.02
50 47.6 91.6 423 84.6  0.52 5.00

内部で保持する初期シャント抵抗値を0.52Ω,5.0Ωとする(調整機能は実装済)

消費電力

USB簡易電圧・電流チェッカーで計測できなかった消費電力を計測しようと「USBテスターツール」(こちらを参考)を作製

USB tester

しかし・・・電流は0

電流値

少し悩んだ末,0.15Ωのシャント抵抗を付けてドロップ電圧を測定

ドロップ電圧

2.6mVと出た

ここの計算はシビアで無くても良いので,2.6 ÷ 0.15 ≒ 17mA,5 × 17 = 85mW

効率を無視(100%)して,85 ÷ 3.3 = 25mA となる

電源は50mAも出せれば十分そうなので,「S-812C33AY-B-G」を使用する

バックライトを消灯して計測したところ2.1mVで,とても省電力なバックライトだった(LEDなのか?)

ページ移動

  • ページ
  • 1
  • 2

ユーティリティ

検索

エントリー検索フォーム
キーワード

新着コメント

過去ログ

Feed