  | 
	  | 
		 
	 
	
		| View previous topic :: View next topic   | 
	 
	
	
		| Author | 
		Message | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Tue Sep 15, 2009 6:19 pm     | 
				     | 
			 
			
				
  | 
			 
			
				I was able to make it work in parasite mode.   I think the problem was
 
mainly in the timing of when the DQ pin should be set high.  I will post
 
the list of modifications later, after I test it some more. | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Kenny
 
 
  Joined: 07 Sep 2003 Posts: 173 Location: Australia 
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Wed Sep 16, 2009 9:13 am     | 
				     | 
			 
			
				
  | 
			 
			
				Edited:
 
 
Deleted post.
 
 
Testing showed that the delay at the end of write_bit() wasn't critical within the specified timeslot width. 
 
Had to be a long way outside the specified range before it stopped working. | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Sep 17, 2009 6:00 am     | 
				     | 
			 
			
				
  | 
			 
			
				PCM, 
 
 
Many thanks, I'm eagerly awaiting your findings!
 
 
Joe | 
			 
		  | 
	 
	
		  | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Sep 17, 2009 2:23 pm     | 
				     | 
			 
			
				
  | 
			 
			
				This is basically what you need to do.  Modify your write_byte() routine
 
so it has a parameter to tell it to optionally turn on Bus power at the
 
end of the transmission.  Get rid of the separate write_bit() routine.
 
 	  | Code: | 	 		  
 
void write_byte(int8 val, int8 power_on) 
 
{ 
 
int i; 
 
 
 for (i=0; i<8; i++) 
 
 { 
 
  output_low(DQ); 
 
  delay_us( 2 );  
 
  output_bit(DQ, shift_right(&val,1,0));  
 
 
  delay_us(60);
 
  
 
  if((i == 7) && (power_on == 1))
 
    {
 
     output_high(DQ);
 
    }
 
  else
 
    {
 
     output_float(DQ); 
 
     delay_us( 2 );  
 
    } 
 
 } 
 
 
 
} | 	  
 
 
Then modify all the calls to write_byte() in your main code, so they
 
have the power on parameter.  Then set it to turn power on after
 
the Temp Convert command is sent.   Here's the relevant part:
 
 	  | Code: | 	 		  
 
while(1) 
 
   { 
 
      ow_reset(); 
 
      write_byte(0xCC, 0); // Skip Rom command 
 
      write_byte(0x44, 1); // Temperature Convert command 
 
 
      delay_ms(750);    // Max. time for conversion is 750mS 
 
    
 
      ow_reset(); 
 
      write_byte(0xCC, 0); // Skip Rom command 
 
      write_byte(0xBE, 0); // Read scratch pad command 
 
    
 
      // Get the data bytes 
 
      for (i=0 ; i<8 ; i++) 
 
      { 
 
          scratch[i] = read_byte();  
 
      } 
 
    
 
      ow_reset();  | 	  
 
 
Then it should work.  Putting my finger on the DS18B20 chip causes
 
the temperature to rise:
 
 	  | Quote: | 	 		  
 
Temp:   25 C
 
Temp:   25 C
 
Temp:   25 C
 
Temp:   25 C
 
Temp:   25 C
 
Temp:   25 C
 
Temp:   26 C
 
Temp:   27 C
 
Temp:   27 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   29 C
 
Temp:   29 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
Temp:   28 C
 
 | 	  
 
I didn't completely test this, and I didn't check the timing with a scope
 
or logic analyzer to see if it fits the data sheet's spec.   You'll have to
 
do that. | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Sep 17, 2009 8:47 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Hi PCM,
 
 
That works - many thanks!
 
 
Interestingly, I experimented with a similar 'fix' that did not include the 'Power-on' flag. In retrospect that prevented my solution from working.
 
 
This experience has convinced me to get a scope, and I've got one on the way off eBay. When I get it, I'll look at the timing and verify that it's 'in spec.' For anyone following the thread, I'll report my findings sometime next week.
 
 
Thanks again for your interest, and your effort!
 
 
Joe | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Oct 01, 2009 1:16 pm     | 
				     | 
			 
			
				
  | 
			 
			
				C-coders,
 
 
I'd like to use this code to read two different sensors on two separate input pins. To do this, I was thinking of replacing this line:
 
 
 	  | Code: | 	 		  
 
#define DQ PIN_A0      // One Wire Bus pin assignment
 
 | 	  
 
 
with something like this
 
 
 
 
That would allow me to set DQ to any value from the .h file for my PIC and specify a different sensor using the same DS18B20 subroutines..... The problem is that it doesn't seem to work, and I'm not sure why. It  compiles, but the temperature that is returned is always zero.
 
 
If this is not the proper way to specify different sensors, can someone recommend another method?
 
 
Cheers,
 
 
Greg | 
			 
		  | 
	 
	
		  | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Oct 01, 2009 1:57 pm     | 
				     | 
			 
			
				
  | 
			 
			
				This driver requires careful timing.   The ASM code that CCS generates
 
to do pin i/o functions with a variable argument, is huge.   It takes much
 
longer to execute than if a constant argument is used.  You can see this
 
with a test program:
 
 
 	  | Code: | 	 		  #include <16F877.H>
 
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
 
#use delay(clock=4000000)
 
 
//======================================
 
void main()
 
{
 
int8 pin = PIN_A0;
 
 
output_low(PIN_A0);
 
 
output_low(pin);
 
 
while(1);
 
} | 	  
 
 
Here's the .LST file.  Notice how it takes 4 instructions with a constant,
 
but a huge number with a variable argument.  At 4 MHz, one instruction
 
takes 1 usec.   With a variable argument, all these extra instructions
 
ruin the careful timing of the existing ds18b20 driver.
 
 	  | Code: | 	 		  .................... output_low(PIN_A0); 
 
0030:  BSF    03.5
 
0031:  BCF    05.0
 
0032:  BCF    03.5
 
0033:  BCF    05.0
 
....................  
 
.................... output_low(pin); 
 
0034:  MOVF   21,W
 
0035:  MOVWF  22
 
0036:  CLRF   23
 
0037:  CLRF   25
 
0038:  CLRF   24
 
0039:  CALL   004
 
003A:  MOVF   21,W
 
003B:  MOVWF  22
 
003C:  CLRF   23
 
003D:  CLRF   25
 
003E:  MOVLW  80
 
003F:  MOVWF  24
 
0040:  CALL   004
 
....................  
 
// The routine at 0x0004:
 
0004:  MOVF   22,W
 
0005:  ANDLW  07
 
0006:  MOVWF  77
 
0007:  RRF    22,W
 
0008:  MOVWF  78
 
0009:  RRF    78,F
 
000A:  RRF    78,F
 
000B:  MOVLW  1F
 
000C:  ANDWF  78,F
 
000D:  MOVF   78,W
 
000E:  ADDWF  24,W
 
000F:  MOVWF  04
 
0010:  BCF    03.7
 
0011:  BTFSC  25.0
 
0012:  BSF    03.7
 
0013:  CLRF   78
 
0014:  INCF   78,F
 
0015:  INCF   77,F
 
0016:  GOTO   018
 
0017:  RLF    78,F
 
0018:  DECFSZ 77,F
 
0019:  GOTO   017
 
001A:  MOVF   23,F
 
001B:  BTFSC  03.2
 
001C:  GOTO   020
 
001D:  MOVF   78,W
 
001E:  IORWF  00,F
 
001F:  GOTO   023
 
0020:  COMF   78,F
 
0021:  MOVF   78,W
 
0022:  ANDWF  00,F
 
0023:  RETLW  00 | 	 
  | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Oct 01, 2009 2:10 pm     | 
				     | 
			 
			
				
  | 
			 
			
				PCM,
 
 
OK, I understand the timing issues involved.
 
 
Do you have a recommendation for how I can read sensors on two separate pins using this code?
 
 
Thanks,
 
 
Greg | 
			 
		  | 
	 
	
		  | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Oct 01, 2009 2:13 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Make a copy of the routines and give them new names.  Use your other
 
pin number in the new routines. Call the new routines for the 2nd chip. | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Thu Oct 01, 2009 2:47 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Hehe, I was afraid you were going to say that    !
 
 
I'm going to try a 20 MHz xtal first, and if that doesn't provide sufficient margin, I'll use separate code for each sensor!
 
 
Thanks,
 
 
Greg | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Oct 02, 2009 1:43 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Hi PCM,
 
 
I've been thinking about this issue, and I have a question. I understand that changing the DQ pin designation "on the fly" is time consuming from an instruction point-of-view. Obviously, something happens when the #Define DQ Pin_A0 is executed, and I'm not sure why I can't replicate that functionality to select another pin between readings of my two sensors. Yes, the readings themselves are time critical, but I've got tons of time available between readings. Isn't there some way to get the same effect as the #Define, to switch I/O pins during runtime? I'm not trying to be a pain, just to learn something here about how the compiler works, or its limitations.
 
 
Greg | 
			 
		  | 
	 
	
		  | 
	 
	
		
			Guest
 
 
 
 
 
  
			
			
			
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Oct 02, 2009 2:01 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Another thought is that there is some code written by Peter Anderson that is floating around that supports up to four sensors each on a separate pin. The only issue is that it's written for Port B. I looked at the code and it looks like I could change the PORTB calls to PORTA, and the TRISB to TRISA, and get the same functionality on Port A?
 
 
Greg | 
			 
		  | 
	 
	
		  | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Fri Oct 02, 2009 2:17 pm     | 
				     | 
			 
			
				
  | 
			 
			
				 	  | Quote: | 	 		  | something happens when the #Define DQ Pin_A0 is executed, | 	  
 
It happens at compile-time, not at run-time.  At compile-time, the 
 
compiler creates the machine code for the Hex file.   It uses that
 
#define statement to put the correct numbers into the BSF and BCF
 
instructions in the machine code.  
 
 
You could possibly use a switch-case statement.   Re-write the routines
 
to accept a channel number (0 to 3), and inside each case, you could
 
do the i/o operation on the appropriate pin.
 
 
This is the Peter Anderson code.  It might give you some ideas.
 
http://www.phanderson.com/PIC/PICC/CCS_PCM/ds1820.html | 
			 
		  | 
	 
	
		  | 
	 
	
		
			PCM programmer
 
 
  Joined: 06 Sep 2003 Posts: 21708
  
			
			 
			 
			
			
			
			
			
			
			
  
		  | 
		
			
				 | 
			 
			
				 Posted: Sun Mar 14, 2010 1:22 pm     | 
				     | 
			 
			
				
  | 
			 
			
				Here's the complete test program for the ds18B20 in parasite-power 
 
mode.  This is the original poster's program, with the modifications
 
added, that I recommended in a post above.   I'm posting the integrated 
 
program because of a request.
 
 	  | Code: | 	 		  
 
#include <16F877.H>
 
#fuses XT, NOWDT, BROWNOUT, PUT, NOLVP
 
#use delay(clock=4000000) 
 
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
 
 
#define DQ   PIN_C2   
 
 
//-------------------------------------
 
void ow_reset(void) 
 
{ 
 
output_low(DQ); 
 
delay_us(500);          // Min. 480uS 
 
output_float(DQ); 
 
delay_us(500);          // Wait for end of timeslot 
 
} 
 
 
//-------------------------------------
 
// Read bit on one wire bus 
 
 
int8 read_bit(void) 
 
{ 
 
output_low(DQ); 
 
delay_us(1);          
 
output_float(DQ); 
 
delay_us(12);        // Read within 15uS from start of time slot 
 
return(input(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 power_on) 
 
{ 
 
int i; 
 
 
for(i=0; i<8; i++) 
 
   { 
 
    output_low(DQ); 
 
    delay_us( 2 );  
 
    output_bit(DQ, shift_right(&val,1,0));  
 
 
    delay_us(60);
 
  
 
    if((i == 7) && (power_on == 1))
 
      {
 
       output_high(DQ);
 
      }
 
    else
 
      {
 
       output_float(DQ); 
 
       delay_us( 2 );  
 
      } 
 
   } 
 
 
}
 
 
//==========================================
 
void main(void) 
 
{ 
 
int8 i; 
 
signed int16 temperature; 
 
int8 scratch[9];        
 
    
 
output_float(DQ);      
 
    
 
while(1) 
 
  { 
 
   ow_reset(); 
 
   write_byte(0xCC, 0); // Skip Rom command 
 
   write_byte(0x44, 1); // Temperature Convert command 
 
 
   delay_ms(750);    // Max. time for conversion is 750mS 
 
    
 
   ow_reset(); 
 
   write_byte(0xCC, 0); // Skip Rom command 
 
   write_byte(0xBE, 0); // Read scratch pad command 
 
    
 
   // Get the data bytes 
 
   for(i=0; i < 8; i++) 
 
      { 
 
       scratch[i] = read_byte();  
 
      } 
 
    
 
   ow_reset(); 
 
      
 
   temperature = (signed int16) make16(scratch[1],scratch[0]); 
 
          
 
   if(temperature >= 0) 
 
      temperature = (temperature + 8)/16; 
 
   else 
 
      temperature = (temperature - 8)/16; 
 
            
 
   printf("Temp: %4Ld C \n\r",temperature); 
 
  } 
 
 
}  | 	 
  | 
			 
		  | 
	 
	
		  | 
	 
	
		 | 
	 
 
  
	 
	    
	   | 
	
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
  
		 |