2013/09/18

Arduino練習:壓力感測器(Force-Sensitive Resistor)

類比輸入的形式非常多,譬如我之前寫過的可變電阻光敏電阻,這一篇則是壓力感測器(Force-Sensitive Resistor),顧名思義,加諸不同的力量(擠壓、重量),便會得到不同的電阻,進而改變從Arduino類比輸入腳位所讀取到的電壓值。

這是我向Adafruit買的壓力感測器,型號是Interlink 402,圓形部分半徑1/2吋可感測壓力,有兩支腳,可插入麵包板。


所謂壓力感測器(Force-Sensitive Resistor),其實就是個電阻,根據施加的壓力,其電阻值會改變,此產品的規格如下,無壓力時電阻幾近無限大,施加壓力後,電阻就會變小。


不過施加壓力的力道與電阻之間的變化關係,並非線性。


底下是電路圖,接法跟可變電阻很像,壓力感測器有兩支腳,其中一支接5V,另一支除了串聯10k歐姆電阻接地外,也接到Arduino的類比輸入腳位A0。

我另外從Arduino數位腳位11(具PWM)接了一個LED,將根據壓力感測器的讀數控制LED的亮度。


線路完成後的照片。


以上是硬體線路部分,底下是軟體程式的部份。

// 首先定義腳位
#define led_pin 11
#define fsr_pin A0

void setup()
{
  Serial.begin(115200);
  pinMode(led_pin, OUTPUT);
}

void loop()
{
  int fsr_value = analogRead(fsr_pin); // 讀取FSR
  int led_value = map(fsr_value, 0, 1023, 0, 255); // 從0~1023映射到0~255
  analogWrite(led_pin, led_value); // 改變LED亮度
  Serial.println(fsr_value);
  Serial.println(led_value);
  Serial.println("-------------");
  delay(100);
}

Arduino類比腳位的解析度是10位元(0~1023),而PWM腳位則是8位元(0~255),所以程式中使用map進行映射。

完成後,平時FSR電阻無限大,A0會讀到接地(電壓0V),所以LED不亮;若輕輕按壓FSR,LED就會微亮,用力擠壓FSR的話LED就會更亮一點。

此種壓力感測器價格低、容易使用,但不精確,不可用來偵測確實的力道或重量,而是應該取出幾個範圍,譬如無壓力、有點壓力、中等壓力、很大的壓力、等等,然後加以運用。

105 comments:

  1. 對不起我是門外漢~我想請問一下~
    1.壓力感測器的那兩隻腳~是否可以接線再讓它長一點~
    2.如果我要感側的表面是微濕潤(例如口內黏膜)是否可行??
    謝謝您的詢問 感激

    ReplyDelete
    Replies
    1. 1. 可以。
      2. 不知道耶,試試看吧。

      Delete
    2. http://www.icshop.com.tw/product_info.php/products_id/9752
      Flexiforce壓力傳感器(max:45kg)
      那像這種有標記最大值的壓力感測器是否就可以根據我們所壓出的力量數據化??
      謝謝您的答覆~感激

      Delete
    3. 這產品比這篇的FSR來得好,也比較貴;應該比較穩定,而且已校正過,根據文件有1, 25, or 100磅可選用。

      > 根據我們所壓出的力量數據化?
      可以啊,不過其輸出應該也是對數logarithmic、而非線性linear,
      你給的產品網頁裡有下載資料表的網址,看看裡面有沒有壓力與輸出的表囉。



      Delete
    4. 謝謝你的回覆~我會仔細看資料表~感激

      Delete
    5. 對不起我第一次接觸這類的電子零件
      想請問 FSR400 的電阻要用多少的?

      Delete
    6. short answer:一樣。

      long answer:要看你想量到多少的電壓,在官方文件http://learn.adafruit.com/system/assets/assets/000/010/126/original/fsrguide.pdf中,Figure 9畫出使用100k、47k、30k、10k、3k時的圖形。

      Delete
  2. 你好~我想要請教
    此件施加的壓力與電阻之間的關係
    是可以改變的嗎?
    例如說我只希望感測100g-200g間的壓力變化去調整電阻
    謝謝

    ReplyDelete
    Replies
    1. 你手上的產品跟我手上的產品,即便同一家公司同一型號,施以同樣力量後,仍會有相當大的誤差。
      即便是只使用你手上的產品,施以同樣力量後,也可能得到不同的值,也會有誤差。
      100g-200g對本文章中的感測器來說,是很小的範圍。我"猜測"很難做得很準確。

      想做的話,步驟應該是,接上電路,施以100g-200g之間的力量,然後看輸出值是否範圍夠大,調整分壓電路中另一個電阻的值,使其更明顯。

      Delete
    2. 請問一下我是初學者,為何接地還要加一個10k電阻呢?

      Delete
    3. 形成分壓電路。

      Delete
  3. 您好,我是位剛接觸Arduino的初學者

    因近期有項專題製作,需要作出的項目類型,與版大您的做法類似

    我需要的是,當我壓(按)的越大力的時候,我亮的LED燈會越多顆(暫估5顆)

    請問我的程式設計上,需要怎麼做修正(如果以版大上述分享的程式為例的話)

    不好意思,問了麻煩的問題,還望版大不吝賜教,謝謝!!

    ReplyDelete
    Replies
    1. 根據這篇的作法,先測出不按的時候、Arduino類比腳位讀取到的數值,然後測出以最大力氣按壓時的數值,再切成一段一段,譬如5段。

      然後在loop()裡,不斷讀取數值,根據該數值落於哪一段,點亮相對應數量的LED燈。

      Delete
  4. 抱歉,請問一下
    如果我是買FSR400型號之感測器
    依照您的程式碼無法作動.
    程式碼該如何修改呢..
    抱歉 是這方面新手

    ReplyDelete
    Replies
    1. 請附上清楚的電路圖照片,以及程式碼,
      另外註明使用哪一塊Arduino板子。

      Delete
  5. 請問一下 這個我電路做出來是可以用的 壓越大力也會越亮,請問一下那這個要如何讓LED燈能固定亮著不要滅掉呢? 然後再壓一次就暗掉 這個要如何用Arduino做到

    ReplyDelete
    Replies
    1. 請參考
      Arduino練習:以開關切換LED明滅狀態
      http://yehnan.blogspot.tw/2012/02/arduinoled.html

      Delete
  6. http://www.rakuten.com.tw/shop/icshop/product/368030200137/
    您好我想請問這種的傳感器是否能夠跟arduino連動呢?
    (不好意思我是新手幾乎什麼都不懂><)
    我跟組員想要LED燈亮然後有壓力之後燈熄滅
    不知道Arduino能不能做到...?
    謝謝!

    ReplyDelete
    Replies
    1. 可以。

      此產品利用重量去改變電阻值,量測重量而沒有拉力的話,可使用5V以及串聯一個電阻作分壓。
      與連接一般的光敏電阻、壓力感測器、等等,都差不多。

      Delete
  7. 請問可以教我怎麼用壓力感測器控制震動馬達動嗎

    ReplyDelete
    Replies
    1. 有問題請留言,盡量回答。

      震動馬達只有停跟震兩種狀態嗎?
      那就從壓力感測器讀取數值,設定界限,超過就震,沒超過就停。

      Delete
    2. 是的,請問可以教我怎麼設定界線嗎?本人剛接觸arduino

      Delete
    3. 就在程式裡定義變數,設定界限的值。
      至於值要設多少,先測試壓力感測器,得知多少壓力會得到多大的輸入值,然後根據你的需求,取其中一個值。

      當然,也可以取其中一個範圍,而不是單一固定值。不過這樣一來,程式就要改寫。

      Delete
    4. 請問可以教我怎麼取其中一個範圍嗎?

      Delete
    5. 施加不同力量到你的壓力感測器,讀取讀數,
      看你想要哪個力量範圍(對應到讀數範圍)

      Delete
  8. 葉先進,請教一下,我用壓力感測器測試傳到手機是OK的,但如果我增加了測量外部電池的analog1 之後,我手機端就會產生bug,請問要怎麼解決? 關於手機端我是傳輸了字串才開始接收到壓力感測器的值,但我增加delay的動作,就不會發生此問題,這是我的Arduino程式碼:

    // 首先定義腳位
    #define fsr_pin A0
    #define voltage_pin A1
    #include // 引用程式庫

    // 定義連接藍牙模組的序列埠
    SoftwareSerial BT(8, 9); // 接收腳, 傳送腳
    void setup() {
    pinMode(4, OUTPUT);
    pinMode(5, OUTPUT);
    pinMode(6, OUTPUT);
    BT.begin(9600);
    }

    void loop() {
    int fsr_value = analogRead(fsr_pin); // 讀取FSR
    int voltage_value = analogRead(voltage_pin); // 讀取FSR
    BT.println(fsr_value);
    if(voltage_value >756)
    {
    digitalWrite(4, HIGH); // turn the LED on (HIGH is the voltage level)
    digitalWrite(5, HIGH); // turn the LED on (HIGH is the voltage level)
    digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
    }
    if(voltage_value =523)
    {
    digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
    digitalWrite(5, HIGH); // turn the LED on (HIGH is the voltage level)
    digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
    }
    if(voltage_value = 325)
    {
    digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
    digitalWrite(5, LOW); // turn the LED on (HIGH is the voltage level)
    digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
    }
    if(voltage_value < 100)
    {
    digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
    digitalWrite(5, LOW); // turn the LED on (HIGH is the voltage level)
    digitalWrite(6, LOW); // turn the LED on (HIGH is the voltage level)
    }

    }

    ReplyDelete
    Replies
    1. > 我手機端就會產生bug,請問要怎麼解決?
      什麼bug?

      > 關於手機端我是傳輸了字串才開始接收到壓力感測器的值,
      從你的程式碼看不到「傳輸了字串」這部份。

      > 但我增加delay的動作,就不會發生此問題
      delay增加在哪?

      Delete
    2. 我後來解決了

      // 首先定義腳位
      #define fsr_pin A0
      #define voltage_pin A1
      #include // 引用程式庫

      // 定義連接藍牙模組的序列埠
      SoftwareSerial BT(8, 9); // 接收腳, 傳送腳
      void setup() {
      pinMode(4, OUTPUT);
      pinMode(5, OUTPUT);
      pinMode(6, OUTPUT);
      BT.begin(9600);
      }

      void loop() {
      while (BT.available() > 0){
      int fsr_value = analogRead(fsr_pin); // 讀取FSR
      BT.println(fsr_value);
      delay(100);
      }

      int voltage_value = analogRead(voltage_pin); // 讀取外部電池

      if(voltage_value >756)
      {
      digitalWrite(4, HIGH); // turn the LED on (HIGH is the voltage level)
      digitalWrite(5, HIGH); // turn the LED on (HIGH is the voltage level)
      digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
      }
      if(voltage_value >=523 && voltage_value <= 756)
      {
      digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
      digitalWrite(5, HIGH); // turn the LED on (HIGH is the voltage level)
      digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
      }
      if(voltage_value > 325 && voltage_value <=523 )
      {
      digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
      digitalWrite(5, LOW); // turn the LED on (HIGH is the voltage level)
      digitalWrite(6, HIGH); // turn the LED on (HIGH is the voltage level)
      }
      if(voltage_value < 100)
      {
      digitalWrite(4, LOW); // turn the LED on (HIGH is the voltage level)
      digitalWrite(5, LOW); // turn the LED on (HIGH is the voltage level)
      digitalWrite(6, LOW); // turn the LED on (HIGH is the voltage level)
      }

      }

      Delete
  9. 請問有8051的程式碼嗎

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
  10. 請問上面程式碼的Serial.begin(115200);
    115200是什麼數值呢?

    ReplyDelete
  11. 不好意思,我是初學者,可以請教你
    1.不管哪一種Arduino,程式語言都可以通用嗎?,我是使用Blueduino rev2
    2.當我的arduino和電腦連接時,在Arduino IDE裡打完程式後,要點選哪一個鍵才是把程式傳給arduino呢?... 那要怎樣才可以得知有執行成功?

    ReplyDelete
    Replies
    1. 1. Blueduino說它相容於Arduino,所以答案是yes。
      根據網路上找到的資訊,Arduino IDE應該選板子「LilyPad USB」。
      2. Arduino IDE左上方的「向右箭頭」按鈕;或是選單「草稿碼-上傳」。
      若最後出現上傳完畢或完成等字樣,就代表上傳動作成功。

      Delete
    2. 謝謝你!
      我還想請問你 如果只想測試壓力感測器的話 程式該怎麼打呢?

      Delete
    3. #define fsr_pin A0
      void setup() {
      Serial.begin(115200);
      // put your setup code here, to run once:

      }

      void loop() {
      int fsr_value=analogRead(fsr_pin);
      Serial.println(fsr_value);

      // put your main code here, to run repeatedly:

      }

      這樣的程式來測試壓力感測器是否正確?

      Delete
    4. 對。

      另外,這篇文章不是也有程式嗎?

      Delete
    5. 我在測試時 壓了壓力感測器後 視窗上只顯示1023,我該怎麼知道他的數值?

      Delete
    6. 數值就是1023啊。

      你電路接錯了吧。

      Delete
  12. 你好,因為我也有買同一款感測器但是測試出來發現精準度不夠,所以想請問您有沒有推薦比較精準的壓力感測器,希望能精準測出較小範圍例如100~200g那種。

    ReplyDelete
    Replies
    1. 不清楚,無法回答。

      Delete
    2. 此類型的壓力感測器,規格書都會強調不應作為定量的測量。其誤差常介於正負5~25之間。

      Delete
  13. 你好,上述程式有成功執行過了
    接下來我想使用藍芽模組,讓主端的壓力感測器
    能讓從端的LED發亮
    請問該如何使上述程式分成兩部份呢?(藍芽主與從端部分已經成功互相連線)

    ReplyDelete
    Replies
    1. > 上述程式有成功執行過了
      哪裡的程式?

      > 請問該如何...
      不懂問題所在。什麼叫做分成兩部分?
      既然已成功連線,就可由主端根據壓力感測器的數值,傳出命令交由從端控制LED亮滅。

      Delete
    2. 本篇的程式
      因為裡面有些參數是互相呼應的
      所以不懂該如何分成兩部分
      意思是目前程式無法讓LED正常工作
      我是參考這篇文章去改的

      Delete
    3. 嗯,主端的程式碼應該跟這篇差不多,但要把
      analogWrite(led_pin, led_value);
      改成經由藍牙向從端發送led_value,

      從端從藍牙收到該值後,以之修改LED的明暗度。

      另外要加大delay的值,譬如每五秒就是delay(5000);,才不會過快。

      Delete
  14. 現在問題是不知道為何在程式及腳位都沒有錯誤的情況下
    會亮到其他不相干的LED
    我是設定PIN腳11
    可是他對PIN腳13的LED有反應 11的則不會動作

    ReplyDelete
    Replies
    1. > 在程式及腳位都沒有錯誤的情況下
      既然你都說沒有錯誤,那我也不知道。

      程式碼?

      Delete
    2. 主端部分:
      int fsr_value = analogRead(fsr_pin); // 讀取FSR
      int led_value = map(fsr_value, 0, 1023, 0, 255); // 從0~1023映射到0~255

      BT.print(val);
      BT.print(led_value);

      if (buttonstate == HIGH) {
      val = '1';
      }
      if (buttonstatea == HIGH) {
      val = '2';
      }
      if (buttonstatea == LOW && buttonstate == LOW) {
      val = '0';
      }
      從端部分:
      if (BT.available()) {
      val = BT.read();

      if(led_value>0){
      analogWrite(LED_PINc, led_value); // 改變LED亮度
      delay(100);
      }
      從端剩下的就是很單純按按鈕讓LED亮( if val==? 哪個就會亮這樣)

      Delete
    3. 從你給的程式碼,看不出問題。

      Delete
  15. 請問壓力感測器的圓形感測區,
    有沒有辦法增加面積?

    ReplyDelete
    Replies
    1. 自己沒辦法吧。

      買大一點的?

      Delete
  16. This comment has been removed by the author.

    ReplyDelete
  17. 請問怎麼把壓力感測的放進陣列裡面呢?
    (沒有限定要測幾次,希望讀到幾次放幾個)

    ReplyDelete
    Replies
    1. 事先不知道幾次的話,要用動態記憶體配置。

      Delete
  18. 請問壓力感測器有兩隻腳,為何要串連一個電阻後才可接地?運用何種原理?

    ReplyDelete
  19. 請問壓力感測器有兩隻腳,為何要串連一個電阻後才可接地?運用何種原理?

    ReplyDelete
  20. 請參閱拙作《Arduino輕鬆入門》第4章,
    主要原理就是「4.1 分壓器」,裡頭有詳細說明。

    ReplyDelete
    Replies
    1. 可是這個書沒有電子版的吧。我就想知道這一個問題,能否在這裡回復呢?或者email給我?

      Delete
    2. 我寫成文章
      http://yehnan.blogspot.tw/2012/02/arduino_21.html
      與書籍《Arduino輕鬆入門》,
      原因之一就是不想重複回答問題。

      可搜尋關鍵字「arduino 分壓 類比」,
      譬如底下這些分享文章:
      http://yhhuang1966.blogspot.tw/2015/10/arduino.html

      http://www.digikey.tw/zh/articles/techzone/2012/feb/arduinos-analog-functions-how-to-use-them-in-your-next-design

      http://swf.com.tw/?p=729

      http://dshps.blogspot.tw/2015/03/blog-post_17.html

      Delete
  21. 你好 我想請問一下 我想要做一個壓力感測計次的裝置 請問一下這個程式碼有辦法做到 數值低於多少算一次 高於多少不算 累進的方式嗎?

    ReplyDelete
    Replies
    1. 訂出你要的範圍,低數值與高數值,
      並且訂出當壓力小於低數值後,應維持多少時間才計次一次,
      超過該時間後,要不要重複計次,

      訂出種種相關規格,
      然後改寫程式。

      Delete
  22. 你好,我想問您,如果想要用arduino透過藍芽連接的話,在arduino上的藍芽code要怎麼寫呢?

    ReplyDelete
    Replies
    1. 查藍牙模組的文件,看如何連接,如何控制。
      HC-06藍牙模組的話,使用序列埠介面,下達AT指令。

      Delete
    2. 我是使用BlueDuino Rev2,這個板子本身內建就有BLE。
      那我這樣打是對的嗎?

      #include
      #include
      SoftwareSerial mySerial(11,12);

      void setup() {
      Serial.begin(9600);
      mySerial.begin(9600);
      }

      Delete
    3. BlueDuino Rev2的CC254x藍牙模組,經由硬體序列埠Serial1與ATMega32U4溝通。

      詳細介紹請看
      http://wiki.aprbrother.com/wiki/BlueDuino_rev2

      這裡有範例程式
      https://github.com/AprilBrother/BlueDuino-Library/tree/master/examples

      Delete
    4. 我想問你 硬體序列埠和軟體序列埠的差別是什麼?

      Delete
    5. 顧名思義,硬體序列埠就是由電子晶片提供序列傳輸功能,
      軟體序列埠,是由軟體程式模擬出來的。

      Delete
  23. 這樣是不是100k是最好的?

    ReplyDelete
  24. 這一款壓力感測 最大重量能夠感測到10kg, 請問如果施加大於10kg的力量,此感測器會壞掉(破裂之類的)嗎??

    ReplyDelete
    Replies
    1. 不知道。
      規格書沒寫。

      Delete
  25. 請問 我用Mega2560電路跟您的接法一樣
    程式碼也都相同 可是這樣LED卻不會亮
    可以請問是什麼原因嗎

    ReplyDelete
    Replies
    1. 程式未燒錄成功?LED壞了?壓力感測器壞了?

      Delete
    2. 程式上傳有成功,LED也是正常的
      可是壓力感測器剛買的,不知道怎麼測試是否正常

      Delete
    3. 我後來又把LED的程式碼部分刪掉,測是壓力感測是正常的
      後來再把LED的部份加回去,是可以測到值可是沒有辦法改變LED亮度
      LED線路應該是正確的,我有先run過一次

      Delete
    4. show me the code.

      Delete
    5. led串聯的電阻弄錯了?

      Delete
    6. 我的code跟你這篇文章的一樣
      會不會是壓力值太小,無法驅使LED亮起來呢?
      妳測出來的壓力範圍大概再多少左右LED可以亮?

      Delete
    7. 大概是吧。

      忘了。

      Delete
    8. 我用手壓測出來大概70幾左右 不知道正不正常

      Delete
    9. 這個出來的數值 可以轉換成力的數值嗎?(幾克重幾克重這樣子
      因為我想作一個測量力然後可以計數這樣 計數的部分可以請問該怎麼寫嗎

      Delete
    10. 70幾是哪個?如果是fsr,算很小。
      何不改程式碼?加大放大倍率不就好了?

      > 轉換成力的數值嗎?
      文章中有張對應圖。

      Delete
  26. 放大倍率後可以控制LED亮暗了 謝謝!
    文章中那個圖,我該怎麼把0-1023那數值轉成力的大小?

    ReplyDelete
    Replies
    1. 從0~1023轉成電壓,根據你接的分壓電路,算出FSR受力時的電阻,再從圖查出對應的力。

      Delete
  27. 我想請問一下~如果我要在86Duino上加上排成要怎麼加呢?
    我想要的功能是我要讓馬達一邊運作一邊收他的資料。

    ReplyDelete
    Replies
    1. 我沒有86Duino。

      同時做兩件事情,有很多種方式。

      馬達是哪種馬達? 重要的是程式庫應提供非阻斷式API。

      Delete
    2. 能用四個感測器來秤重嗎

      Delete
    3. 可以用四個,
      可以秤重,
      但不準吧,我想。

      Delete
    4. 那請問您有建議用甚麼原件結合Arduino來秤重嗎??

      Delete
    5. This comment has been removed by the author.

      Delete
  28. 請問我要讓壓力感測器當開關使用 壓一下led on 再壓一下led off 做得到嗎?

    ReplyDelete
  29. 請問我要讓壓力感測器當開關使用 壓一下led on 再壓一下led off 做得到嗎?

    ReplyDelete
    Replies
    1. 做得到。

      Arduino練習:以開關切換LED明滅狀態
      http://yehnan.blogspot.com/2012/02/arduinoled.html
      的程式改一改,改成根據壓力感測器的數值來判斷,就可以了。

      Delete
    2. 請問要怎麼知道壓力感測器的數值?

      Delete
    3. 請看本篇內文。

      Delete
  30. 可以請問一下如何用這元件來秤重嗎??

    ReplyDelete
  31. 可以請問一下如何用這元件來秤重嗎??

    ReplyDelete
    Replies
    1. 嗯,讀取數值後,推導出電阻值,再推出力,最後得到重量。
      ㄟ,以上所說,僅是臆測,沒真正做過。
      況且,這個元件的 力-電阻 關係圖,並非線性。
      況且,其精確度到多少,我不知道,說不定誤差甚大。

      Delete
  32. 請問
    如果我想即時顯示出電阻值或是直接顯示出當下的荷重
    請問程式部份該怎麼打
    電阻值換算成荷重的公式 該增加在哪呢?

    ReplyDelete
    Replies
    1. 施加壓力的力道與電阻之間的變化關係,在本文的第三張圖,我不知道公式。

      > 顯示出
      不就是print

      Delete