Sử dụng cảm biến bụi (Dust Sensor) trên Raspberry Pi thông qua Adapter ARPI600

Cảm biến bụi (Dust Sensor) là thiết bị giúp chúng ta đo đạc, tính toán ra lượng bụi trong không khí để biết chất lượng không khí trong khu vực đo đang như thế nào. Tuy nhiên kết quả Output của cảm biến này lại là Analog nên Raspberry Pi sẽ không ghi nhận được dữ liệu này.

Vì vậy, chúng ta sẽ cần thêm bo mạch Adapter ARPI600 – một adapter board dùng cho Raspberry Pi và Arduino để giúp chúng ta đọc các dữ liệu Analog. ARPI600 còn có rất nhiều tính năng hữu hiệu khác như Real-time, Xbee, …

Chuẩn bị phần cứng để đọc dữ liệu cảm biến bụi trên Raspberry Pi

Chúng ta sẽ cần

Sơ đồ kết nối để đọc dữ liệu cảm biến bụi trên Raspberry Pi

Module cảm biến bụi ARPI600 đã kết nối RPi
VCC 3.3V
GND GND
AOUT T_A6
iLED P1

Hình ảnh kết nối

Kịch bản đo và báo cáo kết quả nồng độ bụi trong không khí với Raspberry Pi

  • Kích hoạt các diot hồng ngoại bằng cách thiết lập các pin LED ở mức HIGH.
  • Chờ 0.28ms, sau đó bắt đầu để lấy mẫu điện áp từ pin Aout của module. Ghi chú rằng tín hiệu đầu ra sẽ mất 0.28ms để đạt trạng thái ổn định sau khi diot hồng ngoại được kích hoạt
  • Chu kì lấy mẫu là 0.004ms . Khi hoàn tất, thiết lập các pin LED LOW để vô hiệu hóa các diot hồng ngoại.
  • Tính nồng độ bụi theo mối quan hệ giữa điện áp đầu ra và nồng độ bụi.
Biểu đồ điện áp và nồng độ bụi

Bảng quan hệ giữa giá trị điện áp ra và nồng độ bụi

Và giờ thì chúng ta bắt tay vào đo thôi.

Ứng dụng mẫu đo và cảnh báo mức độ ô nhiễm trong văn phòng qua cảm biến bụi

Trước hết, chúng ta cần thực hiện cài thư viện wiringPi

cd /tmp
wget https://project-downloads.drogon.net/wiringpi-latest.deb
sudo dpkg -i wiringpi-latest.deb

Sau khi cài đặt, chúng ta sẽ chạy lệnh dưới đây để kiểm tra xem wiringPi đã cài chưa

gpio -v

Kết quả sẽ hiển thị như thế này

Chúng ta sẽ tạo 1 file tên là General_Sensor.c thông qua lệnh

sudo nano General_Sensor.c

Và chúng ta copy đoạn code dưới đây vào

#include <stdio.h>
#include <wiringPi.h>
#define  Clock    27
#define  Address       28
#define  DataOut      29
#define        COV_RATIO                                0.2            //ug/mmm / mv
#define        NO_DUST_VOLTAGE                 400            //mv
#define        SYS_VOLTAGE                           3300
#define D0 0
#define S0 1 //iLed
int adcvalue = 0;
float voltage = 0;
int Filter(int m)
{
  static int flag_first = 0, _buff[10], sum;
  const int _buff_max = 10;
  int i;
  if(flag_first == 0)
  {
    flag_first = 1;
    for(i = 0, sum = 0; i < _buff_max; i++)
    {
      _buff[i] = m;
      sum += _buff[i];
    }
    return m;
  }
  else
  {
    sum -= _buff[0];
    for(i = 0; i < (_buff_max - 1); i++)
    {
      _buff[i] = _buff[i + 1];
    }
    _buff[9] = m;
    sum += _buff[9];
    i = sum / 10.0;
    return i;
  }
}
unsigned int ADC_Read(unsigned char channel)
{
       unsigned int value;
       unsigned char i;
       unsigned char LSB = 0, MSB = 0;
       channel = channel << 4;
       for (i = 0; i < 4; i ++)
       {
             if(channel & 0x80)
                    digitalWrite(Address,1);
             else
                    digitalWrite(Address,0);
             digitalWrite(Clock ,1);
             digitalWrite(Clock ,0);
             channel = channel << 1;
       }
       for (i = 0; i < 6;i ++)
       {
             digitalWrite(Clock ,1);
             digitalWrite(Clock ,0);
       }
       delayMicroseconds(15);
       for (i = 0; i < 2; i ++)
       {
             digitalWrite(Clock ,1);
             MSB <<= 1;
             if (digitalRead(DataOut))
                    MSB |= 0x1;
             digitalWrite(Clock ,0);
       }
       for (i = 0; i < 8; i ++)
       {
             digitalWrite(Clock ,1);
             LSB <<= 1;
             if (digitalRead(DataOut))
                    LSB |= 0x1;
             digitalWrite(Clock ,0);
       }
       value = MSB;
       value <<= 8;
       value |= LSB;
       return value;
}
void Level_Polution( float den){
       if(den <= 35)
       {
             printf(" Moi Truong sach!\n");
       }
       else if(den <= 75)
       {
             printf(" Moi Truong o muc trung binh!\n");
       }
       else if(den <= 115)
       {
             printf(" Moi Truong o muc o nhiem nhe!\n");
       }
       else if(den <= 150)
       {
             printf(" Moi Truong o muc o nhiem vua!\n");
       }
       else if(den <= 250)
       {
             printf(" Moi Truong o muc o nhiem nang!\n");
       }
       else
       {
             printf(" Moi Truong o nhiem nghiem trong!\n");
       }
}
int main()
{
       if (wiringPiSetup() < 0)return 1 ;
       pinMode (DataOut,INPUT);
       pullUpDnControl(DataOut, PUD_UP);
       pinMode(Clock,OUTPUT);
       pinMode(Address,OUTPUT);
       pinMode(D0,INPUT);
       digitalWrite(D0,0);
       float density = 0;
       pinMode(S0, OUTPUT);
       while(1)
       {            //lay tin hieu dien ap
                    digitalWrite(S0, HIGH);   // bat dau lay tin hieu analog
                    delayMicroseconds(280); // chờ 280us
                     adcvalue = ADC_Read(6);
                    digitalWrite(S0, LOW);  // ket thuc lay tin hieu
                    //loc tin hieu
                    adcvalue = Filter(adcvalue);
                    // tinh toan
                    voltage =( SYS_VOLTAGE/1024.0)*adcvalue*11;
                     if(voltage >= NO_DUST_VOLTAGE )
                     {
                        voltage -= NO_DUST_VOLTAGE;
                        density = voltage * COV_RATIO;
                     }
                   else
                     density = 0;
                    printf(" Do bui: %f  ug/m3\n", density);
                    Level_Polution(density);
             delay(1000);
       }
}

Chúng ta bấm Ctrl + X để thoát trình soạn thảo nano, sau đó bấm YEnter để lưu lại file

Tiếp theo, chúng ta sẽ biên dịch file này thông qua lệnh

gcc -Wall -o General_Sensor General_Sensor.c -lwiringPi

Cuối cùng, chúng ta sẽ thử xem kết quả hiển thị thế nào thông qua lệnh

sudo ./General_Sensor

Và tèn ten, nếu chúng ta làm đúng, kết quả sẽ như thế này