痞酷網_PIGOO

 找回密碼
 立即註冊
!!! [系統偵測到廣告阻擋軟體] !!!

如果您覺得痞酷網對您有些許幫助,或者您認同痞酷網的理想,

那麼希望您將痞酷網設定為白名單.

並請在上論壇的時候,動動您的手指,用行動支持我們.

謝謝!
查看: 9128|回復: 27

[實做與討論] Arduino的按鍵擴充電路

[複製鏈接]
發表於 2019-4-20 21:55:00 | 顯示全部樓層 |閱讀模式
本文章最後由 jasonboy99 於 2019-4-20 10:01 PM 編輯

前幾天在用mini-pro時發現port被我用到一點都不剩,於是在網路上尋找到多按鍵擴充的電路,只需要用一個類比埠就可以讀取多組按鍵,名稱為ADKEY,零件很簡單只有電阻,原理是利用不同的電阻降壓來判斷按鍵,研究一下電路後決定來DIY一片。

MWSnap306.jpg

不同於網路上的版本多是用不同阻值的電阻串於按鍵前來取值, 而因為手上有超多1K的電阻,所以試著用多個1K來串,擴充到10個port後,再用1個10K可變電阻來進行分壓,作為人工校正用,測試後發現效果還可以,因為是類比讀取,程式除了需要處理彈跳外,採樣還要額外容許正負5的誤差。

MWSnap307.jpg

MWSnap308.jpg

可變電阻是"歸零"用的,因為不想日後因為電線還是其它原因造成讀值變化,還要一個一個修改,所以就直接裝了一個省得麻煩。我是將SW10的讀值調成500。

MWSnap309.jpg

MWSnap310.jpg

雖然不是什麼高深複雜的東西,但是覺得實用度高,將做好的電路圖放上來一起分享。

ADKEY 20190419v1.pdf (43.04 KB, 下載次數: 7)

評分

20

查看全部評分

發表於 2019-4-21 00:09:23 | 顯示全部樓層
可以改用排阻  這樣有助小型化  
另外按鍵建議並聯一103以下的電容   

這個電路讓我到的R2R DAC  那個是用電子開關做的   

評分

3

查看全部評分

 樓主| 發表於 2019-4-21 09:43:31 | 顯示全部樓層
專炸元件 發表於 2019-4-21 12:09 AM
可以改用排阻  這樣有助小型化  
另外按鍵建議並聯一103以下的電容   

不確定是彈跳還是麵包板線路太長原因,在按下按鍵時讀值有一段時間會呈緩降,約在100ms~300ms之間才會降到0,越遠的按鍵越明顯,並電容應該可以加速,謝謝您的建議。

查了一下R2R DAC,密密麻麻的電阻真是........n_094|
發表於 2019-4-21 11:58:21 | 顯示全部樓層
有源碼的話才算完整, 不然很難抄襲成功
 樓主| 發表於 2019-4-21 13:15:11 | 顯示全部樓層
xiaolaba 發表於 2019-4-21 11:58 AM
有源碼的話才算完整, 不然很難抄襲成功

因為是面板做到一半才發現按鍵不夠用,所以我也還沒寫程式n_081|,只有PCB先做出來而已,想說等線路接完再寫的,實際上在電腦端測試時只有3行指令:

int bt = AnanlogRead(A0);
Serial.println(bt);
delay(1000);

晚點再把程式寫一下補上。
 樓主| 發表於 2019-4-21 13:43:21 | 顯示全部樓層
本文章最後由 jasonboy99 於 2019-4-21 02:03 PM 編輯

補上代碼,因為零件被我用掉了還沒裝上所以沒有測過硬體,但是軟體部份是編譯正確的。 
因為電阻精度都不同,所以第一次用時要自行測試一下讀值。


  1. #define adkey A0        //Arduino的類比輸入埠
  2. #define maxValue 5                //誤差正負5

  3. //開關sw1~sw10的讀取值,第一個0是固定值,接下來是sw1,sw2....sw10
  4. int sw[11]={0,928,848,780,722,673,629,591,558,528,500};

  5. void setup()
  6. {
  7.   Serial.begin(57600);
  8. }

  9. void loop()
  10. {
  11.   if(exKey(sw[1])==true)                // 當sw1被按下則顯示clicked
  12.    Serial.println("sw1 clicked");
  13. }

  14. bool exKey(int key)                        // exKey(開關讀值) ,被按下傳回true
  15. {
  16.   int r = analogRead(adkey);       
  17.   if(r<=key+maxValue && r>=key-maxValue)        // 處理誤差
  18.   {
  19.     delay(500);                                        // 處理彈跳
  20.     return true;
  21.   }
  22.   return false;
  23. }
複製代碼
發表於 2019-4-21 20:09:13 | 顯示全部樓層
本文章最後由 單晶片微電腦 於 2019-4-21 08:13 PM 編輯

這種按鍵不耐用,可以用橡膠按鍵試看看,順便觀察會不會彈跳。

https://cbu01.alicdn.com/img/iba ... 3477400.400x400.jpg
 樓主| 發表於 2019-4-21 21:24:51 | 顯示全部樓層
單晶片微電腦 發表於 2019-4-21 08:09 PM
這種按鍵不耐用,可以用橡膠按鍵試看看,順便觀察會不會彈跳。

https://cbu01.alicdn.com/img/ibank/2016/ ...

我那個按鈕實在是很難用,高度不夠不能鑽孔用而且又沒有帽子,現在都用來做實驗。
彈跳應該是難免的,手速不夠快n_081|,

您說的這種按鍵是不是只要買圖片中的橡膠套,放在類似的電路上就可以導通了?
發表於 2019-4-22 01:06:43 | 顯示全部樓層
如果要用橡皮按鍵的話,單獨一個按鍵用法,+5V -->20K -->按鍵 -->GND。
橡皮按鍵很好取得(例如4X4鍵盤,掌上型計算機、遙控器等等),但PCB板可能要另外洗。
太麻煩就先維持原案。
發表於 2019-4-22 08:30:18 | 顯示全部樓層
這類設計常常因為 按鍵接點電阻 氧化老化 而昇高
造成分壓偏離預設值 A按鍵電阻 送出 B按鍵預設值  然後就是程式誤讀   
因此 適當地提高電阻分壓間隔  給予較多的[容錯空間] 與 按鍵數量 取折衷平衡
分壓間隔包含了  兩概念 1:解析度  2:分壓段曲線 是 線性 非線性

評分

3

查看全部評分

 樓主| 發表於 2019-4-22 13:45:46 | 顯示全部樓層
單晶片微電腦 發表於 2019-4-22 01:06 AM
如果要用橡皮按鍵的話,單獨一個按鍵用法,+5V -->20K -->按鍵 -->GND。
橡皮按鍵很好取得(例如4X4鍵盤,掌 ...

想到家裡有一個壞掉的電腦鍵盤,裡面應該就是這種材質,回家來拆拆看應該就有一堆了。
 樓主| 發表於 2019-4-22 14:07:57 | 顯示全部樓層
SIMON1016 發表於 2019-4-22 08:30 AM
這類設計常常因為 按鍵接點電阻 氧化老化 而昇高
造成分壓偏離預設值 A按鍵電阻 送出 B按鍵預設值  然後就 ...

這種擴充法的確是受限於Arduino 10 bits的解析度而須節制數量,也怕彈跳、噪音等因素使程式誤判按鍵,剛想到如果內建一個校正用的電阻串在所有電阻的最前端,每次開機時讀取電壓來自動校正歸零,也許也是一個好方法。
發表於 2019-4-22 14:43:14 來自手機 | 顯示全部樓層
每個讀值之間不含誤差判斷是不實用的,公差跟容許誤差設計在現實應用很重要

評分

1

查看全部評分

發表於 2019-4-22 15:22:00 | 顯示全部樓層
本文章最後由 ysc 於 2019-4-22 03:34 PM 編輯

這種做法最常見的是汽車方向盤上的控制鍵,由於方向盤必須轉動無法直接把接線拉出來,所以都用軟性電路做成圈狀套在軸心上,這也導致線數受到限制,所以按鍵的部分只好用電阻分壓方式,只需要兩條線就可以傳遞好幾顆按鍵訊息,前不久拆裝SONY環繞擴大機,面板按鍵也是用這種方式。

按鍵都會有彈跳問題,我寫程式處理方式都是持續檢查一段時間鍵碼都一致才算數,如每10mS完成一次鍵盤掃描,連續5次鍵碼相同才算數,當中只要有一次不一致計數就歸零重新算起,按鍵釋放檢查也一樣,這樣的作法可以讓鍵盤讀值很穩定,看過很多人寫法都是讀一次,間隔幾十mS再讀一次,兩次相同就算數,感覺還是不太牢靠。

用A/D方式判斷鍵碼一定要考慮誤差問題,如果誤差預定為正負5%,則每個按鍵佔用10%的範圍,最多只能做到10顆按鍵,因此這種作法大多是用在按鍵數量不多的地方,若是要縮小誤差範圍來增加按鍵數量,那電路精密度就是一個挑戰。

SONY也不敢一個A/D迴路設計太多按鍵,以下這個例子有14顆按鍵要讀取,SONY分成兩路A/D,一路8顆另一路6顆,應該也是穩定性考量。

SONYKY.jpg

6顆這個迴路還有一顆按鍵在下方,照片上看不到。


評分

3

查看全部評分

 樓主| 發表於 2019-4-22 16:39:58 | 顯示全部樓層
xiaolaba 發表於 2019-4-22 02:43 PM
每個讀值之間不含誤差判斷是不實用的,公差跟容許誤差設計在現實應用很重要 ...

明白,現時只能用實驗時的值來抓一個範圍來求精度。
不知久了、老化了之後讀值會怎麼變化,是遞增還是等比例放大,令人好奇。
 樓主| 發表於 2019-4-22 17:10:52 | 顯示全部樓層
ysc 發表於 2019-4-22 03:22 PM
這種做法最常見的是汽車方向盤上的控制鍵,由於方向盤必須轉動無法直接把接線拉出來,所以都用軟性電路做成 ...

很有趣的實例,sony這個電路也是電阻疊加後取值,但是電阻值各不相同,大概是為了拉大差距,有時間來實驗看看。
因電路還沒接,還不確定實際上機後的誤差,電路線路一定是最大的挑戰,所以才把程式留到最後再弄,我也是在想大概要多次採樣才能降低誤判的機率,不過這樣就得要改寫或降低delay的使用了。
發表於 2019-4-22 20:38:24 | 顯示全部樓層
jasonboy99 發表於 2019-4-22 01:45 PM
想到家裡有一個壞掉的電腦鍵盤,裡面應該就是這種材質,回家來拆拆看應該就有一堆了。 ...

電腦鍵盤應該是薄膜鍵盤。
 樓主| 發表於 2019-4-22 21:34:17 | 顯示全部樓層
單晶片微電腦 發表於 2019-4-22 08:38 PM
電腦鍵盤應該是薄膜鍵盤。

是薄膜的沒錯,不一樣嗎?
發表於 2019-4-25 14:06:58 | 顯示全部樓層
幾位先進的經驗非常珍貴,實驗室的結果到量產經常因為環境的變化而受到挑戰,課服人員經常要戴鋼盔被K,久了漸漸把心得回饋到研發單位,或是帶著研發人員去參與會議!!

評分

1

查看全部評分

發表於 2019-4-25 20:59:02 | 顯示全部樓層
jasonboy99 發表於 2019-4-22 09:34 PM
是薄膜的沒錯,不一樣嗎?

電腦鍵盤線路有點複雜,還不如再寫個程式,兩個單晶做串列傳輸。

評分

2

查看全部評分

發表於 2019-4-25 21:44:33 | 顯示全部樓層
sony那個電路,應該是為了key function系統最佳化,在程式讀取key時只需花費 O(1)的時間即可辨識出那顆按鍵。

Big O notation
https://zh.wikipedia.org/wiki/%E5%A4%A7O%E7%AC%A6%E5%8F%B7

原理可能為:
假設 adc 為 12bit~
* 讀取值 1xxxxxxxxxxx 表示沒按鍵
* 讀取值 01xxxxxxxxxx 表示按鍵1
* 讀取值 001xxxxxxxxx 表示按鍵2
* ...............................................
* 讀取值 000000001xx 表示按鍵8
* bit [1-0] 可為按鍵8的電阻值最大誤差量。

程式可使用一條特定功能的組合語言來快速取得按鍵值而達到O(1)的速度。
x86 : bsf(Bit scan forward)/bsr
arm: clz (Count Leading Zeros)
https://en.wikipedia.org/wiki/Find_first_set

評分

3

查看全部評分

 樓主| 發表於 2019-4-25 23:50:35 | 顯示全部樓層
單晶片微電腦 發表於 2019-4-25 08:59 PM
電腦鍵盤線路有點複雜,還不如再寫個程式,兩個單晶做串列傳輸。

只是想說能不能單獨把薄膜的部份剪下來,放在自己的電路基板上作為按押感應用。
 樓主| 發表於 2019-4-26 00:21:32 | 顯示全部樓層
jojoling 發表於 2019-4-25 09:44 PM
sony那個電路,應該是為了key function系統最佳化,在程式讀取key時只需花費 O(1)的時間即可辨識出那顆按鍵 ...

原來硬體有內建這種指令集,可以理解為何分成6/8鍵為一組AD。
學習到新知了,謝謝。
發表於 2019-4-27 01:22:42 | 顯示全部樓層
jasonboy99 發表於 2019-4-26 12:21 AM
原來硬體有內建這種指令集,可以理解為何分成6/8鍵為一組AD。
學習到新知了,謝謝。 ...

這篇擴充多鍵(按鈕)輸入討論串,
有深入探討的價值與重要性...

1. 多鍵(按鈕)輸入
  條件: 類比輸入接腳(Analog Input Pin)

2. 分壓
pull low/high

3. 誤差與軟硬體配合
  誤差--線性/非線性/單bit區隔...

先寫下簡單的主要項目,再來補詳細說明...

評分

1

查看全部評分

發表於 2019-5-2 15:53:03 | 顯示全部樓層
本文章最後由 jason680 於 2019-5-2 04:03 PM 編輯
jason680 發表於 2019-4-27 01:22 AM
這篇擴充多鍵(按鈕)輸入討論串,
有深入探討的價值與重要性...


接下來,  今天討論 分壓 細部討論
1. 多鍵輸入 <==這個是條件就是要符合,應該不是太大問題...
2. 分壓  <==  今天討論重點---詳以下
3. 誤差與軟硬體配合  <==  待討論....

2. 分壓,以下分pull low與pull high來討論
  2A: pull low 接地電阻是固定值,每個按鈕電阻(Rvar)不同
    Vcc ---Rvar--+--Rfix---GND
  註: Rvar變動, Rfix(固定)接地. +為Vin分壓點
  分壓公式 Vin = Vcc * Rfix / (Rvar + Rfix)
   把 Rvar看成 Rfix的倍數
  例: Rfix = 1K,  Rvar=1K = 1倍* Rfix
   Rvar=2K = 2倍* Rfix,  Rvar = 500 = 0.5倍 * Rfix

   Rvar用 N * Rfix代入, 公式改為
   Vin = Vcc * Rfix / ( N* Rfix + Rfix)       ,Rfix提出來
   Vin = Vcc * Rfix / (Rfix*(N+1) )           ,Rfix消掉
   Vin = Vcc * 1 / (N+1)           ,Rfix消掉
  N = 10,    Vin = Vcc * 1/11
  N = 0.1,    Vin = Vcc * 1/1.1
  Pull Low小結:
   分壓結果最大值 約為 0.9Vcc (在N=0.1時)
   分壓結果最小值 約為 0.09Vcc (在N=10時)
   Rvar愈大,N愈大,分壓結果愈小

  2B: pull high
    Vcc ---Rfix--+--Rvar---GND
  註: Rvar變動, Rfix(固定)接Vcc. +為Vin分壓點
  分壓公式
   Vin = Vcc * Rvar / (Rvar + Rfix)

   一樣把 Rvar看成 Rfix的倍數
   Rvar用 N * Rfix代入, 公式改為
   Vin = Vcc * (N* Rfix) / (N* Rfix + Rfix)
   Vin = Vcc * N / (N +1)

  N = 10,    Vin = Vcc * 10/11
  N = 0.1,    Vin = Vcc * 0.1/1.1
  Pull Low小結:
   分壓結果最大值 約為 0.9Vcc (在N=10時)
   分壓結果最小值 約為 0.09Vcc (在N=0.1時)
   Rvar愈大,N愈大,分壓結果愈大


Pull High跟 Pull Low寫在一起
公式比較
pull high:   Vin = Vcc * N / (N +1)  , N愈大,Vin愈大,但差異愈差愈少
pull low:   Vin = Vcc * 1 / (N +1)   ,  N愈大,Vin愈小,差異也是愈差愈少

把Vcc移到左邊,用比率(百分比)表示,就可以簡化計算評估誤差問題
pull high:   Vin/Vcc =  N / (N +1)  
pull low:   Vin/Vcc = 1 / (N +1)  

註: 誤差問題,是之後才要詳細討論,在這裏先簡單說一下
當你做一片時,稍為費心調整一下軟硬體,可能就可以work
但如果要量產,對誤差沒有正確評估,可能怎麼調怎麼不對...

註: 誤差容許,如果太少只有2.X%, 一般電阻5%就不能用,
用1%的精密電阻,仍然可能讓人很頭大...
提問者寫的..."採樣還要額外容許正負5的誤差。"
正負5的誤差,大約只有5/1000 = +-0.5%
1%的精密電阻可能就把你的 正負5(0.5%)的誤差 吃掉了


提問者用的方法為 pull low,N大約在0.1到1之間(附圖 紅色框框)
最少差異只有2.6%,不到3%有點少...
附圖上,可以看出,採線性電阻分壓,但差異卻不是等比率...
不管1/(N+1)或N/(N+1)本來以為差異會不同,結果卻相同(藍色框框)...

pull_high_low.png

發表於 2019-5-31 16:39:54 | 顯示全部樓層
jason680 發表於 2019-5-2 03:53 PM
接下來,  今天討論 分壓 細部討論
1. 多鍵輸入

本來以為誤差應該就跟電阻本身誤差(5%或1%)差不多來算...
加上分壓後,誤差變化反而變小了,用一般電阻5%誤差就能有很好特性
電阻誤差加上串聯使用,使得整個ADC電路誤差計算
不是當初想的那樣,簡單用電阻誤差就可以知道...

用5%電阻,用最大誤差5%計算結果最大誤差1.21%
參考附圖 電阻誤差.png

評分

1

查看全部評分

 樓主| 發表於 2019-5-31 21:02:55 | 顯示全部樓層
本文章最後由 jasonboy99 於 2019-5-31 09:08 PM 編輯
jason680 發表於 2019-5-31 04:39 PM
本來以為誤差應該就跟電阻本身誤差(5%或1%)差不多來算...
加上分壓後,誤差變化反而變小了,用一般電阻5%誤 ...


您也太用心了,我的板子雖然畫好了但是還沒用上,
最近又修改了一下,整合後用3個pin控制10個按鍵和8個LED。

MWSnap372.jpg
發表於 2019-6-25 09:10:50 | 顯示全部樓層
含金量高的技術貼,讚
在arduino library manager以及 github上有不少此類應用並搭配 open source 函式庫可用,趕時間的話可直接拿來用,也可一並學習其作者的概念。
您需要登錄後才可以回帖 登錄 | 立即註冊

本版積分規則

關閉

站長小叮嚀上一條 /1 下一條

禁閉室|手機版|連繫我們|痞酷網電子技術論壇

GMT+8, 2024-4-23 08:48 PM , Processed in 0.099703 second(s), 22 queries , Gzip On.

Powered by Discuz! X3.4 Licensed

© 2001-2023 Discuz! Team.