2016年10月2日 星期日

使用Arduino 掃描I2C裝置的位址

#Arduino #Arduino UNO #Arduino MEGA2560 #Arduino DUE #I2C #IIC #I2C LCD #1602 LCD #LCD

這裏我先用一張圖來解釋Arduino 專案的發展需要的工具
我們常常到購物網買一些Arduino的sensor。。。由於Sensor 百花齊放,做的人沒有提供資料,賣的人也不清楚,技術資料轉來轉去,大家一片混亂,拿I2C界面LCD來講,明明範例的位置是0x27,但是我們照着寫就是動不了,差半天才知道LCD模組的位置不同,現在我就提供大家一個方法I2C address Scan 程式有了它就不用再傷腦了。

完整的程式碼如下:

// I2C Scanner
// Written by Nick Gammon http://gammon.com.au/i2c
// Date: 20th April 2011
// 2016-09-30
//中文註解李進衛
//IIC 位址掃描程式
//適用於Arduino UNO,DUE,MEGA2560
// 技術參考網址 http://playground.arduino.cc/Main/I2cScanner
// 作者網址(他有詳細說明I2C通信格式與原理) : http://gammon.com.au/i2c

#include

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

  // Leonardo: wait for serial port to connect
  while (!Serial)
    {
    }

  Serial.println ();
  Serial.println ("I2C scanner. Scanning ...");
  byte count = 0;
 
  Wire.begin();
  for (byte i = 8; i < 120; i++) //地址掃描
  {
    Wire.beginTransmission (i); //對裝置發出I2C位址函數解釋請參考: https://www.arduino.cc/en/Reference/WireBeginTransmission
    if (Wire.endTransmission () == 0) //假如裝置有ACK 就顯示其位址資訊藉由RS232傳送出來
// 函數解釋請參考: https://www.arduino.cc/en/Reference/WireEndTransmission
      {
      Serial.print ("Found address: ");
      Serial.print (i, DEC);
      Serial.print (" (0x");
      Serial.print (i, HEX);
      Serial.println (")");
      count++;
      delay (1);  // maybe unneeded?
      } // end of good response
  } // end of for loop
  Serial.println ("Done.");
  Serial.print ("Found ");
  Serial.print (count, DEC);
  Serial.println (" device(s).");
}  // end of setup

void loop() {}


2016年9月24日 星期六

Rotary Encoder的程式動作原理以及Arduino程式的實現

#Arduino
#Rotary Encoder
#編碼器
#旋轉編碼器
Rotary Encoder 在一般的儀器或者家電產品常常看到他的蹤影在此特別的說明一下他的原理與程式的實現。






Rotary Encoder 外觀


這一張圖是ENCODER的工作原理【橘色】的部分是接地片或這是電源片,A,B兩點是信號它是利用角度的時間差來判斷正傳或者是反轉的,我個人覺得他的圖畫的很好再次引用說明。
圖片來源:http://howtomechatronics.com/tutorials/arduino/rotary-encoder-works-use-arduino/
【圖片版權屬該網站作者所有】


分別處於兩個角度當旋轉是ON、OFF就會輸出AB相位信號。
根據這個信號圖撰寫程式,程式如附檔這個程式有實測過是OK的
寫ENCODER程式會有幾個環節必須注意
  1. 外部中斷的設定方式:
Arduino 建議的語法如下:
attachInterrupt(digitalPinToInterrupt(18), interrupt1,RISING); //CHANGE);
必須使用這個語法才能動作,官方網站建議接腳的定義要寫這個【digitalPinToInterrupt(18)】,不能寫IO PORT
一般網路的寫法如下:
 attachInterrupt(0, doEncoder, CHANGE);  // encoder pin on interrupt 0 - pin 2
我在Arduino MEGA2560測試一直無法成功啓動外部中斷我不知道爲什麼,因爲無法看到compiler之後的組合語言所以無法得知爲什麼。
還有TOUCH功能和VR功能還沒有實現,繼續努力。

Arduino 範例:
void ENCODER_SUB(void)
{
if ((f_cw_start ==0)||(f_ccw_start==0))
{
// if(digitalRead(outputB)==1)
if (bit_is_set(P_ENC,BP_ENCB))
{
f_cw_start = 1;
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,RISING);  //CHANGE);
} else{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,RISING);  //CHANGE);
f_ccw_start = 1;
}
}

if ((f_cw_start ==1)||(f_ccw_start==1))
{
// if(digitalRead(outputB)==0)
if (bit_is_clear(P_ENC,BP_ENCB))
{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,FALLING);  if(encoder_counter <13 div="">
{
encoder_counter++;
}else{ 
encoder_counter = 0;
}
f_cw_start = 0;
}else{
attachInterrupt(digitalPinToInterrupt(outputA), ENCODER_SUB,FALLING); 
if (encoder_counter >0)
{
encoder_counter--;
}else{
encoder_counter = 13;
}
f_ccw_start = 0;
}


}
 Serial.print("Interrupt-->");
 Serial.println(encoder_counter);
}


這個程式經過測試是OK的沒有漏格現象,但是由於我的Encoder他的AB相位只差1.3ms~3ms所以當你旋轉速度過快程式會反應不及,因爲Arduino的IO函數有延遲,使用我將digitalRead()改爲bit_is_set or bit_is_clear 兩個巨集指令。



如何使用終端機軟體收集來自於Arduino的資料

  將治具使用Micro USB cable 連上電腦 開啟終端機軟體 選擇 Serial🡪按下OK File🡪Log…  設定log file要存放位置,建議檔案名稱直接取名為*.CSV 例如:20231224.csv 按下治具Reset按鍵開始收集資料