비교 PT100 온도 센서 조사 및 DS18B20 모듈
1) 신호 획득의 기본 원리
① PT100의 저항은 온도에 비례하여 변화합니다. (온도가 높을수록, 저항이 클수록), 그러나 저항 변화는 매우 작습니다., ~에 대한 0.385 오 / 도;
PT100의 온도 측정 범위는 -200 ℃ -200 ℃입니다., 그리고 0 ℃에서, 저항은 정확히 동일합니다 100 오;
pt100의 작업 전류는 5 엄마;
pt100의 저항은 온도에 비례하여 변하지만, 변화율 (그건, k 값 k 값 k 값) 온도 범위에서 다릅니다.
2) PT100 온도 저항 변화 테이블
3. PT100 드라이브 회로
1) 전압 디비전 방법을 통해, 광고는 온도를 계산하기 위해 저항 값을 얻기 위해 PT100 전압을 수집합니다.
실온에서 물에서 PT100의 저항 값 (25℃ 25 ℃ 25 ℃) 약 109.89 오.
마이크로 컨트롤러는 3.3V 전압을 출력합니다, PT100으로 나눈 전압은 대략입니다:
109.89 * 0.005 = 0.54945 V
광고 변환 공식에 따라 변환 된 광고 값은 대략입니다.:
0.54945 / 3.3 * 4096 = 681.98 ≈ 682
온도가 1도 상승하면, PT100의 저항이 방금 증가한다고 가정합니다 0.385 오, 분할 된 전압의 변화 값은 거의:
0.385 * 0.005 = 0.001925 V
광고 변환 공식에 따라 변환 된 광고 값은 대략입니다.:
0.001925 / 3.3 * 4096 = 2.39 ≈ 2
실험에서, STM32 전원 공급 장치의 불안정한 3.3V 전압으로 인해, ADC는 PT100 전압 변동을 수집하고 전압 분할 오류가 컸습니다.. 최적화 솔루션은 일정한 전류 소스 회로를 설계하는 것입니다.. PT100의 전압 및 상수 전류 소스의 전류를 수집하여, PT100의 저항을 얻을 수 있습니다, 그런 다음 온도 값을 얻을 수 있습니다.
2) LDO 조절기를 기반으로 한 일정한 전류 소스 회로 (MD5333)
인터넷에서 PT100을 테스트하기위한 많은 주행 회로가 있습니다., DC 브리지 회로와 같은, 작동 증폭기를 기반으로 한 일정한 전류 소스 회로, 등. 저자는 또한 운전 회로를 선택하는 데 많은 시간을 보냈습니다., 보드 제작의 어려움과 구성 요소 수 고려, 그리고 마지막으로 LDO 레귤레이터를 기반으로 상수 전류 소스 회로를 선택했습니다. (MD5333). 회로도는 다음과 같습니다:
이 시점에서, 하드웨어 선택은 기본적으로 완료되었습니다. 사용 된 개발 보드는 Zhengdian Atom F10ZET6 Elite Board입니다.
DS18B20 모듈
실시간 온도와 PT100 온도 비교를 테스트하기 위해, 교정 비교 테스트를 위해 DS18B20 모듈이 추가됩니다
1) DS18B20 소개
DS18B20은 시험 온도 범위가 -55 ~+125 ℃이고 정확도 ± 0.5 ℃의 단일 버스 온도 센서입니다.. 현장 온도는 단일 버스 디지털 방식으로 직접 전송됩니다., 이는 시스템의 간섭 방지 능력을 크게 향상시킵니다. 측정 된 온도를 직접 읽을 수 있습니다, 실제 요구 사항에 따라 간단한 프로그래밍을 통해 9 ~ 12 비트 디지털 가치 판독 방법을 실현할 수 있습니다.. 작동 전압 범위는 3 ~ 5.5V입니다, 그리고 다양한 포장 양식을 사용합니다, 시스템 설정을 유연하고 편리하게 만듭니다. 사용자가 설정 한 설정 해상도 및 경보 온도는 EEPROM에 저장되며 정전 후에도 여전히 저장됩니다..
2) DS18B20 작업 타이밍 소개
모든 단일 버스 장치에는 데이터 무결성을 보장하기 위해 엄격한 신호 타이밍이 필요합니다.. DS18B20이 있습니다 6 신호 유형: 펄스 재설정, 응답 펄스, 쓰다 0, 쓰다 1, 읽다 0 그리고 읽습니다 1. 이 모든 신호, 응답 펄스를 제외하고, 호스트가 보내는 동기 신호입니다. 그리고 모든 명령과 데이터는 먼저 바이트의 낮은 비트로 전송됩니다..
펄스 및 응답 펄스를 재설정합니다
단일 버스의 모든 통신은 초기화 시퀀스로 시작합니다.. 호스트는 낮은 레벨을 출력하고 480US 이상이 낮은 레벨을 유지하여 재설정 펄스를 생성합니다.. 그런 다음 호스트는 버스를 풀어줍니다, 그리고 4.7k 풀업 저항은 단일 버스를 높이 끌어 당깁니다., 지연 시간은 15 ~ 60us입니다, 수신 모드로 들어갑니다 (RX). 그런 다음 DS18B20은 버스를 60 ~ 240US로 낮추어 저수준 응답 펄스를 생성합니다..
timing 쓰기 타이밍
쓰기 타이밍에는 쓰기가 포함됩니다 0 타이밍과 쓰기 1 타이밍. 모든 쓰기 타이밍에는 60US 이상이 필요합니다, 그리고 두 개의 독립적 인 쓰기 타이밍 사이에 최소 1US 복구 시간이 필요합니다.. 두 글쓰기 타이밍은 호스트가 버스를 끌어내는 것으로 시작합니다.. 쓰다 1 타이밍: 호스트는 낮은 레벨을 출력합니다, 2US에 대한 지연, 그런 다음 버스를 출시합니다, 60US 지연. 쓰다 0 타이밍: 호스트는 낮은 레벨을 출력합니다, 60us에 대한 지연, 그런 다음 2US의 지연으로 버스를 출시합니다..
③ 타이밍을 읽으십시오
단일 버스 장치는 호스트가 읽기 타이밍을 발행하는 경우에만 데이터를 호스트에 전송합니다.. 그러므로, 호스트가 읽은 후 읽기 데이터 명령을 발행합니다, 슬레이브가 데이터를 전송할 수 있도록 읽기 타이밍을 즉시 생성해야합니다.. 모든 읽기 타이밍에는 60US 이상이 필요합니다, 그리고 두 개의 독립적 인 읽기 타이밍 사이에 최소 1US 복구 시간이 필요합니다.. 각각의 읽기 타이밍은 호스트가 시작합니다, 버스를 최소 1US로 끌어 당깁니다. 호스트는 읽기 타이밍 중에 버스를 릴리스하고 타이밍이 시작된 후 15US 이내에 버스 상태를 샘플링해야합니다.. 일반적인 읽기 타이밍 프로세스는 다음과 같습니다: 호스트는 2US의 낮은 레벨 지연을 출력합니다, 그런 다음 호스트는 12US의 입력 모드 지연으로 전환합니다., 그런 다음 단일 버스의 현재 레벨을 읽습니다, 그런 다음 50us를 지연시킵니다.
단일 버스 타이밍을 이해 한 후, DS18B20의 일반적인 온도 읽기 과정을 살펴 보겠습니다.. DS18B20의 전형적인 온도 판독 과정은 다음과 같습니다: 재설정 → Skiprom을 보내십시오 (0XCC) → 시작 변환 명령을 보냅니다 (0x44) → 지연 → 재설정 → Skiprom 명령을 송신합니다 (0XCC) → 메모리 명령을 보내십시오 (0XBE) → 두 바이트의 데이터를 읽습니다 (즉. 온도) 지속적으로 → 끝.
3) 회로도 및 Cubemax 구성
회로도에서, PG11 포트는 DS18B20이 온도 정보를 인쇄하기 위해 직렬 포트를 열도록 활성화된다는 것을 알 수 있습니다.
4) 코드 부분
코드 부품은 Zhengdian Atom의 DS18B20 라이브러리를 이식하고 약간 수정합니다.
#ifndef __DS18B20_H
#__DS18B20_H를 정의하십시오
#포함하다 “Tim.h”
/***********************************************************************************/
/* DS18B20 핀 정의 */
#DS18B20_DQ_GPIO_PORT GPIOG 정의
#DS18B20_DQ_GPIO_PIN GPIO_PIN_11을 정의하십시오
#DS18B20_DQ_GPIO_CLK_ENABLE을 정의하십시오() 하다{ __hal_rcc_gpiog_clk_enable(); }~하는 동안(0) /* PG 포트 시계 활성화 */
/**********************************************************************************************/
/* IO 작동 기능 */
#DS18B20_DQ_OUT를 정의하십시오(엑스) 하다{ 엑스 ? \
HAL_GPIO_WRITEPIN(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN, gpio_pin_set) : \
HAL_GPIO_WRITEPIN(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN, gpio_pin_reset); \
}~하는 동안(0) /* 데이터 포트 출력 */
#DS18B20_DQ_IN HAL_GPIO_READPIN을 정의하십시오(DS18B20_DQ_GPIO_PORT, DS18B20_DQ_GPIO_PIN) /* 데이터 포트 입력 */
UINT8_T DS18B20_INIT(무효의); /* DS18B20 초기화 */
UINT8_T DS18B20_CHECK(무효의); /* DS18B20이 있는지 확인하십시오 */
짧은 ds18b20_get_temperature(무효의);/* 온도를 얻으십시오 */
#endif
5. 적외선 원격 제어 모듈
1) 무선 모듈 코딩 프로토콜
적외선 원격 제어에 널리 사용되는 코딩 방법은 다음과 같습니다.: PWM의 NEC 프로토콜 (펄스 폭 변조) 및 필립스 PPM의 RC-5 프로토콜 (펄스 위치 변조). 개발위원회와 함께 제공되는 원격 제어는 NEC 프로토콜을 사용합니다., 다음과 같은 기능이 있습니다:
1. 8-비트 주소 및 8 비트 명령 길이;
2. 주소와 명령은 두 번 전송됩니다 (신뢰성을 보장합니다);
3. PWM 펄스 위치 변조, 전달 된 적외선 캐리어의 듀티 사이클 “0” 그리고 “1”;
4. 캐리어 주파수는 38kHz입니다;
5. 비트 시간은 1.125ms 또는 2.25ms입니다;
NEC 프로토콜에서, 프로토콜에서 데이터를 설정하는 방법 ‘0’ 또는‘1’? 여기, 적외선 수신기 및 적외선 송신기가 분리됩니다.
적외선 송신기: 프로토콜 데이터 보내기‘0’= 560US의 캐리어 신호 전송 + 560캐리어 신호 전송이없는 미국
프로토콜 데이터 보내기‘1’= 560US의 캐리어 신호 전송 + 1680캐리어 신호 전송이없는 미국
적외선 송신기의 비트 정의는 아래 그림에 나와 있습니다.
적외선 수신기: 프로토콜 데이터 '0'= 560us 낮은 레벨을받습니다 + 560미국 높은 수준
프로토콜 데이터 '1'= 560us 낮은 레벨을받습니다 + 1680미국 높은 수준
NEC 원격 제어 명령의 데이터 형식은 다음과 같습니다: 동기화 터미널, 주소 코드, 역 코드 주소, 제어 코드, 역 코드를 제어하십시오. 동기화 코드는 9ms 낮은 레벨과 4.5ms 높은 레벨로 구성됩니다.. 주소 코드, 역 코드 주소, 제어 코드, 제어 역 코드는 모두 8 비트 데이터 형식입니다. 그들은 낮은 비트의 순서대로 전송됩니다.. 역 코드는 전송의 신뢰성을 높이는 데 사용됩니다..
그러므로, 입력 캡처는 원격 제어 디코딩을 달성하기 위해 높은 레벨의 펄스 폭을 측정하는 데 사용될 수 있습니다..
2) 회로도 및 Cubemax 구성
회로도에서, 무선 모듈이 PB9 핀을 통해 활성화되어 4 TIM4의 채널:
TIM4_CH4의 기본 핀은 PB9가 아닙니다, 따라서 수동으로 설정해야합니다, 인터럽트 설정이 동시에 켜집니다.
3) 코드 부분
Tim 콜백 함수를 통해 상승 에지를 캡처하십시오
이때, 디코딩 된 신호를 얻을 수 있습니다:
이때, 데이터가 더 복잡하고 약간 처리 될 수 있습니다.:
효과는 다음과 같습니다:
마지막 두 자리는 디코딩 된 것과 역 코드입니다.. 이때, 온도 임계 값을 조정하기 위해 매크로로 정의 할 수 있습니다.:
효과는 다음과 같습니다:
적외선 부품 코드:
/* 사용자 코드는 헤더를 시작합니다 */
/**
******************************************************************************
* @파일 : 손 .c
* @짧은 : 주요 프로그램 본문
******************************************************************************
* @주목
*
* <H2><센터>&복사; 저작권 (기음) 2024 stmicroelectronics.
* 모든 권리 보유.</센터></H2>
*
* 이 소프트웨어 구성 요소는 BSD 3-Clause 라이센스에 따라 ST에서 라이센스를 부여합니다.,
* 그만큼 “특허”; 준수 여부를 제외 하고이 파일을 사용할 수 없습니다.
* 특허. 라이센스 사본을 얻을 수 있습니다:
* opensource.org/licenses/bsd-3-clause
*
******************************************************************************
*/
/* 사용자 코드 엔드 헤더 */
/* 포함 ——————————————————————*/
#포함하다 “main.h”
#포함하다 “Tim.h”
#포함하다 “usart.h”
#포함하다 “gpio.h”
/* 개인 포함 ———————————————————-*/
/* 사용자 코드 시작에 포함됩니다 */
#포함하다 “stdio.h”
#포함하다 “문자열 .H”
#Maxup을 정의하십시오 157
#Maxdown을 정의하십시오 87
#Minup을 정의하십시오 221
#Mindown을 정의하십시오 61
/* 사용자 코드 엔드에는 포함됩니다 */
/* 개인 typedef ———————————————————–*/
/* 사용자 코드 시작 PTD */
/* 사용자 코드 엔드 PTD */
/* 개인 정의 ————————————————————*/
/* 사용자 코드 시작 PD */
/* 사용자 코드 엔드 PD */
/* 개인 매크로 ————————————————————-*/
/* 사용자 코드는 PM을 시작합니다 */
/* 사용자 코드 종료 PM */
/* 개인 변수 ———————————————————*/
/* 사용자 코드 시작 PV */
uint32_t upcount = 0;
uint16_t valueup = 0;
uint16_t valuedown = 0;
uint8_t isupcapt = 1;
uint16_t 너비 = 0;
UINT16_T 버퍼[128]={0};
uint16_t bufferid = 0;
uint8_t rcvfalg = 0;
/* 사용자 코드 엔드 PV */
/* 개인 기능 프로토 타입 ———————————————–*/
void SystemClock_config(무효의);
/* 사용자 코드 시작 PFP */
/* 사용자 코드 종료 PFP */
/* 개인 사용자 코드 ———————————————————*/
/* 사용자 코드가 시작됩니다 0 */
void hal_tim_periodelapsedCallback(TIM_HANDLETYPEDEF *HTIM)
{
Upcount ++;
}
void Hal_TIM_IC_CAPTURECALLBACK(TIM_HANDLETYPEDEF *HTIM)
{
만약에(Isupcapt)//가장자리 캡처가 상승하는 경우
{
valueUp = HAL_TIM_READCAPPUDEDVALUE입니다(htim htim,TIM_CHANNEL_4);
isupcapt = 0;
__HAL_TIM_SET_CAPTUREPOLARITY(htim htim,TIM_CHANNEL_4, TIM_ICPAROLITY_FLALING);
upcount = 0;
}
또 다른{
valuedown = HAL_TIM_READCAPPUDEDVALUE(htim htim,TIM_CHANNEL_4);
isupcapt = 1;
__HAL_TIM_SET_CAPTUREPOLARITY(htim htim,TIM_CHANNEL_4, TIM_ICPAROLITY_RISING);
너비 = valuedown+upcount*65536- 값;
만약에(너비>4400&&너비<4600)
{
Bufferid = 0;
완충기[완충 ++]= 너비;
}
그렇지 않으면(완충>0)
{
완충기[완충 ++]= 너비;
만약에(완충>32)
{
rcvfalg = 1;
Bufferid = 0;
}
}
}
}
void bitbuffer2num(문자 수[])
{
숫자[0]= 0;
숫자[1]= 0;
숫자[2]= 0;
숫자[3]= 0;
~을 위한(int i = 0;나<32;i ++)
{
만약에(완충기[I+1]<1000)
{
숫자[I/8]= num[I/8]<<1;
}
또 다른
{
숫자[I/8]= num[I/8]<<1;
숫자[I/8]|= 0x01;
}
}
}
/* 사용자 코드 종료 0 */
/**
* @brief 응용 프로그램 입력 지점.
* @retval int
*/
int 메인(무효의)
{
/* 사용자 코드가 시작됩니다 1 */
문자 프린트 버프[128]={0};
문자 수[4]={0};
숯 키 = 0;
/* 사용자 코드 종료 1 */
/* MCU 구성——————————————————–*/
/* 모든 주변 장치의 재설정, 플래시 인터페이스와 Systick을 초기화합니다. */
hal_init();
/* 사용자 코드 시작 시작 */
/* 사용자 코드 끝 */
/* 시스템 시계를 구성하십시오 */
SystemClock_config();
/* 사용자 코드는 sysinit을 시작합니다 */
/* 사용자 코드 종료 Sysinit */
/* 구성된 모든 주변 장치를 초기화하십시오 */
mx_gpio_init();
MX_TIM4_INIT();
mx_usart1_uart_init();
/* 사용자 코드가 시작됩니다 2 */
/* 사용자 코드 종료 2 */
/* 무한 루프 */
/* 사용자 코드가 시작됩니다 */
HAL_GPIO_TOGGLEPIN(led0_gpio_port,led0_pin);
HAL_TIM_BASE_START_IT(&htim4);//타이머 업데이트는 인터럽트를 생성합니다
HAL_TIM_IC_START_IT(&HTIM4, TIM_CHANNEL_4);//
~하는 동안 (1)
{
만약에(rcvfalg)
{
~을 위한(int i = 0;나<4;i ++)
{
Bitbuffer2num(숫자);
Sprintf(프린트 버프,”0xx “,숫자[나]);
HAL_UART_TRANSMIT(&Huart1, Printbuff,Strlen(프린트 버프),HAL_MAX_DELAY);
}
// Sprintf(프린트 버프,”%유 “,완충기[나]);
// HAL_UART_TRANSMIT(&Huart1, Printbuff,Strlen(프린트 버프),HAL_MAX_DELAY);
// }
HAL_UART_TRANSMIT(&huart1,”\r n”,2,HAL_MAX_DELAY);
rcvfalg = 0;
}
printf(“%d r n”,숫자[3]);
만약에(숫자[3]== 157)
{
printf(“111111\r n”);
}
HAL_DELAY(1000);
/* 사용자 코드 종료 중 */
/* 사용자 코드가 시작됩니다 3 */
}
/* 사용자 코드 종료 3 */
}
/**
* @Brief 시스템 클록 구성
* @retval 없음
*/
void SystemClock_config(무효의)
{
RCC_OSCINITTYPEDEF RCC_OSCINITSTRUCT = {0};
rcc_clkinittypedef rcc_clkinitstruct = {0};