DS18b20 Temp reading MCU 16F18456

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
Hi,
Have been struggeling for long time, and have no ideas,
Temp allways read 0.
Can see that comm to 18b20 should be ok, see atached JPGUdklip.JPG
Read from MCU Pin to DS18b20 sensor.

But somehow the data is not read by the MCU,
Attached most code.
Code:
#include <xc.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// CONFIG1
#pragma config FEXTOSC = OFF    // External Oscillator mode selection bits->Oscillator not enabled
#pragma config RSTOSC = HFINT1    // Power-up default value for COSC bits->HFINTOSC (1MHz)
#pragma config CLKOUTEN = OFF    // Clock Out Enable bit->CLKOUT function is disabled; i/o or oscillator function on OSC2
#pragma config CSWEN = ON    // Clock Switch Enable bit->Writing to NOSC and NDIV is allowed
#pragma config FCMEN = ON    // Fail-Safe Clock Monitor Enable bit->FSCM timer enabled

// CONFIG2
#pragma config MCLRE = ON    // Master Clear Enable bit->MCLR pin is Master Clear function
#pragma config PWRTS = OFF    // Power-up Timer Enable bit->PWRT disabled
#pragma config LPBOREN = OFF    // Low-Power BOR enable bit->ULPBOR disabled
#pragma config BOREN = ON    // Brown-out reset enable bits->Brown-out Reset Enabled, SBOREN bit is ignored
#pragma config BORV = LO    // Brown-out Reset Voltage Selection->Brown-out Reset Voltage (VBOR) set to 2.45V
#pragma config ZCDDIS = OFF    // Zero-cross detect disable->Zero-cross detect circuit is disabled at POR.
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
#pragma config STVREN = ON    // Stack Overflow/Underflow Reset Enable bit->Stack Overflow or Underflow will cause a reset

// CONFIG3
#pragma config WDTCPS = WDTCPS_31    // WDT Period Select bits->Divider ratio 1:65536; software control of WDTPS
#pragma config WDTE = OFF    // WDT operating mode->WDT Disabled, SWDTEN is ignored
#pragma config WDTCWS = WDTCWS_7    // WDT Window Select bits->window always open (100%); software control; keyed access not required
#pragma config WDTCCS = SC    // WDT input clock selector->Software Control

// CONFIG4
#pragma config BBSIZE = BB512    // Boot Block Size Selection bits->512 words boot block size
#pragma config BBEN = OFF    // Boot Block Enable bit->Boot Block disabled
#pragma config SAFEN = OFF    // SAF Enable bit->SAF disabled
#pragma config WRTAPP = OFF    // Application Block Write Protection bit->Application Block not write protected
#pragma config WRTB = OFF    // Boot Block Write Protection bit->Boot Block not write protected
#pragma config WRTC = OFF    // Configuration Register Write Protection bit->Configuration Register not write protected
#pragma config WRTD = OFF    // Data EEPROM write protection bit->Data EEPROM NOT write protected
#pragma config WRTSAF = OFF    // Storage Area Flash Write Protection bit->SAF not write protected
#pragma config LVP = ON    // Low Voltage Programming Enable bit->Low Voltage programming enabled. MCLR/Vpp pin function is MCLR.

// CONFIG5
#pragma config CP = OFF    // UserNVM Program memory code protection bit->UserNVM code protection disabled



#define _XTAL_FREQ 32000000
#define Skip_ROM             0xCC
#define Convert_T             0x44
#define Read_scratchpad     0xBE

#define Port_18B20             RB2
#define Tx_18B20             TRISB2=0
#define Rx_18B20             TRISB2=1

#define WAIT1                1000
#define WAIT2                500

#define DS18B20_CONV_TIME    750
#define DS18B20_RESET_PULSE 480
#define DS18B20_WAIT_TIME     60
#define DS18B20_PULLUP_TIME 2

#define ONEWIRE_PRESENT     0
#define ONEWIRE_ABSENT         1

unsigned char lsb;
    unsigned char msb;
    unsigned char decimal;
    unsigned char buffer[11];
    unsigned int sign_flag =0;
    unsigned int integer =0;
    unsigned int integer1 =0;
    unsigned int integer2 =0;
    unsigned int integer3 =0;
    unsigned int integer4 =0;
    signed int total,fraction;

void __interrupt() myISR(void)
{
//interrupt on INT ,  Timer1 .
    if (TMR0IF) // interrupt timer1 ~ 8,45 sec gone, time for new Temp reading
    {
        TMR0IF=0; // clear interrupt
        sec8_gone=1; // set flag.
        RC3=!RC3; // test
    } // end 8 sec interrupt.
    
    if (INTF) // interrupt to falling edge rain.
    {INTF=0;
    rain_today++;
    } // end Rain interrupt
    
    
}

void setup (void)
{ // OSC and PIN
  OSCCON1 = 0x60;
    // CSWHOLD may proceed; SOSCPWR Low power;
    OSCCON3 = 0x00;
    // MFOEN disabled; LFOEN disabled; ADOEN disabled; SOSCEN disabled; EXTOEN disabled; HFOEN disabled;
    OSCEN = 0x10; // 31 khz enabel.
    
    // HFFRQ 32_MHz;
    OSCFRQ = 0x06;
    
    
    // MFOR not ready;
    OSCSTAT = 0x00;
    // HFTUN 0;
    OSCTUNE = 0x00;
    
    
    
    // -------------- INT Setup --------------------//
    INTCONbits.INTEDG = 0; // falling edge on INT pin, for driving rain,
    
    
    /////////////////  EUSART Setup ------------------------------
   PIE3bits.RC2IE = 0; // disabel interrupt
    // ABDOVF no_overflow; SCKP Non-Inverted; BRG16 16bit_generator; WUE disabled; ABDEN disabled;
    BAUD2CON = 0x00;

    // SPEN enabled; RX9 8-bit; CREN enabled; ADDEN disabled; SREN disabled;
    RC2STA = 0x90;

    // TX9 8-bit; TX9D 0; SENDB sync_break_complete; TXEN disabled; SYNC asynchronous; BRGH hi_speed; CSRC slave;
    TX2STA = 0x00;

  
    
    SP2BRG = 0x33; // running 9600 Baudrate-.
  
            
 //--------------------- pin setup-----
     /**
    LATx registers
    */
    LATE = 0x00;
    LATA = 0x00;
    LATB = 0x00;
    LATC = 0x00;

    /**
    TRISx registers
    */
    TRISE = 0x08;
    TRISA = 0x00;
    TRISB = 0x81;
    TRISC = 0x00; // all output.

    /**
    ANSELx registers
    */
    ANSELC = 0x00;
    ANSELB = 0x00;
    ANSELA = 0x00;

    /**
    WPUx registers
    */
    WPUE = 0x00;
    WPUB = 0x00;
    WPUA = 0x00;
    WPUC = 0x00;

    /**
    ODx registers
    */
    ODCONE = 0x00;
    ODCONA = 0x00;
    ODCONB = 0x00;
    ODCONC = 0x00;

    /**
    SLRCONx registers
    */
    SLRCONA = 0xFF;
    SLRCONB = 0xFF;
    SLRCONC = 0xFF;

    /**
    INLVLx registers
    */
    INLVLA = 0x3F;
    INLVLB = 0x3F;
    INLVLC = 0x3F;
    
    INTPPS = 0x08;   //RB0->EXT_INT:INT;     
   //  RB6PPS = 0x25;   //RB6->EUSART2:TX2;   
   // CK2PPS = 0x07; // RB6 Port to TX2-
    RB6PPS=0x25; // RB6 output UART
     //RX2DTPPS = 0x0F;   //RB7->EUSART2:RX2;   
    RX2PPS = 0x0F; // try again
    
    
    //------------------- timer 0 ----------------------------///
       T0CON1 = 0x82; // LFINTOSC  SYNC 1:4 prescale

    // TMR0H 0;
    TMR0H = 0x00;

    // TMR0L 0;
    TMR0L = 0x00;
    T0CON0 = 0x90;  // setting timer to input from 16 bit,POTSCALE 1:1, and interrupr ~ 8,45 sec.
}

/////////////   TEMPERATURE READING //////////////////////

  unsigned char reset(void)
{
      
    Tx_18B20;
    Port_18B20 = 0;
    __delay_us(DS18B20_RESET_PULSE);
    Rx_18B20;
    __delay_us(DS18B20_WAIT_TIME);

    if (Port_18B20 == 1)
    {
        __delay_us(DS18B20_RESET_PULSE);
        return ONEWIRE_PRESENT;
    }
    else
    {__delay_us(DS18B20_RESET_PULSE);
    return ONEWIRE_ABSENT;}
}

void write(char WRT)
{
    char i,Cmd;
    Cmd = WRT;
    Rx_18B20;
    for(i = 0; i < 8; i++)
    {
        if((Cmd & (1<<i))!= 0)
        {

            Tx_18B20;
            Port_18B20 = 0;
            __delay_us(DS18B20_PULLUP_TIME);
            Rx_18B20;
            __delay_us(DS18B20_WAIT_TIME);
        }
        else
        {

            Tx_18B20;
            Port_18B20 = 0;
            __delay_us(DS18B20_WAIT_TIME);
            Rx_18B20;
        }
    }
}


unsigned char read()
{
    char i,result = 0;
    Rx_18B20;
    for(i = 0; i < 8; i++)
    {
        Tx_18B20;
        Port_18B20 = 0;
        __delay_us(DS18B20_PULLUP_TIME);
        Rx_18B20;
        if(Port_18B20 != 0)
        {
            result |= 1<<i;//i
        }
        __delay_us(DS18B20_WAIT_TIME);
    }
    return result;
}

void laestemp (void)
{
    reset();
                write(Skip_ROM);
                write(Convert_T);
                __delay_ms(DS18B20_CONV_TIME);

               reset();
                write(Skip_ROM);
                write(Read_scratchpad);
                lsb = read();
                msb = read();
             reset(); 
                unsigned int sign = 248 & msb;
                if(sign==0)
                    decimal = lsb & 15;

                if(sign!=0)
                {
                    decimal = lsb ^ 15;
                    decimal = decimal^255;

                }

                unsigned char places[4]= {0};
                if((decimal&8) == 8)
                {

                    places[0] =  places[0] + 5;

                }

                if((decimal&4)==4)
                {
                    places[0] = places[0] + 2;
                    places[1] = places[1] + 5;
                }

                if((decimal&2)==2)
                {
                    places[0] = places[0] + 1;
                    places[1] = places[1] + 2;
                    places[2] = places[2] + 5;
                }

                if((decimal&1)==1)
                {
                    places[1] = places[1] + 6;
                    if(places[1]>9)
                    {
                        places[1]= places[1]-10;
                        places[0]= places[0]+1;
                    }

                    places[2] = places[2] + 2;
                    places[3] = places[3] + 5;

                }


                if(sign!=0)
                {
                    integer1 =(places[0]*1000);
                    integer2 = (places[1]*100);
                    integer3 = (places[2]*10);
                    integer4 = (places[3]);
                    integer = integer1+integer2+integer3+integer4;
                    if(integer==0)
                    {
                        sign_flag=1;
                    }
                    integer = 10000-integer;

                    integer1 = integer/1000;
                    integer2 = (integer/100)-(10*integer1);
                    integer3 = (integer/10)-(100*integer1)-(10*integer2);
                    places[0]= integer1;
                    places[1]= integer2;
                    places[2]= integer3;
                    places[3]= integer4;

                }
                lsb = lsb >> 3;
                msb = msb << 5;
                lsb = msb | lsb;
                if(sign !=0)
                {
                    lsb =(lsb)^255;
                    buffer[0]='-';
                }
                else
                    buffer[0] = '+';

                lsb = lsb >>1;
                printf("sign %d\n", sign_flag);

                buffer[1] = ((lsb / 100)%10) + 48;
                buffer[2] = (((lsb / 10)%10) + 48);
                buffer[3] = (((lsb)%10))+ 48 + sign_flag;
                buffer[4] = '.';
                buffer[5] = ((places[0]%10)+48);
                buffer[6] = ((places[1]%10)+48);
                buffer[7] = ((places[2]%10)+48);
                buffer[8] = ((places[3]%10)+48);
                buffer[9] = ' ' ;//0xF8;
                buffer[10]= 'C';
                total=0;
                total=((lsb / 100)%10)* 100;
                total=total+(((lsb / 10)%10) * 10);
                total=total+(((lsb)% 10))+  sign_flag;
                fraction=0;
                fraction=((places[0]%10)+48)-48;
                 if (sign!=0)
                        
                    {now=500-((total*10)+fraction); // add 50 degree, so no negativ result
                    
                 }
                     if (sign==0)
                      {
                         now=500+((total*10)+fraction); // add 50 degrees
                    
                }
}

void main (void)
{
    setup();
    PIR0bits.TMR0IF = 0;
    PIE0bits.TMR0IE = 1;
    T0CON0bits.T0EN = 1;
   PEIE=1; // enabel interrupt.
    GIE=1; // Global interrupt.
    INTF=0;
    INTE=1; // enabel interrupt on INT Pin
    rain_today=0;
    now=0;
  // TX2STAbits.TXEN=1;
    
    while(1)
    {
              
        if (sec8_gone==1)
        {sec8_gone=0;
        laestemp(); // read temperatur.
            //send temperatur return, and rain, accept before setting 0 in rain,
      // send_rain_temp();
        
        }
        if (clear_to_reset==1)
        {clear_to_reset=0;
        rain_today=0;
        
        }
        
            
              
        
    }// end while
    
} // end main
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
Have been testing a lot, and somehow the "Input" from my Ds18b20 allways read 0, but by scope an logic analyser i got some data.
IF i do a test without the Probe, the input is correct read by MCU, High-Low. (Flashing LED when input low and no light when input is high.).
 

hexreader

Joined Apr 16, 2011
547
Code:
#pragma config PPS1WAY = ON    // Peripheral Pin Select one-way control->The PPSLOCK bit can be cleared and set only once in software
I prefer setting this to be OFF, not ON ....

EDIT: I don't think it is strictly necessary for your code, since you do not lock PPS, but OFF has fixed issues for me in the past.

Apologies - a better reading of the datasheet makes me think that this is a pointless post - ignore it
 
Last edited:

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
Some must have a hint, i am blind, Have testet / Changing a lot, The MCU will not read correct. Only test i have done is by letting MCU read in Pin and setting outpin, so it can read, Have tried different ports and all setting WPU SLEV ect. 3 different Probe ds18b20.test22.JPG
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
Any suggestions have tried with 4 different sensor. Different settings
Have found other codes, but they came out with same result.
Sensor reply presence, but after that i dont think it reply anything.
 

atferrari

Joined Jan 6, 2004
4,577
I wrote my own code (Assembly) and every sensor was, first of all, identified and ID saved somewhere. If identification failed there was a warning and stopped so it won't proceed any further.
 

JohnInTX

Joined Jun 26, 2012
4,654
Can you use the other two traces on the analyzer to output a quick pulse to an unused output port when you do the read sampling? That would show what the actual timing is. Use the other one for when you switch from TX to RX and back or whatever you find useful.

You can use macros to turn them on and off easily:
//#define ShowRX LATx,x = 1; nop(); LATx=0; // or something like that
//#define ShowRX ;
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
HAve done some test
Connected LogicAnalyser to 3 channels.
1 = Read
2 = High when start RESET and Low when start WRITE
3 = Probe.
Modified Read procedure to


Code:
unsigned char read()
{
    char i,result = 0;
    Rx_18B20;
    for(i = 0; i < 8; i++)
    {
        Tx_18B20;
        Port_18B20 = 0;
        Port_Test=!Port_Test;
        __delay_us(DS18B20_PULLUP_TIME);
        Rx_18B20;
        if(Port_18B20 != 0)
        {
            result |= 1<<i;//i
        }
        __delay_us(DS18B20_WAIT_TIME);
    }
    return result;
}
And here is result.
3 inout.JPGResulution is 125us.
Between start RESET ( Blue Line) and start READ(Purple Line) is 2,67 ms.

EDIT. Second RESET,.
reset();
write(Skip_ROM);
write(Read_scratchpad);
 
Last edited:

JohnInTX

Joined Jun 26, 2012
4,654
Ahh.. you are setting the TRIS bit in line 11 then reading immediately in line 12. At 32MHz, there is no way that the signal line gets pulled up that fast. You will read 0 every time. I would split up the various delays to read in the middle of the bit cell after release.

I did print out your original code but didn’t have an opportunity to read it in detail but the problem is there also.

At 125uS resolution on the analyser you would be hard-pressed to see the actual problem but you can infer that the timings are closer than you want.

Don’t forget that interrupts will affect your delays also.
 

Thread Starter

FroceMaster

Joined Jan 28, 2012
678
Code:
unsigned char read()
{
    char i =0;
     result = 0;
    Rx_18B20;
  
    for(i = 0; i < 8; i++)
    {
        Tx_18B20;
         Port_18B20 = 0;
        __delay_us(1);//DS18B20_PULLUP_TIME);
        Rx_18B20;
        __delay_us(2);
    
        if(Port_18B20 != 0)
        {
            result |= 1<<i;
        
        }
        __delay_us(DS18B20_WAIT_TIME);
    }
    return result;
}
Thanks, JohnInTX,. That did the work.
Reason to run at 32 MHz, is easyer to set up, when comm with another MCU by SERIAL same config both places.
 
Top