CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

three DS18B20...
Goto page Previous  1, 2, 3  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 3:11 pm     Reply with quote

Version 4.081
Kenny



Joined: 07 Sep 2003
Posts: 173
Location: Australia

View user's profile Send private message

PostPosted: Sun Feb 15, 2009 9:28 pm     Reply with quote

It worked for me using a 16F876. A 16x2 lcd was connected to port B and the CCS driver lcd.c was used. Compiler version was 4.084.

I had to make changes. In FindDevices() the device number was displayed on the first line, and the address (16 hex digits) on the second line. The original printf formatting was used to show all 16 digits. A delay was needed to allow viewing of each address sequentially.

Before the do-while loop:

Code:

printf(lcd_putc,"\fDevice ");


In the loop:

Code:

lcd_gotoxy(8,1);
printf(lcd_putc,"%u  ",numROMs);

printf(lcd_putc, "\n%X%X%X%X%X%X%X%X",
FoundROM[numROMs][7],FoundROM[numROMs][6],FoundROM[numROMs][5], \
FoundROM[numROMs][4],FoundROM[numROMs][3],FoundROM[numROMs][2], \
FoundROM[numROMs][1],FoundROM[numROMs][0]);
           
delay_ms(1000);




Could be a hardware problem. Try adding a 100nF ceramic bypass capacitor on the DS18B20 - not necessary though normally.
Are the devices far from the PIC? If so try it with them next to the PIC.
Confirm that each device works individually with the code for a single device.

The other thing to try would be increasing the delay in ow_reset() from 488uS.
This could be marginal as stated by ckielstra in another thread. The spec is 480uS minimum.
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Feb 16, 2009 1:16 am     Reply with quote

I'm not sure what the error was, but after updating to version 4.084, it began to display something on lcd, but not the right temp. After making some changes in the display part, now it simulate ok.
but if I use the development board (pickit 2, and only one DS18B20 senzor - I should receive the others this week), the result is not the same, the sensor is not "seen". If I use the program for one sensor, the temp is displayed correctly. The distance is 20 cm from the pic. I will try to use another port, or adding a 100n capacitor, or maybe incresing the delay.

Thanks for helping me, I will write as soon as I made this modifications.
spiffy_chimp
Guest







PostPosted: Mon Feb 16, 2009 9:38 am     Reply with quote

Something you might check is what value of pullup resistor you are using on the DQ line and how you are powering the DS18B20. If you are powering it in parasite mode, you need to pull the DQ line high within 10uS of issuing the CONVERT command. . . . or something like that. I'd need to check the datasheet to be sure of the timing, but it's required to happen very fast. You could scope the line and make sure the sensors are getting the power they need during conversion.

Another thing to check, although it might be in your code already: with multiple sensors on a single wire, you can use the CONVERT_ALL command and have all of the temp sensors do a conversion at the same time. Otherwise you need to individually address each sensor, start it's conversion and then wait the 750ms while it converts. You can't use the line while any sensor is doing a conversion (in parasite power mode at least).

I moved away from bit-banging 1Wire specifically to avoid the timing issues I was constantly experiencing. It might not be practical for your project, but the DS2482 IC (1 channel or 8 channel versions) took away almost all of the need to handle shaping of signals on the line. They even have a built-in function to enable the fast pullup required during conversions.
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Feb 16, 2009 3:07 pm     Reply with quote

the problem is from here:
Code:

int8 ow_reset(void)
{
   int8 presence;

   output_low(DQ);
   delay_us(488);          // Min. 480uS
   output_float(DQ);
   delay_us(72);           // Takes 15 to 60uS for devices to respond
   presence = input(DQ);
   delay_us(424);          // Wait for end of timeslot

   return(presence); 
}

presence - is always true (1). I tried increasing timing here, but the result is the same.

I don't understand what exactly means "parasite mode", my english is not so good. The sensor it's powered from a pickit2, who is powered from a pc USB port. Between +5v line, and DQ, I have a 4.7K resistor.
In this moment I use only one DS18B20, does it matter that I'm not using more sensors? If so, I will wait to receive the other two sensors.

In ISIS it runs ok.
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Wed Jun 24, 2009 2:23 am     Reply with quote

After a new try, and a new pic, I succeeded to get the rom of 2 ds18b20 sensors.
But the speed is only 4Mhz, and I need to work with 20Mhz.

I want to convert the delay_us from 4Mhz to 20Mhz.
Code:
int8 ow_reset(void)
{
   int8 presence;

   output_low(DQ);
   delay_us(488);          // Min. 480uS
   output_float(DQ);
   delay_us(72);           // Takes 15 to 60uS for devices to respond
   presence = input(DQ);
   delay_us(424);          // Wait for end of timeslot

   return(presence); 
}

Please somebody give me a related link. I know there is a post on this forum, but I can't find it :(

Thanks.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Wed Jun 24, 2009 5:54 pm     Reply with quote

pyu wrote:
I want to convert the delay_us from 4Mhz to 20Mhz.
I'm not sure what you mean with this. You can change the processor clock speed if you want to and the CCS compiler will adapt the function delay_us for this new speed, assuming you entered the speed in the '#use delay' line.

If you do mean to change the communication speed with the DS18B20 then you can't. The DS18B20 clock timing has to meet certain minimum timings and these are already at the highest speed in the given code.

Quote:
I don't understand what exactly means "parasite mode"
Normally the DS18B20 has 3 connections: Vdd, DQ and GND. Parasite mode is a special feature of these chips where you use the data line to supply power to the chip, so you need only two wires instead of three. Vdd is not connected in this mode.
Parasite mode is a nice feature but can cause a lot of problems. Best is to start with normal mode (Vdd connected to +5V) and when everything is working OK then you can consider to use the parasite mode.
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Thu Jun 25, 2009 2:00 am     Reply with quote

Thanks ckielstra for your fast reply.
Sorry for my misunderstanding and my english Embarassed

I use #use delay(clock=20000000) or #use delay(clock=4000000)

I still don't know why this code:
Code:
int8 ow_reset(void)
{
   int8 presence;

   output_low(DQ);
   delay_us(488);          // Min. 480uS
   output_float(DQ);
   delay_us(72);           // Takes 15 to 60uS for devices to respond
   presence = input(DQ);
   delay_us(424);          // Wait for end of timeslot

   return(presence); 
}

Is working at 4Mhz, and isn't working at 20Mhz.

But I will analyze what you said, and will be back with other questions in case it will not work.
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Jun 26, 2009 3:43 pm     Reply with quote

When you change 4MHz to 20MHz, what are the other things you change?
Do you change the crystal too?
What #fuses do you use?

Are you testing with real hardware or in ISIS?

Are you sure it is running at 20MHz? For example, when blinking a LED every 20M cycles, does it blink 1 time every second?
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Jun 29, 2009 2:10 am     Reply with quote

Hi.
Here is the main.c:
Code:
#include <16F887.H>
#fuses XT,NOWDT,NOLVP,PUT,NOPROTECT,NOBROWNOUT,NOWRT
//#use delay(clock = 20000000)
#use delay(clock = 4000000)
#include "Flex_LCD420.c"

#define DQ PIN_E0 // One Wire Bus pin assignment

//header
//#include "DS18B20.h"

//source
//#include "DS18B20.c"
#include "onewire.c"



void main(void)
{
   int8 i;
   signed int16 temperature;
   int8 scratch[9];       

    lcd_init();

   output_float(DQ);       // Set as input. 4k7 pullup on bus.
   FindDevices();         
   
   while(1)
   {
      if (!ow_reset())     // If a device is present
      {
         write_byte(0xCC); // Skip Rom command
         write_byte(0x44); // Temperature convert command
         output_float(DQ);
         delay_ms(750);    // Max. conv. time is 750mS for 12 bit
         ow_reset();
 
         // Now get the device raw temperature data using Match ROM with the
         // addresses obtained with FindDevices().
         // If the received crc is same as calculated then data is valid.
         // Scale and round to nearest degree C.
         // Scaling is 0.0625 (1/16) deg.C/bit with default 12 bit resolution.
         // Round by adding half denominator for positive temperatures and
         // subtracting half denominator for negative temperatures.
                     
         for (numRoms=1;numRoms<=2;numRoms++)
         {
            if (Send_MatchRom())
            {
               write_byte(0xBE); // Read scratch pad command
               dowcrc = 0;       
               
               // Get the data bytes
               
               for (i=0;i<=7;i++)
               {
                   scratch[i] = read_byte();
                   ow_crc(scratch[i]);     
               }
   
               scratch[8] = read_byte();   // Get crc byte
               ow_reset();
   
               // If calculated crc from incoming bytes equal to crc byte
               // then data is valid.
                                         
               if (scratch[8] == dowcrc) 
               {
                  temperature = (signed int16) make16(scratch[1],scratch[0]);
                 
                  if (temperature >= 0)
                     temperature = (temperature + 8)/16.0;
               
                  else
                     temperature = (temperature - 8)/16.0;
                     
                  //printf("%4Ld ",temperature);
               printf(lcd_putc,"\n%4Ld", temperature);
               }
               
               else
                  printf(lcd_putc, "\nError in data");
            }
         }
         
        // putc('\n'); putc('\r');
      }   
   }
}


onewire.c:
Code:

// One Wire bus functions - from Dallas publication AN162
// "Interfacing DS18x20/DS1822 1-wire Temperature Sensor in a Microcontroller
// Environment". Delays calculated from values given for 8051.
// Changed variable name ROM[] to RomBytes[] because ROM is a reserved word
// in version 4 of the CCS compiler.

// Global variables
int8 RomBytes[8];     
int8 lastDiscrep = 0;
short doneFlag = 0;
int8 FoundROM[9][8];    // Table of found ROM codes, 8 bytes for each
int8 numROMs;
int8 dowcrc;            // crc is accumulated in this variable

// crc lookup table
int8 const dscrc_table[] = {
   0,94,188,226,97,63,221,131,194,156,126,32,163,253,31,65,
   157,195,33,127,252,162,64,30,95,1,227,189,62,96,130,220,
   35,125,159,193,66,28,254,160,225,191,93,3,128,222,60,98,
   190,224,2,92,223,129,99,61,124,34,192,158,29,67,161,255,
   70,24,250,164,39,121,155,197,132,218,56,102,229,187,89,7,
   219,133,103,57,186,228,6,88,25,71,165,251,120,38,196,154,
   101,59,217,135,4,90,184,230,167,249,27,69,198,152,122,36,
   248,166,68,26,153,199,37,123,58,100,134,216,91,5,231,185,
   140,210,48,110,237,179,81,15,78,16,242,172,47,113,147,205,
   17,79,173,243,112,46,204,146,211,141,111,49,178,236,14,80,
   175,241,19,77,206,144,114,44,109,51,209,143,12,82,176,238,
   50,108,142,208,83,13,239,177,240,174,76,18,145,207,45,115,
   202,148,118,40,171,245,23,73,8,86,180,234,105,55,213,139,
   87,9,235,181,54,104,138,212,149,203,41,119,244,170,72,22,
   233,183,85,11,136,214,52,106,43,117,151,201,74,20,246,168,
   116,42,200,150,21,75,169,247,182,232,10,84,215,137,107,53
};

// Returns 0 for one wire device presence, 1 for none
int8 ow_reset(void)
{
   int8 presence;

   output_low(DQ);
   delay_us(488);          // Min. 480uS
   output_float(DQ);
   delay_us(72);           // Takes 15 to 60uS for devices to respond
   presence = input(DQ);
   delay_us(424);          // Wait for end of timeslot
   return(presence);
}
//******************************************************************************
// Read bit on one wire bus
int8 read_bit(void)
{
   output_low(DQ);
   delay_us(1);         // Added, 1uS min. Code relied on 8051 being slow.
   output_float(DQ);
   delay_us(12);        // Read within 15uS from start of time slot
   return(input(DQ));   
}                       
//******************************************************************************
void write_bit(int8 bitval)
{
   output_low(DQ);

   if(bitval == 1) {
      delay_us(1);      // 1uS min. Code relied on 8051 being slow.
      output_float(DQ);
   }
   delay_us(105);       // Wait for end of timeslot
   output_float(DQ);
}
//******************************************************************************
int8 read_byte(void)
{
   int8 i;
   int8 val = 0;

   for(i=0;i<8;i++)
   {
      if(read_bit()) val |= (0x01 << i);
      delay_us(120);  // To finish time slot
   }

   return val;
}
//******************************************************************************
void write_byte(int8 val)
{
   int8 i;
   int8 temp;

   for (i=0;i<8;i++)
   {
      temp = val >> i;
      temp &= 0x01;
      write_bit(temp);
   }

   delay_us(105);
}
//******************************************************************************
// One wire crc
int8 ow_crc(int8 x)
{
   dowcrc = dscrc_table[dowcrc^x];
   return dowcrc;
}
//******************************************************************************
// Searches for the next device on the one wire bus. If there are no more
// devices on the bus then false is returned.
int8 Next(void)
{
   int8 m = 1;             // ROM Bit index
   int8 n = 0;             // ROM Byte index
   int8 k = 1;             // Bit mask
   int8 x = 0;
   int8 discrepMarker = 0;
   int8 g;                 // Output bit
   int8 nxt;               // Return value
   short flag;


   nxt = FALSE;            // Reset next flag to false

   dowcrc = 0;             // Reset the dowcrc

   flag = ow_reset();

   if (flag||doneFlag)     // If no parts return false
   {
      lastDiscrep = 0;     // Reset the search
      return FALSE;
   }

   write_byte(0xF0);       // Send SearchROM command

   do
   {
      x = 0;
      if (read_bit() == 1) x = 2;
      delay_us(120);
      if (read_bit() == 1) x |= 1;   // And it's complement

      if (x == 3)                   // There are no devices on the one wire bus
      break;
      else
      {
         if (x > 0)                 // All devices coupled have 0 or 1
            g = x >> 1;             // Bit write value for search

         // If this discrepancy is before the last discrepancy on a previous
         // Next then pick the same as last time.
         else
         {
            if (m < lastDiscrep)
               g = ((RomBytes[n] & k) > 0);
            // If equal to last pick 1
            else
               g = (m == lastDiscrep);  // If not then pick 0

               // If 0 was picked then record position with mask k
               if (g == 0) discrepMarker = m;
         }

         // Isolate bit in ROM[n] with mask k
         if (g == 1) RomBytes[n] |= k;
         else RomBytes[n] &= ~k;

         write_bit(g);  // ROM search write

         m++;           // Increment bit counter m
         k = k << 1;    // and shift the bit mask k
         // If the mask is 0 then go to new ROM
         if (k == 0)
         {  // Byte n and reset mask
            ow_crc(RomBytes[n]);      // Accumulate the crc
            n++;
            k++;
         }
      }
   } while (n < 8);  // Loop through until through all ROM bytes 0-7

   if (m < (65||dowcrc))   // If search was unsuccessful then
      lastDiscrep = 0;     // reset the last Discrepancy to zero

   else  // Search was successful, so set lastDiscrep, lastOne, nxt
   {
      lastDiscrep = discrepMarker;
      doneFlag = (lastDiscrep == 0);
      nxt = TRUE; // Indicates search not yet complete, more parts remain
   }

   return nxt;
}
//******************************************************************************
// Resets current state of a ROM search and calls Next to find the first device
// on the one wire bus.
int8 First(void)
{
   lastDiscrep = 0;
   doneFlag = FALSE;
   return Next();    // Call Next and return it's return value;
}
//******************************************************************************
void FindDevices(void)
{
   int8 m;

   if(!ow_reset())
   {
      if(First())    // Begins when at least one part found
      {
         numROMs = 0;

         do
         {
            numROMs++;

            for (m=0;m<8;m++)
            {
               FoundROM[numROMs][m] = RomBytes[m];
            }

            printf(lcd_putc,"Device No.%u address ",numROMs);

            printf(lcd_putc, "%X%X%X%X%X%X%X%X\n\r",
            FoundROM[numROMs][7],FoundROM[numROMs][6],FoundROM[numROMs][5],
            FoundROM[numROMs][4],FoundROM[numROMs][3],FoundROM[numROMs][2],
            FoundROM[numROMs][1],FoundROM[numROMs][0]);

         } while (Next() && (numROMs<10));   // Continues until no additional
                                             // devices found.
      }
   }
   //putc('\n'); putc('\r');
printf(lcd_putc, "\n");
}
//******************************************************************************
// Sends Match ROM command to bus then device address
int8 Send_MatchRom(void)
{
   int8 i;
   if (ow_reset()) return FALSE;          // 0 if device present
   write_byte(0x55);                      // Match ROM

   for (i=0;i<8;i++)
   {
      write_byte(FoundRom[numROMs][i]);   // Send ROM code
   }

   return TRUE;
}


When I change de delay,
#use delay(clock = 20000000)
//#use delay(clock = 4000000)
the program is not working in 20Mhz.
I did not use external crystal.
The testing is ok in ISIS, but real hardware is working only at 4Mhz.

Quote:
Are you sure it is running at 20MHz? For example, when blinking a LED every 20M cycles, does it blink 1 time every second?


I don't know, I will try after work, in weekend I was gone in a litle vacation, and I didn't do anything on this project Smile

Thanks again for your reply Smile
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Mon Jun 29, 2009 1:45 pm     Reply with quote

Quote:
Are you sure it is running at 20MHz? For example, when blinking a LED every 20M cycles, does it blink 1 time every second?


I made a test program:
Code:

#include <16F887.H>
#fuses XT,NOWDT,NOLVP,PUT,NOPROTECT,NOBROWNOUT,NOWRT
#use delay(clock = 20000000)
void main(void)
{
   while(1)
   {
      delay_ms(200);
      output_toggle(PIN_E1);
   }
}


The led is ON 1 second, then OFF 1 seccond.

What is the frequency in this case?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Jun 29, 2009 3:37 pm     Reply with quote

Your observed delay is 5x the delay_ms() value.

Therefore, your #use delay() value is 5x too high.


The #use delay() value can only be used to set the PIC's oscillator
frequency if you are using the internal oscillator (and only for the
specific frequencies specified in the PIC data sheet).

If you are using a crystal, the #use delay() value must match
the crystal frequency. Exception: If your PIC has PLL capability
and you enable the PLL, then the #use delay() must match the
PLL-multplied frequency value.
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Jun 30, 2009 2:02 am     Reply with quote

Yes, you are right, the current speed is 4Mhz ( so I think ), even I used
Code:
#use delay(clock = 20000000)


In this moment, I didn't have an external oscillator.
Could this be the problem?
Or because I was running this testing in debug mode (PicKit 2)?
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Tue Jun 30, 2009 11:40 am     Reply with quote

The PicKit2 is a programmer. What board are you using for your
project ?
pyu



Joined: 04 Feb 2009
Posts: 51

View user's profile Send private message Yahoo Messenger

PostPosted: Tue Jun 30, 2009 2:53 pm     Reply with quote

PCM programmer wrote:
The PicKit2 is a programmer. What board are you using for your
project ?


I use PICkit 2 Debug Express. ( http://www.microchipdirect.com/productsearch.aspx?Keywords=DV164121 )



Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page Previous  1, 2, 3  Next
Page 2 of 3

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group