Arduino ATtiny85 割り込み RISINGとFALLINGを両方扱いたい
attachInterrupt(digitalPinToInterrupt(2), _interrupt1, RISING); attachInterrupt(digitalPinToInterrupt(2), _interrupt0, FALLING);
2つは登録できない。
attachInterrupt(digitalPinToInterrupt(2), _interrupt, CHANGE); で両方とれる。が今の状態が分からない。 void _interrupt(){ flag_interrupt_ = digitalRead(PIN_SWITCH); //or flag_interrupt_ = !flag_interrupt_; }
digitalReadを処理している間に次の割り込み等が入る。 フラグを裏返すのも、何かのタイミングでひっくり返りそう。
下記で安定した。
#define PIN_SWITCH 2 #define PIN_OUTPUT 0 volatile uint8_t flag_interrupt_ = 0; uint8_t flag_interrupt_tmp_ = 0; uint8_t pin_ = 0; uint8_t old_pin_ = 0; void setup() { pinMode(PIN_SWITCH, INPUT); pinMode(PIN_OUTPUT , OUTPUT); //PB2 INT0 attachInterrupt(digitalPinToInterrupt(2), _interrupt, RISING); } void loop() { pin_ = flag_interrupt_; flag_interrupt_tmp_ = digitalRead(PIN_SWITCH); flag_interrupt_ = flag_interrupt_tmp_;//assume atomic operation if(pin_ == 1 && old_pin_ == 0){ digitalWrite(PIN_OUTPUT , HIGH); }else if(pin_ == 0 && old_pin_ == 1){ digitalWrite(PIN_OUTPUT , LOW); } old_pin_ = pin_; } void _interrupt() { flag_interrupt_ = 1; }
基板ケースの3Dプリント検証・インサートナット
基板ケースを3Dプリンタで作りたい。
そのために必要な2要素について検証してみた。
- 基板固定用の爪の高さ
- インサートナットの下穴の大きさ
基板固定用の爪の高さ
省スペースのため、ネジではなく、爪でパチンと基板をケースに固定することにした。 1mm厚基板用に、爪までの高さを1.5mm、爪の高さを2mmにしてみた。
縦と横は、実際の基板サイズよりも4辺0.5mmずつ大きなスペースを作っている。
爪が高すぎたのと、爪の下部のサポート材が上手く取れなかったので、リューターで爪高が0.5mmぐらいになるまで削った。
パチンと気持ちよく嵌った。
爪がない辺は、0.5mmマージンは大きすぎたのか少しカコカコする。
インサートナットの下穴の大きさ
インサートナット
- M3
- OD 5.3mm
- Length 5mm
検証用にパターンを用意した。
穴の深さは、 Length * 1.5程が良いらしいので 7.5mmにした。
結果
- 直径 5mm
すんなり入る。 手で引っ張っても抜けない。 隙間が少しあるように見える。
- 直径 4.5mm
なかなか入らない。 無理やり入れようとして斜めってぐちゃぐちゃになった。
- 直径 4.7 or 4.8mm
バランス良さそう。
- 穴の壁厚 2mm
十分安定している
- 穴の壁厚 1.6mm
実用できそうではあるが、見た目心もとない。 余裕があるなら 2mm以上にしたい。
- 穴のbevel
CAD上で掛けたが、プリント精密限界のため実物は掛かっていなかった。そのためインサートが若干斜めった。 大げさにかけた方がよい。
- 穴の深さ
7.5mm で丁度ネジが5mmほど入った。
M2 インサートナット
OD = 3.5mm length = 3mm
3mm穴が丁度良さそう。
- 画像左
入口に大きなすり鉢加工を施した。 圧入時にズレる幅が大きくなった。
- 画像中
ナット長 * 1.5が穴の長さの目安らしいので4.5mmにしてみた。 穴の途中までPLAが上がってきてネジが途中までしか入らなくなった。
- 画像右
穴の深さ6mm
入口のすり鉢はほぼ無し
ズレ防止のため壁厚を2mmに増強
タッピングネジ
M2
wilco タッピングネジ Pタイト M2 5mm
鉄(三価クロメート黒色) +なべPタイト FPP-0000EB【ウィルコ-WILCO-】ねじ(ネジ)の通販・販売
ネジの図面上の呼び径1.7mmだが、3Dプリントだと2.1mmが丁度よい。初回のネジ締めは少し硬く、何回でも締めなおせる具合になる。
M3
ネジの図面上の呼び径2.7mmで、 3Dプリントサイズ3.0mmで良かった。もしかしたら2.9mmでもいけるかも。
消費電流調査
8ΩスピーカとテープLED(NeoPixel)の消費電流
前回作った電流計で色々な基板の消費電力を調べてみた。
備忘録として残しておく。
NeoPixelは 70個ほどを同時点灯、色はランダム brightnessは30ほど。
8Ωスピーカ
4回音を鳴らしている
8Ωスピーカ + NeoPixel
NeoPixelは150mAほどの消費
スピーカ 音色別
LEDチカチカ回路
電圧降下1.45V LED 3つ直列
{5v - (1.45v) x 3} / 100Ω = 6.5mA
レベルシフタ回路
RaspberryPi(3.3vロジック)でNeopixel(5v or 12v)を制御するときには、秋月のロジックレベル変換回路を利用している。
4ビット双方向ロジックレベル変換モジュール BSS138使用: 半導体(モジュール) 秋月電子通商-電子部品・ネット通販
自作センサシステム等(6v ~ 5v)からRaspberryPi(3.3v)に入力したい時には、フォトカプラを使用していた。
今回、大量生産も視野に入れたセンサシステム(5v)からRaspberryPi(3.3v)へのレベル変換に最適な回路を考えてみた。
要件
検討
秋月ロジックレベル変換回路
双方向で4回路入り 200円。
高性能。完成品なので安定している。高い。大きい。 今回は不向き。
フォトカプラ
フォトカプラ TLP785(GBランク): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販
20円のこちらで考える。
Typ入力電流が10mAで大きい。(もしかしたら1mAでも動作するかもしれないが、たぶん保証はされていない)
自作レベルシフタ
秋月ロジックレベル変換回路のHigh->Lowパス1chのみを自前で実装するのが良さそう。
NchMOSFET
NchMOSFET 50V300mA BSS138 Panjit製 (25個入): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販
「GateThresholdが低いから、ロジックレベル変換に最適」とある。
GateThresholdが低い -> 立ち上がりに機敏に反応する -> 元信号からなまり辛い
ということだろうか。 今回はセンサのON/OFFのレベル変換で、高周波特性は考えなくてよいので、正直どのMOSFET/トランジスタでも良さそうである。
値段が100円/25個で安いので、このまま使うことにする。
トランジスタ 反転型
秋月ロジックレベル変換 双方向
(2)の双方向性をなくしたもの。 IN、OUTの電源投入タイミングを問わず。
(3)が良さそうである。 ラズパイのGPIOのINPUT電流は0.5mA以下推奨なので、10kΩの抵抗で良さそうである。
参考リンク
Raspberry PiのGPIOピンの電気的仕様 - TECHHOBBY
レベルシフト回路の必要性と動作原理 【Analogista】
ラジオペンチ LTspiceでレベル変換回路をシミュレーション
分圧によるレベルシフト
下記質問スレッド等をまとめると、
- 負荷(入力側インピーダンス)によって電圧が変わる
- 大きな抵抗を用いると波形がなまる。小さいと消費電流が多い
- 電源投入タイミングによって、逆電流が流れる
この問題がクリアできるならば分圧でも問題ない。
シュミットトリガインバータ 分圧
赤外線LEDの20kHz矩形波ををAM検波し、それが遮られたことを検知したい。
今までそのためにAttiy10をプログラムし、割り込み機能(INT0ピン)を使っていた。
秋月のAttiny10は値上げをし50円になり、1つ1つに書き込みが必要なため、大量生産には向かなくなった。
シュミットトリガインバータを用いて、安価にプログラム書き込み不要な代替手段を検証した。
検証に使用したIC
3回路シュミットトリガインバータ TC7W14FU(5個入): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販
3回路もいらないが、手元にあったため。
電気特性
VCC:5Vで検証なので、4.5Vと6Vの間で Hレベル 3V、Lレベル2Vぐらいで見る。
検証1
入力信号(水色 5V AM検波後の信号)
勢いよく遮ると波形が乱れ、一瞬閾値以下に電圧が落ちるため反応する。(黄色が反応信号)
しかし、ゆっくり遮ると閾値以下に電圧が落ちることがないため反応しない。
LOWレベルが既存のATtiny10とは異なるため検知できなくなった。 (ATtiny10のINT0のLOWレベル電圧を仕様書等で調べてみたが見つけられなかった。)
検証2
入力電圧を10kΩと51kΩで分圧することで意図した電圧降下を起こした。 1kΩと5.1kΩだと出力インピーダンスが大きすぎるので、想定以上の電圧降下が起きて不適であった。
上図:分圧なし 下図:分圧あり
入力 5v -> 4v
入力が2V付近まで落ちるように
良い感じ
実際は1回路のこちらを使用する予定(12円/個) シュミットトリガインバータ TC7S14F (5個入): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販
矩形波へのフィルタ
あるセンサで、5kHzと50kHzの矩形波信号を識別したい。
量産(コスト削減)・小型化の目的があるので、オペアンプを使ったアクティブフィルタではなく、単純なパッシブフィルタのみで機能を実現したい。
センサの都合で、5kHz信号は50kHzの2倍ほど強度がある。
こちらのフィルタ回路計算サイトで計算し、色々試してみた。
http://sim.okawa-denshi.jp/RLCtool.php
- CRローパス
- CRハイパス
- RLCバンドパス
- RLCバンドエリミネーション・フィルタ
構成する部品はコイル、コンデンサ、抵抗の3種類があり、それぞれ下記の実装上の制約がある
コイル
1mH以上のコイルは物理的に大きくなり、コストも掛かる
コンデンサ
チップコンデンサを使いたいのでできれば1uF以下
抵抗
フィルタなので、できるだけ抵抗値が低いモノが良いと思っていたが、それをドライブできるだけの電流が無いと正しくフィルタとして機能しない。
↑のサイトで提案された抵抗値が数十Ωで、そのことに気づくのに時間が掛かった。
結論
5kHz減衰 50kHz残し RLCバンドエリミネーション・フィルタ
他のフィルタと比べ周辺周波数の減衰が急峻だったので選択した。
1mH以上のコイルのサイズ・入手性が良くないので、コンデンサを1uFにした。
入力 50kHz
出力 50kHz ぼよよんしているが、今回の用途で使えたのでヨシとする。
出力 5kHz カットできている
5kHz残し 50kHz減衰 CRローパス
出力 5kHz 歪んでいるが通過している
出力 50kHz 入力5vに対して 1.5Vppに振幅。 このあとAMの包括線検波回路に通すので問題なし
包括線検波回路の参考:http://www.gxk.jp/elec/musen/1ama/H14/html/H1408A15_.html
50kHzの矩形波のみをハイパスフィルターで取得することは難しかった。
5kHzの矩形波にも高周波が含まれ↓リンクで紹介されている様に電圧がマイナスになり、処理が面倒くさくなる。
https://misoji-engineer.com/archives/high-low-pass-filter.html
デシベル
-3dB ≒ 1/2 -10dB = 1/10 -20dB = 1/100
電流計 INA219
INA219 + ESP-WROOM-02で電流計を作ってみた
ある基板(システム)が電圧降下を起こして、正常に動かない瞬間があった。
8Ωスピーカ + LEDテープを同時に制御しているので、そのタイミングの消費電流がどうやら怪しい。
テスタでは瞬間の電流を表示できない。
NRF-PPK2 は納品1か月待ちで、待っていられなかったの自作することにした。
電流計はINA219を使用した。 I2Cで電流を取得できる。
取得した電流値をESP-WROOM-02でUDP送信する。
#include <Adafruit_INA219.h> #include <ESP8266WiFi.h> #include <WiFiClient.h> #include <WiFiUDP.h> Adafruit_INA219 ina219; const int CLK = 4; const int DIO = 5; IPAddress HOSTIP (192, 168, 11, 8); IPAddress myIP(192, 168, 11, 39); const char *ssid = "****"; const char *password = "****"; WiFiUDP udp_; #define PORT 12345 void connectWiFi() { WiFi.begin(ssid, password); WiFi.config(myIP, WiFi.gatewayIP(), WiFi.subnetMask()); Serial.println("start_connect"); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } Serial.println("CONNECTED!"); } void sendWiFi(char byteData[]) { if (udp_.beginPacket(HOSTIP, PORT)) { udp_.write(byteData); udp_.endPacket(); } } void setup() { WiFi.mode(WIFI_STA); //STAtion_mode. not AP_mode. Serial.begin(115200); udp_.begin(PORT); connectWiFi(); ina219.begin(); ina219.setCalibration_16V_400mA(); //ina219.setCalibration_32V_1A(); } void loop() { float current_mA = ina219.getCurrent_mA(); Serial.println(current_mA); char result[4]; memcpy(result, ¤t_mA, 4); sendWiFi(result); }
送信したデータは、Unityで作ったグラフアプリで受信し表示するようにした。
グラフ描画は、Unity Asset Store の「Graph And Chart」を使用した。(高ぇ) assetstore.unity.com
家の環境では1秒間に400回以上のデータを取得できた。(UDP送信がボトルネックになっているので、別の通信方式であればもっといけそう)
電流値の分解能は0.1mA以下なので、今回の用途には十分であった。
400FPSだと、ある電流スパイクの時間積分(足し算)にもある程度対応できる。
これを使って回路の電流消費を調べて、電圧降下の対策をしていこうと思う。