間の比較 PT100温度センサー プローブと DS18B20モジュール
1) 信号取得の基本原理
① PT100の抵抗値は温度に比例して変化します。 (温度が高いほど, 抵抗が大きいほど), しかし抵抗変化は非常に小さい, について 0.385 おお / 程度;
pt100の温度測定範囲は-200℃-200℃, および0℃, 抵抗は正確に等しい 100 おお;
pt100の動作電流はより少ないはずです 5 ミリアンペア;
pt100の抵抗は温度に比例して変化しますが, その変更率 (あれは, K値k値k値) 温度範囲が異なります.
2) PT100温度抵抗変化表
3. PT100ドライブ回路
1) 電圧分割法を介して, ADは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エリートボードです
DS18B20モジュール
リアルタイム温度とPT100温度比較をテストするため, DS18B20モジュールは、キャリブレーション比較テストのために追加されています
1) DS18B20の紹介
DS18B20は、テスト温度範囲が-55〜+125℃、精度が±0.5°の単一バス温度センサーです。. フィールド温度は、単一バスのデジタル的な方法で直接送信されます, これにより、システムの干渉防止能力が大幅に向上します. 測定された温度を直接読み取ることができます, そして、実際の要件に応じて簡単なプログラミングを通じて9〜12ビットのデジタル価値読み方を実現できます. その動作電圧範囲は3〜5.5Vです, また、さまざまなパッケージングフォームを使用しています, システム設定を柔軟で便利にします. ユーザーが設定したセット解像度とアラーム温度はEEPROMに保存され、停電後も保存されます.
2) DS18B20の作業タイミングの紹介
すべてのシングルバスデバイスは、データの整合性を確保するために厳密な信号タイミングを必要とします. DS18b20にはあります 6 信号タイプ: パルスをリセットします, 応答パルス, 書く 0, 書く 1, 読む 0 そして読んでください 1. これらすべての信号, 応答パルスを除く, ホストが送信した同期信号です. そして、すべてのコマンドとデータは、最初にバイトの低いビットで送信されます.
pulseと応答パルスをリセットします
単一のバスでのすべての通信は、初期化シーケンスから始まります. ホストは低レベルを出力し、少なくとも480USの低レベルを保持してリセットパルスを生成します. その後、ホストがバスをリリースします, 4.7Kプルアップ抵抗器は単一のバスを高く引っ張ります, 遅延時間は15〜60usです, 受信モードに入ります (Rx). その後、DS18B20はバスを低く引っ張り、60〜240USで低レベルの応答パルスを生成します.
②書き込みタイミング
書き込みタイミングには書き込みが含まれます 0 タイミングと書き込み 1 タイミング. すべての書き込みタイミングには、少なくとも60USが必要です, そして、2つの独立した書き込みタイミングの間に少なくとも1回の回復時間が必要です. Both write timings start with the host pulling down the bus. Write 1 タイミング: the host outputs a low level, delays for 2us, and then releases the bus, delaying 60us. Write 0 タイミング: the host outputs a low level, delays for 60us, and then releases the bus with a delay of 2us.
③ Read timing
Single-bus devices transmit data to the host only when the host issues a read timing. したがって, after the host issues a read data command, a read timing must be generated immediately so that the slave can transmit data. All read timings require at least 60us, and at least 1us recovery time is required between two independent read timings. Each read timing is initiated by the host, which pulls down the bus for at least 1us. The host must release the bus during the read timing and sample the bus status within 15us after the timing starts. 典型的な読み取りタイミングプロセスはです: ホストは、2Uの低レベル遅延を出力します, その後、ホストは12Uの入力モード遅延に切り替えます, 次に、単一のバスの現在のレベルを読み取ります, そして、50usを遅らせます.
単一のバスのタイミングを理解した後, DS18b20の典型的な温度読み取りプロセスを見てみましょう. DS18b20の典型的な温度読み取りプロセスはです: リセット→Skipromを送信します (0XCC) →[開始変換]コマンドを送信します (0x44) →遅延→リセット→Skipromコマンドを送信します (0XCC) →メモリコマンドを送信します (0xbe) →2バイトのデータを読み取ります (つまり. 温度) 連続的に→終了.
3) 概略図とCubemax構成
概略図から, DS18B20がPG11ポートによって有効になっていることがわかります。シリアルポートを開いて温度情報を印刷する
4) コードパーツ
コード部分は、Zhengdian原子のDS18B20ライブラリーを移植し、わずかな変更を加えます
#ifndef __ds18b20_h
#__ds18b20_hを定義します
#含む “ティム”
/***********************************************************************************/
/* DS18B20 PIN定義 */
#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プロトコル (パルス幅変調) およびPhilips PPMのRC-5プロトコル (パルス位置変調). 開発ボードに付属するリモートコントロールは、NECプロトコルを使用します, 次の機能があります:
1. 8-ビットアドレスと8ビット命令長;
2. アドレスとコマンドは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コールバック関数を介して立ち上がりエッジをキャプチャします
現時点では, デコードされた信号を取得できます:
現時点では, データはより複雑で、わずかに処理できます:
効果は次のとおりです:
最後の2桁はデコードされたものとその逆コードです. 現時点では, 温度しきい値を調整するマクロとして定義できます:
効果は次のとおりです:
赤外線部品コード:
/* ユーザーコードはヘッダーを開始します */
/**
******************************************************************************
* @ファイル : hand.c
* @簡単な : メインプログラムボディ
******************************************************************************
* @注意
*
* <H2><中心>&コピー; 著作権 (c) 2024 stmicroelectronics.
* 無断転載を禁じます。</中心></H2>
*
* このソフトウェアコンポーネントは、BSD 3-Clauseライセンスの下でSTによってライセンスされています,
* の “ライセンス”; このファイルを使用することはできません
* ライセンス. ライセンスのコピーを取得できます:
* opensource.org/licenses/bsd-3-clause
*
******************************************************************************
*/
/* ユーザーコードエンドヘッダー */
/* 含まれるもの ——————————————————————*/
#含む “main.h”
#含む “ティム”
#含む “USART.H”
#含む “gpio.h”
/* プライベートインクルード ———————————————————-*/
/* ユーザーコードの開始が含まれます */
#含む “stdio.h”
#含む “string.h”
#Maxupを定義します 157
#maxdownを定義します 87
#minupを定義します 221
#マインドタウンを定義します 61
/* ユーザーコードの終了は含まれます */
/* Private 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 width = 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_readcapturedValue(htim htim,tim_channel_4);
isupcapt = 0;
__hal_tim_set_capturepolarity(htim htim,tim_channel_4、tim_icpolarity_falling);
upcount = 0;
}
それ以外{
Valuedown = hal_tim_readcapturedValue(htim htim,tim_channel_4);
isupcapt = 1;
__hal_tim_set_capturepolarity(htim htim,tim_channel_4、tim_icpolarity_rising);
width = veluedown+upcount*65536-valueup;
もし(幅>4400&&幅<4600)
{
緩衝液= 0;
バッファ[緩衝液++]=幅;
}
elseの場合(緩衝液>0)
{
バッファ[緩衝液++]=幅;
もし(緩衝液>32)
{
rcvfalg = 1;
緩衝液= 0;
}
}
}
}
void bitbuffer2num(char num[])
{
num[0]= 0;
num[1]= 0;
num[2]= 0;
num[3]= 0;
のために(int i = 0;私<32;I ++)
{
もし(バッファ[I+1]<1000)
{
num[I/8]= num[I/8]<<1;
}
それ以外
{
num[I/8]= num[I/8]<<1;
num[I/8]|= 0x01;
}
}
}
/* ユーザーコードの終了 0 */
/**
* @アプリケーションエントリポイント.
* @retval int
*/
int main(空所)
{
/* ユーザーコードが始まります 1 */
Char Printbuff[128]={0};
char num[4]={0};
char key = 0;
/* ユーザーコードの終了 1 */
/* MCU構成——————————————————–*/
/* すべての周辺機器のリセット, フラッシュインターフェイスとサイスティックを初期化します. */
hal_init();
/* ユーザーコードがinitを開始します */
/* ユーザーコードの終了init */
/* システムクロックを構成します */
SystemClock_Config();
/* ユーザーコードはsysinitを開始します */
/* ユーザーコードEnd sysinit */
/* 構成されたすべての周辺機器を初期化します */
mx_gpio_init();
mx_tim4_init();
mx_usart1_uart_init();
/* ユーザーコードが始まります 2 */
/* ユーザーコードの終了 2 */
/* 無限ループ */
/* ユーザーコードはwhenを開始します */
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(num);
sprintf(printbuff,”0x%02x “,num[私]);
hal_uart_transmit(&huart1、printbuff,strlen(printbuff),hal_max_delay);
}
// sprintf(printbuff,”%u “,バッファ[私]);
// hal_uart_transmit(&huart1、printbuff,strlen(printbuff),hal_max_delay);
// }
hal_uart_transmit(&huart1、”\r\n”,2,hal_max_delay);
rcvfalg = 0;
}
printf(“%d\r\n”,num[3]);
もし(num[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};