2018年11月22日 星期四

HackRF 測試 PiFmRds 讓 Raspberry Pi 變身成為廣播電台

    在台灣未經NCC許可發射無線電波是非法行為 !!

警告和免責聲明

     PiFmRds一個的英文實驗程序,僅用於實驗。它決不要的英文個人成為媒體中心或操作無線電台的工具,甚至不能將音頻廣播到自己的立體聲系統。
     在大多數國家,沒有國家頒發的特定於傳輸方式(頻率,功率,帶寬等)的許可證,無線電發送波的英文非法的。
      因此,總是從樹莓派的屏蔽傳輸線直接連接到無線電接收器,從而不發射無線電波。切勿使用天線。
      即使您是有執照的業餘無線電運營商,使用PiFmRds在火腿頻率上傳輸無線電波而樹莓派與天線之間沒有任何濾波也很可能是非法的,因為方波載波的諧波非常豐富,因此可能帶寬要求很高沒見過。
     對於任何濫用您自己的Raspberry Pi的行為,我都不承擔任何責任。任何實驗都由您自己負責。

 PiFmRds  是開源的程式,程式與使用方法在這裡都有,這裡只做一點實際安裝過程的紀錄。

    https://github.com/ChristopheJacquet/PiFmRds

PI-FM-RDS 需要 sndfile 程式庫。

sudo apt-get install libsndfile1-dev

開始安裝PiFmRds

git clone https://github.com/ChristopheJacquet/PiFmRds.git

cd PiFmRds/src

make clean

make

PC上打開 SDR_Radio 我的所在地107.7Mhz 發現有個電台。


Raspberry Pi 執行,預設PiFmRds 發射頻率是107.9Mhz

sudo ./pi_fm_rds

PiFmRds 執行後可在  SDR_Radio 上看到107.9Mhz有RF訊號。


 為了不干擾電台將發射訊號移到 107.3 Mhz

sudo ./pi_fm_rds -freq 107.3 -audio sound.wav

 SDR_Radio 上看到107.3Mhz有RF載波訊號,PC上可以聽到聲音。


PiFmRds語法:

pi_fm_rds [-freq freq] [-audio file] [-ppm ppm_error] [-pi pi_code] [-ps ps_text] [-rt rt_text]

所有參數都是可選的:

-freq指定載波頻率(以MHz為單位)。例如:-freq 107.9。

-audio指定要作為音頻播放的音頻檔案。取樣率無關緊要:PI_FM_RDS會重新編輯取樣並對其進行過濾。如果提供立體聲檔案,PI-FM-RDS將產生FM立體聲信號。示例:-audio sound.wav。支持的格式取決於libsndfile。這包括WAV和Ogg / Vorbis(以及其他),但不包括MP3。

-pi指定RDS廣播的PI代碼.4個十六進制數字。例如:-pi FFFF。

-ps指定RDS廣播的電台名稱(節目服務名稱,PS)。限制:8個字符。例如:-ps RASP-PI。

-rt指定要傳輸的無線電文本(RT)。限制:64個字符。例如:-rt 'Hello, world!'。

-ctl 指定一個命名管道(FIFO),用作控制通道,在執行時更改PS和RT。

-ppm 以百萬分(ppm)表示您的Raspberry Pi振盪器誤差。

 預設情況下,PS在Pi-FmRds序列號之間來回顯示,從...開始00000000。PS每秒變化一次。


2018年11月20日 星期二

HackRF One 開箱

  
    HackRF One 不是甚麼新產品個人現在才有時間玩,HackRF One 只是SDR(Software Defined Radio)一個前端工具,SDR (軟體無線電)是一種實現無線通訊的新概念和體制。其中已在硬體被典型地實現的組件(例如混頻器,濾波器,放大器,調變器 / 解調器,檢測器等),也可以通過軟體手段的個人計算機上或代替實施嵌入式系統。一開始應用在軍事領域,在21世紀初,由於眾多公司的努力,使得它已從軍事領域轉向民用領域,成為經濟的、應用廣泛的、全球通訊的第三代行動通訊系統的戰略基礎。

HackRF One

     HackRF One 是一款軟體定義無線電(SDR, Software Defined Radio) 設備,可發送/接收 1MHz 到 6GHz 的無線電信號。
     HackRF One 被用在現代和下一代無線電技術的測試和開發,是一個開源硬體平台,可用作 USB 外接設備獨立運行

HackRF One 規格

1 MHz 到 6 GHz 工作頻率
半雙工
取樣高達每秒2000萬次
8-bit quadrature samples (8-bit I and 8-bit Q)
相容GNU Radio, SDR# 等
Software-configurable RX and TX gain and baseband filter
Software-controlled antenna port power (50 mA at 3.3 V)
SMA female antenna connector
SMA female clock input and output for synchronization
Convenient buttons for programming
Internal pin headers for expansion
USB 2.0
USB 供電
開源硬體

HackRF One 包裝




HackRF One內容物

 

使用 SH789 測試 HackRF One

裝好天線後的 HackRF One


    使用windows 10 HackRF One 不用裝驅動程式,使用windows 7 需下載 libwdi USB驅動程式。驅動程式連結

https://sourceforge.net/projects/libwdi/files/zadig/

SDR 應用程式CubicSDR

       CubicSDR是一個跨平台的軟體定義無線電應用程式,它允許您導航無線電頻譜並解調您可能發現的任何信號。它目前包括幾種常見的類比解調方式,如AM和FM,並將在未來支持數位模式。現在有許多數位解碼應用可以使用類比輸出來處理數位信號,方法是使用Soundflower,Jack Audio或VBCable等軟體將數據從CubicSDR“管道”到另一個程序。

     CubicSDR支持隨時可用的RTL-SDR,這是一種價格低廉的SDR設備,。此外,CubicSDR現在包括對SDRPlay,HackRF,BladeRF,AirSpy,NetSDR +,Red Pitaya,音頻設備(目前某些特定平台)或具有可用SoapySDR支持模組的任何其他設備的支援。CubicSDR下載位置

https://cubicsdr.com/

CubicSDR 執行畫面


SDR 應用程式  Sdr-radio V3

      Sdr-radio V3 功能多使用需要多花點時間學習,Sdr-radio V3 與 Sdr-radio V2 是獨立的兩套軟體可以裝在同一台電腦部會互相衝突。下載位置

https://www.sdr-radio.com/Software/Downloads

Sdr-radio V3 執行畫面

SDR 應用程式  HDSDR

  HDSDR 功能強大會比Sdr-radio 好學一點。

http://www.hdsdr.de/

 HDSDR 使用 HackRf 需另外下載 extio hackrf.dll 放在HDSDR安裝後的檔案夾。

https://github.com/jocover/ExtIO_HackRF/releases

HDSDR 執行畫面

2017年5月13日 星期六

PSoC 5LP - CY8CKIT-059 + SD112-45-11-221 光電二極體(PD)

     光電二極體與常規的半導體二極體基本相似,只是光電二極體可以直接暴露在光源附近或通過透明小窗、光導纖維封裝,來允許光到達這種器件的光敏感區域來檢測光訊號。許多用來設計光電二極體的二極體使用了一個PIN結,而不是一般的PN接面,來增加器件對訊號的響應速度。光電二極體常常被設計為工作在逆向偏壓狀態。
   一個光電二極體的基礎結構通常是一個PN接面或者PIN結。當一個具有充足能量的光子衝擊到二極體上,它將激發一個電子,從而產生自由電子(同時有一個帶正電的電洞)。這樣的機制也被稱作是內光電效應。如果光子的吸收發生在結的空乏層,則該區域的內電場將會消除其間的屏障,使得電洞能夠向著陽極的方向運動,電子向著陰極的方向運動,於是光電流就產生了。實際的光電流是暗電流和光照產生電流的綜合,因此暗電流必須被最小化來提高器件對光的靈敏度。

   SD112-45-11-221 內含放大器的光電二極體單顆報價80USD算是超級貴的基礎元件。

   PSoC 5LP 內建20Bit的 Delta-Sigma ADC, Delta-Sigma ADC 由微分器、積分器構成的ΔΣ調變電路,會因其微分特性而對量化雜訊(Quantization noise)產生一種高通濾波的效果。一般線性PCM中產生的量化雜訊平均分布在各頻率上,基於前述特性,可以將量化雜訊推往高頻,而產生noise shaping功效。將取樣頻率設高,則人耳可聽到的頻段相對低頻,此時將已經被推往高頻的量化雜訊以低通濾波器濾除,則可以得到量化雜訊較少的原訊號。

SD112-45-11-221



SD112-45-11-221  接腳圖

SD112-45-11-221  需要負電源,我使用LMC7660 把+5V轉換成-5V


PSoC 5LP  規劃內部線路


PSoC 5LP  ADC_Delsig_1 設定


PSoC 5LP 接腳設定,A_in 接 SD112-45-11-221 ,A_in2接地線。


Main 程式碼


#include <project.h>
#include <TFT.h>
#include <device.h>
#include <stdio.h>                    

extern uint16_t MAX_X, MAX_Y ;        

#if defined (__GNUC__)

    asm (".global _printf_float");
#endif

int main()
{
 
    int16 output;
char8 str[10];
 
    SPIM_Start();
 
    ADC_DelSig_1_Start();

    ADC_DelSig_1_StartConvert();
 
 
    TFT_Init(1);
    TFT_FillScreen(0, MAX_X, 0, MAX_Y, BLACK);
    TFT_DrawString("ADC_Output",  0, 0, 2, GREEN);
 
for(;;)
    {
        if(ADC_DelSig_1_IsEndConversion(ADC_DelSig_1_RETURN_STATUS))
        {
            output = ADC_DelSig_1_GetResult16();
output = ADC_DelSig_1_CountsTo_mVolts(output) ;
sprintf(str, "%d mV", output);

TFT_DrawString("         ",1,0,2,RED);
            TFT_DrawString(str,1,32,2,RED);
CyDelay(1000u);
            TFT_FillRectangle(0,  32,   320,    64, BLACK);
        }
 
    }
}
/* [] END OF FILE */

上傳到後PSoC 5LP - CY8CKIT-059就會開始顯示光度值,SD112-45-11-221 的RG高達600Mohm 一般亮度夏一定爆表!!

這是閱讀的亮度下,這已經是超過飽和值。


白天關燈後還是爆表。


關燈再用罩子罩住還會有1.4V輸出。

PSoC 5LP 的 Delta-Sigma ADC 的確可抑制雜訊。

Teensyduino (筆記 4 ) Teensy 3.6 BPW21R 光電二極體(PD)

****軟體使用 Teensyduino  1.36  + Arduino 1.82 ********

    光電二極體與常規的半導體二極體基本相似,只是光電二極體可以直接暴露在光源附近或通過透明小窗、光導纖維封裝,來允許光到達這種器件的光敏感區域來檢測光訊號。許多用來設計光電二極體的二極體使用了一個PIN結,而不是一般的PN接面,來增加器件對訊號的響應速度。光電二極體常常被設計為工作在逆向偏壓狀態。
   一個光電二極體的基礎結構通常是一個PN接面或者PIN結。當一個具有充足能量的光子衝擊到二極體上,它將激發一個電子,從而產生自由電子(同時有一個帶正電的電洞)。這樣的機制也被稱作是內光電效應。如果光子的吸收發生在結的空乏層,則該區域的內電場將會消除其間的屏障,使得電洞能夠向著陽極的方向運動,電子向著陰極的方向運動,於是光電流就產生了。實際的光電流是暗電流和光照產生電流的綜合,因此暗電流必須被最小化來提高器件對光的靈敏度。

 這是BPW21R 的照片現在半導體這樣亮晶晶的包裝不多了


     Teensy 3.6 內部有16Bit 的ADC預設滿檔位3.3v的狀況下提供了65536的分辨率,比Arduino的10Bit 的1024高出許多。

電路圖



/****以下是程式碼****/

#include <Adafruit_GFX.h>
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_ILI9341.h>

#include <ADC.h>

int readPin = A0; // ADC0

ADC *adc = new ADC();; // adc object

#define TFT_RST   24       //LCM  接腳
#define TFT_DC    25
#define TFT_CS    26
#define TFT_MOSI  27
#define TFT_MISO  28
#define TFT_CLK   29

Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_MOSI, TFT_CLK, TFT_RST, TFT_MISO);

void setup() {

    pinMode(readPin, INPUT);
    
    tft.begin();                                          //LCM 啟始
    tft.fillScreen(ILI9341_BLACK);      //LCM 畫面更新為黑色
    tft.setRotation(1);                             // LCM 旋轉90度

    adc->setAveraging(64); // set number of averages
    adc->setResolution(16); // set bits of resolution

    adc->setConversionSpeed(ADC_CONVERSION_SPEED::VERY_LOW_SPEED); // change the conversion speed
    adc->setSamplingSpeed(ADC_SAMPLING_SPEED::VERY_LOW_SPEED); // change the sampling speed
    delay(500);
}

int value = 0;
int pin=0;

void loop() {

    value = adc->adc0->analogRead(readPin); // read a new value, will return ADC_ERROR_VALUE if the comparison is false.
    tft.setCursor(0,0);
    tft.setTextSize(2);
    tft.fillRect(0,0,320,40,0);
    tft.print("Value: ");
    tft.print(value*3.3/adc->getMaxValue(ADC_0), DEC);
    
    delay(1000);

}

上傳到Teensy 3.6後 就會開始顯示光電二極體偵測到的亮度值,因為這設計是要低照度下還能做線性檢出在一般亮度下一定爆表,如果應用在一般亮度須更改放大器的放大倍率!!

這是關燈後的照片感測電路還可輸出1.4V左右


這是開燈後的照片,改測器輸出已經是滿檔的3.2V。


Teensy3.6雖然有16Bit的ADC但是在麵包版上雜訊等問題能達到12Bit的穩定度就很好了。

2017年5月9日 星期二

Raspberry Pi 3 ( 10 ) OpenCV 動態人臉偵測

 Raspberry Pi 3 ( 10 )   OpenCV   動態人臉偵測

     人臉偵測的第一個想到的當然是手機,現在手機、數位相機對人臉的偵測已經是非常普及了,問題是這技術是別人的。OpenCV也提供人臉辨識的資料庫可以讓初學者測試學習。這次就用Raspberry Pi3 + PicameraV2做實驗。

Raspberry Camera


PiCamera 接入Raspberry Pi3


  接下來就先更新一下Rasoberry 。$ 不要輸入!!

$ sudo apt-get update
$ sudo apt-gat upgrade

 再來鳩開啟Rasoberry設定。


將Camera 開啟


先測試一下Canera 是否正常運作。
$ raspistill -o output.jpg


在跟目錄會有一個Test.jpg的檔案。


Test.jpg 就是剛剛照下來的照片。


上一篇我我OpenCV & Python 是安裝在虛擬環境中要再安裝其他的模組也要回虛擬環境。

$ source ~/.profile
$ workon cv
注意提示符號前面會有cv

安裝Picamera 注意要加 array 

$ pip install "picamera[array]"

在這裡有Opencv 有提供建立好的臉部與眼睛 xml 檔案,建議全部下載下來下次可使用。

https://github.com/opencv/opencv/tree/master/data/haarcascades

 把haarcascades的目錄名稱改成face,在這目錄底下建立一個新的文字檔案命名為 face.py。

以下是face.py 的內容,個人慘痛經驗是用文字編輯器比Python 的IDE好用,Python 不能有多的空格!!縮牌要使用 tab 鍵。

#  以下是Python 程式 ***這一行不要拷貝進程式裡******

#-*-coding:cp950-*-

#上一行是讓 Python 能用中文註解

from picamera.array import PiRGBArray
from picamera import PiCamera
import cv2
import time

#設定攝影機
camera = PiCamera()
camera.resolution = (640, 480)
camera.framerate = 30
rawCapture = PiRGBArray(camera, size=(640, 480))

#新視窗命名為Faces
display_window = cv2.namedWindow("Faces")

#載入臉部特徵模組
face_cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

time.sleep(0.1)

for frame in camera.capture_continuous(rawCapture, format="bgr", use_video_port=True):

    image = frame.array

    #臉部辨識
    gray = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)
    faces = face_cascade.detectMultiScale(gray, 1.1, 5)
    for (x,y,w,h) in faces:
        cv2.rectangle(image,(x,y),(x+w,y+h),(255,0,0),2)

    #輸出影像
    cv2.imshow("Faces", image)

    key = cv2.waitKey(1)

    rawCapture.truncate(0)

    if key == ord("q"): # Press 'q' to quit
        break

#  以上是Python 程式 ***這一行不要拷貝進程式裡******

    把整個face目錄用WinSCP傳到Raspberry,用WinSCP對於習慣用Windows的我最大的好處是可以直接編輯Raspberry內的文字檔。


在Raspberry 的終端機輸入
$ cd face
$ Python face.py
Raspberry 就會開啟一個名稱為Faces的視窗,當人臉出現時就會框起來。


以上這段程式是實際測試過的。

2017年5月3日 星期三

Arduino MQ-3 MQ-4 MQ-8 氣體感測器

     MQ 系列感測器又稱為半導體式感測器一般都是用二氧化錫(SnO2) 為基材,二氧化錫在清潔空氣中(含80的氮氣20%的氧氣與少許CO2)導電率非常低,氧化物特點就是本身的活性常低,可長時間保持在同一種狀態,MQ系列感測器壽命可超過20年,二氧化錫(SnO2) 在可燃氣體的催化導電率會升高。MQ系列的結構如下 H 是加溫結構,在加溫後活性氣體通過二氧化錫(SnO2) 時就會改變導電率,只要監測導電率就能判別氣體濃度。

   這是Winsensor 出品的 MQ8 感測器的導電率曲線,MQ8是針對氫氣開發出來的感測器,這圖表能看到紅色的空氣不管濃度多高都不會影響MQ8的導電率,氫氣濃度增加時導電率也會跟著升高,其他顏色是所謂的干擾氣體,也就是乙醇、一氧化碳、甲烷等都會干擾到MQ8的導電率。

下圖是MQ8的溫溼度與導電率的曲線,由此表可看出溫度濕度會影響MQ8的導電率。


   這張圖表是指出當氣體濃度增加時感測器輸出的電壓值,在這張圖表可發現當氣體濃度增加到300ppm後曲線開始平緩到1500ppm時幾乎快成直線。


這是反應時間曲線。

   這是時間變化曲線,把MQ8放在300ppm濃度的氫氣下的輸出電壓變化,由此圖再配合輸出電壓曲線可知MQ8的在300ppm後幾乎不可使用。
 MQ 系列雖然在高濃度時超級不準確但是還有以下優點

1.壽命超長
2.使用簡單
3.價格便宜

     也就是有以上這些優點MQ系列感測器大量應用在氣體洩漏、煙霧感測警報器,這些本來自然界就不該存在的氣體一但洩漏在空氣中超過200ppm~300ppm就發出警報很多人都能接受,只是要拿來當定量使用幾乎不太可能,以下的程式還是照著Datasheet 的曲線期望解出MQ系列的濃度曲線,注意這只是理論!!在上圖MQ8的輸出曲線可得知當超過1500ppm後的電壓變化輸入到只有10bit A/D 轉換器的Arduino根本沒意義。


// 載入 LCD  Library
#include <LiquidCrystal.h>

//      LCD 接腳:  rs, enable, d4, d5, d6, d7
LiquidCrystal  lcd(13, 12, 11, 10 , 9, 8);

/********************* 硬體設定  *************************************/

#define         MQ_3_PIN                         (0)     // MQ_3 輸入腳
#define         MQ_8_PIN                         (1)     // MQ_8 輸入腳
#define         MQ_4_PIN                         (2)     // MQ_4 輸入腳
#define         RL_VALUE                         (5)    // RL電阻為 10K歐姆
#define         MQ_3_Ro_CLEAN_AIR_FACTOR         (1)    //MQ_3在乾淨空氣中的電阻/MQ_3_Ro,
#define         MQ_8_Ro_CLEAN_AIR_FACTOR         (1)    //MQ_8在乾淨空氣中的電阻/MQ_8_Ro,
#define         MQ_4_Ro_CLEAN_AIR_FACTOR         (1)    //MQ_4在乾淨空氣中的電阻/MQ_4_Ro,
                                                   

/*********************** 軟體設定  ************************************/

#define         CALIBARAION_SAMPLE_TIMES     (50)    //設定校準時樣品讀取次數
#define         CALIBRATION_SAMPLE_INTERVAL  (100)   //設定較準時每次讀取採樣的時間間隔(ms)
                                                   
#define         READ_SAMPLE_INTERVAL         (50)    //測試時用幾次的檢測值的平均值
#define         READ_SAMPLE_TIMES            (5)         //測試時每次取樣的間隔時間(ms)
                                         
#define         GAS_Alcohol                  (0)
#define         GAS_H2                       (1)
#define         GAS_CH4                      (2)

/*****************************Globals***********************************************/

float           AlcoholCurve[3]   =  {1.7, -0.77,-1};      // 這斜率參考MQ-3的 Datasheet
                                                                                 
float           MQ_3_Ro           =  10;                           //MQ_3_Ro 的預設值

float           H2Curve[3]        =  {2, -0.6,-1};         // 這斜率參考MQ-8的 Datasheet
                                                                         
float           MQ_8_Ro           =  10;                       //MQ_8_Ro 的預設值

float           CH4Curve[3]       =  {2.48, -0.62,-0.4};   // 這斜率參考MQ-4的 Datasheet
                                                         

float           MQ_4_Ro           =  10;                    //MQ_4_Ro 的預設值


void setup()
{
  lcd.begin(20, 4);                                   //設定 LCM 為 20*4
  lcd.print("Calibrating..");                         //LCM 輸出 Calibrating...
  MQ_3_Ro = MQ_3Calibration(MQ_3_PIN);                //開機校正要確保這段時間內為乾淨空氣
  MQ_8_Ro = MQ_8Calibration(MQ_8_PIN);                //開機校正要確保這段時間內為乾淨空氣
  MQ_4_Ro = MQ_4Calibration(MQ_4_PIN);                //開機校正要確保這段時間內為乾淨空氣
}

void loop()
{
lcd.setCursor(0, 0);                                                 // LCM 游標移到位置 0,0
   lcd.print("Alcohol: ");                                           //顯示文字 Alcohol
   lcd.setCursor(8,0);                                               //LCM 游標移到位置 8,0
   lcd.print(MQ_3GetGasPercentage(MQ_3Read(MQ_3_PIN)/MQ_3_Ro,GAS_Alcohol )); //顯示測到的Alcohol值
   lcd.print(" ppm     ");                                           //LCM 顯示 PPm
   lcd.setCursor(0, 1);                                                 // LCM 游標移到位置 0,0
   lcd.print("  H2  :  ");                                           //顯示文字 H2
   lcd.setCursor(8,1);                                             //LCM 游標移到位置 8,0
   lcd.print(MQ_8GetGasPercentage(MQ_8Read(MQ_8_PIN)/MQ_8_Ro,GAS_H2 )); //顯示測到的H2值
   lcd.print(" ppm     ");                                           //LCM 顯示 PPm
   lcd.setCursor(0, 2);                                                 // LCM 游標移到位置 0,0
   lcd.print("  CH4 :  ");                                           //顯示文字 CH4
   lcd.setCursor(8,2);                                               //LCM 游標移到位置 8,0
   lcd.print(MQ_4GetGasPercentage(MQ_4Read(MQ_4_PIN)/MQ_4_Ro,GAS_CH4 )); //顯示測到的CH4值
   lcd.print(" ppm     ");                                           //LCM 顯示 PPm
   delay(1000);
}

/****************** MQ_Sensor 電阻值換算 ****************************************/



 float MQ_3ResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}

float MQ_8ResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));

}

float MQ_4ResistanceCalculation(int raw_adc)
{
  return ( ((float)RL_VALUE*(1023-raw_adc)/raw_adc));
}

/***************************** MQ_Sensor 校正 ****************************************/

float MQ_3Calibration(int MQ_3_pin)
{
  int i;
  float val=0;

  for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {          
    val += MQ_3ResistanceCalculation(analogRead(MQ_3_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val/CALIBARAION_SAMPLE_TIMES;                

  val = val/MQ_3_Ro_CLEAN_AIR_FACTOR;                      

  return val;
}

float MQ_8Calibration(int MQ_8_pin)
{
  int i;
  float val=0;

  for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {          
    val += MQ_8ResistanceCalculation(analogRead(MQ_8_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val/CALIBARAION_SAMPLE_TIMES;                

  val = val/MQ_8_Ro_CLEAN_AIR_FACTOR;                      

  return val;
}

float MQ_4Calibration(int MQ_4_pin)
{
  int i;
  float val=0;

  for (i=0;i<CALIBARAION_SAMPLE_TIMES;i++) {          
    val += MQ_4ResistanceCalculation(analogRead(MQ_4_pin));
    delay(CALIBRATION_SAMPLE_INTERVAL);
  }
  val = val/CALIBARAION_SAMPLE_TIMES;                

  val = val/MQ_4_Ro_CLEAN_AIR_FACTOR;                      

  return val;
}


/*****************************  MQ_Sensor 讀取*********************************************/


 float MQ_3Read(int MQ_3_pin)
{
  int i;
  float rs=0;

  for (i=0;i<READ_SAMPLE_TIMES;i++) {
    rs += MQ_3ResistanceCalculation(analogRead(MQ_3_pin));
    delay(READ_SAMPLE_INTERVAL);
  }

  rs = rs/READ_SAMPLE_TIMES;

  return rs;
}

float MQ_8Read(int MQ_8_pin)
{
  int i;
  float rs=0;

  for (i=0;i<READ_SAMPLE_TIMES;i++) {
    rs += MQ_8ResistanceCalculation(analogRead(MQ_8_pin));
    delay(READ_SAMPLE_INTERVAL);
  }

  rs = rs/READ_SAMPLE_TIMES;

  return rs;
}

float MQ_4Read(int MQ_4_pin)
{
  int i;
  float rs=0;

  for (i=0;i<READ_SAMPLE_TIMES;i++) {
    rs += MQ_4ResistanceCalculation(analogRead(MQ_4_pin));
    delay(READ_SAMPLE_INTERVAL);
  }

  rs = rs/READ_SAMPLE_TIMES;

  return rs;
}

/*****************************  MQ_Sensor 換算ppm **********************************/


int MQ_3GetGasPercentage(float rs_MQ_3_Ro_ratio, int gas_id)
{
  if ( gas_id == GAS_Alcohol) {
     return MQ_3GetPercentage(rs_MQ_3_Ro_ratio,AlcoholCurve);
  }
  return 0;
}

int MQ_8GetGasPercentage(float rs_MQ_8_Ro_ratio, int gas_id)
{
  if ( gas_id == GAS_H2) {
     return MQ_8GetPercentage(rs_MQ_8_Ro_ratio,H2Curve);
  }
  return 0;
}


int MQ_4GetGasPercentage(float rs_MQ_4_Ro_ratio, int gas_id)
{
  if ( gas_id == GAS_CH4) {
     return MQ_4GetPercentage(rs_MQ_4_Ro_ratio,CH4Curve);
  }
  return 0;
}

/*****************************   計算RS MQ_Ro 百分比  **********************************/


int  MQ_3GetPercentage(float rs_MQ_3_Ro_ratio, float *pcurve)
{
  return (pow(10,( ((log(rs_MQ_3_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}

int  MQ_8GetPercentage(float rs_MQ_8_Ro_ratio, float *pcurve)
{
  return (pow(10,( ((log(rs_MQ_8_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}


int  MQ_4GetPercentage(float rs_MQ_4_Ro_ratio, float *pcurve)
{
  return (pow(10,( ((log(rs_MQ_4_Ro_ratio)-pcurve[1])/pcurve[2]) + pcurve[0])));
}


上傳後就會顯示個感測器的值,注意這是沒校正過的只能當參考 !!


     當然還有其他氣體感測器可選擇,比如有比較好的高濃度曲線的平面半導體製程MP系列,催化燃燒的MC系列,幾乎可線性輸出的電化學系列,還有使元紅外線的NDIR技術。會常用來半定量使用的是電化學與NDIR技術,只是電化學感測器(NT$ 1500~4000 )壽命只有兩年!!不管有沒有使用出廠後就只有兩年壽命,NDIR技術雖然貴一點(NT$ 3000~5000 ) 可用5年,MQ售價只要 NT$ 50~3002。

Raspberry CM3 (一) 安裝 Raspbian Jessie Lite

        CM3採用最高時脈為1.2GHz的BCM2837處理器與1GB記憶體,CPU效能為CM1的10倍,記憶體容量則是兩倍,可執行基於Windows 10的IoT Core,適用於採用Raspberry Pi 3的IoT專案。為了迎合客戶的需要,CM3提供了CM3與CM3 Lite兩種版本,前者內建4GB eMMC的快閃儲存空間,後者則讓使用者根據儲存需求自行安裝SD卡。



    Raspberry CM3 的研發模組,比前一代多了SD卡曹方便沒eMMC的CM3 Lite 使用,使用CM3版本時 SD 不能使用。



Raspberry CM3 沒SD卡須要到這裡下載導引程式。

https://www.raspberrypi.org/documentation/hardware/computemodule/cm-emmc-flashing.md



下載後就安裝



    安裝好後就可插入電源與電腦USB,白色線是 IO BOARD 的電源紅色是連入電腦USB,要注意 IO BOARD 上J4跳線要在EN位置!!


正常狀況電腦會辨識出BCM2710 Boot。


如果電腦辨識出數不明裝置,個人的實驗結果是換掉CM3與電腦連接的USB線就可。


再來就執行剛剛安裝的RPi Boot。


執行RPi Boot 後會出現一個磁碟機,不用急著格式化就按取消就好。


下載 Raspbian Jessie Lite ,CM3 容量只有4GB  完整 Raspbian Jessie 會超過4GB 只能安裝Raspbian Jessie Lite。



    下載好後就開啟 Win32 Disk Imager 將 Raspbian Jessie Lite 寫入CM3 ,注意磁碟機位置如果選錯了磁碟機內容就消失了!!





    寫入完成後就可以拆除IO BOARD 與電腦的連線,把 IO BOARD 的 J4跳線移到DIS位置,IO BOARD 插上HDMI與 K/B連接線,就會看到CM3開機畫面。



使用者輸入 : pi
密碼 : raspberry


這樣就完成了。