Operácie

Senzor teploty a vlhkosti SHT31

Zo stránky SensorWiki

Záverečný projekt predmetu MIPS / LS2024 - Marián Sušina


Zadanie

Mojou úlohou v tomto zadaní bolo zapojiť, naprogramovať a overiť funkčnosť senzoru SHT31 a získané informácie vypísať na LCD displej a aj na obrazovku.

Arduino NANO.

SHT31

SHT31 je digitálny snímač teploty a vlhkosti vyrobený spoločnosťou Sensirion. Používa kombináciu senzorov teploty a vlhkosti, ktoré sú umiestnené na jednom čipe. Tieto senzory merajú teplotu a vlhkosť vzduchu a generujú digitálny výstup, ktorý je následne spracovaný mikrokontrlerom alebo iným zariadením. SHT31 komunikuje cez I2C (Inter-Integrated Circuit) zbernicu, pomocou ktorej môže mikrokontroler komunikovať so snímačom a taktiež si vyžiadať údaje o teplote a vlhkosti. Snímače SHT31 sú známe svojou vysokou presnosťou merania teploty a vlhkosti. Jeho presnosť teploty je typicky +-0,2 stupňa Celzia a presnosť relatívnej vlhkosti sa pohybuje v rozmedzí len +-2%.

Senzor teploty a vlhkosti SHT31.

Literatúra:

Analýza a opis riešenia

Na začiatok si môžeme podľa priloženej schémy pripojiť senzor SHT31 k mikrokontroleru. Na jeho správne používanie musíme použiť pri SCL (časovom kanále) a SDA (dátovom kanále) pull up rezistory.

Schéma zapojenia sensoru SHT31.

Po pripojení senzoru si môžeme pripojiť k adruinu aj LCD displej, ktorý taktiež zapojíme podľa priloženej schémy zapojenia.

Schéma zapojenia LCD displeja.

Ak sa nám už správne podarilo pripojiť senzor aj displej, hardvérová časť nášho zadania je hotová. Ďalej nasleduje programová časť. Pri tejto časti budeme používať datasheety, priložené vyššie. Ak chceme aby náš senzor vypisoval informácie na displej, budeme potrebovať knižnicu pre LCD displej. Pre výpis cez sériový kanál na obrazovku budeme potrebovať knižnicu UART, a pre použitie samotného senzora budeme ešte potrebovať používať knižnicu pre I2C zbernicu, ktorá slúži na komunikáciu mikroprocesora so senzorom, pomocou ktorej budeme vedieť zo senzoru vyčítať získané dáta. Samotný program budeme písať podľa datasheetu, kde si naštudujeme ako náš senzor komunikuje s mikroprocesorom a ako z neho čítať dáta. Na to nám slúži obrázok priloženy nižšie, ktorý opisuje ako správne komunikovať a vyčítavať informácie zo senzoru.

Algoritmus čítania dát zo senzoru.

Na začiatku začneme posielať I2C adresu a hodnotu, ktorou nastavíme, že chceme zapisovať dáta. Po prijatí ACK (acknowledge), nastavíme MSB (most significant bit) a s ním si pre jednoduchosť vypneme Clock stretching. Ďalej nastavíme LSB (least significant bit), ktorým si volíme repeatebility. Ďalej pošleme informáciu o adrese a hodnote, a počkáme na ACK, inak posielanie opakujeme v cykle až kým nedostaneme odpoveď. Keď odpoveď dostaneme, môžeme si do bufferu vyčítať dáta ktoré nám prišli zo senzoru. Tieto dáta nám prídu v dvoch častiach. Prvá nám hovorí o teplote a druhá o vlhkosti. Pomocou vzorčekov, ktoré si nájdeme v datasheete si údaje zo senzoru prepočítame a za pomoci nami vytvorenej funkcie na výpočet a výpis ich môžeme vypísať na displej ale aj cez sériovú linku na obrazovku.

Algoritmus a program

Algoritmus programu spočíva v prijímaní informácii zo senzoru, ktoré prekonvertujeme na požadované veličiny (Pre nás stupne Celzia pre teplotu a % pre vlhkosť), a následne ich vypíšeme aby sme si mohli pozrieť, čo sa nám podarilo odmerať a či nám všetko správne funguje.

/*
	SHT31D_projekt.c
	Autor: Marián Sušina
*/


/* hlavickove subory pre komunikaciu s UART, LCD displejom a I2C zbernicou */
#include <avr/io.h>
#include <stdio.h>
#include <util/delay.h>
#include <stdbool.h>
#include "uart.h"
#include "lcd_ch.h"
#include "i2cmaster.h"

/* Inicializacia funkcie printf() cez UART */
FILE mystdout = FDEV_SETUP_STREAM(uart_putc, NULL, _FDEV_SETUP_WRITE);

/* Adresa senzora v I2C zbernici */
#define SHT31 0x44

/* Funkcia na zobrazenie teploty a vlhkosti na LCD displeji a do Terminalu. Teplota a vlhkost sa formatuje s jednym desatinnym miestom */
void display_temperature_humidity(float temperature, float humidity)
{
	char str[20];

	int temp_int = (int)(temperature * 10);							   // Prevod na cele cislo s jednym desatinnym miestom
	sprintf(str, "\fTeplota:%d.%d \x04\r", temp_int / 10, temp_int % 10); // Formatovanie teploty s jednym desatinnym miestom
	lcd_puts(str);													   // Vypis teploty na displej
	printf("Teplota: %d.%d \x04\r\n", temp_int / 10, temp_int % 10);	   // Vypis teploty cez seriovu linku

	int humi_int = (int)(humidity * 10);							// Prevod na cele cislo s jednym desatinnym miestom
	sprintf(str, "Vlhkos\x03:%d.%d %%", humi_int / 10, humi_int % 10); // Formatovanie vlhkosti s jednym desatinnym miestom
	lcd_puts(str);													// Vypis vlhkosti na displej
	printf("Vlhkos\x03: %d.%d %%\r\n", humi_int / 10, humi_int % 10);	// Vypis vlhkosti cez seriovu linku
}

/* Funkcia na meranie teploty a vlhkosti */
void measure()
{
	uint8_t buf[6];
	i2c_start_wait(SHT31 << 1 | I2C_WRITE); // posiela I2C adresu a hodnotu na zapis a caka na potvrdenie ACK
	i2c_write(0x24);						// nastavenie MSB -> vypneme s nim Clock stretching
	i2c_write(0x0B);						// nastavenie LSB -> nastavyme si repeatebility na medium
	i2c_stop();

	_delay_ms(1); // pauza 1ms po prikaze (podla datasheetu)

	while (i2c_start(SHT31 << 1 | I2C_READ)) // posleme adresu a hodnotu na citanie a pockame na ACK
	{
		i2c_stop(); // ak prisiel NAK posleme STOP
	}

	for (uint8_t i = 0; i < 6; i++) // precitame 6 bajtov zo snimaca
	{
		buf[i] = i2c_read(i != 5); // zapiseme hodnoty zo snimaca do bufferu
	}
	i2c_stop();

	uint16_t T_RAW = buf[0] << 8 | buf[1];	// hodnota teploty
	uint16_t RH_RAW = buf[3] << 8 | buf[4]; // hodnota vlhkosti
	float T = 175.0 * T_RAW / 0xFFFF - 45;	// prepocet na stupne C
	float RH = RH_RAW * 100.0 / 0xFFFF;		// prepocet na %

	display_temperature_humidity(T, RH); // spustenie funkcie na vypis teploty a vlhkosti na displeji a v terminale
}

int main(void)
{

	/* inicializacia portov - vstupy / vystupy */

	DDRD |= (1 << LCD_EN_pin); // Pin D4 (Enable)  PORTD  output
	DDRD |= (1 << LCD_RW_pin); // Pin D3 (RW)      PORTD  output
	DDRD |= (1 << LCD_RS_pin); // Pin D2 (RS)      PORTD  output

	LCD_DATA_PORT |= (1 << LCD_D4_pin) | (1 << LCD_D5_pin) | (1 << LCD_D6_pin) | (1 << LCD_D7_pin); // Piny 1,2,3,4, PORTB ako output (Data pre display)

	/* inicializacia I2C, UARTu a LCD displeja */
	i2c_init();
	uart_init();
	lcd_init();
	
	lcd_cursor(false); //vypnutie kurzora
	
	/* inicializacia specialnych znakov */
	def_spec_znaky();
	
	stdout = &mystdout; // funkcia printf();

	lcd_puts("Start");
	_delay_ms(500);
	
	while (1)
	{
		measure();
		_delay_ms(1000);
	}

	return (0);
}


Zdrojový kód obsahujúci všetky použité knižnice: SHT31D.zip


Overenie

Po pripojení senzora SHT31 a LCD displeja si vieme overiť funkčnosť programu. Po jeho spustení sa nám začne na LCD displeji ale aj na obrazovke zobrazovať teplota a vlhkosť v intervaloch jednej sekundy.

Zapojenie v realite.

Video: overenie funkčnosti