phantomshuttle 博客
容栅式数字游标卡尺数据读取

注意 :未验证

参考链接

https://qiita.com/84mota/items/c94e2387d1fc35b22e73

http://radiopench.blog96.fc2.com/blog-entry-324.html

https://blog-imgs-45-origin.fc2.com/r/a/d/radiopench/20120708SlideCaliper.txt

在网上看到有趣的硬件破解记录下来

https://phantomshuttle.com/wp-content/uploads/2022/04/20120710R0022660.jpg
https://phantomshuttle.com/wp-content/uploads/2022/04/20120710CarliperInterface.gif
电路图(网上图片)

电路因为游标卡尺的工作电压在1.5V需要做电平转换

https://phantomshuttle.com/wp-content/uploads/2022/04/20120710R0022654-001.jpg
示波器抓的协议(网上图片)

顶部是时钟,底部是数据,这样的波形出现在大约 230 mS 的周期内。数据间隔约150μS,。 根据前人分析的数据,数据格式如下:・ 从头开始​​的20位是数据,第一边是LSB ,第21位是代码,1表示负值。

不确定第 22 位到第 24 位 (在有的地方文章看到说是单位 那天买个便宜的游标卡尺读一下看看)

程序

#include <LiquidCrystal.h>
/*
デジタルノギスのデータ読み込み(関数のデモ)
 Pin 6: Clock (Trで反転)
 Pin 7; Data(Trで反転)   
 2012/07/08 by Radiopench
 http://radiopench.blog96.fc2.com/
 */

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);    // LCD シールドのピンアサイン
int clockPin = 6;                         // クロック入力ピン番号(Trで反転)
int dataPin = 7;                          // データ入力ピン番号(Trで反転)
int data;

void setup() {                
  Serial.begin(9600);
  lcd.begin(16, 2);                 //LCDのサイズ設定

  pinMode(clockPin, INPUT);
  pinMode(dataPin, INPUT);
  digitalWrite(clockPin, HIGH);
  digitalWrite( dataPin, HIGH);
  pinMode(13, OUTPUT); 
}

void loop() {         
  data = ReadCaliper();                     // ノギスからデータを読む
  lcddisp(data);                            // 液晶に書いて
  Serial.println(data);                    // シリアルに書き出し
}

int ReadCaliper() {                          // ノギスからデータ読んで値をinで返す関数
  boolean dataStarted = false;
  unsigned long t0, bitOpr, oprResult;
  int n, outData;

  bitOpr = 0x00000001;                        // ビット操作オペレータ
  oprResult = 0x00000000;

  //   データ転送開始まで待つ
  while(dataStarted == false) {
    t0 = micros();                            // タイミングを記録
    while(digitalRead(clockPin) == LOW){      // クロックピンがLOWの期間を検出
    }
    if(micros() >= t0 + 1000) {                // LOWが1mS以上続いていたらデータ開始とみなす
      dataStarted = true;                      // 但し、micros は70分でゼロに戻るのでその時は取りこぼす、ゴメン!
    }
  }                                            // クロックがHIGHになりデータ転送が始まる

  //   データのビット列を読み込み
  digitalWrite(13, HIGH);
  for(n = 1; n <= 24; n++){                   // 24ビット読み出しループ
    while(digitalRead(clockPin) == HIGH){     // クロックピンがLOWになるまで待つ
    }
    if(digitalRead(dataPin) == LOW){
      oprResult = oprResult | bitOpr;         // 1(負論理なのでLOW)だったらビットを立てる  
    }
    if( n != 24 ){                            // 最後のビットでなければ
      bitOpr = bitOpr << 1;                   // ビット操作オペレータを左にシフト
      while(digitalRead(clockPin) == LOW){    // クロックがHIGHになるまで待つ
      }
    }
  }

  //  データを取り出しint型に整形
  outData = oprResult;                     // データを16ビットint変数に代入
  if( (oprResult & 0x00100000)  != 0 ){    // 負の値のフラグ(21ビット目)が立っていたら
    outData = ( ~ outData ) + 1;           // 2の補数形式の負の値に変換
  }
  digitalWrite(13, LOW);
  return outData;                          // 値を返して関数終了
}

void lcddisp(int x) {            // デジタルノギス測定結果のLCD表示
  int lcdout;
  lcd.setCursor(0, 0);
  if(x < 0) {                    
    lcd.print("-");   
  }                             // マイナス表示
  else { 
    lcd.print(" ");  
  }

  lcdout = abs(x/100);
  if(lcdout  >= 100)  { 
    lcd.print(lcdout);  
  }
  else if(lcdout  >= 10 ) { 
    lcd.print(" ");               // ゼロサプレスひとつ
    lcd.print(lcdout);  
  }
  else if(lcdout  >= 1  ) { 
    lcd.print("  ");              // ゼロサプレス二つ
    lcd.print(lcdout);  
  }
  else { 
    lcd.print("  0");             // 最下位がゼロの場合は0を表示
  }
  lcd.print(".");                 // 小数点表示
  lcdout = abs(x % 100);
  if(lcdout  >= 10) {             // 小数点以下1位がゼロでなければそのまま表示
    lcd.print(lcdout); 
  }
  else  { 
    lcd.print("0");                //  ゼロだったら0を表示
    lcd.print(lcdout); 
  }
  lcd.print("mm");
}

另外一份代码

#include "Keyboard.h"
#include <Arduino.h>

int clockPin = 4;  // クロック入力ピン番号(Trで反転) clock input from caliper (reversed by Tr.)
int dataPin = 5;   // データ入力ピン番号(Trで反転) Data input from caliper (reversed by Tr.)
int switchpin = 2; // テキスト送信用スイッチ入力 Switch input for torigger to transmission to PC
int data;
float key_data = 0;
bool pushed = false;

int ReadCaliper()
{ // ノギスからデータ読んで値返す関数  Function for reading measurement data of digital caliper
  boolean dataStarted = false;
  unsigned long t0, bitOpr, oprResult;
  int n, outData;

  bitOpr = 0x00000001; // ビット操作オペレータ  Bit operator
  oprResult = 0x00000000;

  //   データ転送開始まで待つ
  while (dataStarted == false)
  {
    t0 = micros(); // タイミングを記録  Memory current time
    while (digitalRead(clockPin) == LOW)
    { // クロックピンがLOWの期間を検出 Detect period of low signal of clock
    }
    if (micros() >= t0 + 1000)
    {                     // LOWが1mS以上続いていたらデータ開始とみなす Its assumed data starting if LOW continue more than 1ms
      dataStarted = true; // 但し、micros は70分でゼロに戻るのでその時は取りこぼす、ゴメン!
    }
  } // クロックがHIGHになりデータ転送が始まる

  //   データのビット列を読み込み  Reading data bit stream

  for (n = 1; n <= 24; n++)
  { // 24ビット読み出しループ
    while (digitalRead(clockPin) == HIGH)
    { // クロックピンがLOWになるまで待つ waiting for low of clock
    }
    if (digitalRead(dataPin) == LOW)
    {
      oprResult = oprResult | bitOpr; // 1(負論理なのでLOW)だったらビットを立てる
    }
    if (n != 24)
    {                       // 最後のビットでなければ
      bitOpr = bitOpr << 1; // ビット操作オペレータを左にシフト
      while (digitalRead(clockPin) == LOW)
      { // クロックがHIGHになるまで待つ
      }
    }
  }

  //  データを取り出しint型に整形  Pick data and change type to "int"
  outData = oprResult; // データを16ビットint変数に代入
  if ((oprResult & 0x00100000) != 0)
  {                           // 負の値のフラグ(21ビット目)が立っていたら
    outData = (~outData) + 1; // 2の補数形式の負の値に変換
  }
  return outData; // 値を返して関数終了
}

void setup()
{
  Keyboard.begin();
  pinMode(17, OUTPUT);

  pinMode(clockPin, INPUT_PULLUP);
  pinMode(dataPin, INPUT_PULLUP);
  digitalWrite(clockPin, HIGH);
  digitalWrite(dataPin, HIGH);

  pinMode(switchpin, INPUT_PULLUP);
  Serial.begin(11520);
}

void loop()
{

  data = ReadCaliper();     // ノギスからデータを読む  Reading data from caliper
  Serial.println(key_data); // シリアルに書き出し Output serial communication to debug

// 最初に押された時だけ送信する Transmitting data when switch is  pushed at first time only
  if (digitalRead(switchpin) == LOW && pushed == false)  
  {

    key_data = (float)data / 100;
    Keyboard.print(key_data);
    pushed = true;
    digitalWrite(17, LOW);
    delay(200);
  }
  else if (digitalRead(switchpin) == LOW && pushed == true)
  {
  }
  else if (digitalRead(switchpin) == HIGH)
  {

    pushed = false;

    digitalWrite(17, LOW);
  }
}

网上做的成品

https://phantomshuttle.com/wp-content/uploads/2022/04/Screenshot-2022-04-29-000217.png
可以输出数据到电脑上的游标卡尺

发表回复

textsms
account_circle
email

phantomshuttle 博客

容栅式数字游标卡尺数据读取
注意 :未验证 参考链接 https://qiita.com/84mota/items/c94e2387d1fc35b22e73 http://radiopench.blog96.fc2.com/blog-entry-324.html https://blog-imgs-45-origin.fc2.co…
扫描二维码继续阅读
2022-04-29