星期四, 3月 27, 2014

Arduino 3鍵 Orange-skin 橘子皮電子琴

運用 Arduino 的 Capacitive Sensor 功能來製作 3 鍵電子琴,
感應平台使用橘子皮作為電子琴鍵



星期一, 3月 17, 2014

印表機出現 0x00000002 錯誤的解決方式

在 win 7 或 win 8 系統中印表機連線出現 0x0000002 錯誤,可以使用 [控制台]--[系統管理工具] -- [電腦管理]--[服務與應用程式] -- [服務] -- [print spooler],重新啟動

星期四, 3月 06, 2014

Arduino 測試電容量 Native Capacitive Sensors without additional Hardware

Native Capacitive Sensors without additional Hardware

You can create a touch-sensitive input on any of the Arduino's pins. It requires no special hardware, nevertheless a capacitor of 1nF is recommended in line with the pin to decouple 50Hz noises.
Connect a wire or some metallic plate to a pin.
The code works by setting the pin to ground, turning on the internal pull-up resistor, and measuring the time it takes for the pin to return to the HIGH state. If untouched readCapacitivePin returns a low value e.g. "1"; when touched it rises to about 5. By adding some comparision with a threshold you can make it a boolean key input.

DO NOT CONNECT ANY ACTIVE DRIVER TO THE USED PIN !

the pin is toggled to output mode to discharge the port, and if connected to a voltage source, will short circuit the pin, potentially damaging the Arduino and any hardware attached to the pin.
Original code by Mario Becker, Fraunhofer IGD, 2007http://www.igd.fhg.de/igd-a4
Updated by: Alan Chatham http://unojoy.tumblr.com
Updated by Paul Stoffregen: Replaced '328 specific code with portOutputRegister, etc for compatibility with Arduino Mega, Teensy, Sanguino and other boards
Gratuitous optimization to improve sensitivity by Casey Rodarmor.
Updated by Martin Renold: disable interrupts while measuring. This fixes the occasional too-low results.
Updated by InvScribe for Arduino Due.
With this function, you can call readCapacitivePin( pinNumber) and get a number from 0 to 17 corresponding to the level of capacitance on the pin - the number will be higher when you touch the pin.

// readCapacitivePin
//  Input: Arduino pin number
//  Output: A number, from 0 to 17 expressing
//  how much capacitance is on the pin
//  When you touch the pin, or whatever you have
//  attached to it, the number will get higher
#include "pins_arduino.h" // Arduino pre-1.0 needs this
uint8_t readCapacitivePin(int pinToMeasure) {
  // Variables used to translate from Arduino to AVR pin naming
  volatile uint8_t* port;
  volatile uint8_t* ddr;
  volatile uint8_t* pin;
  // Here we translate the input pin number from
  //  Arduino pin number to the AVR PORT, PIN, DDR,
  //  and which bit of those registers we care about.
  byte bitmask;
  port = portOutputRegister(digitalPinToPort(pinToMeasure));
  ddr = portModeRegister(digitalPinToPort(pinToMeasure));
  bitmask = digitalPinToBitMask(pinToMeasure);
  pin = portInputRegister(digitalPinToPort(pinToMeasure));
  // Discharge the pin first by setting it low and output
  *port &= ~(bitmask);
  *ddr  |= bitmask;
  delay(1);
  // Prevent the timer IRQ from disturbing our measurement
  noInterrupts();
  // Make the pin an input with the internal pull-up on
  *ddr &= ~(bitmask);
  *port |= bitmask;

  // Now see how long the pin to get pulled up. This manual unrolling of the loop
  // decreases the number of hardware cycles between each read of the pin,
  // thus increasing sensitivity.
  uint8_t cycles = 17;
       if (*pin & bitmask) { cycles =  0;}
  else if (*pin & bitmask) { cycles =  1;}
  else if (*pin & bitmask) { cycles =  2;}
  else if (*pin & bitmask) { cycles =  3;}
  else if (*pin & bitmask) { cycles =  4;}
  else if (*pin & bitmask) { cycles =  5;}
  else if (*pin & bitmask) { cycles =  6;}
  else if (*pin & bitmask) { cycles =  7;}
  else if (*pin & bitmask) { cycles =  8;}
  else if (*pin & bitmask) { cycles =  9;}
  else if (*pin & bitmask) { cycles = 10;}
  else if (*pin & bitmask) { cycles = 11;}
  else if (*pin & bitmask) { cycles = 12;}
  else if (*pin & bitmask) { cycles = 13;}
  else if (*pin & bitmask) { cycles = 14;}
  else if (*pin & bitmask) { cycles = 15;}
  else if (*pin & bitmask) { cycles = 16;}

  // End of timing-critical section
  interrupts();

  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to 
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  *port &= ~(bitmask);
  *ddr  |= bitmask;

  return cycles;
}

For Arduino Due

// readCapacitivePin
//  Input: Arduino pin number
//  Output: A number, from 0 to 17 expressing
//  how much capacitance is on the pin
//  When you touch the pin, or whatever you have
//  attached to it, the number will get higher
uint8_t readCapacitivePin(int pinToMeasure) {
  pinMode(pinToMeasure, OUTPUT);
  digitalWrite(pinToMeasure, LOW);
  delay(1);
  // Prevent the timer IRQ from disturbing our measurement
  noInterrupts();
  // Make the pin an input with the internal pull-up on
  pinMode(pinToMeasure, INPUT_PULLUP);

  // Now see how long the pin to get pulled up. This manual unrolling of the loop
  // decreases the number of hardware cycles between each read of the pin,
  // thus increasing sensitivity.
  uint8_t cycles = 17;
       if (digitalRead(pinToMeasure)) { cycles =  0;}
  else if (digitalRead(pinToMeasure)) { cycles =  1;}
  else if (digitalRead(pinToMeasure)) { cycles =  2;}
  else if (digitalRead(pinToMeasure)) { cycles =  3;}
  else if (digitalRead(pinToMeasure)) { cycles =  4;}
  else if (digitalRead(pinToMeasure)) { cycles =  5;}
  else if (digitalRead(pinToMeasure)) { cycles =  6;}
  else if (digitalRead(pinToMeasure)) { cycles =  7;}
  else if (digitalRead(pinToMeasure)) { cycles =  8;}
  else if (digitalRead(pinToMeasure)) { cycles =  9;}
  else if (digitalRead(pinToMeasure)) { cycles = 10;}
  else if (digitalRead(pinToMeasure)) { cycles = 11;}
  else if (digitalRead(pinToMeasure)) { cycles = 12;}
  else if (digitalRead(pinToMeasure)) { cycles = 13;}
  else if (digitalRead(pinToMeasure)) { cycles = 14;}
  else if (digitalRead(pinToMeasure)) { cycles = 15;}
  else if (digitalRead(pinToMeasure)) { cycles = 16;}

  // End of timing-critical section
  interrupts();

  // Discharge the pin again by setting it low and output
  //  It's important to leave the pins low if you want to 
  //  be able to touch more than 1 sensor at a time - if
  //  the sensor is left pulled high, when you touch
  //  two sensors, your body will transfer the charge between
  //  sensors.
  digitalWrite(pinToMeasure, LOW);
  pinMode(pinToMeasure, OUTPUT);

  return cycles;
}


  • 資料來源:
http://playground.arduino.cc/Code/CapacitiveSensor 

知識學習--電容式觸控使用者介面

運用電容式觸控方法來製作 Paper Piano for Arduino

使用 Arduino 的 capacitive sensing library 功能,結合人體手指電容來驅動鉛筆畫製好的紙鍵盤。

How it works

The capacitiveSensor method toggles a microcontroller send pin to a new state and then waits for the receive pin to change to the same state as the send pin. A variable is incremented inside a while loop to time the receive pin's state change. The method then reports the variable's value, which is in arbitrary units.
The physical setup includes a medium to high value (100 kilohm - 50 megohm) resistor between the send pin and the receive (sensor) pin. The receive pin is the sensor terminal. A wire connected to this pin with a piece of foil at the end makes a good sensor. For many applications, a more useful range of values is obtained if the sensor is covered with paper, plastic, or another insulating material, so that users do not actually touch the metal foil. Research has shown that a small capacitor (100 pF) or so from sensor pin to ground improves stability and repeatability.
When the send pin changes state, it will eventually change the state of the receive pin. The delay between the send pin changing and the receive pin changing is determined by an RC time constant, defined by R * C, where R is the value of the resistor and C is the capacitance at the receive pin, plus any other capacitance (e.g. human body interaction) present at the sensor (receive) pin. Adding small capacitor (20 - 400 pF) in parallel with the body capacitance, is highly desirable too, as it stabilizes the sensed readings.

============================================================

知識學習--利用現有資源建構電容式觸控使用者介面

2011/12/08-DIGITIMES企劃  

若嵌入式系統設計中已包含微控制器,為了節省成本,也許可以使用電容式觸控介面取代按鈕和距離感測器(proximity sensor)。電容式觸控介面可保持產品的美觀且具有時尚風潮感;無需外嵌的零件特性,也方便設計人員將觸控系統密封起來,保護內部元件,並實現簡潔俐落的控制面板。即使大多數嵌入式系統中的微控制器已包含用來實現電容式觸控感測功能的零件、例如距離感測器和觸控按鈕;但設計人員仍未能加以善用並實現電容式觸控感測介面。本文將提供下列幾種方法,協助設計人員利用系統現有資源,設計電容式觸控感測介面:
1. 僅利用微控制器內部類比數位轉換器(ADC)新增電容式觸控感測功能
2. 使用內部精密恆流源(precision current source)和類比數位轉換器測量電容
3. 藉助內嵌於微控制器I/O接腳的電容感測電路以及內建的計數器/計時器。

引言

電容式觸控感測介面因簡潔的單面板控制特性,除了讓產品設計更具美感之外,還有更高的可靠性和穩定性;在電容式觸控感測介面中沒有活動式零件,避免了接觸磨損或鏽蝕,也避免按鍵式按鈕可能發生的機械故障,有效延長產品壽命。觸控面板可以密封起來、不需直接暴露於空氣,能夠保護內部電子元件免受惡劣環境的干擾,比起覆膜技術更能延長產品使用年限。
圖1,感測器電容。
   
圖2-1,微控制器中的類比通道和ADC電路。

電容式觸控感測技術不需直接連結到電路板上,而是透過特定的材質來感應觸控的動作;甚至當作接近感測器(proximity sensor),當使用者靠近─而非觸碰時作即時反應。
由於許多系統和使用者介面的控制電路中已包含微控制器,只要經過設計,電容式感測器就可取代按鈕、滑動條和轉盤的功能,輕鬆降低系統成本和元件數量。電容式感測器就像電路板中的感應點(conductive pad),不需什麼成本卻可提供高度的可靠性。
當使用者觸碰面板表面時,電容觸控感測電路開始作用,形成接地電容,電容的一端為電路板上的感應點,另一端為使用者的手指。感應點本身就有寄生電容(parasitic capacitance)的存在,而把感應點和微控制器連接起來的電路板走線同樣也有寄生電容(CP)。寄生電容值將隨環境變化(諸如溫度和濕度)而改變。另外,圖1所示的兩個電容是並聯的,我們不能對它們同時進行測量。
使用者手指產生的電容(CF)取決於極板和手指的面積以及面板材料的厚度和介電係數(dielectric),如公式1所示。
其中:
●Cf 是使用者手指產生的電容
●ε0是自由空間的介電常數為8.85 × 10 −12
●εr是兩極間材料的介電係數
●A是兩極重疊區域的面積
●d是兩極之間的距離

所產生的電容量越大,檢測到觸碰或感應到手指接近就越容易。從公式1中,決定所產生電容的關鍵是:用於使用者介面面板的材料和材料的厚度;材料的選擇決定了介電係數,厚度決定了使用者手指和感應點之間的距離。增加感應點的面積對於電容的增加會有一定效果,但面積超過使用者手指面積後則無法再增加電容,因為公式中要求的是重疊區域的面積。不過,對於感應手指接近,感應點可設計地大一些,這樣不僅能輕鬆符合使用者的手指接觸位置,多出來的面積也可提高感應範圍。
出於機械構造的原因,介面面板上的支撐骨架,可能無法緊貼電路板。在電路板上安裝金屬彈簧而非感應點可以克服此一問題。彈簧應緊緊貼合在介面面板上的按鈕區域,填補面板與電路板之間的空隙,使用者手指的感應於是透過面板與彈簧連結。這一方法縮小了電容極板的間距,避免出現空氣間隙(airgap),空氣間隙可能顯著減弱回應的靈敏度。
電容式觸控介面將持續測量感應點的電容量,並追蹤由於環境逐步變化而導致的寄生電容量的變化,並隨時記錄這這種變動以作為判斷觸碰是否發生(例如 : 觸碰發生時電容量的改變所引起的頻率或電壓的變化)。

二、 電容式觸控的測量方法
可利用微控制器測量感應點電容的方法如下:
●電容分壓器(Capacitive Voltage Divider)
●充電時間量測(Charge Time Measurement)
●電容感測模組(Capacitive Sensing Module)

上述這3種方法都不需要外部元件;但微控制器需符合一些要求方能測量和解析電容。
電容分壓器(簡稱CVD)
此方法需要配備內部類比數位轉換器(ADC)的微控制器,目前大多數系統均符合此項要求。此方法使用ADC的內部取樣電容以及電路板上感應點的電容來產生的電容分壓效應,分壓的大小則視感測器的電容而定。先使用ADC測量此分壓,再由軟體進行處理。
正常工作期間,圖2-1中的類比多工電路(analog mux)用來選擇取樣電容的輸入腳位、多工器上方的接腳電壓允許取樣電容器在取樣時間(acquisition time)內充電至接腳電壓,接著採樣開關斷開,多工器切向底下的感測腳,取樣電容向感測器電容放電至一個平衡電位,ADC先轉換這時在取樣電容上的電壓值。
被指定為電容感測的微控制器接腳可被設定為數位I/O功能,藉此將取樣電容充電到VDD或放電至VSS。
這種測量方法需採取若干步驟,其中一些步驟的時機掌握非常重要,因為電容的洩漏和延遲將導致讀數漂移。
步驟一:首先要為測量初始化系統,我們需在系統中對電容進行適當的充放電。透過數位I/O腳的方式,我們可將未使用的接腳設定為High輸出此輸出可以透過內部的類比輸入到類比多工器做輸入Channel的選擇後對內部取樣電容器進行充電至VDD。同時,我們需要確保外部感測器的電容能徹底放電;因此,連接感測器的接腳被設定為Low輸出,將感測器接地以確保感測器的寄生電容能徹底放電到地電位(VSS)。類比多工電路和輸出的狀態可見圖2-2。
步驟二:一旦感測器電容已經放電,且取樣電容器已經充電至正電源電壓(VDD),將感測器的接腳上的輸出功能關閉並設定為ADC類比輸入功能,如圖2-3所示。這時,接腳至寄生電容的線路會浮動(floating)在那裡,寄生電容可透過接腳或電路板(board leakage)獲得一些微量電荷。正因如此,該步驟的時間應盡可能地縮短以減少誤差值。
步驟三:使用多工器切換連接到感測器的接腳,將使取樣電容與感測器並聯。因為這時的取樣電容充電至VDD,而感測器電容則完全放電。其結果就是電流從取樣電容流至感測器電容。類比多工器允許雙向電流,儘管其阻抗確實會導致一些電流耗損但對整體電位的引響還是很小的。
步驟四:因為這時這兩個電容在等效並聯電路裡,取樣電容的電荷會向寄生電容流動,這兩個電容最後會維持在一個相同的電壓,在系統穩定之後,類比數位之間的轉換啟動,採樣開關斷開,如圖2-4所示。緊接著即可測量取樣電容上的電壓。系統穩定所需的時間很短,轉換通常可以在下一條指令處就開始進行。
取樣電容上的電壓取決於感測器電容,若使用者手指對面板表面進行觸碰的話,感測器電容即為感測器寄生電容加上使用者手指電容之和。公式2-1可證明,電壓則由ADC測得。
其中:
• VChold 是由ADC測得的電壓
• Vdd 是微控制器電源電壓
• Chold 是取樣電容的電容,該受測元件顯示為10pF
• Cp 是感測器寄生電容
• Cf 是手指觸碰產生的電容
從公式2-1中我們可以看到,手指觸碰增加的電容將導致取樣電容上的電壓下降。ADC將輸出較低的轉換值。
讀數的解析度由ADC解析度來決定,因此建議使用10位元ADC;較低解析度的ADC雖然也可使用,但它將需要更明顯的電容量的改變─所以兩極間距需更小、介面面板也要更薄。因為測得的電壓通常要低很多,為了提高ADC解析度,可以使用比VDD更低的參考電壓來進行轉換。這個參考電壓的改變將增加每一位元所能夠解析的電壓值,但要小心避免飽和。飽和是指當被轉換電壓超過參考電壓,而 ADC只能以其最大輸出碼進行回應的情況。因為電容測量耗時很短,通常只要10-20µs,感測器就可進行過採樣(oversample),以便提高解析度。
上述是使用未佔用接腳對取樣電容進行充電的情況。但若要測量多個電容觸控感測器,連接另一感測器的接腳則可暫時借用來對取樣電容進行充電。用於輸入的感測器在未被測量的時候,因為涉及的電容小,並且數位輸出的輸出阻抗也較低,所以可將該輸入驅動為高電平。至ADC的任何內部參考電壓也可用來為取樣電容充電。
充電時間測量(CTMU)
一些微控制器會合併恆流源(constant current source)的設計,可為感測器電容在一定的時間內進行充電,如圖2-6所示為以恆流源充電的電壓測量結果,。
如公式2-2。使用者手指所產生、加上感測器的電容總和,將減少ADC測得的電壓。
其中:
• V 是ADC測得的電壓
• i 是來自恆流源的電流
• tcharge 是感測器充電的固定時間長度
• Chold 是取樣電容的電容值,該受測元件顯示為10pF
• Cp 是感測器的寄生電容
• Cf 是手指觸碰產生的電容
此方案使用ADC的類比多工電路(analog channel-select mux of the ADC),見圖2-7。來選擇微控制器的不同接腳。藉此掃描多個感測器,而且取樣電容充電時是與感測器電容並聯的,從而避免形成電容分壓器(capacitive voltage divider)。
在恆流源啟動之前,電容的電荷需為一個已知值。因此,可利用微控制器中的內部(internal gate)接地,將電容完全放電。在軟體中可調節恆流源以加速充電時間,從而允許在掃描多個感測器時進行快速測量。在Microchip多款接腳數較高的微控制器上都提供恆流源,這些微控制器也配備許多類比通道,允許安裝多個電容式感測器。
電容感測模組(CSM)
如圖2-8,許多新款的通用型微控制器還配備電容式感測模組,整合了用來感測電容的特殊電路。這些新款微控制器包含多輸入的類比多工電路(large analog mux),能夠對用於多按鈕介面的多個電容式感測器進行掃描;除了電容感測模組之外,此類微控制器也配備一對內建的計數器/計時器(Timer)。
模組根據較低和較高觸發點交替使用內部恆流源的流入和流出(sink)對感測器電容進行充放電,產生如圖2-9所示的波形。
電流源流入和流出之間的切換由模組自動處理,充/放電週期則取決於感測器電容─電容增加、週期也將拉長。

量測的方法會使用到一個計時器(Timer)和一個計數器(Counter),計時器提供一個基準時間作為計算頻率的依據,計數器則用來測量震盪器的頻率。在計時開始時將計數器歸零然後重新啟動,計時終了停止計數並讀取計數器的值,即可知道在該段時間內出現了多少次振盪。電容的增加,例如因為手指觸碰所導致的電容增加,會降低振盪頻率,導致記錄的讀數變小,如圖2-10所示。時間長度可由另一個計時器來控制,這個計時器還可以自動停止計算振盪次數,以釋出處理器的資源處理其他任務。時間的長度也可以利用來自看門狗計時器(WDT)的振盪器來計算,WDT的功耗極低,當CSM仍然在運作中並遞增計數器時,微控制器可以保持低功耗休眠模式,並由WDT週期性地喚醒微控制器,再利用軟體讀取並處理振盪次數。

為了處理不斷變化的電路寄生電容,我們需要記錄當前寄生電容的基準值(baseline value),而這通常由移動平均濾波器來對感測器的的讀值進行移動平均值的計算以過濾一些雜訊的干擾。由於可用的儲存空間有限,通常採用IIR的移動平均演算法,避免儲存太多過去採樣的值。

為了確定是否出現觸碰,把對感測器電容的最新測量值與基準值進行比較。如果差異大於設計的門檻,就認定確實出現觸碰,並交由軟體進一步處理。根據不同的應用,對測量後的值進行過濾或平均、而非直接使用電容測量所得的值。

電容式感測模組可用來感測物體接近及觸碰,因其工作原理是相同的;不同之處在於接近感測所需的兩極板之間距更大。透過增加測量時間,電容的變化將更小,暫態雜訊也將被消除。然而,測量時間也不能過長,因為延遲可能使得介面回應變的遲鈍。
對於接近感測,使用計數器/計時器測量一段時間內波形的振盪次數,可以提高解析度,並從而補償了兩極間距過大而不易感測的缺點。
三、 討論
電容式觸控感測(CSM)提供了諸多優點,實現了新型的人機交互介面。減少使用週邊元件例如滑動條等可增加系統可靠性,把使用者介面密封起來也可保障不受其工作環境的影響。如果在應用中採用微控制器,那麼利用電容式介面來替代各種開關則幾乎不會增加成本,因為只要加裝感應點即可。然而,電容式觸控感測可能對系統有另外的要求—例如對機械安裝和材料的介電質—以確保電容耦合的程度。
電容分壓器(CVD)和充電時間測量單元(CTMU)都提供了對電容的高速測量,但需要確定的時序,還有處理器以管理測量步驟。高速測量讓系統在大多數時間處於低功耗的休眠狀態,只需週期性地喚醒並測量用戶觸碰即可。電容分壓器善加結合ADC的優點,目前ADC目前已普遍存在於各種微控制器之中,對於大多數應用而言也是必須的功能;電容分壓器只需在很短時間內使用ADC週邊,設計人員易於將這兩者結合,並在大量系統中應用。而CTMU則是Microchip在許多高接腳數的元件裡的標準週邊。
電容式感測模組提供了較高解析度的測量,適用於接近感測,其測量方法是對一段時間內的若干振盪進行計數,移動平均演算法濾掉暫態雜訊。當微控制器處於低功耗休眠狀態時它也能工作,從而能夠減少電流消耗,但這種方法需要用到微控制器中的兩個內部計數器/計時器。(本文由Microchip提供)

參考來源:
1.Capacitive Sensing Library,  http://playground.arduino.cc//Main/CapacitiveSensor?from=Main.CapSense#.UxfHdT-PW-1







2.DIGITIMES中文網 原文網址: 利用現有資源建構電容式觸控使用者介面 http://www.digitimes.com.tw/tw/dt/n/shwnws.asp?CnlID=13&id=0000262383_JHD2DGH79LV7CB2GE8M28&ct=1&OneNewsPage=2&Page=1#ixzz2v8fyWByv