工場改善 IoT Arduino開発

現場の悩みに解決手段を

A&D社製の重量計の値を取り込んでみる。

お仕事でA&Dの重量計の値ををPCに取り込みたくなったのでサクッと作ってみました。
備忘メモとして残します。

【やりたいこと】
重量計ではかる。そしてエクセルに重量を手入力する。
それを何回もやる。打ち間違えるし、面倒だからやりたくな~い!
ボタンを押したらそのまま値をキーボード入力打ちする。
パソコンも変わるしドライバ入れたりとかやるのもめんどくさいからやりたくない。
だからUSB HIDで入力できるようにしたい。

基本的に前作ったDSUB9ピンから出力されるRS232cを電圧をTTLレベルに変換して、
USB HIDで出力するものと同じです。
何が違うかというと、A&D標準フォーマットの値部分のみを、出力してくれるだけ。
入力速度は遅いですが、手入力を置き換える程度のPC入力なので問題ないです。

【構成】
重量計のRS232c端子から出力した信号をTTLレベルに変換して、値部分のみをUSBのHIDで出力する。

A&D FX-i シリーズの計測器
汎用電子天びん FX-iシリーズ | 計量 | 商品・サービス | 株式会社エー・アンド・デイ
 |
RS232cストレートケーブル(9pinオスーオス)
 |
RS232c→USB変換器(★今回作ったやつ)
 |
USBケーブル(TypeA to C)
 |
取り込みたいPC


RS232c→USB変換器の部材】
・Seeeduino XINO
https://wiki.seeedstudio.com/jp/Seeeduino-XIAO/

・極小RS232-TTLコンバータモジュール- Dサブ9ピン オスコネクタ(NS-RS232-02)
https://www.nulsom.com/datasheet/NS-RS232_en.pdf

・ちょうど良いサイズの容器(やっぱりフリ〇クが最高)

【機器の入出力のフォーマット】
A&D標準フォーマットのデータ例:ST,+00012.78 gCrLf  ←CrLfは改行コード
USB HIDで出力されるデータ例12.78CrLf
ちなみに「ST,-00012.78 gCrLf」の場合は「-12.78CrLf」が出力される。

【変換器とRS323C TTLコンバータとの接続】
Seeedino XINOのUART1(RX:GPIO7、TX:GPIO6)とRS232-TTLコンバータを以下のように結線する。

接続
Seeedino XINO--RS232-TTLコンバータ
RX:GPIO7 -- ②TX
TX:GPIO6 -- ③RX
GND --①GND
3.3V --④VCC



【A&D重量計の設定】
ボーレート:9600
ビット長:8ビット、パリティ:なし、ストップビット:なし(SERIAL_8N1)
設定方法は計測器のメーカサイトの取扱説明書を参照してください。

【開発環境】
Arduino IDE2.0.0

【コード】Arduino IDEで書いてみました。
ライブラリ(adafruit/Adafruit_TinyUSB_Arduino)を利用しました。
https://github.com/adafruit/Adafruit_TinyUSB_Arduino

#include <Keyboard.h>

#define BPS0 9600       //シリアル送信側UART0(USB)
#define BPS1 9600       //シリアル受信側UART1
#define DATA_BUFFER 17  // 文字列の格納領域のバイト数

char resDATA[DATA_BUFFER];  //送信用データ
uint8_t pData = 0;


void AandDFormatSend() {
  // A&D標準フォーマットから値部分のデータを切り出してデータ送信
  // データ例:ST,+00012.78  gCrLf
  //CrLfはresDATA格納時に除いている。

  //HIDでデータをPCに送信マイナスの場合は'-'(0x2d)を送信
  if (resDATA[3] == '-') {
    // Serial.print('-');
    Keyboard.print('-');
  } else if (resDATA[3] != '+') {  // '+'(0x2b)フォーマットエラー
    // Serial.println("Data Format Error");
    return;
  }

  uint8_t pPass = 4;
  do {
    if (resDATA[pPass] != '0') { // 重量値の上位'0'(0x30)埋めの値は送信しない
      break;  //数値がゼロ以外になったら抜ける
    }
    pPass++;
  } while (pPass < 8);

  for (uint8_t pSend = pPass; pSend <= 12; pSend++) {
    // Serial.print(resDATA[pSend]);
    Keyboard.print(resDATA[pSend]);
  }

  // Serial.println("");
  Keyboard.println("");

  return;
}

void bufferReset() {
  //char配列とシリアルバッファを消去する。
  for (pData = 0; pData < DATA_BUFFER; pData++) {
    resDATA[pData] = '\0';
  }
  pData = 0;
  while (Serial1.available() > 0) {
    Serial1.read();
  }
}

/***********************************************************************
  初期化
 **********************************************************************/
void setup() {
  Keyboard.begin();
  // Serial.begin(BPS0); // 通信速度bps、UART0
  Serial1.begin(BPS1);  // 通信速度bps、UART1
  delay(50);

  bufferReset();
}

/***********************************************************************
  UART1から受信シリアル受信
  1バイトづつ読み込みstrDATAに結合しUSB HID送信
   **********************************************************************/
void loop() {
  while (Serial1.available() > 0) {  // 受信したデータバッファが1バイト以上存在する場合

    char inChar = (char)Serial1.read();  // シリアル1からデータ読み込み

    if (inChar == '\n') {  // 改行(LF:0x0a)がある場合の処理
      for (uint i = 0; i < pData; i++) {
        // Serial.print(resDATA[i]);
        // Keyboard.print(resDATA[i]);
      }
      // Serial.println("");
      // Keyboard.println("");

      AandDFormatSend();
      bufferReset();

    } else if (inChar != '\r') {  // 復帰(CR:0x0d)の場合は結合しない

      if (pData < DATA_BUFFER) {
        resDATA[pData] = inChar;
        pData++;

      } else {  //データバッファ溢れが発生する不正データは一旦リセット
        // Serial.println("Buffer over Error");
        bufferReset();
      }
    }
  }
  delay(1);
}