技術メモ

電子工作 Unityとか

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以上にしたい。

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)の消費電流

前回作った電流計で色々な基板の消費電力を調べてみた。

備忘録として残しておく。

wayabi.hatenablog.com

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)へのレベル変換に最適な回路を考えてみた。

要件

  • できるだけ安価
  • 省スペース
  • 5v -> 3.3v オンリー。
  • 出力側インピーダンスは高い。1mA以下の入力をしたい。
  • 1ch
  • 低周波(センサのオンオフレベル)
  • nano秒レベルのディレイを許容

検討

秋月ロジックレベル変換回路

双方向で4回路入り 200円。

高性能。完成品なので安定している。高い。大きい。 今回は不向き。

フォトカプラ

フォトカプラ TLP785(GBランク): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販

20円のこちらで考える。

Typ入力電流が10mAで大きい。(もしかしたら1mAでも動作するかもしれないが、たぶん保証はされていない)

自作レベルシフタ

秋月ロジックレベル変換回路のHigh->Lowパス1chのみを自前で実装するのが良さそう。

NchMOSFET

NchMOSFET 50V300mA BSS138 Panjit製 (25個入): 半導体(モジュール) 秋月電子通商-電子部品・ネット通販

「GateThresholdが低いから、ロジックレベル変換に最適」とある。

GateThresholdが低い -> 立ち上がりに機敏に反応する -> 元信号からなまり辛い

ということだろうか。 今回はセンサのON/OFFのレベル変換で、高周波特性は考えなくてよいので、正直どのMOSFET/トランジスタでも良さそうである。

値段が100円/25個で安いので、このまま使うことにする。

  1. トランジスタ 反転型

  2. 秋月ロジックレベル変換 双方向

  3. (2)の双方向性をなくしたもの。 IN、OUTの電源投入タイミングを問わず。

(3)が良さそうである。 ラズパイのGPIOのINPUT電流は0.5mA以下推奨なので、10kΩの抵抗で良さそうである。

参考リンク

Raspberry PiのGPIOピンの電気的仕様 - TECHHOBBY

レベルシフト回路の必要性と動作原理 【Analogista】

ラジオペンチ LTspiceでレベル変換回路をシミュレーション

分圧によるレベルシフト

下記質問スレッド等をまとめると、

  • 負荷(入力側インピーダンス)によって電圧が変わる
  • 大きな抵抗を用いると波形がなまる。小さいと消費電流が多い
  • 電源投入タイミングによって、逆電流が流れる

この問題がクリアできるならば分圧でも問題ない。

5->3.3vへのレベル変換を調べると、抵抗分圧の物が、”アマチュアの場... - Yahoo!知恵袋

シュミットトリガインバータ 分圧

赤外線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

構成する部品はコイル、コンデンサ、抵抗の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-02UDP送信する。

#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, &current_mA, 4);
  sendWiFi(result);
}

送信したデータは、Unityで作ったグラフアプリで受信し表示するようにした。

グラフ描画は、Unity Asset Store の「Graph And Chart」を使用した。(高ぇ) assetstore.unity.com

家の環境では1秒間に400回以上のデータを取得できた。(UDP送信がボトルネックになっているので、別の通信方式であればもっといけそう)

電流値の分解能は0.1mA以下なので、今回の用途には十分であった。

400FPSだと、ある電流スパイクの時間積分(足し算)にもある程度対応できる。

これを使って回路の電流消費を調べて、電圧降下の対策をしていこうと思う。