Search

2012年8月29日 星期三

Heartbeat Sensor

    前幾天看到這篇Arduino 心拍センサシールド感覺很有趣所以也來實做看看,原理是利用心臟收縮與擴張時血液流通使末梢組織的透明度發生變化,這時候將手指放上CNY70會因為這樣讓反射回來的紅外線有差異產生PWM,因此就可以靠產生的PWM測出心跳以及次數。

Part List :


  1. CNY70(或者其他種類的上照式光遮斷器)
  2. 紅色LED
  3. 10k Ohm可變電阻
  4. 220 Ohm電阻 X 2
  5. 4.7k Ohm電阻
  6. 1k Ohm電阻
  7. 100k Ohm電阻
  8. 1M Ohm電阻
  9. 0.1uF陶瓷、積層、無極性電解電容 X 2
  10. 1uF陶瓷、積層、無極性電解電容
  11. LM358雙運算放大器(我買到的上面寫HA17358,但是我發現不是所有運放都可以,例如NE5532、JRC4556AD就不行,所以這邊就用原本的358運放,可能還是要請有電子背景的朋友研究一下datasheet解答差別)

電路說明:

    左邊那個四腳的IC就是CNY70,將CNY70的紅外線發射(負極)與接收(射極)晶體接地,紅外線發射正極接上220Ohm的電阻再接上5V電源,接著將10k的可變電阻左端接上4.7k的電阻再接上5V電源分壓,然後右端接地,接著中間輸出腳(圖中黃色接線的部份)分別接上CNY70的接收晶體(集極)以及1uF的電容,並且將電容另一隻腳接到LM358的第三隻腳(正向輸入端),而這隻腳還要再接一個 100k的電阻接地,接著LM358的第二隻腳(反向輸入端)要接一個1k電阻接地,並且還要連接一個1M電阻與0.1uF電容到LM358的第一隻腳(輸出端)做回授,然後LM358的第四隻腳要接地,LM358的第八隻腳要接5V電源
並且要再接一個0.1uF電容接地消除雜訊,最後將LM358的第一隻腳(輸出端)分別接到一個220k的電阻與LED上(圖中綠色接線的部份)以及接到Arduino的Analog Pin 0(圖中紫色接線部份)。



程式:

    每秒取樣50次左右,並且確定積分值是否有達到形成PWM的程度來判斷是否有PWM,並且以每個PWM的波谷區隔每個波來更新心跳次數。


int sensor_pin = 0;
int n = 0;
int n_1 = 0;
int diff = 0;
int count = 0;
int elapse_up = 0;
int elapse_down = 0;
int integral_plus = 0;
int integral_minus = 0;

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

void loop()
{
  n = analogRead(sensor_pin); //取得現在得到的值
  diff = (n - n_1);           //將現在的值減去上次得到的值(N -(N-1))
  n_1 = n;                    //更新上一次的值

  //如果差值趨近零,則表示到達波谷又要進到新的一個PWM中。
  //並且在確定上個PWM的爬升(integral_plus)與下降(integral_minus)
  //是否有到達積分值來確定是否有PWM。
  //兩者成立則更新所有狀態。
  if(diff < 10 && diff > -10 &&
  integral_plus > 160 && integral_minus < -200){
    if(elapse_up > 50 && elapse_up < 400 &&
    elapse_down > 96 && elapse_down < 800){
      ++count;
      Serial.print(count);
      Serial.println(" Heartbeat");
    }
    elapse_up = 0;
    elapse_down = 0;
    integral_plus = 0;
    integral_minus = 0;
  }
  else if(diff > 20 && diff < 280){
    //PWM上升
    integral_plus += diff;
    elapse_up += 20;
  }
  else if(diff < -20 && diff > -200){
    //PWM下降
    integral_minus += diff;
    elapse_down += 20;
  }

  //每20ms取樣,即一秒取樣50次。
  delay(20);
}


DEMO:

    使用的時候要先調整10k可變電阻,將手指放上CNY70完全蓋住但是不能大力壓緊,接著觀察到LED會隨著心跳變動就可以了,如果不行則繼續調整可變電阻的分壓。


=============2012/09/17===============
最近有空把它Layout成板子,有+ -號那邊就是電源。






Simple Kalman Filter

    本來將這篇放到 Arduino - 使用 Wii Nunchuck後面算是針對單個角度值做一維的卡爾曼濾波的簡單應用,不過感覺放在後面有點亂所以還是另外開一篇,下次在寫多維卡爾曼濾波融合加速度計與陀螺儀的應用

   Kalman FIilter的應用最常見的地方在慣性導航系統中,比如四軸飛行器或者火箭以及SEGWAY平衡的PID值預測,OpenCV中也有個Kalman Filter,用來做物體追蹤預測位置或者速度,Kalman FIilter可以從前一個預測結果計算出現在的最佳結果以及下個結果,而Kalman FIilter光是線性與非線性版本就有很多種,維數的少到多與難度從簡單到複雜成正比,簡單的Kalman FIilter可以用來校正加速度計的角度之類的值,或者將陀螺儀的角速度積分後的值與加速度計的角度做Kalman FIilter後取最佳的角度,而簡化後的Simple Kalman Filter只有幾個計算跑在Arduino上也很容易。


Simple Kalman Filter:

    q是預測誤差、r是感測器誤差、k是卡爾曼增益、x用來紀錄狀態值、p直接取q與r的平方和開根號,接著隨著時間更新時,現在的結果會是上一個結果加上上一個結果和現在量測結果的差再乘以增益的值(x += k * (value - x);),而下一個結果預測的偏差值就可以將p乘上1 - k後的值在加上q預測誤差值得到下一個要修正的結果,如此把Covariance遞迴下去就可以一直計算出現在的最佳結果,而且只需要從上一個保存的結果推算。


#include <math.h>

class KalmanFilter
{
   public:

      KalmanFilter(double q,double r);
      double Update(double);
      double GetK(){return k;}

   private:

      double k; //kalman gain
      double p; //estimation error cvariance
      double q; //process noise cvariance
      double r; //measurement noise covariance
      double x; //value
};

KalmanFilter::KalmanFilter(double q,double r):q(q),r(r),x(0.0)
{
  p = sqrt(q * q + r * r);
}

double KalmanFilter::Update(double value)
{
   p += q;
   k = p / (p + r);
   x += k * (value - x);
   p *= (1 - k);

   return x;
}

Used:
 
    假設預測誤差為2,感測器測量誤差為1.5(這兩個值看情況調整)。

KalmanFilter kalman(2.0,1.5);
    然後將每次測量的值用Update更新取得修正結果即可,會發現得到修正的結果會比沒修正的結果變動幅度較為平滑。



void loop()
{
  double Angle = Accelerometer();
  double k_value = kalman.Update(Angle);
}


直接用兩個OpenGL View Port其中各有一個方塊,並將角度值直接帶入World Matrix直接套用矩陣旋轉公式去作矩陣轉換,而兩方塊放在同個畫面可以方便看非使用卡爾曼濾波(螢幕左)以及使用卡爾曼濾波(螢幕右)兩個方塊振動幅度的差別。


2012年8月16日 星期四

TDA1517

    兩個月前在某店看到TDA1517,因為長得很特別而且又是拆機品一個五元就買五個收藏,昨天晚上突然想到又拿出來查看看是做什麼用的,原來是6W小功放,而且Datasheet有使用電路,幫他加入一個VR調整音量之外其他都是他的設計,所以就畫了一個給電腦的小喇叭用,要注意的是下面那九個Pin的直排孔位是TDA1517的位置,靠近字體"IC1"的第一個孔位就是第一隻腳,個人上12V DC的電壓是不會太燙感覺不需要幫TDA1517安裝散熱片,如果太燙在安裝就好,整組做起來不會超過五十元,大約比NE5532AP多一點,所以拿來推推小喇叭不錯用。

Part List:

  1. IC1:TDA1517
  2. C1、C5:0.22uF/63v 金屬皮膜電容
  3. C2:2200uF/25v 有極性電解電容
  4. C3:0.1uF/63v 金屬皮膜電容
  5. C4:100uF/35v 有極性電解電容
  6. C6、C7:1000uF/10v 有極性電解電容
  7. DC:2.1mm DC Jack
  8. 其他:雙連VR 10k Ohm X 1、3.5mm耳機座 X 2



完成正面





完成反面