2023年12月31日日曜日

MT6701のI2C基板をSSIで使ってみた。

 先日MT6701のI2C版基板をArduinoで動作確認が取れたのでSPIライクなSSI接続でも使えるように改造してみた。I2C接続だと双方向通信だけども、SSIだと受信のみしかできないのでパラメータの書き換えとかはできないけど高速に通信できるらしい。

MT6701

まずはMT6701を剥がしてみた。どうやら8番ピンがVCCに直結になっているのでこれをCSとして出さないといけない。PWM/Analog出力は使う予定がないので、ICの下のパターンをカットしてPWM/AnalogのところにCSを出してみた。
画像でいうと赤い線を2箇所カットしてMT6701を実装したところで8番Pinを真ん中の端子にジャンパした感じ。

MT6701

これでI2CとSSIが使える基板となった。CS(改造後の真ん中のPin)をVCCに接続して、SCLとSDAをプルアップすればI2Cとして使えるし(Internal Pullupでもいいし)、SSIとして使う場合はCSとMISO(SDAのピン)とCLK(SCLのピン)の3本をマイコンに接続すれば良い。

#include <SPI.h>

#define CS_PIN PA15

SPIClass SPI_1(PB5, PB4, PB3);  //MOSI=PB5, MISO=PB4, SCK=PB3

void setup() {
  Serial.begin(115200);
  SPI_1.begin();

  pinMode(CS_PIN, OUTPUT);
  digitalWrite(CS_PIN, HIGH);
  Serial.println("MT6701 SSI Angle Reader Start");
}

void loop() {
  digitalWrite(CS_PIN, LOW);
  SPI_1.beginTransaction(SPISettings(8000000, MSBFIRST, SPI_MODE1));
  delayMicroseconds(1);
  uint16_t raw = SPI_1.transfer16(0xFFFF);//ダミーデータ送信
  SPI_1.endTransaction();
  digitalWrite(CS_PIN, HIGH);

  uint16_t angle = raw >> 2;
  float degrees = (angle * 360.0) / 16384.0;
  uint8_t mg = raw & 0b11;

  Serial.print("Raw: ");
  Serial.print(angle);
  Serial.print(", Degrees: ");
  Serial.print(degrees, 2);
  Serial.print(", Status: ");
  switch (mg) {
    case 0b00: Serial.println("OK"); break;
    case 0b01: Serial.println("Too Strong"); break;
    case 0b10: Serial.println("Too Weak"); break;
    case 0b11: Serial.println("Error"); break;
  }

  delay(200);
}

こんな感じでArduno上のBluepillのSPI1のAlternativeピンを使用して読み込んでみた。とりあえずI2C同様問題なく読み込めた。SimpleFOCとかでも使えるようなのでこれならモータ制御で問題なく使えるのかなぁ。

DOに10kのプルアップがあるとより安定するとかなんとか。

SSIだとMT6701には書き込みができないので同じピン配置でなにかデータを書き込んだり設定変更する場合はCSをHighにした状態でInternal Pullupを使ってソフトウェアI2Cを使えば書き込めるかも?

2023年12月30日土曜日

MT6701のI2C版をArduinoで使ってみた。

 モータの回転制御をやってみるのに磁気式エンコーダを購入してみた。Arduinoで使うならAS5600がお手軽で良さそうだったんだけど、MT6701というやつが14bitでいろんなインターフェースに対応しているようだったので購入してみた。

MT6701

小さい磁石も付属していた。

MT6701

今回はI2C版が安かったのでSPI使いたかったら後で改造すればいいかということでI2C版にしてみた。
MT6701のインターフェースとしてはI2C、SSI、アナログ、PWM、ABZに対応してる。アナログとPWMの切り替えはI2Cでレジスタの書き込みを行わないといけないみたい。今回のモジュールはPWM/アナログとI2Cに対応するような配線になっていた。

とりあえずBluepillを使ってI2Cで動作確認してみた。I2CのスレーブIDは0x06。

#include <Wire.h>

#define MT6701_ADDR 0x06  // MT6701のI2Cアドレス

void setup() {
  Serial.begin(115200);
  Wire.begin();  //SDA=PB7, SCL=PB6
  Serial.println("MT6701 Angle Reader Start");
}

void loop() {
  Wire.beginTransmission(MT6701_ADDR);
  Wire.write(0x03);  //MT6701の角度データ上位バイト
  if (Wire.endTransmission(false) != 0) {
    Serial.println("I2C Write Error");
  } else {
    Wire.requestFrom(MT6701_ADDR, 2);  //2バイト読み込み
    if (Wire.available() >= 2) {
      uint8_t high = Wire.read();
      uint8_t low = Wire.read();
      uint16_t angle = ((high & 0x3F) << 8) | low;  //14bit角度データ
      float degrees = (angle / 16384.0) * 360.0;    //degに変換
      uint8_t mg = (high >> 4) & 0x0F; //ステータス
      Serial.print("Raw: ");
      Serial.print(angle);
      Serial.print(", Degrees: ");
      Serial.print(degrees, 2);
      Serial.print(", Status: ");
      Serial.println(mg,BIN);
    } else {
      Serial.println("I2C Read Error");
    }
  }
  delay(200);
}

これでI2CでPB7(SDA)とPB6(SCL)にセンサーを接続すると値が出る用になった。
Statusにはマグネットが近すぎるかとか遠すぎるの他に、プッシュボタン機能や検知できないエラー情報とかも含まれている。
先頭の2bitは磁力の状態。(0→ノーマル、1→近すぎる、10→遠すぎる)

例えば0010だったらプッシュボタンが押されたとか、1だったら磁石が強すぎるとか。詳しくはデータシートのmgの所を参照するといいかも。

SSIモードはSPIライクな受信オンリーモードみたいなのでマイコンのSPIポートを使用して高速に使えるみたい。高回転なモータとかだとSSIモードのほうが良いかもしれないので次回は基板を改造してマイコンのSPIポートで試してみようかと思う。

この基板は8番PinがVCCに直結されてしまっているのでこれをCSとして取り出せば行けそうな感じ。SPIはActive Lowなのでうまく作られている気はする。ちなみに8番PinはプルアップされているのでCSに何も繋がなければI2Cとして動かせそう。6Pinだしてそういう基板にしておいてほしかったな。

データシートによると6VのTVSを電源ラインに追加しておくと良いみたいだけど、こういったモジュールにこそ追加しておかないとな…

2023年12月26日火曜日

ダイソーのUSB Type Cケーブルを買ってみた。

 久しぶりにダイソーに行ったらUSB Type Cケーブルが売っていたので試しに買ってみた。

何種類かあったんだけど100円の5V3Aタイプにしてみた。
セリアで前に60Wタイプを購入したときはデータ転送ができなかったんだけど、これは5V3Aのかわりにデータ転送ができる感じかな。300円商品になるとどっちもできるのが売っていたけど、おそらくケーブルの太さ=銅の量で電流と値段が決まっていそう。
青とシルバーの在庫があった。ケーブルはツルツルしていて少し硬い感じ。やすいケーブルってこんな感じだよね。

そんでもって試しに60WなPD充電器でノートパソコンに繋いでみたら(良い子は真似しないほうがいいかも)ちゃんと充電できた。ってことはこのケーブルの中身は6本でUSB2.0が4本+CC1とCC2で2本結線されてそう。前に買った給電専用のセリアのケーブルは電源2本とCC1とCC2が結線されている感じだったので、おそらく通信用のケーブルが結線されている分電流控えめって感じなのかな。

コネクタ自体はカチッと挿さるのでとりあえずはUSB2.0デバイス用としてはまずまずかも。


2023年12月9日土曜日

PJ-1103Aをtinytuyaで使ってみた。

 前回登録したクランプ式電力計、PJ-1103AのデータをPythonから取ってみることに。tuyaのSmart Homeだけだとなんか使いにくいらしいし…

今回はThonnyを使ってPythonでtinytuyaライブラリを使用してワットチェッカーのデータを吸い出してみた。

まずはThonnyのシステムシェルからtinytuyaをインストール。Windowsのファイヤーウォールを一旦切った状態で

python -m tinytuya scan

をしてみる。するとデバイスが表示された。しかしLocal keyがないためデータが取得できない。iot.tuya.comで開発用アカウントを作ってやる必要があるっぽい。

登録したらCloudのCloud ServicesからIoT Coreを有効にして、CloudのDevelopmentで適当なプロジェクトを作成する。このときSmart Homeアプリのアカウントが日本になっている場合は"Western America Data Center"を選択する。

プロジェクトを開いたら右上のGuide ModeのCloseをクリックしてDevicesのLink App AccountでSmart HomeアカウントとQRコードでリンクさせる。これでデバイスのリストにWIFI dual meterが出てくるはず。

あとはpythonのシステムシェルに戻って

python -m tinytuya wizard

を実行して、先程のプロジェクトのAuthorization KeyとPJ-1103AのDevice IDをコピペ。サーバーはusと入力すればOK。そうするとJSON方式で色々表示される中、keyがゲットできるはず。ちなみにproduct_idはbbcg1hrkrj5rifsdで、modelはPJ1103Bになっていた。

あとはこれでPythonからデータが取れるようになった。

DPSとデータの対比表はこんな感じらしい。

これをベースに簡単なPythonツールを作成してみた。


# -*- coding:utf-8 -*-
import tinytuya
import tkinter
import time
import threading

# 更新する間隔
INTERVAL = 3

d = tinytuya.Device('Device ID', '192.168.x.xxx', 'Local Key', version=3.4)
def poll(): while 1: data = d.status() #print('Device status: %r' % data) print(data["dps"]['112']/10) label.config(text="電圧:" + str(data["dps"]['112']/10) + "V") label1.config(text="周波数:" + str(data["dps"]['111']/100) + "Hz") label2.config(text="電流:" + str(data["dps"]['113']/1000 + data["dps"]['114']/1000) + "A") label3.config(text="(" + str(data["dps"]['113']/1000) + "A+" + str(data["dps"]['114']/1000) + "A)") label4.config(text="電力:" + str(data["dps"]['115']/10) + "W") time.sleep(INTERVAL) def start(): global app th = threading.Thread(target=poll)# スレッドインスタンス生成 th.start()# スレッドスタート # メインウィンドウ作成 app = tkinter.Tk() app.title("電力") app.geometry("500x500") label = tkinter.Label( app, text="0.00", width=12, font=("", 50, "bold"), ) label.pack(padx=10) label1 = tkinter.Label( app, text="0.00", width=12, font=("", 50, "bold"), ) label1.pack(padx=10) label2 = tkinter.Label( app, text="0.00", width=12, font=("", 50, "bold"), ) label2.pack(padx=10) label3 = tkinter.Label( app, text="0.00", width=12, font=("", 50, "bold"), ) label3.pack(padx=10) label4 = tkinter.Label( app, text="0.00", width=12, font=("", 50, "bold"), ) label4.pack(padx=10) start() app.mainloop()

今回は単純にリアルタイムデータを確認するだけだけど、ラズパイとかを使ってAmbientとかに蓄積しても面白いかも。
たしかにこのクランプ電流計、Local Keyを取得するのはちょっと面倒かもしれないけど、ラズパイとかでCTセンサを直接繋いで電力測定するよりも安全で楽かもしれない。内部ではHLW8112という交流の電圧や電流をSPI通信で取得できるICを使ってるみたいだけど、絶縁してラズパイにそのICを直結することを考えてもすごくコスパ高いと思う。

2023年11月23日木曜日

ESP32で昇降圧DCコンバータを使ってみた。

 前にESP32搭載のラジコンでモータのノイズや電圧ドロップでESP32がリセットしてしまう対策に昇圧DCコンバータを使ってみたんだけど、安い昇降圧DCコンバータをAliespressで買ってみたので試してみた。Lipoを使うと結局4.2Vからどんどん下がって3Vになってしまうんだけど、わざわざ昇圧してから3.3VをLDOで作るのも効率が悪そうだし。

DD0603SA

今回購入したのはDD0603SAっていうモジュール。ICの刻印は2149Fってなってる。ME2149っていうICっぽい。このIC自体は昇圧DCコンバータなんだけど、SEPIC方式の昇降圧DCコンバータとして動かしてる模様。
対応電圧が色々あったんだけど、たまたま3V版が安かったので3V版をポチってみた。ESP32で使うにはそのままでも問題ないと思うんだけど、他のICとかを考えると3.3Vにしておきたい。3.0V仕様ではR1が10kΩ、R2が14.0kΩになっていたんだけど、R1を10kΩ、R2を16.5kΩにすれば3.3V仕様に変更できるっぽい。

DD0603SA

3.3V仕様にするのに16.5kΩがなかったので、適当なジャンクボードについていた16kΩを移植してみた。R2の抵抗値が高くなると電圧が高くなるんだと思うんだけど、16kΩでもすでに3.33V出ていたのでちょうどよかったのかもしれない(抵抗の誤差によるものかもしれないけど)

仕様的には0.9Vから6V入力まで対応なので1Sのリチウムイオンだけではなくて、Ni-MHでもESP32を駆動するのにはいい感じに使えそう。試しにESP32を搭載したメカナムラジコンに搭載してみた。このラジコンは1Sのリチウムイオンバッテリ駆動なんだけども、バッテリが減ってくるとESP32がリセットしてしまう対策に昇圧DCコンバータで4.5Vぐらいに昇圧してからLDOで3.3Vを作っていたので、このDCコンバータを使えば自動で昇降圧を切り替えてくれるので効率が良くなるはず…

結果的には駆動時間はほぼ変わらず。昇圧コンバータでノイズ対策したときと同じく、Lipoバッテリを3V付近まで使用できた。ラジコンの場合はESP32よりもモータでバッテリを消費するのでこの使い方の場合は昇圧コンバータ+LDOでも駆動時間はあんまり変わらないのかもしれない。Ni-MHを2本で長時間ESP32を駆動させるようなアプリケーションとか、ソーラバッテリでNi-MHを充電しつつ環境計測するようなシステムだと変わるのかな?

なんにせよ昇圧+LDOとお値段はあまり変わらないのではんだ付けとかなしで使うのであればDD0603の3.3V版を購入すればそのままESP32開発ボードに直結できるので良いかもしれない。


2023年11月19日日曜日

ハイブリッド中華イヤホンのKZ ZNAを買ってみた。

 いままでPCではKZ ZSN ProXというハイブリッド中華イヤホンを使っていたんだけど、もう3年ぐらい使っているので11月11日セールで新しいイヤホンをポチってみた。2261円だったんだけど、ほかに300円ぐらいのものを同時にポチったのでセールで500円引きになった。(2500円で500円引きらしい)

今回購入したのはKZ ZNAってやつ。今回もDD1+BA1なんだけど、DDが12mmとなっているっぽい。ZSN ProXはたしか10mmだったはず。

パッケージはかなりコンパクト。プチプチの袋に入っていただけなのに凹んでいない。Aliexpress Standard Shipping早いし国内は結構ヤマトで届くことが多いので便利。
裏面はこんな感じ。今回はマイク無し仕様にした。
プレートはメタルで、穴から半透明の樹脂部品が出ている感じ。

ケーブルは編んであるタイプじゃなくなったので引っかかりがなくなったのはいいかも。でも芯線が細くなってるような気がするので少し安っぽく感じるかも。

肝心の音質的にはDDが12mmになったので低音もりもりかなと思ったら意外と全体的にクリア感がました気がする。でもまぁZSN ProXで不満はなかったのでこのぐらいの違いならいい感じかな。

結局5年前にTRN V20買ってからPCではハイブリッド中華イヤホンがメインになっている気が…
TRN V20→KZ ZSN→KZ ZSN ProX→KZ ZNAときているのでKZに慣れちゃったってのもあるかも。TRN V20とかに戻るとなんか物足りないし…

逆に有線イヤホンはPCでしか使わなくなったかも。iPhoneにはイヤホンジャックがなくなったし。Yinyoo BT4を活用しないと。


2023年11月18日土曜日

USB Type Cの2Sバランス充電モジュールを買ってみた。

 2SのリポをUSB Type Cで充電できる基板が安く売っていたので試しに購入してみた。以前改造したメカナムホイールなラジコンとかだと模型用のDCモータだから1Sでも良かったし、USBで手軽に充電できるのが良かった。2SのリポもUSBで手軽に充電できたらもっとパワーが有るおもちゃが作れそう…


どうやらIP2326というコントローラチップを搭載した充電モジュールで、2Sと3Sのリポバッテリに対応できるみたい。半田ブリッジジャンパで切り替えられるようになっている。ちなみに2Sだとバランス充電もできちゃうみたい。

今回は2Sのバッテリが使いたかったのでもともと2S設定になってる基板を購入した。Aliexpressで199円だった。

バッテリとの接続はコネクタにしたかったのでバランス充電器でよくあるJSTのXHシリーズにした。昔BeagleBone用に作った2SのバッテリもXHコネクタにしていたし。

このボード自体もXHコネクタを付けてくれと言わんばかりの設計。前回バッテリを作ったときに梅沢無線で買っていたサイド型のXHコネクタがそのまま装着できた。念のため買っておいてよかった…(梅沢が土曜日定休日になってから行ってないな

一応充電電流と充電電圧も変更できるっぽい。VSETは電圧設定で、未実装なので8.4Vになっていた。ISETは100kΩと180kΩが並列つなぎになっていて、64kΩに設定されている。なので充電電流は90000/64000で1.4Aになってるっぽい。最大1.5Aまで設定可能。

前に作った18650の2Sバッテリパックを充電してみた。5VのACアダプタに繋いでもちゃんと昇圧されて充電されてる。あとどうやらPDじゃなくてQCっぽいのでQC対応の充電器だと電圧が自動で切り替わる。中華の充電器のほうがQC対応してて、入力電圧が7Vになっていた。
ちなみにLEDは赤が電源ランプ、青が充電中インジケータのようで、充電中はどっちも光っているので紫っぽく見える。充電が終わると青が消えて赤だけが点灯した状態になっていた。

これは使えそうなのでジャンクのバッテリパックを買ってきて2Sのバッテリパック作ろうかな。