Pembahasan kali ini sudah pernah saya tulis sebelumnya 8 tahun yg lalu, dimana DHT11 merupakan sensor sejuta umat yg sangat umum dipakai untuk belajar IOT. Sensor ini memiliki sistem komunikasi serial 1 bus wire, dimana semua datanya dikirim melalui 1 buah jalur data dengan pembeda 1 dan 0 nya berdasarkan lebar pulsa atau timer dari level logicnya. Jadi untuk pemahaman dasar pembacaan sensornya dapat dibaca di sini : https://www.aisi555.com/2013/05/dht-11-sensor-suhu-dan-kelembaban-murah.html
Jadi jika ingin mengirimkan pembacaan DHT11 menuju serial com di PC, maka scriptnya lumayan memusingkan untuk dilihat, terutama dibagian pembacaan pulsanya.
Namun jangan lupa baca dulu pembahasan pengaturan fusebit nya disini : https://www.aisi555.com/2021/08/attiny2313-vs-arduino-library-bagaimana.html
#define F_CPU 8000000UL //frek clock internal
#include <avr/io.h>
#include <util/delay.h>
#include <avr/pgmspace.h>
#include <string.h>
#include <stdlib.h>
//rumus penentuan baudrate
#define USART_BAUDRATE 9600 // baudrate 9600 bps
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
//deklarasi menu & tulisan .
//gunakan memori flash(PROGMEM) biar cukup
const char suhunya[] PROGMEM = " suhu : ";
const char huminya[] PROGMEM = "C - kelembaban : ";
void init_usart(void)
{
UCSRB |= (1 << TXEN); // kirim aja
UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
UBRRL = BAUD_PRESCALE;
UBRRH = (BAUD_PRESCALE >> 8);
}
//function untuk mengirim char
void USART_Tx(unsigned char data)
{
while (!(UCSRA & (1<<UDRE)));{}
UDR = data; // Send data to the computer
}
//function untuk kirim kalimat dari flash Progmem
void kirim_text(const char *data)
{
while (pgm_read_byte(data) != 0x00)
USART_Tx(pgm_read_byte(data++));
}
void kirim(char *data) //kirim teks dari ram
{
while (*data != 0x00)
USART_Tx(*data++);
}
uint8_t hitung(void)
{
uint8_t a,counter,hasil;
counter=0;
hasil=0;
for (a=8;a>0;a--) // 8 kali tiap perhitungan
{
while(counter <100) // deteksi saat LOW ( tidak ada perhitungan)
{
_delay_us(1);
counter++;
if (bit_is_set(PIND, 3)) break; //tunggu sampai high dan keluar loop
}
counter=0;
while(counter <100)
{
_delay_us(1);
counter++; // counter mendeteksi lebar pulsa
if (bit_is_clear(PIND, 3)) break; //jika low maka keluar dari loop
}
// perhitungan 8 bit decimal dengan geser-geser bit
//jika lebih 25us =1 , kurang < 25 us = 0
if(counter > 25) hasil += (1 << (a-1)) ;
counter=0;
}
return hasil;
}
void baca_sensor()
{
char dum; // variabel sementara
int suhu;
int suhuu;
int humi;
int counter=0;
DDRD|=(1<<PD3); //PD3 sebagai output
_delay_ms(250);
PORTD &=~(1<<PD3); // nolkan PD3
_delay_ms(18); //tunggu 18 ms
PORTD |=(1<<PD3); // naikkan PD3
_delay_us(40); //tunggu 40us
DDRD &=~(1<<PD3); //PD3 sebagai input
//tunggu response dari DHT11
while(counter <100)
{
_delay_us(1);
counter++;
if (bit_is_set(PIND, 3)) break;
}
counter=0;
while(counter <100)
{
_delay_us(1);
counter++;
if (bit_is_clear(PIND, 3)) break;
}
//baca data setelah response, lihat script di pembahasan selanjutnya untuk routine hitung()
//8 bit pertama ( puluhan kelembaban )
humi=hitung();
//8 bit kedua( satuan kelembaban ), tidak usah di baca karena nilai selalu 0 untuk DHT11
hitung();
//8 bit ketiga ( puluhan suhu )
suhu=hitung();
//8 bit keempat ( satuan suhu ), tidak usah di baca karena nilai selalu 0 untuk DHT11
suhuu=hitung();
kirim_text(suhunya);
itoa(suhu,&dum,10);
kirim(&dum);
USART_Tx('.');
itoa(suhuu,&dum,10);
kirim(&dum);
USART_Tx(0xF8);
kirim_text(huminya);
itoa(humi,&dum,10);
kirim(&dum);
USART_Tx('%');
USART_Tx('\n');
USART_Tx('\r');
}
int main(void)
{
init_usart();
while(1) //muter tiada henti
{
baca_sensor();
_delay_ms(5000);
}
}
#define USART_BAUDRATE 9600 // baudrate 9600 bps
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
const char suhunya[] PROGMEM = " suhu : ";
const char huminya[] PROGMEM = " C - kelembaban : ";
int DHT11_Pin = 5; // DHT11 ke pin PD3
int Humidity = 0;
int Temp = 0;
int TempComma = 0;
bool DHTError = false; // Checksum Error
// a Delay routine. Call DelayTimer(time in uSec)
void DelayTimer(long int DelayValue){
long int DelayTime = micros();
do {
}while (micros()-DelayTime < DelayValue);
}
// Main DHT Void
void DHT11(){
long int DataTime = 0;
byte Result[45];
byte DataArray = 0;
byte DataCounter = 0;
byte DHTData[4];
bool BlockDHT=false;
// Trigger Sensor (described in the Datasheet)
pinMode(DHT11_Pin,OUTPUT);
digitalWrite(DHT11_Pin,HIGH);
DelayTimer(250000); //Wait 250millisec
digitalWrite(DHT11_Pin,LOW);
DelayTimer(30000); //Wait 30millisec
digitalWrite(DHT11_Pin,HIGH);
DelayTimer(50); //Wait 50microsec
pinMode(DHT11_Pin,INPUT);
// read the Bits and put them into a Result array (It will count 42 bits. The first two one are useless due my code)
do {
if (digitalRead(DHT11_Pin) == 0 && BlockDHT == false) {BlockDHT = true;Result[DataArray]=(micros()-DataTime);DataArray++;DataTime=micros();} //If DHT pin is low, go to next Dataset
if (digitalRead(DHT11_Pin) == 1) {BlockDHT = false;} // As long as DHT pin is Hight add time in Microseconds to Result
}while((micros()-DataTime) < 150); // if DTH Sensor high for more than 150 usec, leave loop
// Asign 1 or 0 to Result variable. If more than 80uS Data as “1”
// Starting at Data set 02. First two Datasets are ignored!
for (int i=2; i< DataArray; i++) {
if (Result[i] <= 90) Result[i]=0; else Result[i]=1;
}
for (int j=0; j< 5; j++){ // redo it for the 5 Bytes (40 Databits /8 = 5)
for (int i=0; i< 8; i++) {bitWrite(DHTData[j], 7-i, Result[i+2+(j*8)]);} // Create 5 Databytes from the 40 Databits (Ignoring the 2 first Databits)
}
// check checksum }
if (DHTData[4] == (DHTData[0]+DHTData[1]+DHTData[2]+DHTData[3])){Humidity = DHTData[0];Temp = DHTData[2];TempComma = DHTData[3];DHTError=false;} else DHTError=true; //If Checksum is worng, Temp=99 (Dataset 0-3 in addition = Dataset 4 = Checksum OK)
}
void init_usart(void)
{
UCSRB |= (1 << TXEN); // kirim aja
UCSRC |= (1 << UCSZ0) | (1 << UCSZ1);
UBRRL = BAUD_PRESCALE;
UBRRH = (BAUD_PRESCALE >> 8);
}
void USART_Tx(unsigned char data)
{
while (!(UCSRA & (1<<UDRE)));{} // wait till transmit Data register is empty
UDR = data; // Send data to the computer
}
//function untuk kirim kalimat
void kirim_text(const char *data)
{
while (pgm_read_byte(data) != 0x00)
USART_Tx(pgm_read_byte(data++));
}
void kirim(char *data)
{
while (*data != 0x00)
USART_Tx(*data++);
}
void setup() {
// put your setup code here, to run once:
init_usart();
}
void loop() {
char dum;
DHT11();
if (DHTError == false)
{ kirim_text(suhunya);
itoa(Temp,&dum,10);
kirim(&dum);
USART_Tx(',');
itoa(TempComma,&dum,10);
kirim(&dum);
kirim_text(huminya);
itoa(Humidity,&dum,10);
kirim(&dum);
USART_Tx('%');
USART_Tx('\n');
USART_Tx('\r');
}
else kirim("Error");
DelayTimer(1000000); //wait 1 sec
}