Bộ ghi dữ liệu Arduino với thẻ SD, cảm biến DS3231 và DHT22

Bộ ghi dữ liệu Arduino với thẻ SD, cảm biến DS3231 và DHT22

Trong dự án này, chip đồng hồ thời gian thực DS3231 sẽ được sử dụng để duy trì thời gian cũng như ngày, giờ và cảm biến DHT22 để phát hiện độ ẩm và nhiệt độ tương đối. Ngoài ra, trong mạch sẽ có hai nút bấm để thiết lập thời gian và màn hình LCD 20 × 4 để hiển thị tất cả các thông số (thời gian, ngày, nhiệt độ và độ ẩm) như hình dưới đây:

Các linh kiện cần thiết:

  • Board Arduino
  • Board DS3231
  • Cảm biến nhiệt độ và độ ẩm tư DHT22
  • Màn hình LCD 20 × 4 (2004)
  • thẻ SD
  • Ổ cắm thẻ SD (đầu nối)
  • 2 x Nút ấn
  • 2 x Điện trở 10K ohm
  • Điện trở ohm 4,7K
  • 3 x Điện trở 3,3K ohm
  • 3 x Điện trở 2.2K ohm
  • Điện trở 330 ohm
  • Breadboard
  • Dây dẫn

Sơ đồ mạch:

Mạch đầu tiên bao gồm ba bộ chia điện áp để chuyển 5V thành 3V, các bộ chia điện áp dành cho: tín hiệu SS (chip chọn), MOSI (master in Slave out) và SCK (xung nối tiếp).

(Tất cả các điểm mút nối đất được nối với nhau)

Và mạch thứ hai sử dụng mô-đun thẻ micro SD, mô-đun này được cấp nguồn 5V (đến từ board Arduino), nó có bộ điều chỉnh điện áp AMS1117 và bộ dịch mức (74LVC125A) chuyển đổi  5V thành 3,3V cho các dây: SS, MOSI và SCK:

(Tất cả các điểm mút nối đất được nối với nhau)

Với mô-đun thẻ micro SD, các kết nối đơn giản hơn, mô-đun thẻ sd được cung cấp 5V từ board Arduino.

Mô-đun thẻ SD có 6 chân (từ trái sang phải): GND, VCC, MISO, MOSI, SCK và CS (chọn chip).

Trong mạch có hai nút ấn: B1 và ​​B2 được nối tương ứng với các chân Arduino A1 và A2, các nút này được sử dụng để đặt thời gian và ngày của đồng hồ thời gian thực.

Cảm biến DHT22 có 4 chân: VCC, Dữ liệu, NC (không được kết nối) và GND. Nó được nối nguồn 5V (từ board Arduino).

Code cho dự án:

Code bên dưới đọc nhiệt độ và độ ẩm từ cảm biến DHT22, thời gian và ngày từ chip DS3231, sau đó nó lưu dữ liệu vào thẻ SD trong tệp có tên  Logger.txt và cuối cùng nó sẽ gửi cùng một dữ liệu cho PC. Việc đọc và lưu trữ dữ liệu được thực hiện cứ sau 1 giây.

Code arduino đầy đủ là dưới đây.

// Real time clock, calendar, temperature, humidity data logger using Arduino, DS3231 and DHT22 sensor




#include <SPI.h>              // Include SPI library (needed for the SD card)

#include <SD.h>               // Include SD library

#include <LiquidCrystal.h>    // Include LCD library code

#include <Wire.h>             // Include Wire library code (needed for I2C protocol devices)

#include <DHT.h>              // Include DHT library code




// LCD module connections (RS, E, D4, D5, D6, D7)

LiquidCrystal lcd(2, 3, 4, 5, 6, 7);

#define B1      A1            // Button B1 is connected to Arduino pin A1

#define B2      A2            // Button B1 is connected to Arduino pin A2

#define DHTPIN  A3            // DHT22 data pin is connected to Arduino pin A3




#define DHTTYPE DHT22         // DHT22 sensor is used

DHT dht(DHTPIN, DHTTYPE);     // Initialize DHT library




File dataLog;

boolean sd_ok = 0;

char temperature[] = " 00.0";

char humidity[]    = " 00.0 %";

char Time[]     = "  :  :  ";

char Calendar[] = "  /  /20  ";

byte i, second, minute, hour, date, month, year, previous_second;

int Temp, RH;




void setup() {

  // Open serial communications and wait for port to open:

  Serial.begin(9600);

  Serial.print("Initializing SD card...");

  if (!SD.begin())

    Serial.println("initialization failed!");

  else {

    Serial.println("initialization done.");

    sd_ok = 1;

  }

  pinMode(B1, INPUT_PULLUP);

  pinMode(B2, INPUT_PULLUP);

  lcd.begin(20, 4);                              // Set up the LCD's number of columns and rows

  Wire.begin();                                  // Join i2c bus

  dht.begin();

  

  lcd.setCursor(0, 0);   lcd.print("TIME:");

  lcd.setCursor(0, 1);   lcd.print("DATE:");

  lcd.setCursor(0, 2);   lcd.print("Temp =");

  lcd.setCursor(11, 2);  lcd.write(223);         // Print degree symbol ( °)

  lcd.setCursor(12, 2);  lcd.write('C');

  lcd.setCursor(0, 3);   lcd.print("RH   =");

  

  Serial.println("   DATE    |   TIME   | TEMPERATURE | HUMIDITY");

  

  if(sd_ok) {                                       // If SD card initialization was OK

    dataLog = SD.open("Logger.txt", FILE_WRITE);    // Open file Logger.txt

    if(dataLog) {                                   // if the file opened okay, write to it:

      dataLog.println("   DATE    |   TIME   | TEMPERATURE | HUMIDITY");

      dataLog.close();                              // Close the file

    }

  }

}




void DS3231_display(){

  // Convert BCD to decimal

  second = (second >> 4) * 10 + (second & 0x0F);

  minute = (minute >> 4) * 10 + (minute & 0x0F);

  hour   = (hour >> 4)   * 10 + (hour & 0x0F);

  date   = (date >> 4)   * 10 + (date & 0x0F);

  month  = (month >> 4)  * 10 + (month & 0x0F);

  year   = (year >> 4)   * 10 + (year & 0x0F);

  // End conversion

  Time[7]     = second % 10 + 48;

  Time[6]     = second / 10 + 48;

  Time[4]      = minute % 10 + 48;

  Time[3]      = minute / 10 + 48;

  Time[1]      = hour   % 10 + 48;

  Time[0]      = hour   / 10 + 48;

  Calendar[9] = year   % 10 + 48;

  Calendar[8] = year   / 10 + 48;

  Calendar[4]  = month  % 10 + 48;

  Calendar[3]  = month  / 10 + 48;

  Calendar[1]  = date   % 10 + 48;

  Calendar[0]  = date   / 10 + 48;

  lcd.setCursor(5, 0);

  lcd.print(Time);                               // Display time

  lcd.setCursor(5, 1);

  lcd.print(Calendar);                           // Display calendar

}

void blink_parameter(){

  byte j = 0;

  while(j < 10 && digitalRead(B1) && digitalRead(B2)){

    j++;

    delay(25);

  }

}

byte edit(byte x, byte y, byte parameter){

  char text[3];

  while(!digitalRead(B1));                        // Wait until button (pin #8) released

  while(true){

    while(!digitalRead(B2)){                      // If button (pin #9) is pressed

      parameter++;

      if(i == 0 && parameter > 23)               // If hours > 23 ==> hours = 0

        parameter = 0;

      if(i == 1 && parameter > 59)               // If minutes > 59 ==> minutes = 0

        parameter = 0;

      if(i == 2 && parameter > 31)               // If date > 31 ==> date = 1

        parameter = 1;

      if(i == 3 && parameter > 12)               // If month > 12 ==> month = 1

        parameter = 1;

      if(i == 4 && parameter > 99)               // If year > 99 ==> year = 0

        parameter = 0;

      sprintf(text,"%02u", parameter);

      lcd.setCursor(x, y);

      lcd.print(text);

      delay(200);                                // Wait 200ms

    }

    lcd.setCursor(x, y);

    lcd.print("  ");                             // Display two spaces

    blink_parameter();

    sprintf(text,"%02u", parameter);

    lcd.setCursor(x, y);

    lcd.print(text);

    blink_parameter();

    if(!digitalRead(B1)){                         // If button (pin #8) is pressed

      i++;                                       // Increament 'i' for the next parameter

      return parameter;                          // Return parameter value and exit

    }

  }

}

void loop() {

  if(!digitalRead(B1)){                           // If button (pin #8) is pressed

    i = 0;

    hour   = edit(5, 0, hour);

    minute = edit(8, 0, minute);

    date   = edit(5, 1, date);

    month  = edit(8, 1, month);

    year   = edit(13, 1, year);

    // Convert decimal to BCD

    minute = ((minute / 10) << 4) + (minute % 10);

    hour = ((hour / 10) << 4) + (hour % 10);

    date = ((date / 10) << 4) + (date % 10);

    month = ((month / 10) << 4) + (month % 10);

    year = ((year / 10) << 4) + (year % 10);

    // End conversion

    // Write data to DS3231 RTC

    Wire.beginTransmission(0x68);               // Start I2C protocol with DS3231 address

    Wire.write(0);                              // Send register address

    Wire.write(0);                              // Reset sesonds and start oscillator

    Wire.write(minute);                         // Write minute

    Wire.write(hour);                           // Write hour

    Wire.write(1);                              // Write day (not used)

    Wire.write(date);                           // Write date

    Wire.write(month);                          // Write month

    Wire.write(year);                           // Write year

    Wire.endTransmission();                     // Stop transmission and release the I2C bus

    delay(200);                                 // Wait 200ms

  }

  Wire.beginTransmission(0x68);                 // Start I2C protocol with DS3231 address

  Wire.write(0);                                // Send register address

  Wire.endTransmission(false);                  // I2C restart

  Wire.requestFrom(0x68, 7);                    // Request 7 bytes from DS3231 and release I2C bus at end of reading

  second = Wire.read();                         // Read seconds from register 0

  minute = Wire.read();                         // Read minuts from register 1

  hour   = Wire.read();                         // Read hour from register 2

  Wire.read();                                  // Read day from register 3 (not used)

  date   = Wire.read();                         // Read date from register 4

  month  = Wire.read();                         // Read month from register 5

  year   = Wire.read();                         // Read year from register 6

  DS3231_display();                             // Diaplay time & calendar

  if(previous_second != second){

    previous_second = second;

    // Read humidity

    RH = dht.readHumidity() * 10;

    //Read temperature in degree Celsius

    Temp = dht.readTemperature() * 10;

    if(Temp < 0){

      temperature[0] = '-';                     // If temperature < 0 put minus sign

      Temp = abs(Temp);                         // Absolute value of 'Temp'

    }

    else

      temperature[0] = ' ';                     // otherwise (temperature > 0) put space

    temperature[1]   = (Temp / 100) % 10  + 48;

    temperature[2]   = (Temp / 10)  % 10  + 48;

    temperature[4]  =  Temp % 10 + 48;

    if(RH >= 1000)

      humidity[0]    = '1';                     // If humidity >= 100.0% put '1' of hundreds

    else

      humidity[0]    = ' ';                     // otherwise (humidity < 100) put space

    humidity[1]      = (RH / 100) % 10 + 48;    

    humidity[2]      = (RH / 10) % 10 + 48;

    humidity[4]     =  RH % 10 + 48;

    lcd.setCursor(6, 2);

    lcd.print(temperature);

    lcd.setCursor(6, 3);

    lcd.print(humidity);

    // Send data to Arduino IDE serial monitor

    Serial.print(Calendar);

    Serial.print(" | ");

    Serial.print(Time);

    Serial.print(" |   ");

    Serial.print(temperature);

    Serial.print("°C   |  ");

    Serial.println(humidity);

    if(sd_ok) {                                       // If SD card initialization was OK

      dataLog = SD.open("Logger.txt", FILE_WRITE);    // Open file Logger.txt

      if(dataLog) {                                   // if the file opened okay, write to it:

        dataLog.print(Calendar);

        dataLog.print(" | ");

        dataLog.print(Time);

        dataLog.print(" |   ");

        dataLog.print(temperature);

        dataLog.print("°C   | ");

        dataLog.println(humidity);

        dataLog.close();                              // Close the file

      }

    }

  }

  delay(50);                                          // Wait 50ms

}

Kết quả ví dụ:

Kết quả trên serial monitor Arduino IDE được hiển thị dưới đây:

Video demo:

Tải xuống:
Thư viện Adafruit cho DHT (sau khi giải nén, hãy đặt thư mục có tên DHT vào thư mục thư viện của Arduino): 
Tải xuống
Tệp mô phỏng Proteus: 
Tải xuống
Tệp hình ảnh thẻ SD: 
Tải xuống

 

 

 

 

 

 

 

Trả lời

Email của bạn sẽ không được hiển thị công khai. Các trường bắt buộc được đánh dấu *