部落格

如何以Arduino使用ADS1115 ADC的連續模式

德州儀器ADS1115是一個16位元的類比數位轉換器(ADC)。這個ADC是基於ΔΣ架構,取樣率最高為860Hz。 ADS1115必須操作在連續模式(Continuous Mode)下才可以用最高860Hz的取樣率來做轉換。 在這篇文章中,我們會示範如何在Arduino環境下設定ADS1115使用連續模式,並且以860Hz取樣率做轉換。

在連續模式下,ADS1115會在上一次轉換完成後,馬上開始下一次的轉換。 在轉換完成時,也會將ALERT腳位拉低,藉此來告訴Arduino可以讀取轉換結果了。 我們在Arduino上會利用GPIO中斷(interrupt)的方式來讀取ALERT訊號,當我們偵測到ALERT由高變低時,就去讀取ADS1115的轉換結果。

這邊簡單介紹一下GPIO中斷的運作方式: 平常Arduino都在重複執行loop()中的程式,當Arduino偵測到GPIO中斷事件(例如ALERT由高變低)的時候,它會自動呼叫interrupt callback的函式。 在這個函式中,我們要寫一小段程式來處理這個中斷,例如改變一些變數的數值。 執行完callback的小程式之後,Arduino會跳回剛才在loop()中的位置。

本文使用Arduino Uno,它支援GPIO中斷的腳位只有2和3。 因此,依照以下表格來連接ADS1115和Arduino Uno的腳位。

ADS1115 Arduino Uno
VDD 5V
GND GND
SCL A5
SDA A4
ADDR not connected
ALRT D3

ADS1115是使用I2C通訊協定來做資料的交換;因此,我們將使用Adafruit的ADS1X15函式庫來處理與ADS1115的資料交換。

首先,我們要先建立一個Adafruit_ADS1115物件,同時我們也宣告一些之後會用到的變數。

#include <Adafruit_ADS1X15.h>

Adafruit_ADS1115 myADS;
unsigned long t0;
int16_t v;
String str;

接下來,我們要設定中斷處理。 newDataReady()是我們的中斷處理callback函式,當ALERT由高變低時,會自動執行這個callback函式。 我們會利用這個函式來設定new_data這個變數,之後在loop()中會根據這個變數來判斷要等待還是讀取ADS1115的轉換結果。 因為new_data這個變數是由中斷處理來改變,我們必須使用volatile的變數型態,才不會被編譯器優化掉。

const int intPin = 3;
volatile bool new_data = false;
void newDataReady() {
    new_data = true;
}

在setup()中,我們必須做幾件事:

  • 啟用序列埠通訊
  • 啟用GPIO中斷處理
  • 設定ADS1115使用連續模式
  • 讀取初始時間
void setup() {
  Serial.begin(115200);

  // The convertion is ready on the falling edge of a pulse at the ALERT/RDY pin.
  attachInterrupt(digitalPinToInterrupt(intPin), newDataReady, FALLING);

  myADS.begin();
  myADS.setGain(GAIN_FOUR);   // +- 1.024V range
  myADS.setDataRate(RATE_ADS1115_860SPS);
  myADS.startADCReading(ADS1X15_REG_CONFIG_MUX_SINGLE_0, true);
  // We should set "continuous" to true to reach optimal speed.

  t0 = micros();
}

為了每秒傳輸860個轉換結果,我們需要選擇高一點的鮑率,例如115200。 ADS1115的ALERT腳位是連接到intPin,因此我們要將中斷處理利用attachInterrupt()接在這隻腳上,並且設定newDataReady()作為我們的callback函式。

接下來,我們要來設定ADS1115。 我們在這個範例中使用了四行來做設定。

  1. begin()只是用來做初始化。
  2. setGain()是用來設定類比訊號進入ADS1115的放大倍率,可以由2/3倍至16倍。 放大倍率的設定以及對應的輸入電壓範圍請參考datasheet
  3. setDataRate()是用來設定取樣頻率,我們這邊使用最高的860Hz。 ADS1115的連續模式只可以操作在某幾個特定的頻率,請參考datasheet。
  4. startADCReading()是用來啟動ADS1115,第一個參數是選擇輸入的頻道,在這個範例中我們選擇了頻道0;第二個參數必須設為true來使用連續模式

Adafruit ADS1X15函式庫還有許多其他的設定可以調整,詳細的內容可以參考它的Github Repo

最後,在loop()中,當new_data為true時,我們就可以讀取ADS1115的轉換結果了。 記得要在讀取完ADS1115之後把new_data設為false,這樣子我們的中斷處理才能正常運作。 在這個範例中,我們順便把時間用微秒印出來檢查取樣頻率。

void loop() {
  if(!new_data) return;
  // Don't call the ADC until we receive a convertion complete signal.

  v = myADS.getLastConversionResults();
  str = micros() - t0;
  str += " ";
  str += v;
  Serial.println(str);

  new_data = false;
}

Download the source code for this example.

把程式碼上傳到Arduino之後,打開序列埠監控視窗,並且將鮑率設定為115200。 我們應該可以看到Arduino開始回傳資料。

Arduino傳回來的資料的第一個是時間,兩行之間大概差了1130微秒,對應到的取樣頻率是稍微超過860Hz。 第二個資料是ADS1115的轉換結果,會是一個介於-32768到+32767之間的數值。 因為ADS1115有一個模式是測量兩個輸入的電位差,所以可以有負的數值。 現在,我們成功讓ADS1115操作在連續模式,並且用Arduino以最高860Hz的取樣頻率來讀取轉換結果了!