エントリー

カテゴリー「オシロスコープ」の検索結果は以下のとおりです。

DSO138に付けたロータリエンコーダ

DSO138に付けたロータリエンコーダ・・・使えない訳でではないのだが早く回すと今一つの動作なのは感じていた

そこでロータリエンコーダ制御プログラムの修正を行うことにした

//DSO138改造
//ロータリエンコーダを取り付け V1.40
//
// ロータリエンコーダの回転を割込みで処理
// A・B軸割込みを全て受けて前回と今回でインデックス処理し回転カウントを蓄積
// メインループでは蓄積された量によってボタンをエミュレートする回数を決める
// 蓄積が少ない多いでロータリエンコーダの回転速度を判定し
// 初回をある程度の回数をボタン1回とし残りはボタン1回とする数を変動する
// 現在は2段階にしている
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

#define EN_A PB0
#define EN_B PB1
#define OUT1 PB2
#define OUT2 PB3

#define BTNON_TIME_US   (20000)   //ボタンON時間
#define BTNOFF_TIME_US  (10000)   //ボタンOFF時間
#define RT_FIRST_COUNT  (3)       //初回回転カウント数(クリック付きでは1クリック4なので4以下が望ましい)
#define RT_NEXT_COUNT   (2)       //初回以降の回転カウント数

//回転方向テーブル
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
// 0 + - 0 - 0 0 + + 0 0 - 0 - + 0
// 0: 静止,無効,+: 右,-: 左
static const int dir[] = { 0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0 };
static int count = 0;
static int prev = 0;

//ロータリー動作割込み:前回値と今回値でインデックスを作り回転方向を蓄積
ISR(PCINT0_vect) {
int current = (PINB&0x03);
if(prev != current) { //チャタリング対応
int index = ((prev<<2) + current) & 0x0f;
count += dir[index];
prev = current;
}
}

void setup() {
//内蔵のプルアップ抵抗を有効にする場合は、DDRxで該当のピンを入力にした後
//そのピンをHIGHに設定する(有効にしない場合はLOWに設定する)
DDRB = (_BV(OUT1)|_BV(OUT2)); //pinMode(OUT1, OUTPUT); pinMode(OUT2, OUTPUT);
PORTB |= _BV(EN_A); //pinMode(EN_A, INPUT_PULLUP);
PORTB |= _BV(EN_B); //pinMode(EN_B, INPUT_PULLUP);
PORTB |= _BV(OUT1); //digitalWrite(OUT1, HIGH);
PORTB |= _BV(OUT2); //digitalWrite(OUT2, HIGH);

GIMSK |= (1<<PCIE); //PCINT割込みを有効
PCMSK = _BV(EN_A) | _BV(EN_B); //割込み許可ポートの設定
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}

void loop() {
int dt;
boolean cont_flg = false; //連続中フラグ
int cont_cnt = 0; //連続中の前回残りカウント

for(;;) {
cli(); //割り込み禁止
dt = count;
count = 0;
sei(); //割り込み許可

if(dt == 0) {
//今回カウントが0なら回転を止めたと判断
//残りもリセットしてスリープ,残りカウントはクリアしないほうが良さそう
cont_flg = false;
// cont_cnt = 0;
sleep_mode();
} else {
dt += cont_cnt;
if(cont_flg) {
//継続
if(dt > 0) {
//右回転(+)
while(dt >= RT_NEXT_COUNT) {
PORTB &= ~_BV(OUT1); //digitalWrite(OUT1, LOW);
_delay_us(BTNON_TIME_US);
PORTB |= _BV(OUT1); //digitalWrite(OUT1, HIGH);
_delay_us(BTNOFF_TIME_US);
dt -= RT_NEXT_COUNT;
}
} else {
//左回転(-)
while(dt + RT_NEXT_COUNT <= 0) {
PORTB &= ~_BV(OUT2); //digitalWrite(OUT2, LOW);
_delay_us(BTNON_TIME_US);
PORTB |= _BV(OUT2); //digitalWrite(OUT2, HIGH);
_delay_us(BTNOFF_TIME_US);
dt += RT_NEXT_COUNT;
}
}
cont_cnt = dt;
} else {
//初回
//クリック1回分のカウントがあれば実行
if(dt >= RT_FIRST_COUNT) {
//右回転(+)
PORTB &= ~_BV(OUT1); //digitalWrite(OUT1, LOW);
_delay_us(BTNON_TIME_US);
PORTB |= _BV(OUT1); //digitalWrite(OUT1, HIGH);
_delay_us(BTNOFF_TIME_US);
cont_cnt = dt - RT_FIRST_COUNT;
cont_flg = true;
} else if(dt + RT_FIRST_COUNT <= 0) {
//左回転(-)
PORTB &= ~_BV(OUT2); //digitalWrite(OUT2, LOW);
_delay_us(BTNON_TIME_US);
PORTB |= _BV(OUT2); //digitalWrite(OUT2, HIGH);
_delay_us(BTNOFF_TIME_US);
cont_cnt = dt + RT_FIRST_COUNT;
cont_flg = true;
} else {
cont_cnt = dt;
}
}
}
}
}

使用しているロータリエンコーダはクリック付きの物であり1クリックで4回のカウントが出るので単純に4回を1回として数えるだけとかクリックを無視して全カウントを数えるとか試行してみたが操作性が良くならなかった

ロータリエンコーダの動作を得てもボタンのエミュレート処理の方で遅延が発生するためリアルタイムに処理できないためである

テストプラグラムでは右回転だけしていてもチャタリングや高速回転で処理が追い付かない場合もあるのか左回転と判断してしまう事もあることが判っている

そこで最終的に回転結果をQue化にすることにした

Queといっても1つずつ取り出して処理する必要はないので回転数をカウントしておくカウンタであり溜まったカウンタの数から回転速度を想定しボタンエミュレートする

今回は2段階速度の判定で操作性が十分になった

最後に

プログラムは難しいものでないので速攻で出来た・・・のだけど・・・実は思うように動作しないバグがあって情けないことに解決まで3時間位掛かった

デバッグコードが埋め込めないので動作予想できる範囲でコードをコメントアウトしながらデバッグした結果

以下が問題だったことがやっとこさ判る

static const byte dir[] = { 0, 1, -1, 0, -1, 0, 0, 1, 1, 0, 0, -1, 0, -1, 1, 0 };

サイン付きデータなのにサイン無しのbyteになっていたのである

書き換え前はサイン無しデータ(元は-1は2)だったので変更するのを忘れてしまっていた

しかしこれはコンパイラでwarning出して欲しい(それともメッセージ設定があって設定するのをミスってるのかな?)

DSO138の操作性改善に挑戦

今年の1月くらいにJYE Techから新しくDSO150なるオシロスコープキットが出て,スペック的にはDSO138とあまり変わらないが,ケースを追加しロータリエンコーダで操作するようになったようだ

DSO150

ケース付きになって良さそう・・・最近Amazonでも取り扱い開始・・・しかも安いが,いわくつきだけどサインスマートのDSO138があるのでどうしようか・・・

そこで,DSO150を真似てDSO138を改造(改良かな?)してしまおうと考えた

DSO138

サインスマートDSO138のメイン基板,キット制作時にコンデンサの変更やボタンを交換してある

ロータリーエンコーダ―を付ける

DSO150にはDSO138(DSO062も同じ)では操作性の悪い(+)(-)ボタンをロータリーエンコーダ―に変更してあり,ロータリーエンコーダ―の扱いも慣れてきたことだし(+)(-)ボタンを制御するようにすればいけそうなので付けてみる

ここでATMegaを使うのもオーバースペックでサイズ的にも組み込みしにくいのでATtiny13aでドライブすることにした

まずは実験・・・しようとしたが・・・嵌りまくった

実験

開発環境で嵌る

昔構築したIDE1.6環境が怪しげなのでIDE1.8.1で新たに環境構築したが(全てにおいて)ボードへの書込みができない問題が発生

すったもんだして動くようになったがはっきりした原因は不明(つまり何をやったら動くようになったか特定できなかった)

おそらくとなるがhardwareフォルダに昔の情報データがあったため動作不良となっていたのではないか(hardwareフォルダ内で不必要なのは削除した)

開発支援ボードで嵌る

今回UNO互換ボードで(自己開発の)開発支援ボードを使ったがUNOに未対応だった

3.3Vピンがショートしていたり余計なピンが絶縁されていなかった設計不良が発覚(これまで3.3Vピンが出力されていないボードで動作させていたため)

シリアル出力で嵌る

シリアル出力されない場合があり原因不明(ノイズか?)

プログラム開発

コード1KBの世界なので苦労するかと思ったが1KBはやっぱ広い・・・と思うのはTK80やLKIT世代のせいか^^

ただしデータ64Bytesは辛い(PROGMEMもあるけど利用は要注意)

PG

もっとハードウェアレジスタの直接操作でサイズを減らせるけど余裕あったので判りやすいコードで済ませた(とは思っている)

ATtiny13aのPB0とPB1をロータリーエンコーダ入力とし,PB2とPB3をそれぞれ+-ボタンとして出力する

//DSO138改造
//ロータリエンコーダを取り付け
//
#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

#define EN_A PB0
#define EN_B PB1
#define OUT1 PB2
#define OUT2 PB3

#define BTNON_TIME_US 40000

//割込みはsleepから抜けるだけで処理は無い
ISR(PCINT0_vect) {}

void setup() {
pinMode(EN_A, INPUT_PULLUP);
pinMode(EN_B, INPUT_PULLUP);
pinMode(OUT1, OUTPUT);
pinMode(OUT2, OUTPUT);
digitalWrite(OUT1, HIGH);
digitalWrite(OUT2, HIGH);

GIMSK |= (1<<PCIE); //PCINT割込みを有効
PCMSK = _BV(EN_A) | _BV(EN_B); //割込み許可
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
}

void loop() {
unsigned char dt = 0;

for(;;) {
//前回値と今回値でインデックスを作る
dt = ((dt<<2) + (PINB&0x03))&0x0f;

if(dt == 0x07) { //right
digitalWrite(OUT1, LOW);
_delay_us(BTNON_TIME_US);
digitalWrite(OUT1, HIGH);
} else if(dt == 0x0d) { //left
digitalWrite(OUT2, LOW);
_delay_us(BTNON_TIME_US);
digitalWrite(OUT2, HIGH);
} else {
sleep_mode();
}
}
}

制御プログラムは難なく完成したがボタンONーOFF間隔の設定調整に時間を費やした

ボタンONーOFF間隔はロータリーエンコーダの回転速度に(そこそこは)合わせないとスムーズにならない(早くても遅くても駄目)

尚,変化なし時のウエイトは無くても良いことを実働では確認

既にロータリーエンコーダ―化している方もいたので参考にはさせてもらっている

エンコーダ

追加パーツは秋月D基板の取付穴が本体に整合したので右側に置いた

設定ボタンの複数化

DSO062では各設定項目の専用ボタンがあったがDSO138では6つの設定項目を1ボタンで順列選択する操作になった

DSO150ではグループ化して複数ボタンにしたようだ

同じようにするのはしゃくなのでボタンを3つにして選択できる設定項目をまとめた

DSO138の選択(select)ボタンで選択できる設定項目

  1. Horizonal Position
  2. Vertical Position Indicator
  3. Timebase(s/div)
  4. Trigger Mode
  5. Trigger Slope
  6. Trigger Level Indicator

3つのボタンを配置し以下のように割り当てた

  • 1,2  :H/V.Pos
  • 3    :S/Div
  • 4,5,6:Trigger

button

PG2

PB1,PB2,PB3をグループ化したボタン入力とし,本体の設定項目選択ボタンに接続したPB4へ出力する

//DSO138改造
//機能ボタンを追加
//

#include <avr/io.h>
//#include <avr/eeprom.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>

//接続PIN
#define HVPOS            PB3        //PB0では動作しない(不明)
#define SECDIV           PB1
#define TRIGGER          PB2

#define BTNOUT           PB4
#define BTNON_TIME_MS    40        //ボタンON時間
#define BTNOFF_TIME_MS   20        //ボタンOFF時間

static int btint = 0;

//外部ピン変化割込み
ISR(PCINT0_vect) {
    //チャタリング10ms待ち
    _delay_ms(10);

    //ボタンの状態チェック(押下時のみ)
    if(!bit_is_set(PINB, HVPOS)) {
        btint = HVPOS;
    }
    else if(!bit_is_set(PINB, SECDIV)) {
        btint = SECDIV;
    }
    else if(!bit_is_set(PINB, TRIGGER)) {
        btint = TRIGGER;
    }
}

void setup() {
    //機能ボタン(入力)
    pinMode(HVPOS,   INPUT_PULLUP);
    pinMode(SECDIV,  INPUT_PULLUP);
    pinMode(TRIGGER, INPUT_PULLUP);
    //ハンドルボタン(出力)
    pinMode(BTNOUT, OUTPUT);
    digitalWrite(BTNOUT, HIGH);

    //ピン変化割込み許可
    GIMSK |= (1<<PCIE);                            //PCINT割込みを有効
    //PCMSK = (1<<PCINT1)|(1<<PCINT2)|(1<<PCINT3);//PB1,2,3の割込み許可
    PCMSK = (1<<HVPOS)|(1<<SECDIV)|(1<<TRIGGER);//割込み許可
    sei();
}


//    0.Horizonal Position
//    1.Vertical Position Indicator
//    2.Timebase(s/div)
//    3.Trigger Mode
//    4.Trigger Slope
//    5.Trigger Level Indicator

void loop() {
    int nowpos, movpos, btncnt;

    //nowposを復旧
    //(本体は電源OFFで記憶してなかったので処理を外す)
    //eeprom_busy_wait();
    //nowpos = (int)eeprom_read_byte((uint8_t *)0);
    nowpos = 2;
    set_sleep_mode(SLEEP_MODE_PWR_DOWN);

    for(;;) {
        //_delay_ms(1);
        sleep_mode();

        cli();
        if(btint) {
            switch(btint) {
            case HVPOS:
                if(nowpos == 0) {
                    movpos = 1;
                //} else if(nowpos == 1) {
                //    movpos = 0;
                } else {
                    movpos = 0;
                }
                break;
            case SECDIV:
                movpos = 2;
                break;
            case TRIGGER:
                if(nowpos == 3) {
                    movpos = 4;
                } else if(nowpos == 4) {
                    movpos = 5;
                //} else if(nowpos == 5) {
                //    movpos = 3;
                } else {
                    movpos = 3;
                }
                break;
            }
            if(movpos < nowpos) {
                btncnt = movpos + 6 - nowpos;
            } else {
                btncnt = movpos - nowpos;
            }
            while(btncnt--) {
                _delay_ms(BTNOFF_TIME_MS);
                digitalWrite(BTNOUT, LOW);
                _delay_ms(BTNON_TIME_MS);
                digitalWrite(BTNOUT, HIGH);
                _delay_ms(BTNOFF_TIME_MS);
            }
            nowpos = movpos;
            //nowposを退避(本体は電源OFFで記憶してなかったので処理を外す)
            //eeprom_busy_wait();
            //eeprom_write_byte((uint8_t *)0, (uint8_t)nowpos);
            btint = 0;
        }
        sei();
    }
}

完成ボード

操作性はそこそこで(雰囲気がイメージでは判らないので上記画像選択でビデオが観えるようにした)劇的に良くなったとは言えない

スクロールする操作はボタンを押すよりロータリーエンコーダで良くなったとは思う

ボタン

赤:HOLDボタン,回路は本体のボタンと並列で付けている(ATtiny13aは感知しない)

黄:H/V.Posの切替

青:S/Div専用

黒:Trigger関係3箇所の選択

電源と電源SW

本オシロは家の中でもコンパクトなため扱いやすく見易い場所で利用することができるのがメリットである

しかしACアダプタではコンセントまでのケーブル取り回しが厄介なこともあり006Pの充電池(8.4V)を使用することが多い

だが電力消費が9V120mAあるため,連続使用時間が約1時間(持たないことも)程度となる

そこでコンパクトな電源の構想を延々と考えている

・・・小容量のバッテリの昇圧では厳しそう

・・・コンパクトで大容量なら2000mAh+クラスのリポで昇圧・・・だけど高価かな(スマホ充電用の5Vの旧品が安く出回ってはいる)

・・・電子ライターのリポを取り出し3個直列という方法は・・・もともと取扱に気を遣うリポを直列は面倒なので極力パス

・・・やはり単4ニッケル水素×7個か8個かな

電源は電源SWを含み検討中

その他(まとめ)
  • ピンの余裕がないので機能別にATtiny13aを2個使用
  • ケースは横幅が増えたため凝らない程度で作り直しする予定
  • ATtiny13aの使い方を改めて検証できたのと,その開発ボードの欠点(欠陥かな)が判明したので満足
  • こつこつと調整したので記事の公開が遅くなった(最終編集が4/2(日)となる)

格安のPCオシロスコープを購入

タイトルのとおり「格安オシロスコープ」でググってみたら1万円以下のPCオシロ(USB接続)を2つ発見

HANTEK 6022BE

6022BE

チャンネル:2チャンネル

サンプル・レート:48M

帯域幅:20MHzの(-3dB)

自動カーソルのトラッキング測定

最安値¥7,280
サインスマート DDS-120

DDS-120

チャンネル:2チャンネル

サンプリングレート50M

帯域幅:20MHz

薦めの入力値: 1 ~ 15M hz

10 倍電圧プロテクション

10kV ESD プロテクション

1K HZ 方形波出力

最安値¥8,500

仕様はどちらも同じようなもので、この際1つ買ってみるかと2つを比べるため評価をチェック

結果DDS-120を購入することにした

決め手はソフトウェアをDLして起動してみてDDS-120のほうが気に入ったからとACとDCカップリングがサポートされていたこと(6022BEはDCカップリングしかない)、またアマゾンのカスタマレビューが多かったこともある(評価もまあまあ)

ただ中華でHANTEKは有名らしく世界では6022BE評価のほうが多いようだ(多いだけ高いかどうか知らない)

物は在庫があったためかアマゾンで8日夜に注文して10日夜に届いた

001

早速開けてみると、むむ!

002

QCマークが・・・でも日付も担当者も記載されていない

003

中身は本体とプローブなどの付属品の2段となっていた

004

本体、ゴム足が付いてないので後で付けよう

005

プローブは2本

006

P6060の型番が付いていたので60MHzのようだ(秋月価格¥1,100と同等品?)

007

USBケーブルはしっかりしたものが付いていた

008

クイックガイドとソフトウェアCD(8cm)、他にUsersManualもあった、全部英語

009

XP64で動作確認

ドライバは手動にて32bit版をインストール(警告はでる)、ソフトウェアは最新(V1.2だった)をダウンロードして解凍すれば実行可能

マニュアルではXP~8が対象となっており、CDにはドライバXP/7(32bit)と7(64bit)が準備されている(8は必要ないと書かれたファイルがあった)

No driver is needed on Windows 8.
The device would be installed automatically.

1ch動作を確認、1KHzの方形波を表示しプローブのトリマで調整してみたが変化なし

soft1

 2ch動作を確認

soft2

XPで動作確認

古いノートPCがあるのでPCオシロ専用機として使うことにした

ドライバは手動にてXP版をインストール(こちらは専用なので警告はなし)

画面が1024×768なため狭いがとりあえずは使えそうだ

soft3

 

(追加)

CDに入っていたソフトウェアの方が新しかった(Ver1.3)

soft5

メニュが増えている

soft4

秋月の新しいオシロスコープキット(DSO138)を製作

秋月ページをチェックしていたらTFTカラー液晶を採用したDSO138というデジタルオシロスコープキットがあった

こちらのページで存在は知っていてカラーは観易くて良さそうだなと思っていたので早速購入

少し時期遅れで本家のDSO138も販売され少し価格が上がるがファームバージョンが新しいようだ

パッケージ

1つの袋に収まっていた

パッケージ

パーツ

中身は、基板

P1

ブロープ(BNC接続の赤黒のミノムシクリップ)

P2

スイッチなど

P3

抵抗

P4

コンデンサー

P5

半導体(LED・ダイオード・トランジスタ)、インダクター

P6

液晶はちゃんとプチプチで包装

P7

P8

製作

パッケージはパーツのみでパーツリストとか説明書などの紙類はなしだったので、説明書を秋月ページからのリンクでダウンロードして印刷した

基板には表面実装パーツは既に載っており、その他のパーツを半田付けすると約3時間位で完成する(説明書通りで難易度は高くない)

完成後の電圧チェック(説明書には各所の電圧チェックの記載がある)

電圧チェック

電圧確認後、ジャンパを結線して液晶を載せて起動する

起動2

起動1

起動3

0Vポジションがずれているので説明書通りに調整(GNDでVPOS選択後、OKを2秒位押す)

0V調整1

0V調整2

 

尚、右側のタクトスイッチはいまいちなのでボタンスイッチ(これ)に変更、左側のスイッチには以下のようにゲタ(2mmのピンソケット)を履かせて取り付けている

スイッチゲタ

 

ケース

悩んだ末・・・どうしてもスイッチの位置(正確には高さ)が解決できなかったため安易なまな板ケースとした

表板はクリアアクリルで左側のスイッチは高さを確保できないので切り込みしている

これで少なくとも上から何かが入って接触ってことは安易には起こらない

表板

裏板にはアルミ板を付けてみた

裏板

持ち易いし、ゴム足も付けて置き易くもなっている

バッテリ利用のためのバッテリ設置場所を確保できていないのが問題点

(追記)

公称の消費電力が9V200mAなんで006P7セル8.4Vで稼動確認してみて問題なし

1時間位は使えるはず、ポータブル運用としてバッテリボックスも考えないといけないかな

 

追記)長い間DSO130と記載していたDSO138が正しいようだ(2016.03.11:なんで間違ったのだろう?)

ページ移動

  • ページ
  • 1
  • 2
  • 3
  • 4

ユーティリティ

タグクラウド

検索

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

Feed