본문 바로가기

개발자/Arduino

Arduino와 여러 개 DS18B20 디지털 온도 센서 인터페이스

반응형

 

DS18B20의 특징 중 하나는 동일한 1-Wire 버스에 여러 대의 DS18B20이 공존할 수 있다는 것입니다. 각 DS18B20은 고유한 64비트 직렬 코드로 사전 프로그래밍되어 있기 때문에 서로 구별할 수 있습니다. 

 

다음 튜토리얼에서는 동일한 버스에 연결된 여러 DS18B20에서 온도를 읽는 방법을 보여드립니다. 이 기능은 넓은 지역에 걸쳐 여러 대의 DS18B20을 제어해야 할 때 매우 유용할 수 있습니다. 이 튜토리얼을 진행하기 전에 DS18B20 단선 온도 센서의 기본 사항을 숙지해야 합니다. 이 링크를 따라 튜토리얼을 먼저 읽어보시기 바랍니다

 

더 이상 고민할 필요 없이 DS18B20을 아두이노에 연결해 보겠습니다. 

 

여러 개의 DS18B20 센서를 Arduino에 배선하기 

 

연결은 매우 간단합니다. 먼저 모든 DS18B20을 병렬로 연결하여 모든 VDD, GND 및 신호 핀을 공유합니다. 그런 다음 VDD를 아두이노의 5V 출력에, GND를 아두이노의 접지에, 신호 핀을 아두이노의 디지털 핀 2에 연결합니다. 

 

데이터 전송을 안정적으로 유지하려면 신호와 전원 핀 사이에 전체 버스에 4.7k 풀업 저항을 하나씩 추가하세요(참고: Arduino의 내부 풀업은 여기서 작동하지 않습니다). 

 

 

 

 

아두이노 통합 개발환경 IDE 2.0 이상에서는 아래 이미지를 참고하여 라이브러리를 설치하세요.

 

 

 

DS18B20용 라이브러리 설치하기 - 예전 아두이노 IDE 버전

 

1-Wire 프로토콜은 약간 복잡하고 작동하려면 많은 코드가 필요합니다. DallasTemperature.h는 이러한 불필요한 복잡성을 추상화하여 센서에서 온도 판독값을 얻기 위한 간단한 명령을 실행할 수 있도록 작성되었습니다.

 

 

라이브러리를 설치하려면 스케치 > 라이브러리 포함 > 라이브러리 관리...로 이동하여 라이브러리 관리자가 라이브러리 색인을 다운로드하고 설치된 라이브러리 목록을 업데이트할 때까지 기다리세요.(Arduino IDE 2.0 이전 버전)

 

 

 

'ds18b20'을 입력하여 검색을 필터링합니다. 몇 개의 항목이 나올 것입니다. Miles Burton의 DallasTemperature를 찾습니다. 해당 항목을 클릭한 다음 설치를 선택합니다. 

 

 

 

아래 설명은 지금은 무시해도 됩니다.

Dallas Temperature는 하위 레벨 기능을 처리하는 하드웨어 전용 라이브러리입니다. DS18B20뿐만 아니라 모든 원와이어 장치와 통신하려면 원와이어 라이브러리와 페어링해야 합니다. 이 라이브러리도 설치하세요. 

 

https://lastminuteengineers.com/multiple-ds18b20-arduino-tutorial/

 

여러 대의 DS18B20을 읽는 방법

 

동일한 버스에 연결된 여러 대의 DS18B20을 읽는 방법에는 두 가지가 있습니다. 

 

  • 인덱스 기준 - 이 방법에서는 인덱스(라이브러리에서 할당)를 사용하여 각 센서를 정확히 찾아 온도를 읽습니다.
  • 주소 기준 - 이 방법에서는 각 센서가 자체 64비트 주소(미리 프로그래밍된)를 가지고 있다는 사실을 활용하여 각 센서를 개별적으로 읽습니다. 

각 방법을 하나씩 살펴보겠습니다. 

 

방법 1: 인덱스별로 DS18B20 읽기

 

Dallas 온도 라이브러리가 초기화되면 동일한 버스를 공유하는 모든 센서가 있는지 버스를 스캔합니다. 전체 버스를 센서 배열로 간주하고 각 센서에 인덱스를 할당합니다. 따라서 각 센서를 인덱스로 식별하고 온도를 읽을 수 있습니다. 다음은 버스에서 모든 DSB1820의 위치를 찾은 다음 각 센서의 온도를 표시하는 간단한 스케치입니다. 

 

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into digital pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);	

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

int deviceCount = 0;
float tempC;

void setup(void)
{
  sensors.begin();	// Start up the library
  Serial.begin(9600);
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");
}

void loop(void)
{ 
  // Send command to all the sensors for temperature conversion
  sensors.requestTemperatures(); 
  
  // Display temperature from each sensor
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i+1);
    Serial.print(" : ");
    tempC = sensors.getTempCByIndex(i);
    Serial.print(tempC);
    Serial.print((char)176);//shows degrees character
    Serial.print("C  |  ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
    Serial.print((char)176);//shows degrees character
    Serial.println("F");
  }
  
  Serial.println("");
  delay(1000);
}

 

 

결과는 다음과 같습니다: 

 

 

 

코드 설명입니다.

 

스케치는 라이브러리를 포함하고, 센서 버스가 연결된 핀을 선언하고, DallasTemperature 라이브러리 객체를 생성하는 것으로 시작됩니다. 동일한 전역 범위에서 두 개의 변수가 정의됩니다. deviceCount는 버스에 있는 센서의 수를 저장하고 tempC는 각 센서에서 읽은 온도를 저장합니다. 

 

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into digital pin 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire device
OneWire oneWire(ONE_WIRE_BUS);	

// Pass oneWire reference to DallasTemperature library
DallasTemperature sensors(&oneWire);

int deviceCount = 0;
float tempC;

 

 

코드의 설정 섹션에서 먼저 시작() 함수를 호출합니다. 이 함수는 버스를 초기화하고 연결된 모든 DS18B20을 감지합니다. 그런 다음 각 센서에 인덱스가 할당되고 비트 해상도가 12비트로 설정됩니다. 그런 다음 getDeviceCount() 함수를 호출하여 버스에서 검색된 장치 수를 인쇄합니다. 

 

void setup(void)
{
  sensors.begin();	// Start up the library
  Serial.begin(9600);
  
  // locate devices on the bus
  Serial.print("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");
}

 

 

 

코드의 루핑 섹션에서는 요청 온도() 함수를 사용하여 버스에 있는 모든 센서에 온도 변환을 수행하도록 지시합니다. 마지막으로 간단한 for 루프를 사용하여 센서 배열을 반복하고 getTempCByIndex(i) 함수를 호출하여 특정 DS18B20의 온도를 읽습니다. 

 

void loop(void)
{ 
  // Send command to all the sensors for temperature conversion
  sensors.requestTemperatures(); 
  
  // Display temperature from each sensor
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i+1);
    Serial.print(" : ");
    tempC = sensors.getTempCByIndex(i);
    Serial.print(tempC);
    Serial.print((char)176);//shows degrees character
    Serial.print("C  |  ");
    Serial.print(DallasTemperature::toFahrenheit(tempC));
    Serial.print((char)176);//shows degrees character
    Serial.println("F");
  }
  
  Serial.println("");
  delay(1000);
}

 

 

방법 2: 주소로 DS18B20 읽기

 

각 DS18B20은 제조 시 고유한 64비트 주소로 프로그래밍되어 있어 서로 구별할 수 있습니다. 따라서 하나의 스케치를 사용하여 각 센서의 주소를 찾아서 기록한 다음 다른 스케치를 사용하여 각 센서를 개별적으로 읽습니다. 

 

버스에서 DS18B20의 주소 찾기

 

아래 스케치는 버스에 있는 모든 DS18B20을 감지하여 직렬 모니터에 단선 주소를 인쇄합니다. 각 센서의 주소를 찾아 이름을 지정할 수 있도록 한 번에 하나의 센서만 연결할 것을 권장합니다. 

 

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// variable to hold device addresses
DeviceAddress Thermometer;

int deviceCount = 0;

void setup(void)
{
  // start serial port
  Serial.begin(9600);

  // Start up the library
  sensors.begin();

  // locate devices on the bus
  Serial.println("Locating devices...");
  Serial.print("Found ");
  deviceCount = sensors.getDeviceCount();
  Serial.print(deviceCount, DEC);
  Serial.println(" devices.");
  Serial.println("");
  
  Serial.println("Printing addresses...");
  for (int i = 0;  i < deviceCount;  i++)
  {
    Serial.print("Sensor ");
    Serial.print(i+1);
    Serial.print(" : ");
    sensors.getAddress(Thermometer, i);
    printAddress(Thermometer);
  }
}

void loop(void)
{}

void printAddress(DeviceAddress deviceAddress)
{ 
  for (uint8_t i = 0; i < 8; i++)
  {
    Serial.print("0x");
    if (deviceAddress[i] < 0x10) Serial.print("0");
    Serial.print(deviceAddress[i], HEX);
    if (i < 7) Serial.print(", ");
  }
  Serial.println("");
}

 

 

이제 직렬 모니터를 엽니다. 다음과 같은 화면이 표시됩니다. 

 

 

 

다음 스케치에서 필요하므로 모든 주소를 메모해 두세요.

 

주소로 DS18B20 읽기

 

아래 스케치는 DS18B20의 주소를 사용하여 온도를 읽습니다. 스케치 업로드를 시작하기 전에 DS18B20의 주소를 이전 스케치에서 찾은 주소로 바꿔야 합니다. 

 

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

// Addresses of 3 DS18B20s
uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27 };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 };

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

void loop(void)
{
  sensors.requestTemperatures();
  
  Serial.print("Sensor 1: ");
  printTemperature(sensor1);
  
  Serial.print("Sensor 2: ");
  printTemperature(sensor2);
  
  Serial.print("Sensor 3: ");
  printTemperature(sensor3);
  
  Serial.println();
  delay(1000);
}

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print((char)176);
  Serial.print("C  |  ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
  Serial.print((char)176);
  Serial.println("F");
}

 

위 스케치의 출력은 다음과 같습니다: 

 

 

코드 설명입니다.

 

스케치는 평소와 같이 라이브러리를 포함하고, 센서 버스가 연결된 핀을 선언하고, DallasTemperature 라이브러리의 객체를 생성하는 것으로 시작합니다. 

 

 

#include <OneWire.h>
#include <DallasTemperature.h>

// Data wire is plugged into port 2 on the Arduino
#define ONE_WIRE_BUS 2

// Setup a oneWire instance to communicate with any OneWire devices
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature.
DallasTemperature sensors(&oneWire);

 

 

다음으로 각 온도 센서에 대해 이전에 검색한 주소를 입력합니다. 

 

uint8_t sensor1[8] = { 0x28, 0xEE, 0xD5, 0x64, 0x1A, 0x16, 0x02, 0xEC };
uint8_t sensor2[8] = { 0x28, 0x61, 0x64, 0x12, 0x3C, 0x7C, 0x2F, 0x27 };
uint8_t sensor3[8] = { 0x28, 0x61, 0x64, 0x12, 0x3F, 0xFD, 0x80, 0xC6 };

 

 

설정 섹션에서는 PC와의 직렬 통신을 초기화하고 begin() 함수를 호출합니다. begin() 함수는 버스를 초기화하고, 연결된 모든 DS18B20을 감지하고, 각각의 비트 해상도를 12비트로 설정합니다. 

 

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

 

 

코드의 루핑 섹션에서는 요청Temperatures() 함수를 사용하여 버스에 있는 모든 센서에 온도 변환을 수행하도록 지시합니다. 마지막으로 사용자 지정 함수 printTemperature(deviceAddress)를 호출하여 장치 주소가 파라미터로 전달된 센서의 온도를 인쇄합니다. 

 

void loop(void)
{
  sensors.requestTemperatures();
  
  Serial.print("Sensor 1: ");
  printTemperature(sensor1);
  
  Serial.print("Sensor 2: ");
  printTemperature(sensor2);
  
  Serial.print("Sensor 3: ");
  printTemperature(sensor3);
  
  Serial.println();
  delay(1000);
}

 

사용자 지정 함수 printTemperature()는 라이브러리의 getTempC(deviceAddress) 함수를 호출하여 온도를 섭씨로 표시하고 DallasTemperature::toFahrenheit() 함수를 호출하여 화씨로 표시하기만 하면 됩니다. 

 

void printTemperature(DeviceAddress deviceAddress)
{
  float tempC = sensors.getTempC(deviceAddress);
  Serial.print(tempC);
  Serial.print((char)176);
  Serial.print("C  |  ");
  Serial.print(DallasTemperature::toFahrenheit(tempC));
  Serial.print((char)176);
  Serial.println("F");
}

 

여기까지입니다.

 

고생하셨습니다.

 

 

참고자료

Interfacing Multiple DS18B20 Digital Temperature Sensors with Arduino 

 

 

반응형

더욱 좋은 정보를 제공하겠습니다.~ ^^