Fork me on GitHub

Microcontrolandos

O Blog está passando por uma fase de mudanças. Todos os posts estão sendo atualizados, códigos, links e imagens estão sendo arrumados. Conteúdos novos ainda estão por vir.

PIC: DS18S20 e DS18B20

Share:

PIC: DS18S20 e DS18B20


Neste post mostrarei como utilizar o sensor de temperatura DS18B20 e DS18S20 com o PIC. Este sensor utiliza o protocolo One-Wire, e requer apenas um fio de comunicação.



Mostrarei o jeito mais simples de realizar a leitura do sensor. Criei uma função que faz a leitura e salva em uma string prontinha pra ser escrita num display de LCD.


BIBLIOTECA
#include <built_in.h>

#define RES9 3
#define RES10 2
#define RES11 1
#define RES12 0

static char resolution = 0;

void DS18B20_getTemp( char *DS18x20_PORT, char DS18x20_PIN, char *outTemp )
{
unsigned temp, Temp_f;
char i;

 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xCC );  //Skip ROM
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0x44 );  //Inicia a conversao
    
 //Espera o tempo da conversao
 for(i = 0; i < (1 << (3 - resolution)); i++)
    Delay_ms( 95 );
    
 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xCC );  //Skip ROM
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xBE );  //Inicia a leitura
    
 Lo(temp) =  Ow_Read( DS18x20_PORT, DS18x20_PIN );
 Hi(temp) =  Ow_Read( DS18x20_PORT, DS18x20_PIN );
    
 outTemp[0] = 32;
 outTemp[4] = '.';

 if(Hi(temp).B7)
 {
     temp = ~temp + 1;
     outTemp[0] = '-';
 }
        
 temp <<= 4;
 Lo(temp) >>= ( 4 + resolution );
 Temp_f = Lo(temp) * 625;

 outTemp[1] = Hi(temp) / 100 + '0';
 outTemp[2] = (Hi(temp) / 10) % 10 + '0';
 outTemp[3] = Hi(temp) % 10 + '0';
 outTemp[5] = Temp_f / 1000 + '0';
 outTemp[6] = (Temp_f / 100) % 10 + '0';
 outTemp[7] = (Temp_f / 10) % 10 + '0';
 outTemp[8] = (Temp_f % 10) + '0';
 outTemp[9] = 223; //simbolo de graus 
 outTemp[10] = 'C';
 outTemp[11] = 0;
}

void DS18S20_getTemp( char *DS18x20_PORT, char DS18x20_PIN, char *outTemp )
{
unsigned temp;
 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xCC );  //Skip ROM
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0x44 );  //Inicia a conversao
    
 //Espera o tempo da conversao
 Delay_ms( 750 );
    
 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xCC );  //Skip ROM
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xBE );  //Inicia a leitura
    
 Lo(temp) =  Ow_Read( DS18x20_PORT, DS18x20_PIN );
 Hi(temp) =  Ow_Read( DS18x20_PORT, DS18x20_PIN );
    
 outTemp[0] = 32;
 outTemp[4] = '.';
 
 if(Hi(temp).B7)
 {
   Lo(temp) = ~Lo(temp);
   outTemp[0] = '-';
 }
        
 outTemp[5] = (Lo(temp).B0 == 1) ? '5' : '0';
 Lo(temp) >>= 1;
 outTemp[1] = Lo(temp) / 100 + '0';
 outTemp[2] = (Lo(temp) / 10) % 10 + '0';
 outTemp[3] = Lo(temp) % 10 + '0';
 outTemp[6] = 223;
 outTemp[7] = 'C';
 outTemp[8] = 0;
}

void DS18B20_Set_Resolution( char *DS18x20_PORT, char DS18x20_PIN, char res )
{
 resolution = res;
 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0xCC );  //Skip ROM
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0x4E );  //Write Scratchpad
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0 );  //Th
 Ow_Write( DS18x20_PORT, DS18x20_PIN, 0 );  //Tl
 Ow_Write( DS18x20_PORT, DS18x20_PIN, (0x1F | (res << 5)) );  //Config
 Ow_Reset( DS18x20_PORT, DS18x20_PIN );
}


DS18B20_getTemp( char *DS18x20_PORT, char DS18x20_PIN, char *outTemp )
DS18S20_getTemp( char *DS18x20_PORTchar DS18x20_PINchar *outTemp )
*DS18x20_PORT - Porta onde está conectado o sensor.
DS18x20_PIN - Pino onde está conectado o sensor.
*outTemp - String onde será salvo o valor da temperatura.

DS18B20_Set_Resolution( char *DS18x20_PORT, char DS18x20_PIN, char res )
res - Resolução:
RES9 - 9 Bits de resolução
RES10 - 10 Bits Bits de resolução
RES11 - 11 Bits Bits de resolução
RES12 - 12 Bits Bits de resolução



EXEMPLO:
MikroC PRO PIC
sbit LCD_RS at RB0_bit;
sbit LCD_EN at RB1_bit;
sbit LCD_D4 at RB2_bit;
sbit LCD_D5 at RB3_bit;
sbit LCD_D6 at RB4_bit;
sbit LCD_D7 at RB5_bit;

sbit LCD_RS_Direction at TRISB0_bit;
sbit LCD_EN_Direction at TRISB1_bit;
sbit LCD_D4_Direction at TRISB2_bit;
sbit LCD_D5_Direction at TRISB3_bit;
sbit LCD_D6_Direction at TRISB4_bit;
sbit LCD_D7_Direction at TRISB5_bit;

//COPIE E COLE O CÓDIGO ACIMA AQUI!!!

char Temperatura[12];

void main()
{
   CMCON = 0x07;
   Lcd_Init();
   Lcd_Cmd( _LCD_CURSOR_OFF );
   
   while(1)
   {
      //Faz a leitura do sensor DS18B20 conectado no pino RA0
      Ds18B20_getTemp( &PORTA, 0, Temperatura );
      
      Lcd_Out( 1, 1, Temperatura );
      
      //Faz a leitura do sensor DS18S20 conectado no pino RA1
      Ds18S20_getTemp( &PORTA, 1, Temperatura );
      
      Lcd_Out( 2, 1, Temperatura );
   }
}

13 comentários:

  1. No caso eu quero utilizar o DS18B20 poderia me informar oq devo fazer? Estou utilizando C no HI-TECH

    ResponderExcluir
    Respostas
    1. se reparar no exemplo ele usa DS18B20_gettemp para obter temperatura do DS18B20! agora HITECH nao seria como ficaria o codigo! eu mexo mto com MIKROC

      Excluir
  2. Boa Noite, alguem já testou este codigo, copiei mais não estou conseguindo ler o ds18b20.

    ResponderExcluir
  3. Funcionou perfeitamente, muito obrigado !

    ResponderExcluir
  4. Boa tarde , obrigado pelo código, mas estou com um problema , no simulador a resolução funciona 12bist perfeitamente, mas quando jogo na placa ele mostra resolução de de 10bits ou seja de 0,5 a 0,5 ºc . Vc poderia mim ajudar. meu e-mail e gr1_automacao@hotmail.com

    ResponderExcluir
    Respostas
    1. recomendavel deixa em 10 bits na programacao pq ele da atrasos de leitura e/ou leituras incorretas!

      Excluir
  5. pessoal boa tarde, estou tendo dificuldade em algumas comandos dessa programação, na biblioteca do sensor DS18B20_getTemp( char *DS18x20_PORT, char DS18x20_PIN, char *outTemp )
    DS18S20_getTemp( char *DS18x20_PORT, char DS18x20_PIN, char *outTemp ), eu tenho que mudar o port, pin e outtempo certo? esse outtemp que numero ou qual comando tenho que colocar?
    e DS18B20_Set_Resolution( char *DS18x20_PORT, char DS18x20_PIN, char res ) eu tambem tenho que mudar o port, pin, e char res? se eu quero 10bits eu tenho que colocar RES10 ou só 10? estou utilizando o pic16f877A, e nao to conseguindo ler o valor dos sensores no PORTA RA1 e RA0, o que mais da biblioteca ou programação teria que mudar?

    ResponderExcluir
  6. boa noite; trabalho com um equipamento que tem sua temperatura monitorada por um sensor DS1820. O sensor queimou e subistitui pelo ds18b20, porem, os numeros mostrados no display estao muito estranhos; isto tem haver com a resolução?

    ResponderExcluir
  7. Olá, tudo bom? Cara eu não consigo de jeito nenhum mostrar a temperatura, sempre fica em 0.00. Já tentei de tudo e nada acontece, o meus sensor DS18B20 é encapsulado, por isso fica dificil a identificação do pino. Mas, fui testando de um a um e mesmo assim não consegui mostrar nenhuma temperatura, o que pode ser?

    ResponderExcluir
    Respostas
    1. Problema solucionado, encontrei a pinagem correta. Valeu por disponibilizar este incrível código!

      Excluir
  8. Olá, tudo bem?
    Precisaria desse código, para um termostato (sem LCD)... Tentei adaptar uma leitura com bloco if da temperatura para ativar um cooler, mas não obtive sucesso... Quebrando cabeça aqui...
    Teria como me ajudar?
    Obrigado!

    ResponderExcluir
  9. Alguem conseguiu usar esse código? Não está funcionando aqui.

    ResponderExcluir
  10. Boa noite! Ótimo conteúdo! Tenho uma dúvida. Qual é o procedimento de atualização da resolução. No código, a atualização não é automática, ou seja, não existe nenhuma chamada da função "DS18B20_Set_Resolution( char *DS18x20_PORT, char DS18x20_PIN, char res )". Como então, por favor, atualizarei a resolução? Desde já, obrigado!

    ResponderExcluir