ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • ds18b20 온도센서 공부
    카테고리 없음 2025. 6. 21. 18:10

    먼저 나는 Ds18b20 이라는 온도센서를 사용했다.

    회로도를 보면 3.3V를 사용하고, GND로 전류를 흘러보낸다. PA2번에 연결해서 사용한다.

    One-wire 방식으로 통신한다.

    먼저, 데이터시트에 따르면 이 온도센서의 해상도는 9, 10, 11, 12비트로 구성할 수 있다.

    이에 따른 측정값의 증가 단위는 각각 0.5, 0.25, 0.125, 0.0625이다.

    Ds18b20은 1-Wire 방식으로, 여러 개의 센서를 하나의 선에 붙일 수 있다.

    센서마다 고유한 64비트(8바이트) ROM 주소가 있다.

    온도값을 저장할 Temperature, 데이터가 정상적으로 읽어지는지 확인하는 DataIsValid 변수이다.

    static uint8_t m_init = 0;		// 초기화 여부
    static uint8_t m_busy = 0;		// 통신 여부
    static uint8_t m_isConverting = 0;		// 변환 여부
    uint8_t isTemperSensorInit(){
    	return m_init;
    }
    
    uint8_t isBusy(){
    	return isBusyLine();
    }
    
    uint8_t isConverting(){
    
    	return m_isConverting;
    }
    	HAL_TIM_Base_Start_IT(&htim3);
    
    	Ds18b20_Init_Simple();

    먼저 위 코드는 main함수에서 호출하는 순서이다. 먼저 타이머 인터럽트를 등록하고 시작한 뒤,

    센서도 바로 초기화해서 m_init = 1이 된다.

    bool    Ds18b20_Init_Simple(){
    		m_init = 0;
    		OneWire_Init(&OneWire,_DS18B20_GPIO ,_DS18B20_PIN);
    
    		OneWire.ROM_NO[0] = 0x28;
    		OneWire.ROM_NO[1] = 0x25;
    		OneWire.ROM_NO[2] = 0xF8;
    		OneWire.ROM_NO[3] = 0x87;
    		OneWire.ROM_NO[4] = 0x00;
    		OneWire.ROM_NO[5] = 0x7F;
    		OneWire.ROM_NO[6] = 0x09;
    		OneWire.ROM_NO[7] = 0xB6;
    
    		OneWire_GetFullROM(&OneWire, temperSensor.Address);
    		Ds18b20Delay(50);
    		DS18B20_SetResolution(&OneWire, temperSensor.Address, DS18B20_Resolution_12bits);
    		Ds18b20Delay(50);
    		DS18B20_DisableAlarmTemperature(&OneWire,  temperSensor.Address);
    		m_init = 1;
    		return true;
    }

    여기서 m_init = 1로 초기화가 되면 타이머 함수에서 Init()함수가 1로 되고, isBusy()도 1일때 온도 계산을 수행한다.

    ROM 주소를 8칸의 배열로 나눈 이유는 데이터 시트에 보면

    ROM 주소를 8바이트로 이루어진다한다.

    Byte 0번은 패밀리 코드로 0x28이고,

    Byte 1~6번은 고유 시리얼 번호,

    Byte 7은 CRC (오류 검출용 체크섬) 이다.

    	if (isTemperSensorInit() && !isBusy()) {
    		digit4_temper((int)(getCurrentTemper() *10));
    	}

     

    위 Ds18b20_Init_Simple() 함수를 보면, m_init을 0으로 초기화한 뒤 OneWire_Init()함수를 호출한다.

    void OneWire_Init(OneWire_t* OneWireStruct, GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 
    {	
    	m_busy_line = 0;
    	HAL_TIM_Base_Start(&_DS18B20_TIMER);
    
    	OneWireStruct->GPIOx = GPIOx;
    	OneWireStruct->GPIO_Pin = GPIO_Pin;
    	ONEWIRE_OUTPUT(OneWireStruct);
    	ONEWIRE_HIGH(OneWireStruct);
    	OneWireDelay(1000);
    	ONEWIRE_LOW(OneWireStruct);
    	OneWireDelay(1000);
    	ONEWIRE_HIGH(OneWireStruct);
    	OneWireDelay(2000);
    }

    OneWire_Init함수가 하는 동작은 통신을 하기 위한 준비가 마쳤다는 동작이다.

    초기 상태는 High이고 마스터가 480ms 이상 LOW로 유지해서 통신을 시작한다고 알린다.

    라인 설정을 하고 HIgh 상태로 다시 올리고, Slave는 약 60~240μs 동안 LOW를 보내며 응답한다.

    OneWire 통신을 할 준비를 마치고, 나는 온도센서를 하나만 사용하기 때문에 ROM_NO의 주소를 고정값으로 저장하였다.

    GetFullROM 함수는 센서의 고유 주소를 읽고, 정밀도 설정을 한다.

    그리고 m_init을 1로 초기화해주며 준비를 마치면 타이머 인터럽트에서 온도를 읽고 화면에 표시한다.

    정리하면, MCU가 DS18b20을 초기화하고, ROM 주소를 MCU 내부에 저장한다.

    MCU가 센서에 온도 변환 명령을 전송하고, 변환 완료 한뒤, 온도데이터를 읽는다.

     

    변환 과정

    	while (1)
    	  {
    
    		checkButton();
    
    		  if((m_count > 100) || !m_first){
    			  if(!isConverting()){
    					  StartConverting();
    				  }
    
    				  checkConverting();
    
    				  if(!isConverting()){
    					  temper = getTemper();
    					  if(getSwState() == ON_t){
    						  heaterControl(temper);
    					  }else{
    						  if(getHeaterState() == ON_t){
    							  heaterOnOff(OFF_t);
    						  }
    					  }
    					  m_count = 0;
    					  m_first = 1;
    				  }
    		  }
    
    		  m_count++;
    		  HAL_Delay(10);

    main 함수에서 if(!isConverting()) 부분은 isConverting이 1이 아닐경우(0일 경우) 변환을 시작하는 것이다.

    m_busy = 1은 MCU와 센서가 통신중을 의미하고, DS18B20_StartAll() 함수는 DS18B20 전체에 변환 명령을 전송한다.

    void DS18B20_StartAll(OneWire_t* OneWire)
    {
    	/* Reset pulse */
    	OneWire_Reset(OneWire);
    	/* Skip rom */
    	OneWire_WriteByte(OneWire, ONEWIRE_CMD_SKIPROM);
    	/* Start conversion on all connected devices */
    	OneWire_WriteByte(OneWire, DS18B20_CMD_CONVERTTEMP);
    }

    함수를 보면 모든 센서를 대상으로, 온도 변환 명령을 한다.

    그러면 m_isConverting 변수값은 0에서 1로 바뀌고, m_busy = 0으로 통신 완료 표시를 한다.

     

    다음으로 checkConverting 함수를 호출하는데

    void checkConverting(){
    	m_busy = 1;
    	m_isConverting = !DS18B20_AllDone(&OneWire); //완료 1,비완료 0
    	m_busy = 0;
    }

    m_isConverting은 변환중이면 1, 완료됐으면 0으로 업데이트한다.

    DS18B20_AllDone 함수는 

    uint8_t DS18B20_AllDone(OneWire_t* OneWire)
    {
    	/* If read bit is low, then device is not finished yet with calculation temperature */
    	return OneWire_ReadBit(OneWire);
    }

    데이터 라인을 1-Wire 방식으로 읽어와 1이면 완료로 판단한다.

    float getTemper(){
    
    	Ds18b20Delay(100);
    	m_busy = 1;
    	temperSensor.DataIsValid = DS18B20_Read(&OneWire, temperSensor.Address, &temperSensor.Temperature);
    	m_busy = 0;
    	return temperSensor.Temperature;
    }

    DS18B20 센서는 온도 데이터로 변환한 뒤, 온도 값은 temperSensor.Temperature에 저장하고,

    성공/실패 여부는 true/false로 DataIsValid에 저장한다.

     

Designed by Tistory.