13.7.DS18B20による温度計測
プロジェクトの概要
赤=Vcc
黒=GND
白=SIG
DS18B20を使用した防水ケーブル構造の温度センサーを使用した温度計測プロジェクトです。このため、液体、屋外等での温度計測が可能です。仕様は以下です。
電源 ;3.0~5.5V
温度範囲 ;-55°C ~ +125°C
精度 ;-10°C~+85°Cで±0.5°C
Picoとの通信は専用の1 ワイヤ インターフェイスです。プローブは直径7mm、長さ約26mm。全長は 約183cmです。温度計の分解能は、9 ~ 12 ビットでプログラム可能です。
部品リスト
DS18B20搭載 温度センサ(高温、防水)
GROVEの16 x 2 LCD 1 スイッチサイエンス
配線図

ソースリスト
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "pico/stdlib.h"
#include "hardware/i2c.h"
#include "hardware/rtc.h"
#include "hardware/adc.h"
//#define PICO_DEFAULT_LED_PIN 25
#define LED_PIN PICO_DEFAULT_LED_PIN
#define I2C_PORT i2c0
#define I2C_SDA 8
#define I2C_SCL 9
#define BS18_PIN 10
//setup ----------------------
//----------------
//adc-------------
//------------------
//rtc --------------
//--------------------
//DS18B20 ------------
bool presence() {
gpio_set_dir(BS18_PIN, GPIO_OUT);
gpio_put(BS18_PIN, 0);
sleep_us(500); //Min 480
gpio_set_dir(BS18_PIN, GPIO_IN);
sleep_us(70); //MIN 15 + 60
int b = gpio_get(BS18_PIN);
sleep_us(420); //Max 480 - 70
if(b == 1){
return false;
}
return true;
}
void writeBit(int b){
int delay1, delay2;
if(b == 1){
delay1 = 7; //6;
delay2 = 100 -7; //64;
}else{
delay1 = 90; //80;
delay2 = 100 - 90; //10;
}
gpio_set_dir(BS18_PIN, GPIO_OUT);
gpio_put(BS18_PIN, 0);
sleep_us(delay1);
gpio_set_dir(BS18_PIN, GPIO_IN);
sleep_us(delay2);
}
void writeByte(int byte){
for(int i = 0; i < 8; i++){
if(byte & 1){
writeBit(1);
}else{
writeBit(0);
}
byte = byte >> 1;
}
}
uint8_t readBit(){
gpio_set_dir(BS18_PIN, GPIO_OUT);
gpio_put(BS18_PIN,0);
sleep_us(2);// sleep_us(8);
gpio_set_dir(BS18_PIN, GPIO_IN);
sleep_us(15); //sleep_us(2);
uint8_t b = gpio_get(BS18_PIN);
sleep_us(50);//sleep_us(60)
return b;
}
uint8_t readByte(){
uint8_t byte = 0;
for(int i = 0; i < 8; i++) {
byte = byte | (readBit() << i);
}
return byte;
}
int convert(){
int i;
writeByte(0x44);
for(i = 0; i < 500; i++)
{
gpio_set_dir(BS18_PIN, GPIO_OUT);
gpio_put(BS18_PIN,0);
sleep_us(2);// sleep_us(8);
gpio_set_dir(BS18_PIN, GPIO_IN);
sleep_us(15); //sleep_us(2);
uint8_t b = gpio_get(BS18_PIN);
sleep_us(50);//sleep_us(60)
if(b == 1) {
break;
}
sleep_ms(10);
}
return i;
}
uint8_t crc8(uint8_t *data, uint8_t len){
uint8_t i;
uint8_t j;
uint8_t temp;
uint8_t databyte;
uint8_t crc = 0;
for(i = 0; i < len; i++){
databyte = data[i];
for (j = 0; j < 8; j++) {
temp = (crc ^ databyte) & 0x01;
crc >>= 1;
if(temp){
crc ^= 0x8c;
}
databyte >>= 1;
}
}
return crc;
}
bool InitDs()
{
gpio_init(BS18_PIN);
gpio_set_dir(BS18_PIN, GPIO_IN);
gpio_pull_up(BS18_PIN);
if(!presence()){
return false;
}
return true;
}
bool getDsTemperature(float *temperature){
int ret;
int i, j;
if(!presence()){
return false;
}
writeByte(0xCC); //skip rom command
ret = convert();
presence();
writeByte(0xCC);
writeByte(0xBE);
uint8_t data[9];
for(i = 0; i < 9; i++){
data[i] = readByte();
}
uint8_t crc = crc8(data, 9);
if(crc != 0){
return false;
}
int t1 = data[0];
int t2 = data[1];
int16_t temp1 = (t2 << 8) | t1;
float temp = ((float)temp1)/16.0;
*temperature = temp;
return true;
}
//-----------------------
//lcd -------------------
//---------------------------
int main()
{
stdio_init_all();
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_put(LED_PIN, 0);
i2c_init(I2C_PORT, 400*1000);
gpio_set_function(I2C_SDA, GPIO_FUNC_I2C);
gpio_set_function(I2C_SCL, GPIO_FUNC_I2C);
gpio_pull_up(I2C_SDA);
gpio_pull_up(I2C_SCL);
WaitTerminalStartup(30*1000);
printf("\nTerminal connected\n");
ScanI2CBus();
printf("I2C Scan completed\n");
lcd_init();
InitAdc();
InitRtc();
if(!InitDs()){
printf("No device\n");
return 0;
}
printf("Detect device\n");
char buf[128];
datetime_t nowdt;
int presec = -1;
float dsTemp;
while (1) {
rtc_get_datetime(&nowdt);
if(presec != nowdt.sec)
{
float bTemp = ReadOnBoardTemperature();
getDsTemperature(&dsTemp);
sprintf(buf, "%02d/%02d %02d:%02d:%02d",
nowdt.month, nowdt.day, nowdt.hour,nowdt.min, nowdt.sec);
lcd_set_cursor(0, 0);
lcd_string(buf);
sprintf(buf, " DS:%4.1f AD:%4.1f", dsTemp, bTemp);
printf("%4d/%02d/%02d %02d:%02d:%02d DsTemp:%4.1fC AdTemp:%4.1fC\n",
nowdt.year, nowdt.month, nowdt.day,
nowdt.hour,nowdt.min, nowdt.sec, dsTemp, bTemp);
lcd_set_cursor(1, 0);
lcd_string(buf);
}
presec = nowdt.sec;
sleep_ms(200);
}
return 0;
}

コメントをお書きください