Onewire sensor scanning problem

Thread Starter

motzey

Joined Apr 22, 2011
1
I am using the EasyPIC6 dev board & MikroC to program a 16F887 to scan the DS18S20 temp. sensor and display it on a 4X16 LCD. I then modified the code to drive the LCD from PORTD on a 18F4685 MCU and it compiled and ran OK on the EasyPIC6 board. I then put the 18F4685 into a prototype board I built and the LCD displays the temperaure and 000.0000 text OK, but the temp. from the DS18S20 never comes up on the display. The RE2 PORTE pin is used to scan and control the sensor and I have tried other PORT pins with no luck. I feel the PORT latch function may be where I am coding it wrong. I have checked & double checked my prototype board wiring & it all looks OK. At wits end on this one. Thanks HD

Rich (BB code):
/*
 * Project name:  Modified from 18F8520 to 18F4685
     OneWire (Interfacing the DS1820 temperature sensor - all versions)
 * Copyright:
     (c) mikroElektronika, 2008.
 * Revision History:
     20081218:
       - initial release;
 * Description:
     This code demonstrates one-wire communication with temperature sensor
     DS18x20 connected to RE5 pin.
     MCU reads temperature from the sensor and prints it on the LCD.
     The display format of the temperature is 'xxx.xxxx°C'. To obtain correct
     results, the 18x20's temperature resolution has to be adjusted (constant
     TEMP_RESOLUTION).
 * Test configuration:
     MCU:             P18F4685
                      http://ww1.microchip.com/downloads/en/DeviceDoc/39609b.pdf
     Dev.Board:       EasyPIC6
                      http://www.mikroe.com/en/tools/bigpic6/
     Oscillator:      HS, 8.0 MHz
     Ext. Modules:    DS18S20, LCD_2x16
     SW:              mikroC PRO for PIC
                      http://www.mikroe.com/en/compilers/mikroc/pro/pic/
 * NOTES:
     - //Turn on DS1820 switch SW12.8
 -// Pull up(jumper J5) and turning off diode (switch SW10) on pin RE5
       // ( board specific) used for one wire bus may be required.
*/

// ******************** Code for using PORTB for LCD ************************

sbit LCD_RS at LATB4_bit;
sbit LCD_EN at LATB5_bit;
sbit LCD_D4 at LATB0_bit;
sbit LCD_D5 at LATB1_bit;
sbit LCD_D6 at LATB2_bit;
sbit LCD_D7 at LATB3_bit;

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



// LCD module connections
//sbit LCD_RS at LATD2_bit;  // for writing to output pin always use latch (PIC18)
//sbit LCD_EN at LATD3_bit;  // for writing to output pin always use latch (PIC18)
//sbit LCD_D4 at LATD4_bit;  // for writing to output pin always use latch (PIC18)
//sbit LCD_D5 at LATD5_bit;  // for writing to output pin always use latch (PIC18)
//sbit LCD_D6 at LATD6_bit;  // for writing to output pin always use latch (PIC18)
//sbit LCD_D7 at LATD7_bit;  // for writing to output pin always use latch (PIC18)

//sbit LCD_RS_Direction at TRISD2_bit;
//sbit LCD_EN_Direction at TRISD3_bit;
//sbit LCD_D4_Direction at TRISD4_bit;
//sbit LCD_D5_Direction at TRISD5_bit;
//sbit LCD_D6_Direction at TRISD6_bit;
//sbit LCD_D7_Direction at TRISD7_bit;
// End LCD module connections

//  Set TEMP_RESOLUTION to the corresponding resolution of used DS18x20 sensor:
//  18S20: 9  (default setting; can be 9,10,11,or 12)
//  18B20: 12
const unsigned short TEMP_RESOLUTION = 9;

char *text = "000.0000";
unsigned temp;

void Display_Temperature(unsigned int temp2write) {
  const unsigned short RES_SHIFT = TEMP_RESOLUTION - 8;
  char temp_whole;
  unsigned int temp_fraction;

  // check if temperature is negative
  if (temp2write & 0x8000) {
     text[0] = '-';
     temp2write = ~temp2write + 1;
     }

  // extract temp_whole
  temp_whole = temp2write >> RES_SHIFT ;

  // convert temp_whole to characters
  if (temp_whole/100)
     text[0] = temp_whole/100  + 48;
  else
     text[0] = '0';

  text[1] = (temp_whole/10)%10 + 48;             // Extract tens digit
  text[2] =  temp_whole%10     + 48;             // Extract ones digit

  // extract temp_fraction and convert it to unsigned int
  temp_fraction  = temp2write << (4-RES_SHIFT);
  temp_fraction &= 0x000F;
  temp_fraction *= 625;

  // convert temp_fraction to characters
  text[4] =  temp_fraction/1000    + 48;         // Extract thousands digit
  text[5] = (temp_fraction/100)%10 + 48;         // Extract hundreds digit
  text[6] = (temp_fraction/10)%10  + 48;         // Extract tens digit
  text[7] =  temp_fraction%10      + 48;         // Extract ones digit

  // print temperature on LCD
  Lcd_Out(2, 5, text);
}

void main() {

  ADCON1 |= 0x0F;                                // Configure AN pins as digital
  CMCON  |= 7;                                   // Disable comparators
  TRISD =0;
  Lcd_Init();                                    // Initialize LCD
  Lcd_Cmd(_LCD_CLEAR);                           // Clear LCD
  Lcd_Cmd(_LCD_CURSOR_OFF);                      // Turn cursor off
  Lcd_Out(1, 1, " Temperature:   ");
  // Print degree character, 'C' for Centigrades
  Lcd_Chr(2,13,178); // different LCD displays have different char code for deg.
                  // if you see greek alpha letter try typing 178 instead of 223

  Lcd_Chr(2,14,'C');

  //--- main loop
  do {
    //--- perform temperature reading
    Ow_Reset(&PORTE, 2);                         // Onewire reset signal
    Ow_Write(&PORTE, 2, 0xCC);                   // Issue command SKIP_ROM
    Ow_Write(&PORTE, 2, 0x44);                   // Issue command CONVERT_T
    Delay_us(120);

    Ow_Reset(&PORTE, 2);
    Ow_Write(&PORTE, 2, 0xCC);                 // Issue command SKIP_ROM
    Ow_Write(&PORTE, 2, 0xBE);                 // Issue command READ_SCRATCHPAD
    Delay_ms(400);

    temp =  Ow_Read(&PORTE, 2);
    temp = (Ow_Read(&PORTE, 2) << 8) + temp ;
     PORTD = 1;
    //--- Format and display result on Lcd
    Display_Temperature(temp);

    Delay_ms(3000);
    PORTD = 0;
  } while (1);
}
 
Last edited by a moderator:

coldpenguin

Joined Apr 18, 2010
165
Are you running in powered or parasitic mode? If parasitic, I think that you are missing a hard pull-up after your 0x44
Also, I reckon your timings are the wrong way around. The s20 will require much longer after the 0x44 than after the 0xbe, I would swap over your timings.
In fact, what I do (however others don't like my coding), is to perform the 0xcc, 0x44 at the end of the while loop,
i.e.
temp=(OW_read...)
OW_Reset()
OW_Write(0xcc)
OW_Write(0x44)
Display_Temperature();
Delay_ms(3000);
} /end while

You will of course be running 3 seconds lag in this setup.....
I don't see a TRISE statement, but I guess this is dealt with by the OW routines.

Do you have a logic analyser? I found one very useful for debugging this protocol.

One thing to note, which kind-of ties in with what I said above about timings, if a sensor has not completed its conversion, it returns 0x00 for every read command that it receives.
If the s20 does not manage a conversion, it returns 85, given that you are seeing a temperature of 0 degrees, this suggests a conversion has not completed.
However, this doesn't make sense as being the fault if all you have done is move from one port to another.
It does make sense if you have moved from normal to parasitic power, as the conversion takes longer (however in theory 0x00 shouldn't be returnable in parasitic mode).
Have you double-checked you haven't attached the pull-up resistor to ground instead of +ve by accident, and what value of pull-up are you using?
 
Top