|
|
View previous topic :: View next topic |
Author |
Message |
respected
Joined: 16 May 2006 Posts: 95
|
what is different (conf. settings at 18f46J50) |
Posted: Fri Feb 05, 2016 4:09 pm |
|
|
hi;
I use multi ds18b20
my code works at this conf
Code: |
#include <18F46J50.h>
#fuses HSPLL,NOWDT,NOXINST,PLL3,CPUDIV6
#use delay(clock=8M,crystal=12M)
|
but it doesn't work this conf
Code: |
#include <18F46J50.h>
#fuses HSPLL,NOWDT,NOXINST,PLL3,CPUDIV3
#use delay(clock=16M,crystal=12M)
|
What is different?
Thanks for your answers |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
|
Posted: Fri Feb 05, 2016 6:01 pm |
|
|
post the CODE and explain WHAT about it does not work.
read the data sheet. USB does NOT work with any old arbitrary clock setting. |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Fri Feb 05, 2016 6:18 pm |
|
|
multi use code for ds18b20 doesn't work
main.c
Code: |
#include <18F46J50.h>
#device ADC=8;
#fuses HSPLL,NOWDT,NOXINST,PLL3,NOCPUDIV//CPUDIV6//NOCPUDIV//,RTCOSC_T1,PROTECT
#use delay(clock=48M,crystal=12M)
//!#include <18F46J50.h>
//!#fuses INTRC_IO, NOWDT
//!#use delay(clock=4M)
#include <flexlcd420.c>
#include <onewire.c>
int8 i,tmp,numDev = 0;
int8 scratch[2];
float TEMPERATURE[2];
void main()
{
setup_oscillator(OSC_PLL_ON);
lcd_init();
output_float(DQ);
output_high(PIN_A3);
numDev = FindDevices();
for(i=1; i<=numDev; i++)
{
lcd_gotoxy(1,i);
printf(lcd_putc,"S%u:",i);
lcd_gotoxy(4,i);
for (tmp=0; tmp<8; tmp++)
printf(lcd_putc,"%X",FoundROM[i][tmp]);
}
signed int16 tem3;
while (TRUE)
{
if (!ow_reset()) // If a device is present and it's time to send string
{
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();
// read all devices on bus
for (numRoms=1; numRoms <= numDev; numRoms++)
{
if (Send_MatchRom())
{
write_byte(0xBE); // Read scratch pad command
for(i=0; i<2; i++)
{
scratch[i]= read_byte();
}
// raw sensor data (16bit)
tem3 = make16(scratch[1], scratch[0]);
TEMPERATURE[numRoms-1]=(float) tem3 / 16.0;
} // if (Send_MatchRom())
delay_ms(200);
lcd_gotoxy(1,3);
printf (lcd_putc,"PROB:%3.1f",TEMPERATURE[0]);
lcd_gotoxy(1,4);
printf (lcd_putc,"PROB:%3.1f",TEMPERATURE[1]);
} // for (numRoms=1; numRoms <= numDev; numRoms++)
}
} //while
}//main
|
onewire.c
Code: |
// 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
#define DQ PIN_A0
//calc_CRC - INTERNAL FUNCTION
//Purpose: To calculate an 8-bit CRC based on a polynomial and the series
// of data bytes
//Note: Polynomial used x^8 + x^5 + x^4 + 1 = 10001100
//Inputs: A pointer to an array of the data bytes and an int saying how many
// bytes there are in the data array
//Outputs: An int8 which is the calculated CRC
int8 calc_CRC(int8* data, int8 bytes)
{
#define CRC_POLY 0x8C
int8 shift_register = 0, i, datab, bits;
for(i = 0; i < bytes; ++i)
{
datab = *(data + i);
for(bits = 0; bits < 12; ++bits) //8
{
if(bit_test((shift_register ^ datab), 0))
{
shift_register = shift_register >> 1;
shift_register ^= CRC_POLY;
}
else
{
shift_register = shift_register >> 1;
}
datab = datab >> 1;
}
}
return shift_register;
} //calc_CRC
// 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(60); // 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 = calc_CRC(x,8);
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_rom_index = 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_rom_index < lastDiscrep)
g = ((RomBytes[n] & k) > 0);
// If equal to last pick 1
else
g = (m_rom_index == lastDiscrep); // If not then pick 0
// If 0 was picked then record position with mask k
if (g == 0) discrepMarker = m_rom_index;
}
// 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_rom_index++; // 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_rom_index < (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;
}
//******************************************************************************
int8 FindDevices(void)
{
int8 m, cont = 0;
if(!ow_reset())
{
if(First()) // Begins when at least one part found
{
numROMs = 0;
do
{
numROMs++;
cont++;
for (m=0;m<12;m++) //8
{
FoundROM[numROMs][m] = RomBytes[m];
}
} while (Next()); // Continues until no additional
}
}
return cont;
}
//******************************************************************************
// 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;
}
float ds1820_read()
{
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
ow_reset();
write_byte(0xCC);
write_byte(0x44);
while (busy == 0)
busy = read_byte();
ow_reset();
write_byte(0xCC);
write_byte(0xBE);
temp1 = read_byte();
temp2 = read_byte();
temp3 = make16(temp2, temp1);
result = (float) temp3 / 16.0;
delay_ms(200);
return(result);
} |
|
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Fri Feb 05, 2016 6:24 pm |
|
|
If the problem is in communcating with the DS18B20 devices it might be the wrong driver.
There's 2 or 3 different variations of them and the driver must match the device. ds1820 is NOT the same as ds18B20 from what I recall.
Also the timing needs to be correct.
1st thing is to confirm the PIC will run a 1Hz LED program and is accurate.
2nd get ONE sensor to work....
3rd try a 2nd sensor.
i used them 5-6 years ago so all this is from memory.
Jay |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Fri Feb 05, 2016 6:30 pm |
|
|
when I changed oscillator frequency , it works. and when i used only one sensor. it has no problem. But 2 sensors have problem with 16 or higher frequency |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Fri Feb 05, 2016 9:05 pm |
|
|
what are hardware details of your one wire bus?
value of pullup resistor
length of wires to sensors
PCB, wirewrap or ???
Jay |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Sat Feb 06, 2016 4:03 am |
|
|
pull-up resistor 4K7. I use 2 sensors and i use PCB.
It works 2 sensors at 4MHz |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sat Feb 06, 2016 6:47 am |
|
|
Does it find both sensors and display their ID numbers and then 'fail'?
Are the sensor very close to the PCB or on wires ?
I used 4k7 pullup on DQ line with 5 volt PIC.
Also my project only used 4 sensors so I used individual I/O pins for each sensor. It was a lot easier for wiring and no need for the ID routines. I used integers for temp not float.
Also, you have a 200ms delay after reading, not sure why .
My PIC 18F46K22 is running at 16MHz .
edit: Need to know HOW you are connecting to the DS18B20 devices !!
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Sat Feb 06, 2016 1:49 pm |
|
|
A bit of searching here, finds that the driver you have has problems at higher speeds. Following thread has a fix for this:
<http://www.ccsinfo.com/forum/viewtopic.php?t=41878&highlight=ds18b20>
Problem is that once speed goes up two of the bit transactions are done too quickly. |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Sat Feb 06, 2016 2:17 pm |
|
|
I think My problem is speed. I decided to use low speed (4 or 8 MHz) I use 2 sensors and normal mode not powered mode. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9245 Location: Greensville,Ontario
|
|
Posted: Sat Feb 06, 2016 6:00 pm |
|
|
Here's the driver I've used for a few years. It might be of some help ?
Code: | // Reset one wire bus ,#1
void ow1_reset(void)
{
output_low(OW1);
delay_us(500); // Min. 480uS
output_float(OW1);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Reset one wire bus, #2
void ow2_reset(void)
{
output_low(OW2);
delay_us(500); // Min. 480uS
output_float(OW2);
delay_us(500); // Wait for end of timeslot
}
//-------------------------------------
// Read bit on one wire bus ,#1
int8 ow1_read_bit(void)
{
output_low(OW1);
delay_us(1);
output_float(OW1);
delay_us(12); // Read within 15uS from start of time slot
return(input(OW1));
}
//-------------------------------------
// Read bit on one wire bus ,#2
int8 ow2_read_bit(void)
{
output_low(OW2);
delay_us(1);
output_float(OW2);
delay_us(12); // Read within 15uS from start of time slot
return(input(OW2));
}
//-------------------------------------
// read a byte from device
int8 ow1_read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(ow1_read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
// read a byte from device,bus #2
int8 ow2_read_byte(void)
{
int8 i;
int8 val = 0;
for(i=0 ; i<8 ; i++)
{
if(ow2_read_bit()) val |= (0x01 << i);
delay_us(120); // To finish time slot
}
return val;
}
//-------------------------------------
// Write a byte to device,bus #1
void ow1_write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(OW1);
delay_us( 2 );
output_bit(OW1, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(OW1);
}
else
{
output_float(OW1);
delay_us( 2 );
}
}
}
//-------------------------------------
// Write a byte to device,bus #2
void ow2_write_byte(int8 val, int8 power_on)
{
int i;
for(i=0; i<8; i++)
{
output_low(OW2);
delay_us( 2 );
output_bit(OW2, shift_right(&val,1,0));
delay_us(60);
if((i == 7) && (power_on == 1))
{
output_high(OW2);
}
else
{
output_float(OW2);
delay_us( 2 );
}
}
}
// first device read temperature...
signed int16 ow1_read_temp(){
ow1_reset();
ow1_write_byte(0xCC, 0); // Skip Rom command
ow1_write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = ow1_read_byte();
}
ow1_reset();
t1 = (signed int16) make16(scratch[1],scratch[0]);
if(t1 >= 0)
t1 = (t1 + 8)/16;
else
t1 = (t1 - 8)/16;
return(t1);
}
//second device read temperature...
signed int16 ow2_read_temp(){
ow2_reset();
ow2_write_byte(0xCC, 0); // Skip Rom command
ow2_write_byte(0xBE, 0); // Read scratch pad command
// Get the data bytes
for(i=0; i < 8; i++)
{
scratch[i] = ow2_read_byte();
}
t2 = (signed int16) make16(scratch[1],scratch[0]);
if(t2 >= 0)
t2 = (t2 + 8)/16;
else
t2 = (t2 - 8)/16;
return(t2);
}
|
OW1 refers to the 'One Wire bus #1'
OW2 refers to the 'One Wire bus #2'
I used the parasitic mode for the devices, as it only requires 2 wires per sensor, making it for simpler hardware. used on 16F877, 16F88 and 18F46K22 at up to 16MHz with no problems. As the driver controls the timing it might be a good idea to put an oscilloscope on the bus and see what the actual timing is for the PIC.
As each sensor is on it's own I/O pin I didn't need the CRC or ID functions. The datalogger got a 1Hz interrupt from an RTC device that told main() to read the chips,display,log, then trigger a convert command.
Jay
Jay |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Sun Feb 07, 2016 2:38 am |
|
|
As a general comment, more devices on the bus will inherently imply more capacitance. So edges (rising in particular) will be slower. Anything that is tight on timing, can then fall 'over the edge'. Now the chip has specified 'minima' for the bit timings, of 1uSec. The code has this as a delay, while the thread I point to, extends this to 5uSec, when working at a higher clock rate.
I'd suggest extending these times to 2uSec, and slightly reducing the pull up resistor (the thermometer can pull down a maximum of 4mA - a lower resistance will improve the rising edges, and improve the power available for the chip). I'd suggest 3KR.
The code is working for 'one device per bus', and it is only failing with multiple devices. Obviously the solution does exist of having multiple busses as Temtronic does (this brings the big advantage of not having to scan for ID's etc.). However it should be possible to get multiple devices to work. |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Sun Feb 07, 2016 4:20 am |
|
|
In fact I tried 2K2 Pull-up resistor. It works only find devices function. so It found 2 chips and serial number but it has problem reading temp. while reading operations, it didn't any answer
@temtronic
thanks. good idea. but I want to use only one wire. Because of I have to use low speed |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19545
|
|
Posted: Sun Feb 07, 2016 4:25 am |
|
|
2K2, is getting rather low. The chip only has every limited pull down capability. Hence my suggestion to just reduce a _little_.
Key thing though is have you extended the times as shown in the post?.
Running at 8MHz (say), with a 1uSec delay, the actual 'time' between the clock, and testing, will be the 1uSec, plus two instruction times. Another micro second. So 2uSec. However at 16MHz, this drops to just 1.5uSec. It only takes the rise time of the signal to be perhaps 3/4uSec with the standard pull-up, for this to then fail..... |
|
|
respected
Joined: 16 May 2006 Posts: 95
|
|
Posted: Wed Feb 24, 2016 2:12 pm |
|
|
I tried but it doesn't work at 16MHz or higher. maybe driver is wrong.
This is great!! It works now. at 48MHz
Code: | #fuses HSPLL,NOWDT,NOXINST,DSBOR,RTCOSC_T1,PROTECT,PLL3,NOCPUDIV//CPUDIV3
#use delay(clock=48M,crystal=12M) |
Code: | int8 read_bit(void)
{
output_low(DQ);
delay_us(5); // Added, 1uS min. Code relied on 8051 being slow.
output_float(DQ);
delay_us(20); // Read within 15uS from start of time slot
return(input(DQ));
}
//******************************************************************************
void write_bit(int8 bitval)
{
output_low(DQ);
if(bitval == 1) {
delay_us(5); // 1uS min. Code relied on 8051 being slow.
output_float(DQ);
}
delay_us(60); // Wait for end of timeslot
output_float(DQ);
}
|
|
|
|
|
|
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
|