|
|
View previous topic :: View next topic |
Author |
Message |
dyeatman
Joined: 06 Sep 2003 Posts: 1934 Location: Norman, OK
|
|
Posted: Sun Feb 15, 2009 3:11 pm |
|
|
Version 4.081 |
|
|
Kenny
Joined: 07 Sep 2003 Posts: 173 Location: Australia
|
|
Posted: Sun Feb 15, 2009 9:28 pm |
|
|
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
|
|
Posted: Mon Feb 16, 2009 1:16 am |
|
|
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
|
|
Posted: Mon Feb 16, 2009 9:38 am |
|
|
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
|
|
Posted: Mon Feb 16, 2009 3:07 pm |
|
|
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
|
|
Posted: Wed Jun 24, 2009 2:23 am |
|
|
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
|
|
Posted: Wed Jun 24, 2009 5:54 pm |
|
|
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
|
|
Posted: Thu Jun 25, 2009 2:00 am |
|
|
Thanks ckielstra for your fast reply.
Sorry for my misunderstanding and my english
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
|
|
Posted: Fri Jun 26, 2009 3:43 pm |
|
|
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
|
|
Posted: Mon Jun 29, 2009 2:10 am |
|
|
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
Thanks again for your reply |
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
Posted: Mon Jun 29, 2009 1:45 pm |
|
|
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
|
|
Posted: Mon Jun 29, 2009 3:37 pm |
|
|
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
|
|
Posted: Tue Jun 30, 2009 2:02 am |
|
|
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
|
|
Posted: Tue Jun 30, 2009 11:40 am |
|
|
The PicKit2 is a programmer. What board are you using for your
project ? |
|
|
pyu
Joined: 04 Feb 2009 Posts: 51
|
|
|
|
|
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
|