Temperature wrong ds18b20

Thread Starter

FroceMaster

Joined Jan 28, 2012
702
Hi
When i read out the temperature i get a wrong output.
-1.7500
-1,8125
-1,8750
-1,9375
-1,0000
-2,0625
-2,1250
-2,1875
-2,2500
-2,3125

See my point ?
all code i got in here from one of you.
here is the part that "convert" to text.

Code:
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] = ' ' ;
                buffer[10]= 'C';
And here you have all the code.
PIC 16F1509
Code:
#include <htc.h>
#include <stdio.h>
#include <stdlib.h>
#include "lcd.h"
#include <string.h>

#pragma config FOSC = LP//INTOSC      // Oscillator Selection Bits (XT Oscillator, Crystal/resonator connected between OSC1 and OSC2 pins)
#pragma config WDTE = OFF       // Watchdog Timer Enable (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable (PWRT disabled)
#pragma config MCLRE = OFF      // MCLR Pin Function Select (MCLR/VPP pin function is digital input)
#pragma config CP = OFF         // Flash Program Memory Code Protection (Program memory code protection is disabled)
#pragma config BOREN = OFF      // Brown-out Reset Enable (Brown-out Reset enabled)
#pragma config CLKOUTEN = OFF   // Clock Out Enable (CLKOUT function is disabled. I/O or oscillator function on the CLKOUT pin)
#pragma config IESO = OFF       // Internal/External Switchover Mode (Internal/External Switchover Mode is enabled)
#pragma config FCMEN = ON       // Fail-Safe Clock Monitor Enable (Fail-Safe Clock Monitor is enabled)

// CONFIG2
#pragma config WRT = OFF        // Flash Memory Self-Write Protection (Write protection off)
#pragma config STVREN = ON      // Stack Overflow/Underflow Reset Enable (Stack Overflow or Underflow will cause a Reset)
#pragma config BORV = LO        // Brown-out Reset Voltage Selection (Brown-out Reset Voltage (Vbor), low trip point selected.)
#pragma config LPBOR = OFF      // Low-Power Brown Out Reset (Low-Power BOR is disabled)
#pragma config LVP = ON         // Low-Voltage Programming Enable (Low-voltage programming enabled)

#define _XTAL_FREQ 8000000
#define FOSC 2000000L

#define set_hour RB4 //Buttons
#define set_minut RC2
#define set_week RC1
#define set_time RC3

#define SCS_BIT                0x00
#define INT_OSC_8MHZ         (0b01110000 | SCS_BIT)

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

#define Port_18B20             RB5
#define Tx_18B20             TRISB5 = 0
#define Rx_18B20             TRISB5 = 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 min,max,minold,minhele,minfraction,maxhele,maxfraction,total,fraction,now;
    int tempmax,minnegativ,maxnegativ;
    char hele[10],deci[10];
bit sec,vis;
int xpulse,secund,minut,hour,x,today_rain,r_regn,rainTMR0,visning,f_gennemlob,negativ,maxxpulse;
char test[10];
unsigned char raindays[31];
volatile unsigned char week_day;
unsigned char mintime[3],maxx[3];
unsigned char maxtime[3],minx[3];
char mintemp[3],maxtemp[3];

const char * const day_of_week_names[] = {"Mandag ",
                                          "Tirsdag",
                                          "Onsdag ",
                                          "Torsdag",
                                          "Fredag ",
                                          "Lordag ",
                                          "Sondag "
                                         };

static void interrupt isr(void)   // Here is interrupt function - the name is unimportant.
{
 
if(TMR1IF)             // Was this a timer overflow?
    {
          TMR1IF=0;        // Clear interrupt flag, ready for next
         TMR1L=0x00;
         TMR1H=0x80;     // If we set TMR1 to start at 0x8000 (32768), the TMR1 will overflow every 1 second
         //timer_tick=1;    // 1 sec went.
         sec=1;             // adds a sec.
     //RB7=!RB7;
    /*if (sec==60)         // if sec = 60
    {
        sec=0;           // sekund = 0
           minut_tick=1;      // adds 1 minute.
 
    }                    // end "if second"
     */
    }
/*if(TMR2IF)
{
TMR2IF=0;
maxxpulse++;
//if (xpulse==maxxpulse)
//{ xpulse=0;
//sec=1;
if (maxxpulse==25)
{ sec=1;
maxxpulse=0;
}
}*/
}

void setup (void)
{

IRCF0=0; //8 mhz
IRCF1=1;
IRCF2=1;
IRCF3=1;
TRISA=0; //set all port out
TRISA2=1; // set port 2 in
TRISA4=1; // set port 4 ind.
TRISA5=1; // set port 5 ind.
TRISB4=1; // port B 4 in
TRISB5=1; // port b 5 in // temp
TRISB6=0; // b6 ud
TRISB7=1; // port b7 in
TRISC0=0;
TRISC1=1;
TRISC2=1;
TRISC3=1;
TRISC4=0;
TRISC5=0;
TRISC6=0;
TRISC7=0;
OSCCON = INT_OSC_8MHZ;

CM1CON0 = 0;
    CM2CON0 = 0;
//Timer 0 is counter to rain. input RA2
TMR0CS=1; //use t0cki.
PSA=1; // no prescaller
TMR0SE=1; // high to low transiton

//timer 1 ... ur
TMR1CS1=1; //CLOCK SOURCE S-ELECTIONS
TMR1CS0=0;
//11 =Timer1 clock source is Capacitive Sensing Oscillator (CAPOSC)
//10 =Timer1 clock source is pin or oscillator:
//If T1OSCEN = 0:
//External clock from T1CKI pin (on the rising edge)
//If T1OSCEN = 1:
//Crystal oscillator on SOSCI/SOSCO pins
//01 =Timer1 clock source is system clock (FOSC)
//00 =Timer1 clock source is instruction clock (FOSC/4)
T1CKPS1=0; // <1:0>: Timer1 Input Clock Prescale Select bits
T1CKPS0=0;
//11 = 1:8 Prescale value
//10 = 1:4 Prescale value
//01 = 1:2 Prescale value
//00 = 1:1 Prescale value
T1OSCEN=1;//LP Oscillator Enable Control bit
//1 = Dedicated Timer1 oscillator circuit enabled
//0 = Dedicated Timer1 oscillator circuit disabled
nT1SYNC=1; //: Timer1 Synchronization Control bit
TMR1ON=0;//: Timer1 On bit
TMR1H = 0x80;     // preset for timer1 MSB register
TMR1L = 0x00;     // preset for timer1 LSB register
TMR1GE=0; // gate for timer1 disable.
//T1GCON: TIMER1 GATE CONTROL REGISTER
//bit 7 TMR1GE: Timer1 Gate Enable bit
//If TMR1ON = 0:
//This bit is ignored
//If TMR1ON = 1:
//1 = Timer1 counting is controlled by the Timer1 gate function
//0 = Timer1 counts regardless of Timer1 gate function
  //Timer1 Interrupt prepare
   TMR1IE=1;// PIE1 register
   PEIE=1; //INTCON register
    PIR1=0; // Clear all bits PERIPHERAL INTERRUPT REQUEST REGISTER 1

    // internal ext interrupt
//    INTE=1;
 
// TIMER 2.....
T2CKPS0=1;//Prescale 64
T2CKPS1=1;
T2OUTPS0=1; // postscale 10
T2OUTPS1=0;
T2OUTPS2=0;
T2OUTPS3=1;
PR2=0x7D; // 125

GIE = 0;  // Global interrupt disable just in case
//ANSELA = 0b00000001;  // Set PORT AN0 to analog input AN1 to AN7 digital I/O
ANSELA=0; // set alle digital.
ANSELB=0;
ANSELC=0;//turn off all analog functions
lcd_init();
//T1CKPS1=1;
//T1CKPS0=1;
//nT1SYNC=1;
//maxxpulse=25;
}
void vis_maxmin(void) // viser max og min
{        
                lcd_clear();
                lcd_goto(0x00);
                lcd_puts(day_of_week_names[mintime[2]]);
                if (mintime[2]!=1 || mintime[2]!=3)
                {
                lcd_puts(" ");
                    } 
                if (mintime[0]<10)lcd_puts("0");
                utoa(minx, mintime[0], 10);
                lcd_puts(minx);
                lcd_puts(":");
                if (mintime[1]<10)lcd_puts("0");
                utoa(minx, mintime[1], 10);
                lcd_puts(minx);
                lcd_puts(" ");
                if (minnegativ!=0)
                {
                    minhele=(500-min)/10;
                    minfraction= (500-min)-(minhele*10);
                    lcd_puts("-");
                }
                if (minnegativ==0)
                {
                 minhele=(min-500)/10;
                minfraction= (min-500)-(minhele*10);
                lcd_puts(" ");
                }
                utoa(mintemp,minhele,10);
                if (minhele<10)lcd_puts(" ");
                lcd_puts(mintemp);
                lcd_puts(".");
                utoa(mintemp,minfraction,10);
                lcd_puts(mintemp);
                lcd_puts("ß");
 
                // max temp kl bob bob
                lcd_goto(0x40);
                lcd_puts(day_of_week_names[maxtime[2]]);
                if (maxtime[2]!=1 || maxtime[2]!=3)
                {
                lcd_puts(" ");
                    } 
                if (maxtime[0]<10)lcd_puts("0");
                utoa(minx, maxtime[0], 10);
                lcd_puts(minx);
                lcd_puts(":");
                if (maxtime[1]<10)lcd_puts("0");
                utoa(minx, maxtime[1], 10);
                lcd_puts(minx);
             
                lcd_puts(" ");
                if (maxnegativ!=0)
                {
                maxhele=(500-max)/10;
                maxfraction= (500-max)-(maxhele*10);
                lcd_puts("-");
                }
               if (maxnegativ==0)
               {
                maxhele=(max-500)/10;
                maxfraction= (max-500)-(maxhele*10);
               lcd_puts(" ");
               }
            
                utoa(maxtemp,maxhele,10);
                if (maxhele<10)lcd_puts(" ");
                lcd_puts(maxtemp);
                lcd_puts(".");
                utoa(maxtemp,maxfraction,10);
                lcd_puts(maxtemp);
                lcd_puts("ß");
             
             
 
                        
                
}


void vaelg_dage (void) // Vælger dagene
    {
int sel,y;
    sel=1;
        x=0;
        __delay_ms(100);
        while (x<40)
    {
    if (!set_hour)  // Ved hver tryk inden for 4 sec vælges næste dag
    {char regn[4];
            lcd_goto(0x40);
        lcd_puts("Regn dag -");
        lcd_goto(0x4a);
        if (sel<10)lcd_puts(" ");
        utoa(regn, sel, 10);
        lcd_puts(regn);
        lcd_goto(0x4c);
        lcd_puts(" :");
     
        y=raindays[sel];
        if (y<100)lcd_puts(" ");
        if (y<10)lcd_puts(" ");
        utoa(regn, y, 10);
     
        lcd_puts(regn);
        lcd_puts(" MM");
        sel++;
        x=0;
        if (sel==30)sel=1;
    __delay_ms(255);
    }
    __delay_ms(100);
        x++;
 
    }
}



void reset_temp (void) //sletter temp.
{
     lcd_clear();                            // sletter skærm
     lcd_goto(0x00);                        // linje 1
     lcd_puts("Nulstil Max-Min temp ?");    // skriver
     lcd_goto(0x45);                        // linje 2
     lcd_puts("JA / NEJ ");                    // spørger
     lcd_goto(0x00);                        // linje 1
    x=0;                                    // tæller 0
    while (x<100)                            // løkke til 100*100 = 10 sec
    {
     if (!set_time)                            // hvis tryk på nulstil
     {
      
         min=0;
         max=0;
         lcd_clear();                        // sletter skærm
         lcd_goto(0x04);                    // linje 1
         lcd_puts("Nulstillet !");            // skriver
         lcd_goto(0x00);                    // linje 1
         __delay_ms(1000);                    // pause 1 sec
        x=99;                                // afslutter løkken
        }
        if(!set_week)x=0;                    // hvis tryk igen, omstart løkke
     
        x++;                                 // lægger til løkken
        __delay_ms(100);                    // pause
}                // end while løkken
}    // SLUT RESET TEMP
void reset_regn (void) //sletter total regn.
{
lcd_clear();                        // sletter skærm
lcd_goto(0x00);                    // går til linje1
lcd_puts(" Nulstil total regn ?");    // skriver
lcd_goto(0x45);                    // går til linje 2
lcd_puts("JA / NEJ ");                // skriver
lcd_goto(0x00);                    // går til linje 1
    x=0;                            // tæller 0
while (x<100)                        // løkke 100 gange *100 = 10 sec.
    {
     if (!set_time)                    // hvis man trykker JA knappen
     {TMR0=0;
         r_regn=0;
         today_rain=0;
         lcd_clear();                // sletter skærm
         lcd_goto(0x04);            // går linje 1
         lcd_puts("Nulstillet !");    // skriver
         lcd_goto(0x00);            // linje 1
         __delay_ms(1000);            // Pause 1 sec
        x=99;                        // slutter løkken
        }
        if(!set_week)x=0;            // hvis der trykkes igen, starter løkken forfra
     
        x++;                         // tæller løkken op
        __delay_ms(100);            // 100 ms pause
}
    }         // SLUT NULSTIL REGN

unsigned char reset()
{
    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;
    }

    __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) //red out temperature-
{

                write(Skip_ROM);
                write(Convert_T);
                __delay_ms(DS18B20_CONV_TIME);

                reset();
                write(Skip_ROM);
                write(Read_scratchpad);
                lsb = read();
                msb = read();
                if (f_gennemlob==0) lcd_clear();
                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] = ' ' ;
                buffer[10]= 'C';
             
             
}             


void vis_klokken(void)
{
char timestr[3];
    lcd_goto(0x00);                    // går til første linje
    lcd_puts("Klokken er: ");        // skriver
    utoa(timestr, hour, 10);        // laver om til streng
    if (hour<10)lcd_puts("0");        // hvis timer er under 10 skriv 0
        lcd_puts(timestr);            // skriver timer
        lcd_puts(":");                // skriver
        utoa(timestr, minut, 10);    // laver om til streng
    if (minut<10)lcd_puts("0");     // hvis minut er under 10 skriv 0
        lcd_puts(timestr);            // skriver minut
        lcd_puts(":");                // skriver
        utoa(timestr, secund, 10);        // laver til streng
    if (secund<10)lcd_puts("0");        // hvis sec er under 10 skriv 0
        lcd_puts(timestr);            // skriver
        lcd_goto(0x40);                // går til anden linje
    lcd_puts("Dagen er  : ");        // skriver
     for (unsigned char i=0;i<7;i++) lcd_putch(day_of_week_names[week_day][i]);
lcd_goto(0x00);                        // går til første linje
}    // slut "sub vis klokken"

void start_ur (void) // Starter uret.
{
    RA0=0;
GIE = 1;      // Global interrupt enable
TMR2ON=1;     // timer1 on
}     // slut "sub "start ur"

void sluk_ur (void) // Slukker uret
{
GIE = 0;         // Global interrupt disable as we are setting the time
TMR2ON=0;       // slukker timer til uret.
//secund=0;            // sætter sec = 0
RA0=1;         // tænder lys

}// slut "sub sluk ur "

void stil_ur (void) //Indstiller uret
{
    sluk_ur();         // Stopper tiden
    lcd_clear();
    vis_klokken();     // Viser uret
    //secund=0;
   do                  // Læser på knapperne
   {
    if (!set_hour)     // Stiller timer fremad
   {
       hour++;                    // Lægger en time til
        if (hour==24) hour=0;     // hvis timer = 24 så 0.
        vis_klokken();            // viser vi har tælt en op
        __delay_ms(255);         // venter lidt.
        __delay_ms(255);
               }
    if (!set_minut) // Stiller minutter frem
   {
        minut++;                // lægger 1 minut til.
         if (minut==60) minut=0;// hvis minut = 60 så 0.
           vis_klokken();            // viser vi har talt op.
         __delay_ms(255);         // venter lidt.
         __delay_ms(255);
               } 
    if (!set_week)  // Stiller ugedagen
   {
          week_day++;             // lægger 1 dag til.
         if (week_day==7) week_day=0; // hvis dag 7 så dag 0.
         vis_klokken();            // viser vi har talt op.
         __delay_ms(255);         // venter lidt.
               } 
      
    } while (!set_time); // Når knappen slippes igen
 
start_ur();  //Starter uret
//     vis_regn();
}// end stil uret

void midnat(void)    //thing to do at midnight. shift of date.
{int d;
week_day++;
if (week_day==7) week_day=0;
r_regn=r_regn+today_rain;
for(d=30;d>1;d--)
{
raindays[d]=raindays[d-1];
}

raindays[1]=today_rain;
today_rain=0;

}        // slut midnat


void uret(void)
      {
 
           minut++;      // og plusser et minut
    if (minut>=60)  // hvis minut = 60
    {    minut=0;    // minut = 0
        hour++;        // og plusser en time.
    if (hour>=24)    // hvis time er 24
    {    hour=0;        // time = 0
        midnat();    // kører sub midnat.
    }    // slut "if hour"
    }    // slut "if minut"
    }    // slut "sub uret" 

void fyldarray (void)
{int d;
     for(d=0;d<30;d++)
     {
         raindays[d]=0;
        }
    }     // fyld data

void vis_regn(void)
    {
        //lcd_clear();
    char regn[4], idag[4];     // defines
//lcd_clear();                // slet skærm
lcd_goto(0x00);                // går til 0
lcd_puts("Regn Total  : ");    // skriver
if (TMR0<100)lcd_puts(" ");    // højrestiller korrekt
if (TMR0<10)lcd_puts(" ");    // højrestiller igen
utoa(regn, TMR0, 10);        // laver tekststreng
lcd_puts(regn);                // skriver regnen
lcd_puts(" MM");            // i MM
lcd_goto(0x40);                // går til linje 2
lcd_puts("Regn ");            // skriver
for (unsigned char i=0;i<7;i++) lcd_putch(day_of_week_names[week_day][i]);
lcd_puts(": ");            // skriver :

today_rain=TMR0-r_regn;        // r_regn er resttal som skal bruges.

if (today_rain<100)lcd_puts(" ");    // Højrestiller
if (today_rain<10)lcd_puts(" ");    // højrestiller
utoa(idag, today_rain, 10);            // til tekststreng
lcd_puts(idag);            // skriver
lcd_puts(" MM");            // husker MM

}    //slut vis regn
void main (void)
{setup();         //kører setup


   TMR1ON=1;    // tænder timer1
   sec=0;
   PEIE=1;
   GIE=1;
   TMR1GE=0;
   //TMR0=0;        // timer 0 til 0
   xpulse=0;
   TMR2IE=0; // tænder interrupt timer2
   TMR2ON=0; // timer 2 on.
   TMR0=0; // regn nulstilles
   secund=-1;
   min=0;
   max=0;
   lcd_clear();
       lcd_goto(0x00);
       lcd_puts("1234567890abcdefghij");
       lcd_goto(0x40);
       lcd_puts("abcdefghij1234567890");
       fyldarray();
      __delay_ms(1000);
      lcd_clear();
lcd_goto(0x00);

   while (1)
   {
       if (sec==1)
       {
           secund++;   // add 1 sec.
           visning++;  // add til visning
        
           if (secund==60) // hvis det er talt til 60
               {secund =0; // sætter sekund 0
           uret();  // kører sub uret.
        
           }
           if (visning==5)  // hvis talt til 5,
           {
               visning=0;   // sætter tæller til 0
           
               if (vis==0)  // hvis visning = regn
               {vis=1;   // visning = temp
               f_gennemlob=0;
               }
               else
               {vis=0;      // sæt vis = regn
                lcd_clear();  // sletter skærmm
               }
            
            
           }
       sec=0;
           }
    
       if (vis==0)
       {
           vis_regn();  // viser regnen
       }
       else
       {
           if (!reset() == ONEWIRE_PRESENT)
            {
           laestemp();  // viser temperatur
            f_gennemlob=1;
            }
       }
    
if (!set_time) // indstiller uret.
       {
           stil_ur();
    
       }
if(!set_week)            // hvis tryk på set week  viser max min,
                {  vis_maxmin();
                int x;
                x=0;                // tæller til 0         
                    while (x<100)    // løkke indtil 100*100=10 SEC
                        {
                    if (!set_week) x=0;        // hvis der trykkes igen, nulstiller vi tæller
                        __delay_ms(100);    // i 10 sec.
                        x++;                // tæller op
                        }    //END WHILE tryk på vis max min
                }        // END IF set_week
     

//SET MINUT  NULSTILLER DIVERSE.     
if (!set_minut)        // hvis tryk på set minut  KLAR TIL NULSTILLING AF DIVERSE.
        {
            //sluk_ur();        // slukker uret.
            RA0=1;            // tænder led for at vise vi sletter
              //vis_regn();        // vis regn sub.
               x=0;            // tæller til 0         
while (x<50)                // løkke indtil 50*100=5 SEC
{
if (!set_minut) x=0;        // hvis der trykkes igen, nulstiller vi tæller
__delay_ms(100);            // pause
x++;                        // tæller op
if (!set_week)                // hvis der trykkes på nulstil.
{
reset_regn();                // viser reset sub
}
}
vis_maxmin();                    // viser temperatur sub
x=0;                        // tæller på 0
while (x<50)                // løkke indtil 50*100
{
if (!set_minut) x=0;        // hvis der trykkes nulstiller vi temp.
__delay_ms(100);            // pauser
x++;                        // tæller op
if (!set_week)                // hvis der trykkes på nulstil
{
reset_temp();                // viser rest temp sub
}
}



//start_ur();                    // starter ur igen
RA0=0;                        // slukker LED igen.
        }                    // end set minut
    
    
// SET HOUR  SKIFTER MELLLEM DAGE.
if (!set_hour)
{vis_regn();
    vaelg_dage();

}
       // more if.

   }
}

The only problem i have is the wrong showing of negativ degrees
 
Last edited:

spinnaker

Joined Oct 29, 2009
7,830
840 lines of code and all you say is "i read out the temperature i get a wrong output". Do you really expect someone to sift through that many lines of code and try to figure it out with no effort on your part? At least narrow the code down to the relevant section.


If your only issue is reading negative degrees then you are not reading the negative it properly. The bit is different depending on the device. You need to read the datasheet.

Here is an example for getting the result from a DS1820.

unsigned integerPart = result.temperature >> 1;
unsigned fractPart = ((result.temperature & 0b00000001) * 5);

You will need to adapt to your code.

I can't remember how to determine if is negative or not but this will indeed return the correct value if positive. I need to run but will look at how the negative flag is determined later if you still need it.
 

ErnieM

Joined Apr 24, 2011
8,377
I see your point and that is the end of it.

The first code fragment could possible be useful if the 3 variables it depends on are somehow defined. The second code section is completely useless.

Show just the smallest piece of code that reproduces your issue. Cut it from your project and create another project to run on your simulator, fit it there, and paste it back.

On the surface, I suspect this is a rounding issue.
 

MMcLaren

Joined Feb 14, 2010
861
Hi FroceMaster.

I see a couple things in the code that I'd like to investigate when I get back home in an hour or so. Hang in there.

Cheerful regards, Mike
 

spinnaker

Joined Oct 29, 2009
7,830
Here is the format for the DS18B20

upload_2016-1-17_10-25-12.png

Bits 11-15 will determine the sign.

And I think you have more issues than a negative sign. You ar getting numbers in the 1000's of degrees. Are you running a blast furnace?

Reading one wire is not a trivial task. Attached is code I have written and works except there are issues with Search ROM that occurred when I moved to XC8 that I have not had time to work out.

You should only need to modify OW_config.h and OW_delay.h to get it to work.

Here is a sample of how to call it. It assumes only one sensor.

Code:
void temperatureDisplay()
{

  struct OW_ROM OWrom;
  struct DSOWTherm_result result;

  DSOWTherm_convertAll();

  // Give some time for the conversion
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);
  __delay_ms(20);



  if (DSOWTherm_getCentigradeSingle(&result) == OW_SUCCESS)
  {
  DSOWTherm_getROMSingle(&OWrom);
  uart_putStringRom("\r\n\r\nThe temperature of device ");

  char output[30];

  uart_putStringRom("= ");


  // This conversion is for the DS1820.  It will also work for the DS18S20
  // Consult datasheet and / or see header file or help file for conversion for your device.

  unsigned integerPart = result.temperature >> 1;
  unsigned fractPart = ((result.temperature & 0b00000001) * 5);


  if (tempUnit == 'F')
  {

  float f = (integerPart *  1.8)  + 32;

  if (fractPart)
  f = f + .9;

  int status = 0;
 
  strcpy(output, ftoa(f, &status));
  strcat(output, " Degrees F");
  uart_putString(output);
  }
  else
  {

  char bufIntegerPart[5];
  char bufFractPart[3];

  strcpy(output, itoa(bufIntegerPart, integerPart, 10));
  strcat(output, ".");
  strcat(output, itoa(bufFractPart, fractPart, 10));
  strcat(output, " Degrees C");
  uart_putString(output);

  }


  }
  else
  {
  uart_putStringRom("\r\nThere was an error getting the temperature!\r\n");
  uart_putStringRom("Press any key to continue.\r\n\r\n");
  uart_getChar();
  }

}
 

Attachments

atferrari

Joined Jan 6, 2004
4,767
Show just the smallest piece of code that reproduces your issue. Cut it from your project and create another project to run on your simulator, fit it there, and paste it back.
After learning to test and debug code progressively by adding new sections to what was already working, the above is the best second advise ever.

If you comply with the first, the second comes almost naturally always.
 

nerdegutta

Joined Dec 15, 2009
2,684
Is this the rain sensor @t06afre helped you with a few years ago?

I talked to someone right outside of Copenhagen this morning. He said he would stay inside today. They had -10C. :)
 

MMcLaren

Joined Feb 14, 2010
861
Hi FroceMaster,

It looks like you are not "twos complementing" a negative temperature value correctly (at line 472 and line 540). When you "twos complement" a number you need to complement the number and add 1 to it. Attempting to "twos complement" the integer and fractional portions of the negative temperature value separately may be problematic. That is, after complementing and adding 1 to the fractional portion of the number you'll need a way to propagate a carry from the fractional portion to the integer portion.

May I suggest you collect the raw "sign extended twos complement" temperature data into a 16-bit variable and perform the "twos complement" on that number and then separate out the integer and fractional portions? A quick experiment using XC8 (below) was used to verify the conversion.

Good luck on your project. Please don't be afraid to click on the <like> button if this post was helpful.

Cheerful regards, Mike

C:
  /******************************************************************
   *  DS18B20 "sign extended twos complement" to decimal example    *
   ******************************************************************/

      char temp[] = {"          "};     // temperature string
      signed int rawtemp = 0xFFE1;      // raw temperature * 16
      int frac;                         // 4-bit fraction * 16

      if(rawtemp < 0)                   // if negative
      { rawtemp = -rawtemp;             // twos complement it
        temp[0] = '-';                  // indicate negative
      }                                 //
  /*                                                                *
   *  separate raw temperature into integer & fractional portions   *
   *                                                                */
      frac = (rawtemp & 15) * 625;      // extract fraction
      rawtemp >>= 4;                    // remove fraction, 0..125
  /*                                                                *
   *  build temperature string. example; raw FFE1 -> "-01.9375°C"   *
   *                                                                */
      if(temp[0] != '-')                //
        temp[0] = (rawtemp/100)%10|'0'; // hundreds
      temp[1] = (rawtemp/10)%10|'0';    // tens
      temp[2] = (rawtemp%10)|'0';       // ones
      temp[3] = '.';                    //
      temp[4] = (frac/1000)%10|'0';     // 1st decimal place
      temp[5] = (frac/100)%10|'0';      // 2nd decimal place
      temp[6] = (frac/10)%10|'0';       // 3rd decimal place
      temp[7] = (frac%10)|'0';          // 4th decimal place
      temp[8] = '°';                    //
      temp[9] = 'C';                    //
 
Last edited:

dannyf

Joined Sep 13, 2015
2,197
here is the part that "convert" to text.
It is more than that. Once you have msb.lsb, you can combine them into a 16-signed type, and the conversion into "displayable" decimal is fairly simple. Check the datasheet for sure.

The code you have is poorly written.
 
Top