2019年12月30日月曜日

SSI-4の簡易的なエミュレータを作ってみた

ちょっと部屋の掃除をしていたらSTM32Duinoで遊ぼうと買っていたBluepillが出てきた。
そういやSTM32F103Cにはシリアルポート複数ついていたなということで、この前作ったInnovateのSSI-4エミュレータを移植してみた。一応シリアルポートが複数ついているのでデイジーチェーンもサポートしたつもり。

今回はArduino Core STM32を使用した。Arduino用の開発環境が複数あるようでタイマーでハマったけどなんとか動く用になった。
更に今回は一台のArduinoでSSI-4を2台分エミュレートしてみた。
まぁ今の所色々決め打ちだけど、きれいに整えたい。

//SSI-4 x2 emulator on Bluepill Arduino Core STM32
#define LED_BUILTIN PC13
//HardwareSerial Serial2(PA3, PA2);
HardwareSerial Serial3(PB11, PB10);
HardwareTimer *Timer1 = new HardwareTimer(TIM2);

volatile boolean mts_sending = false;
volatile int res = 0;
volatile unsigned int aux[8];

const char DEVICE_NAME0[8] = {'A', 'U', 'X', '1', 0x00, 0x00, 0x00, 0x00};
const char DEVICE_NAME1[8] = {'A', 'U', 'X', '2', 0x00, 0x00, 0x00, 0x00};
const char ID_SSI4[8] = {'S', 'S', 'I', '4'};
char INPUT_DEVICE_NAME[240];
char INPUT_DEVICE_TYPE[240];

int DEVICE_CNT = 2;
int STREAM_LEN = 0;
volatile boolean thru = false;
volatile int INPUT_STAT = 0;

void mts_send(HardwareTimer*){
  mts_sending = true;
  //Serial1.println(micros());
  byte datalenByte;
  switch (res){
    case 0:
      datalenByte = 8 + STREAM_LEN;
      //Header Word
      //1011 0010 1000 0100
      //0xB2 0x84
      Serial1.write(0xB2 | ((datalenByte & 0x80) >> 1));
      Serial1.write(0x80 | (datalenByte & 0x7F));
      
      //Aux Channels
      //0000 D10D9D8D7 0D6D5D4 D3D2D1D0
      for (int i = 0; i <= 7; ++i){
        byte auxword[2];
        auxword[1] = lowByte(aux[i]) & 0x7F;
        auxword[0] = ((highByte(aux[i]) & 0x07) << 1) | ((lowByte(aux[i]) & 0x80) >> 7);
        Serial1.write(auxword,2);
      }
      if(thru){
        for (int i = 0; i <= (STREAM_LEN * 2) - 1; ++i){
          Serial1.write(Serial3.read());
        }
        thru = false;
        digitalWrite(LED_BUILTIN, LOW);//debug
      }
      break;
    case 1://0xCE
      datalenByte = 9 + (DEVICE_CNT * 8);
      //Header Word
      //1010 0010 1000 0101
      //0xA2 0x85
      Serial1.write(0xA2 | ((datalenByte & 0x80) >> 1));
      Serial1.write(0x80 | (datalenByte & 0x7F));

      //0xCE
      //0000 0001 0100 1110
      //0x01 0x4E
      Serial1.write(0x01);
      Serial1.write(0x4E);

      //Device Name
      Serial1.write(DEVICE_NAME0,8);
      Serial1.write(DEVICE_NAME1,8);
      res = 0;
      
      //Input device
      Serial1.write(INPUT_DEVICE_NAME, DEVICE_CNT * 8);
      
      digitalWrite(LED_BUILTIN, LOW);//debug
      break;
     case 2://0xF3
      datalenByte = 9 + (DEVICE_CNT * 8);
      //Header Word
      //1010 0010 1000 0101
      //0xA2 0x85
      Serial1.write(0xA2 | ((datalenByte & 0x80) >> 1));
      Serial1.write(0x80 | (datalenByte & 0x7F));

      //0xF3
      //0000 0001 0111 0011
      //0x01 0x73
      Serial1.write(0x01);
      Serial1.write(0x73);
      //Firmware Version
      Serial1.write(0x10);
      Serial1.write(0x0F);
      //Identifier
      Serial1.write(ID_SSI4,4);
      //CPU
      Serial1.write(0x01);
      //Channnel/Flags
      Serial1.write(0x04);
      
      //Firmware Version
      Serial1.write(0x12);
      Serial1.write(0x3A);
      //Identifier
      Serial1.write(ID_SSI4,4);
      //CPU
      Serial1.write(0x01);
      //Channnel/Flags
      Serial1.write(0x04);
      //Input device
      Serial1.write(INPUT_DEVICE_TYPE, DEVICE_CNT * 8);

      res = 0;
      digitalWrite(LED_BUILTIN, LOW);//debug
      break;
  }
  mts_sending = false;
}


void setup() {
  Serial1.begin(19200);//out
  Serial3.setTimeout(82);
  Serial3.begin(19200);//in
  Timer1->setMode(2, TIMER_OUTPUT_COMPARE);
  Timer1->setPrescaleFactor(90);//72000000/90 = 800000
  Timer1->setOverflow(65536, TICK_FORMAT);//65536/800000 = 0.08192s(81.92ms)
  Timer1->attachInterrupt(mts_send);
  Timer1->resume();

  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW);//debug
  Serial3.print("H");
  Serial.begin(19200);//debug
}

void loop() {
  switch(INPUT_STAT){
    case 1:
      Serial3.write(0xF3);
      break;
    case 2:
      Serial3.write(0xCE);
      break;
  }
  if(!mts_sending){
    aux[0] = analogRead(PA0);
    aux[1] = analogRead(PA1);
    aux[2] = analogRead(PA2);
    aux[3] = analogRead(PA3);
    aux[4] = analogRead(PA4);
    aux[5] = analogRead(PA5);
    aux[6] = analogRead(PA6);
    aux[7] = analogRead(PA7);
  }
  
  serialEvent1();
  serialEvent3();
}

void serialEvent1() {//out
  while (Serial1.available()) {
    digitalWrite(LED_BUILTIN, HIGH);//debug
    switch (Serial1.read()) {
      case 0xCE:
        res = 1;//obtain device names
        break;
      case 0xF3:
        res = 2;//obtain device types
        break;
      case 'c':
        Serial3.write('c');//pass to upstream
        break;
      case 'H':
        Timer1->refresh();//Timer1 reset
        break;
    }
  }
}

void serialEvent3() {//in
  while (Serial3.available() && !thru) {
    digitalWrite(LED_BUILTIN, HIGH);//debug
    byte mtshead[2];
    Serial3.readBytes(mtshead,1);
    if((mtshead[0] & 0xA2) == 0xA2){
      mtshead[1] = mtshead[0];
      Serial3.readBytes(mtshead,1);
      if((mtshead[1] & 0x80) == 0x80){
        if(INPUT_STAT <= 0){
          INPUT_STAT = 1;
        }
        STREAM_LEN = int(((mtshead[1] & 0x01) << 7) | (mtshead[0] & 0x7F));
        if((mtshead[1] & 0x10) == 0x00){
          byte response[2];
          Serial3.readBytes(response,2);
          byte responseByte = (((response[0] & 0x01) << 7) | (response[1] & 0x7F));
          switch(responseByte){
            case 0xF3:
              INPUT_STAT = 2;
              DEVICE_CNT = 2 + (STREAM_LEN - 1) / 4;
              Serial3.readBytes(INPUT_DEVICE_TYPE , ((STREAM_LEN - 1) * 2));
              break;
            case 0xCE:
              INPUT_STAT = 3;
              Serial3.readBytes(INPUT_DEVICE_NAME, ((STREAM_LEN - 1) * 2));
              break;
              }
        }
        //Serial.println(STREAM_LEN);
        thru = true;
        return;
      }else{
        return;
      }
    }else{
      return;
    }
  }
}

Input側のヘッダ判別するあたりでSerial.read()を使うと何故か2バイト目が0xFFになってしまうのにハマったのでSerial.readByteで1バイトずつ読み込むようにしてる。
条件分岐入れないとちゃんと1バイトずつ読めてる感じがするんだけどよくわからん…
多分ここらへんはもっと効率よく取り込める方法がありそうだけど、これで動いてるので良しとしよう。

STM32Duinoは3.3V駆動でADもMax3.3Vなんだけど、ADは12Bitあるので抵抗分圧で分圧してうまいこと10Bitにmapして使えば5V以上の入力とかにもソフト側の変更だけで柔軟に対応できるかも(MTSの仕様は今の所10Bitまでだし)
20Vまで入力できるように9.1kと1.8kで分圧してやって10bit分だけ使えば丁度0~5Vになるのでは?とか思ったり。10V入力したいときはその分だけmapやら2分の1してやればよいし。
他のMTS対応デバイスとつなぐときはRS-232トランシーバを介せばおk。フローコントロール使わないので1個でinputとoutput側使えそう。LC-1はMAX202を1個でやってるみたいだし。
ST232CDRは5V対応なんだけど試しに3.3Vで駆動してみたらちゃんと動いたからとりあえずこれで…
とりあえず2台作ってデイジーチェーンしてみた。

1台でSSI-4を2台分エミュレートしてるので16chのUSB接続ロガーとして使える!
まぁサンプリングレートが81.92msだけどね。
今回はInput側になにかつながっているかをパケットで判断しているんだけど、本家はハードで判断してそう。途中でデバイス数変わったときにも対応できるようにしておいたほうが良いのかなぁ…
MTSの仕様を全部実装したわけじゃないので他のデバイスとつないだときにどうなるかはわからないという。なんかinput側の受信処理あたりで条件分岐が怪しいような気がしてるんだけど動いてるから良しとしてる。
Bluepillはまだシリアルポートがもう1ポートあるので、ELM327とか使ってOBD2からデータとってそのままMTSに乗せたりできるかも。

一応Input側も実装したことによりこいつをMTSのチェーンの一番最後に入れてOutput側をそのままUSBデバイスとして認識させたりとか、TTLレベルのままRN-42とかESP32でBluetooth化とかもできて便利かもしれないな。Bluetooth化するならESP32にそのまま移植すればいいのか…ADの使い方面倒そうだけど…

2019年12月29日日曜日

Nextion HMIディスプレイを買ってみた

ArduinoとかでLCDディスプレイのUIを作ろうと思うとけっこう大変。Nextion HMIはLCDにマイコンが搭載されていてシリアル通信で制御できるっぽいので試しにポチってみた。LCDのUIは専用ツールから作成できるらしい。一応タッチディスプレイ。


今回はAliexpressでBASICモデルの2.8インチを購入。送料込みで17.38ドルだった。
NextionはTJCとそっくりなんだけど、TJCはNextionのツールが使えないので注意かも。TJCは中国語のツールらしい。



付属品はMicroUSBから電源を取るやつとケーブル。


裏面。MicroSDカードを差し込めるところがある。

Nextion HMIはNextion Editorという専用ツールで画面を作成できるんだけど、作成後にNextion HMIに転送する手法がシリアル接続とMicroSDから読み込みの2種類似対応している。


とりあえず手持ちのUSB TTL変換アダプタに接続。
電源を入れるとデモが流れる。

Nextion EditorではToolboxに用意されている部品を画面上に並べて行く感じでGUIが作成できるみたい。

Basicモデルで使用できるのはこのぐらい。

これらを並べて適当にシリアル接続で転送してみた。
Baudrateはデフォルトだと転送が遅かったので最大の921600pbsで転送してみたけど特に不具合はなくて結構早い。
Arduinoとの通信部分がまだ理解できていないのでちょっと調べてみようかな。

2019年12月28日土曜日

ArduinoでMTSプロトコルでデータを送信してみる

InnovateのMTSプロトコルをArduinoで出力してみた。といっても本家MTSのようにデイジーチェーンまでは実装していないけど…
とりあえずLogWorks3で認識してくれるようなレベルなSSI-4互換機的なものを作ってみた。
応用すればPLX SM-AFRのiMFDプロトコルをMTSプロトコルに変換したりとかできるかも?
一応プロトコルの仕様書とかSDKは公開されているのでそいつらを参考にした。
実機はRS-232CでコネクタはMicro-Fit 3.0もしくは2.5mmジャック。
白がRX、赤がTX、黒はGNDで青をGNDに落とすと接続検知になってる。
Baudrate 19200bpsで81.92ms間隔でのデータストリームになっているっぽい。
とりあえずSSI-4として振る舞い、Aux1~4にADCのデータを突っ込むサンプル。
MAX31855を使って熱電対の情報を入れたり、BMP388を使って圧力ログったりできるかも。

volatile unsigned long ofc = 0;
volatile boolean ovf = false;
volatile int res = 0;
volatile unsigned int aux[4]={0,0,0,0};


//Timer2 overflow interrupt vector handler
ISR(TIMER2_OVF_vect) {
  ofc++;
  //256(8bit)x1024(Prescaler)/16000000(Clock)*5 = 81.92ms
  if(!ovf && ofc >= 5){
    ofc = 0;
    ovf = true;
    mts_send();
    ovf = false;
  }
};

void mts_send(){
  switch (res){
    case 0:
      //Header Word
      //1011 0010 1000 0100
      //0xB2 0x84
      Serial.write(0xB2);
      Serial.write(0x84);
      
      //Aux Channels
      //0000 D10D9D8D7 0D6D5D4 D3D2D1D0
      for (int i = 0; i <= 3; ++i){
        byte auxword[2];
        auxword[1] = lowByte(aux[i]) & 0x7F;
        auxword[0] = ((highByte(aux[i]) & 0x07) << 1) | ((lowByte(aux[i]) & 0x80) >> 7);
        Serial.write(auxword,2);
      }

      break;
    case 1://0xCE
      //Header Word
      //1010 0010 1000 0101
      //0xA2 0x85
      Serial.write(0xA2);
      Serial.write(0x85);

      //0xCE
      //0000 0001 0100 1110
      //0x01 0x4E
      Serial.write(0x01);
      Serial.write(0x4E);

      //Device Name
      Serial.write(0x53);//S
      Serial.write(0x53);//S
      Serial.write(0x49);//I
      Serial.write(0x34);//4
      Serial.write(0x00);
      Serial.write(0x00);
      Serial.write(0x00);
      Serial.write(0x00);
      res = 0;
      digitalWrite(LED_BUILTIN, LOW);//debug
      break;
     case 2://0xF3
      //Header Word
      //1010 0010 1000 0101
      //0xA2 0x85
      Serial.write(0xA2);
      Serial.write(0x85);

      //0xF3
      //0000 0001 0111 0011
      //0x01 0x73
      Serial.write(0x01);
      Serial.write(0x73);
      //Firmware Version
      Serial.write(0x12);
      Serial.write(0x3A);
      //Identifier
      Serial.write(0x53);
      Serial.write(0x53);
      Serial.write(0x49);
      Serial.write(0x34);
      //CPU
      Serial.write(0x01);
      //Channnel/Flags
      Serial.write(0x04);

      res = 0;
      digitalWrite(LED_BUILTIN, LOW);//debug
      break;
  }
}


void setup() {
  //Timer2 Settings: Timer Prescaler /1024, WGM mode 0
  TCCR2A = 0;
  TCCR2B = 1<<CS22 | 1<<CS21 | 1<<CS20;

  //Timer2 Overflow Interrupt Enable  
  TIMSK2 = 1<<TOIE2;

  //reset timer
  TCNT2 = 0;

  Serial.begin(19200);
  pinMode(LED_BUILTIN, OUTPUT);//debug

}

void loop() {
  aux[0] = analogRead(A0);
  aux[1] = analogRead(A1);
  aux[2] = analogRead(A2);
  aux[3] = analogRead(A3);
}

void serialEvent() {
  while (Serial.available()) {
    switch (Serial.read()) {
      digitalWrite(LED_BUILTIN, HIGH);//debug
      case 0xCE:
        res = 1;//obtain device names
        break;
      case 0xF3:
        res = 2;//obtain device types
        break;
      case 'H':
        TCNT2 = 0;
        break;
    }
  }
}

こんなもんでLogWorks3で認識されてる。

今回は81.92ms間隔でデータを送信するのに8bitタイマーを5回オーバーフローさせて使ってるけど(本家は16bitタイマーっぽい表記があるけど)そこらへんの精度の問題とかもよくわからん…
あとADのデータを割り込み内で取り込むべきかどうかとかとかも悩む。

こいつを応用すればArduino 1台で複数のMTS対応デバイスをエミュレートできるかも。
Arduino一つでSSI-4を2台分とか。

2019年12月21日土曜日

D02HWのSIMロック解除してDocomo系SIMを使ってみた

ラズパイでモバイル通信するのに安いモデムを探していたら昔友人からもらったD02HWがあったのを思い出し、どうやらSIMロック解除できるっぽいので解除してみた。
対応バンドも少ないし、LTEにも対応していないけどラズパイ用途なら問題なさそうだし。
まずは、SIMフリー化によりDocomoのSIMカードが使えるか試してみた。


しばらくぶりに出してきたのでDC UnlockerでSIMロックの状態を確認してみた。
実はこれATコマンドでも見れるようなので、DC Unlockerは使わなくてもいいかも。
EMOBILE HW Utilityで認識できる状態で虫眼鏡マークを押すだけで確認できる。
D02HWの自動インストール結構微妙かも…差し込むたびにautorun動かさないとCOMポートが認識されない…

それはさておきLockedなのでUnlockコードを入手する必要があるんだけど、フリーで生成してくれるサイトがあったのでそちらを利用させてもらった。
必要なのはIMEIなので、本体の裏側をみるか、EMOBILEのユーティリティーからコピペでもOK。

何個か解除コードが生成されるんだけど、今回はよくわからなかったので"Old code V1"を利用した。

コードを入力したら適当なシリアル接続ができるツールでモデムに接続する。ボーレートは9600だった。COMポートはデバイスマネージャーでHUAWEI Mobile Connect -3G PC UI Interfaceってなってるやつの番号。

今回はCooltermのLine Modeを使用した。
実はSIMロックの状態はATコマンドでも確認できる。
AT^CARDLOCK?
と送ると帰ってくる値が1から始まっていたらロックされている
2だったらロック解除済みらしい。次の数字は残りの試行回数。
ロック解除パスワードを10回ミスるとロック解除できなくなるらしい。

次にロック解除コマンド
AT^CARDLOCK="88888888"
8がいっぱい入ってるところは自分のIMEIから生成したロック解除コードに置き換えて送信。
もう一回AT^CARDLOCK?コマンドで2から始まる番号が帰ってきたらSIMロック解除成功。


一応DC Unlockerでも確認してみたらロック解除されてる。


SIM変換アダプタを使用してnano SIMを入れてみた
しかしずっと赤ランプ点滅で電波を掴まないし、EMOBILE HW Utilityからも接続ボタンがグレーアウトして押せない…

調べてみるとMobile Partnerというツールを使うとEMOBILE HW Utilityよりも詳細設定ができて、検索Bandを変更できる?らしい。
早速ダウンロードしてインストールし、ToolのOptionからNetworkを開いて

Network TypeをWCDMA preferredに、BandをGSM900/GSM1800/WCDMA2100に設定する。
実はここのBand設定で結構つまずいて、最初All Bandsにしてたんだけどなかなかつながらなくて、最終的にGSM900/GSM1800/WCDMA2100にすることによりつながった。一旦GSM900/GSM1800/WCDMA2100を選択してApplyを押すとAll Bandsを選択してからApplyを押してもつながるという不思議な感じ…


Registration ModeをManualにしてRefreshすると検索が始まる。
うまくいくとDocomoが表示されるので選択してRegisterを押せばおk。
すると本体が赤ランプ点滅から青ランプ点滅に変わる。

Mobile Partnerからでも設定すればつながるみたいだけど、EMOBILE HW UtilityのほうにAPN設定してしまったのでEMOBILE HW Utilityから接続してみた。

接続ボタンが押せるようになってる!


おつながった!
もともとWDCMA1700しか使えないようにBand無効化されてたのかな
まぁ確かにWeb上の仕様だと1.7GHz帯しか対応していないことになっているし…

とりあえずこの状態でラズパイにつないでもちゃんと青ランプが点滅しているので一旦Mobile Partnerで設定すればDocomoの電波を掴むようになるっぽい。
ラズパイの設定しないと。


2019年12月15日日曜日

イヤホンをMMCX化してみた

友人からイヤホンの断線修理を頼まれたのでMMCX化してみた。
ウォークマンのノイキャン用のマイク付きのイヤホンらしいけど、どうせ壊れているのでノイキャン機能はなくてもいいということだったので…


MMCX端子はAliexpressで5個入りで1.4ドルだった。
本来はPCBに水平に取り付けるタイプかな。


イヤホン側、どうやって分解しようかなと思って引っ張ってみたら簡単に割れた…
根本からケーブルハンダできるタイプだったので、半田でケーブルを外してMMCX端子を付けただけ。
MMCX端子は足を少しカットする必要があった。

あとは接着剤で張り合わせて固定。


最後にエポキシパテで端子の周りを固めてみた。
初めてMMCX化したけどMMCX端子は丸いタイプのほうが合わせやすいかも?
ちなみにケーブルの方はeBayで3ドルぐらいのMMCXケーブルをとりあえず付けておいた。
これで次回断線しても本人にケーブルだけ購入してもらえば良いし。

2019年12月7日土曜日

Xbox Oneコントローラをアップデートしてみた。

HaloがSteamで発売ということで久しぶりにパッドでFPSしてみようということでXbox Oneコントローラを出してきたんだけども、Xboxアクセサリーアプリで確認したらファームウェアアップデートがあったのでアップデートしてみた。

前もBluetooth対応版(オーディオジャック付き)に買い替えたときにもアップデートをしたらBluetoothでの再接続が安定したりしていたのでたまに確認するといいかも。

Xbox One本体を持っていないのでWindowsでアップデートする場合はXboxアクセサリーと言うアプリをインストールする必要がある。
Windows 10のMicrosoft Storeからダウンロードできる。

Eliteコントローラとかの設定とかには必要みたいだけどノーマルコントローラだとあんまりいらないアプリだと思っていたらいつの間にかボタンを入れ替えたりみたいなカスタマイズできるようになっていたりしていた…


Bluetoothで接続されているとUSBでつなぐように促される。


USBで接続したら"…"をクリック。

するとアップデートがある場合は更新するかどうか確認されるので更新ボタンを押す。

更新中に抜き差しとかケーブルの接触悪いと失敗してしまうので静かに放置。
ちなみに失敗した場合でUSBでつなぐと"Xbox One Controller DFU"と認識されている場合はもう一度Xboxアクセサリーアプリを立ち上げるとコントローラーの更新が必要ですというボタンが現れるのでそのボタンを押せば再試行できるらしい。

今回のアップデートでv4.8.1923.0にアップデートされた。
2019年10月23日に更新されていたようで、更新内容は
・コンソールとのワイヤレス接続信頼性の向上
・Bluetoothペアリングの改善
・Android端末にBluetooth接続した際のしいたけボタンの挙動変更
・Bluetooth接続時の信頼性の修正
らしい。

ちなみにアップデート後はBluetooth再ペアリングしないとつながらなかった。

さてHALO Reachプレイするか

2019年11月30日土曜日

Blue PillでHID Bootloaderを使ってみた。

Arduino IDEを更新してArduino Core STM32を久しぶりに更新したらだいぶ項目が増えていて、その中でも対応Bootloaderも増えていたのでちょっと気になったHID Bootloaderに書き換えてみた。

Blue PillはBootloaderによってUSB書き込みできるのが便利なんだけど、ユーザープログラムが入っているやつを新規のPCにつないだりするとDFUのドライバインストールにちょっとコツが必要だったり(不明なデバイスになってすぐユーザープログラムのUSBデバイスになったり)するのでデバイスドライバいらずのHID bootloaderはどうなんだろうと。

今回使用したのはArduino側からはHID Bootloader 2.2と言われているもの。
最新版は2.2.2だったけど問題なく使えました。

ダウンロードはGithubのreleaseのところからバイナリをダウンロードできる。
stm32_binaries.zipをダウンロードしたら、F103の中のlow_and_medium_densityの中に入っている"hid_generic_pc13.bin"を使用した。
書き換え方法は以前DFUブートローダーを書き込んだ記事とかぶるのでそっちを参照いただければ。

Arduino側のセッティングはこんな感じにしてみた。USB SupportでCDCのCOMポートにしておくと書き込み時にオートリセットができるので便利。
リセットボタン側のジャンパを1にすると常時ブートローダーになるっぽいので何かあったときはそれで対応できそう。

2019年11月29日金曜日

Raspberry Pi 4 4GBのセットアップ

友人がRaspberry Pi 4を普段遣い用(Youtube視聴とネットらしい)にポチってみたらしいのでセットアップする代わりに借りてきた。6.6k円ぐらいで購入できるらしいのでたしかにお安いけどどのぐらい使えるのかもついでに試した見た。

RSで購入したらしく、OKdoのロゴが入っているっぽいのでUSB Type Cの不具合対策品っぽい。USB Type Cの不具合対策品だとUSB Type C対応充電器で問題なく動くらしい。
基板は相変わらず同じサイズ。HDMIがmicroHDMI×2になっているのでデュアルディスプレイもOKだけど、今回一緒に借りてきたmicroHDMI→HDMI変換アダプタだとUSB Type Cとも干渉してHDMI1にしか刺さらないので、ケーブル購入時注意かも。

ちゃんと裏面には技適がシルクで入っている。

とりあえずOSのダウンロード。今回はデスクトップとしての使用するらしいので、Raspbian Buster with desktop and recommended softwareを使用した。

Win32 Disk ImagerでmicroSDに書き込み。

microSDカードスロットはスプリングタイプじゃないので耐久性は安心かも。
起動するとウィザードに従って設定できるので便利。
ただしアップデートに時間がかかるので不安になるやつ
しっかし起動が早い。Raspberianのロゴも一瞬だし。

さすがにメモリ4GBもあるので結構サクサク感がつよい。通常のインターネットぐらいだったら常用できそう。microSDカードの速度にもよるのかな?Youtubeのサムネ読み込みはちょっともたついてる感があるかも。
しかしラズパイもここまで来ると普通に使えそうだなぁ。ただし結構発熱しているのでヒートシンクとかつけないとだめかも。ヒートシンクケースは購入したらしい。
ヒートシンクケースをつけたら普通に常用できるんではないだろうか…

自分も欲しくなってきたのでポチってしまおうかなぁ

2019年11月2日土曜日

Wiiリモコンのコネクタ取り用にモーションプラスを買ってみた。

友人とラーメンライブに行った帰りにブックオフに寄ってみたらWiiモーションプラスが100円で売っていたのでWiiリモコンの端子取り用に買ってみた。

これが出た当初はみんな解析して3軸ジャイロとして使おうとしてたりしてたけど、Wiiリモコンにモーションプラスが内蔵されたりしてもう100円で売られる時代に。
でもWiiリモコンのコネクタが100円なら安い気がしている。

大量にあったのできれいなやつを買ってみたけどコネクタ自体もすげーキレイだった。

分解にはY型ドライバが必要。結構高そうな作りをしていた。一応ライブラリもありそうなのでArduinoでi2c接続の3軸ジャイロとして使えそう。だけどドリフト対策とかができるような6軸のMPU-6050とかを使ったほうが情報量も多いし使いやすいかも…

コネクタ側も結構高級な作りしている。今回はメス側のコネクタを使いたいのでこいつをハンダで外せばオッケー。ピッチが1.778mmなのか合うコネクタがないのでどうしよう…

これでArduinoでヌンチャクとかクラシックコントローラが使いやすくなりそう。ロックがないとやっぱり抜けたとき1本ずつ指すのは面倒…
今となっては延長ケーブル買うより断然安いし。


2019年10月26日土曜日

Pythonでシリアルポートを自動で選択してみた。

ラズパイ上のPythonでArduinoとかにシリアル通信で接続するときに、通信中に間違ってリセットしたりするとCOMポート番号が変わってしまったりして面倒なので自動でつながるようにしてみた。


import serial.tools.list_ports

ports = list(serial.tools.list_ports.comports())

for p in ports:
    print("Port:" + str(p.device))
    print("VID:0x{:x}".format(int(0 if p.vid is None else p.vid)))
    print("PID:0x{:x}".format(int(0 if p.pid is None else p.pid)))
    print("")
とりあえずPythonでシリアルポートの一覧を作成して各ポートのUSBのVIDとPIDを表示してみる。ラズパイはデフォルトでGPIOにシリアルポートが付いてるのでUSBじゃないシリアルポートに関しては0x0になる。

ためしにこれをこちらの環境で実行すると
Port:/dev/ttyUSB0
VID:0x10c4
PID:0xea60

Port:/dev/ttyAMA0
VID:0x0
PID:0x0
となった。
ttyUSB0は対象のArduinoの情報。ttyAMA0はUSBじゃないのでVIDとPIDが出ない。

というわけでこれを利用して

import serial
import serial.tools.list_ports

ports = list(serial.tools.list_ports.comports())

for p in ports:
    print("Port:" + str(p.device))
    print("VID:0x{:x}".format(int(0 if p.vid is None else p.vid)))
    print("PID:0x{:x}".format(int(0 if p.pid is None else p.pid)))
    print("")
    if(p.vid == 0x10C4 and p.pid == 0xEA60):
        print("Device found")
        ser = serial.Serial(p.device, baudrate=115200,timeout=0.05)
        break

print(ser.readline())
これで特定のVIDとPIDのデバイスを自動で選んで接続してくれるようになった。
これ便利なんだけどVIDとPIDがかぶってたりするとあんまり使えないかも…
listには他にも情報が格納されてるようなのでその中で判別に使えるものがあればよいのだが…(未確認

2019年10月19日土曜日

ラズパイでCAN通信を使ってみた。

OBD2のテストとかするのにデバッグ環境が欲しくなったので、Raspberry Piで使えるUSB-CANコンバータを使ってみた。
InnomakerってところのUSB2CAN-Moduleってやつ。絶縁タイプのUSB-CANコンバータなのに激安なうえ、RSコンポーネンツでも扱っているのでAmazonの中華変換アダプタよりも安心である。同じものがRSよりAmazonのほうが安くて3000円切ってる…
 
RSでは商品説明に付属品がちゃんと書いてあったけど、Amazonでもちゃんとターミナルブロックはついてくるみたい。2500円とは思えない豪華さ。

このUSB2CANは一応WindowsやMacにも対応しているらしいけど、ラズパイで使うならgs_canモジュールでそのままSocketCANデバイスとして使えるから便利。ネットワークデバイスとしてそのままifconfigで立ち上げれば使える。これは便利。
MCP2515モジュールをラズパイにつなぐより楽かも。CANトランシーバーを3.3V品に交換するか、パターンカットして3.3Vと5V分けなくてもいいし。ターミナルブロックも付属しているし…
アイソレーションされてるCANトランシーバを搭載していることを考えるとコスパは高いかも。

とりあえずラズパイ3BにUSBで接続して見るとTXとRxがチカチカしたあとにLinkが点灯する。lsusbしてみると
1d50:606f OpenMoko, Inc.
として認識されていた。PIDを調べてみるとGeschwister Schneider CAN adapterとなっていた。gs_canモジュールのgsはGeschwister Schneiderを略したのかな?

まずはcan-utilsをラズパイにインストール。
sudo apt-get install can-utils
あとは
sudo ip link set can0 up type can bitrate 500000
をするだけでSocketCANデバイスとして使えるようになる。ビットレートは適宜。
ifconfigをすればcan0が追加されてるのを確認できる。
TXとRXのLEDも点灯する。通信すると点滅するっぽい。

あとはcandump can0したりwiresharkしたり普通のSocketCANデバイスが使えるアプリケーションで扱える。

CANコネクタ側にはジャンパ抵抗をハンダすれば絶縁DC-DCコンバータからの5Vも供給できたりするみたい。5Vが必要なデバイスでは有効にすると便利な場合があるのかな。

このアダプタの部品構成的にはCANとUSB対応のSTM32F072C8T6、絶縁CANトランシーバのISO1050DUBR、I2C接続のEEPROMに絶縁DC-DCコンバータが主な部品構成っぽい。CANの変換アダプタって結構高価なものが多いからこれはだいぶお安いなぁ。さすが中華製。
しかし中華製だけあってか、情報が少ない…
RSだとMS123って品番で、USB-CANコンバータになってたり、AmazonだとUSB2CANってなってたり、同じ商品名で別な商品があるから探しにくかったり…
まぁラズパイでプラグアンドプレイで使えるからいいか。RSでもラズパイ用として扱われてたし、WindowsとかMacでも使えそうだけどSocketCANみたいに超簡単ではないのかもしれない。
今度はWindowsで使えるか試してみようかな。

2019年10月3日木曜日

USB PD Quick Charge両対応のカーチャージャーを買ってみた

USB Power DeliveryとQuick Charge 3.0両対応のカーチャージャーが安かったので購入してみた。

BaseusのBS-C16C1というやつ。
色違いやUSB Type Cの代わりに両方USBのAタイプがついているものもあるけど、USB PDも使えるタイプを購入してみた。
Aliexpressで5ドルだった。
アルミタイプのBS-C15Cだともうちょっと高いけど中身同じかも?

一応ちゃんとしたパッケージに入っている。
CCALL-YS01という品番的なシールが貼られていた。

本体はかなり小さい。多分車種によっては指したままでシガソケの蓋が閉まってしまう気がする。
抜きづらそうだけどね…

差込口はカーボン調。


本体にもスペックが印刷されているのはわかりやすくて良いかも。
24V車にも対応している。
12V車だとUSB PDで5V/3A、9V/3A、12V/2.5A、USB PD PPS(Programmable Power Supply)で3-5.9V/3A、3-11V/3Aに対応しているらしい。
24V車だとさらに15V/2A、20V/1.5Aが使えるらしい。
QCのほうは4.5V/5A、5.0V/4.5A、9V/3A、12V/2.5Aの対応で、24V車だと15Vと20VがQC4+(PDと同様)に対応しているらしい。
ちなみにUSB Type CとUSB Aタイプを同時使用のときは5V/5A(2ポート合計最大)担ってしまうので注意。まぁ最大出力30Wなのでこんなもんでしょう…

Nintendo SwitchをやMac Bookを最大の性能で充電するためには24V車じゃないといけないけど、スマホやiPad Proとかだったら12V車でも最大の充電性能で充電できそう。
問題はこの小ささで発熱が気になるところ…

2019年9月28日土曜日

KTV-FSUSB2のドライバを簡単にインストール

OS入れ替えたらKTV-FSUSB2のドライバがデジタル署名の問題とかでテストモード使ったり、自己署名のセットアップしないといけなかったりと面倒だったので掲示板で見かけたzadigを使う方法を試してみた。

ちなみに今回使用したKTV-FSUSB2のシリアルナンバーはK0806。シリアルナンバーによってPIDが変わるのでWikiとかで確認するといいかも。デバイス接続しても見れるけど。
GUIDはktv-fsusb2n.infの中のDeviceInterfaceGUIDから持ってきているのでここも変更するとUS-3POUTとかでも応用できるかも。

用意するものはzadigとコンフィグファイルのみ。

[device]
Description = "ISDB-T DTV Tuner KTV-FSUSB2"
VID = 0x0511
PID = 0x0029
GUID = "{b35924d6-3e09-4a9e-9782-5524a4b79ba4}"
コンフィグファイルはこれを適当にメモ帳とかに貼り付けてfsusb2n.cfgとかにしておく。(ファイル名は関係ない)

ちなみにzadigでセットアップが完了するまでKTV-FSUSB2は接続しないほうがいいかも。
まずはzadigを起動。
Device→Load Preset Deviceをクリックするとファイルを開く画面が出るので先程作成したfsusb2n.cfgを選択。

WinUSBが選ばれていることを確認してInstall Driverボタンをクリック。
そこそこ待って完了したらKTV-FSUSB2を挿せばちゃんと認識するようになってるはず。

これは便利だ…
あとはBonDriver_FSUSB2NとTvTestで視聴できる。

ちなみにこのドライバのアンインストールするときはデバイスマネージャーのユニバーサル シリアル バス デバイスのところにあるISDB-T Full Segment Deviceを右クリックしてデバイスのアンインストールを押せばオッケー

そのときに「このデバイスのドライバー ソフトウェアを削除します。」にチェックを入れないとだめなので注意。

ちなみにZadig起動前にKTV-FSUSB2を指しておくとZadigでそのままWinUSBのドライバをインストールできそうな感じだったんだけど、それでインストールしてもBondriverから認識されなかった…
どうやら上のコンフィグファイルが重要らしい?何回か試してみたけどZadigでドライバインストール完了するまでKTV-FSUSB2を接続しないほうがうまくいくと思う。
configファイルミスってドライバのインストールがうまくいかなかったときはデバイスマネージャで"表示"→"非表示のデバイスの表示"でデバイスが出てくると思うのでアンインストールできるとおもう。

ちなみにKTV-FSPCIEでもPIDの変更だけで同様の手順で使えると思う。

2019年9月22日日曜日

Micron 1300 2TBを買ってみた。

というわけでちょっくら東京に行く用事があったので秋葉原でSSDを買ってきた。

現在のストレージ構成はM.2 SSD 500GBと2.5インチSSD 500GBの合計1TBなんだけど、ゲームとか入れてると結構カツカツになるので2.5インチの方を2TBに交換してみた。


Micron 1300というSSDでツクモで税抜2万円切るぐらいの低価格。
コントローラICはMX300と一緒で、NANDが96層の3D TLCらしい。
バルク品で3年保証付き。

早速速度を測定してみた。
速度の方はMX200よりランダムが遅い感じ。まぁ今回はデータ用だから問題ないかなぁ
シーケンシャルは同じぐらい出ているしね。


Crystal Disk Infoで確認してみるとファームウェアバージョンはM5MU000だった。
MicronのサイトからM5MU030がダウンロードできるっぽいんだけど、Micron Strage Exectiveでみると最新のファームウェアが適応されていますというふうに出ててよくわからん…


2019年9月7日土曜日

WiiクラシックコントローラProのジャンクを買ってみた。

ブックオフに行ったらクラシックコントローラProがジャンクボックスの中で500円で売っていたので買ってきてみた。

といってもWii用ではなくArduino用。この前ヌンチャクをESP32にi2cで接続して使ってみたけど、クラシックコントローラならi2c接続でアナログスティックが2つも。ボタンもたくさんあるし。本当はトリガがアナログなProじゃない方のクラシックコントローラが欲しかったんだけど売ってなかった…

ProはLとRがデジタルスイッチになって、ZLとZRが押しやすいところに移動されている。グリップも付いて持ちやすくなってるけど。

中を掃除するために分解してみた。意外ときれい。分解にはY型ドライバが必要。

ZRスイッチとZLスイッチのところ凝ってるなぁ…
ちなみにケーブルはSDAが緑、SCLが黄色につながっていた。赤が3.3Vで白がGNDで黒いところはシールド(GND)。

スティックのところもキレイだった。

全体的にはスティックとか十字キーが少し黄ばんでるかなぁ?ぐらいで結構キレイだった。スティックがちょっとベタついていたのでシリコンスプレーを布に付けて拭いておいた。(シリコンスプレーはアナログスティックの可変抵抗の接触不良のもとになったりするので直接吹きかけないほうが良い)

Arduino環境のESP32でヌンチャク使ったときと同じくNintendo Extension Controller Libraryを使って認識することができた。ちなみにクラシックコントローラのプロトコルの解析結果を公開してくれているサイトによると、データフォーマットが3種類切り替えられるようでアナログスティックは最大10Bitの分解能を持っていそう。PS3のコントローラでも8bitっぽいので8bitあれば足りるんだろうけど…