DS18B20 and PIC16F690

Thread Starter

Litch

Joined Jan 25, 2013
85
So, my first day of PIC programming.

I've found it is very much write and pray for the small footprint chips, no real-time debugging like I'm used to on a PC (at least not on the small PICs without more ICD hardware).

Anyway, PIC asm can get stuffed, I don't have time to learn a whole new set of opcodes so I installed the HI-TECH C Compiler, MPLAB IDE etc...

I have a "Pickit2 Low Pin Count Demo" board and a Pickit2 ISCP USB programmer.

Project: Use a PIC16F690 to gather temperatures from multiple DS18B20 digital thermometers and output to RS232 to be logged by a server.

So my idea was to output to RS232 and log temps, but before I went throwing MAX232s around I wanted to make sure the FIRST part was working (temp I/O) so the PICkit2 board has 4 LEDs on it, connected to RC0-RC3. I thought, well I'd just display nibble by nibble with a delay so I could scribble down the temp and verify it's accuracy (and just be sure that part's working before I go adding more 1-wire devices).

BUT. I get nothing, no lights.

The nibble([0-15]) function works fine, the delay_ms() works fine, and I have no idea where to go from here to debug this thing...

Help?

Schematic and code attached, power is drawn from the ICSP (USB 5v).
 

Attachments

ErnieM

Joined Apr 24, 2011
8,415
The good news is the PICKIT2 allows you to do in circuit debugging just like on a PC... in fact you use your PC to view the PIC.

The bad news is the PICKIT2 doesn't come with lessons in C.

I'm not sure if the HI-TECH compiler works as seamlessly as the XC8 (free donload) compiler does.
 

ErnieM

Joined Apr 24, 2011
8,415
I also noted your I/O pins have analog functions... make sure you turn them OFF, they are on by default.

Post the code. Use code tags please.
 

Thread Starter

Litch

Joined Jan 25, 2013
85
The LEDs work fine, the function I wrote (nibble()) completely works as expected. This is purely an issue between the DS18B20 and the PIC - the code I've got detects the 1-wire presence, but does not communicate with the DS18B20.

The source code and schematic it attached to my first post but if you want it pasted in here:

Rich (BB code):
#include <htc.h>			//include hitech C header file

#define	_XTAL_FREQ			8000000

// This configuration bits are for PIC16F690 using internal crystal
__CONFIG(FOSC_INTRCIO &		// Clock pins are I/O
		 WDTE_OFF &			// Disable Watchdog Timer.
		 PWRTE_ON &			// Enable Power Up Timer.
		 BOREN_OFF);		// Disable Brown Out Reset.

#define SCS_BIT				0x01
#define INT_OSC_8MHZ 		(0b01110000 | SCS_BIT)
#define INT_OSC_4MHZ 		(0b01100000 | SCS_BIT)
#define INT_OSC_2MHZ 		(0b01010000 | SCS_BIT)
#define INT_OSC_1MHZ 		(0b01000000 | SCS_BIT)
#define INT_OSC_500KHZ 		(0b00110000 | SCS_BIT)
#define INT_OSC_250KHZ 		(0b00100000 | SCS_BIT)
#define INT_OSC_125KHZ 		(0b00010000 | SCS_BIT)
#define INT_OSC_31KHZ 		(0b00000000 | SCS_BIT)

#define Skip_ROM 			0xCC
#define Convert_T 			0x44
#define Read_scratchpad 	0xBE

#define Port_18B20 			RB4
#define Tx_18B20 			TRISB4 = 0
#define Rx_18B20 			TRISB4 = 1

#define WAIT1				1000
#define WAIT2				500

#define DS18B20_CONV_TIME	750
#define DS18B20_RESET_PULSE 480
#define DS18B20_WAIT_TIME 	60
#define DS18B20_PULLUP_TIME 2

#define ONEWIRE_PRESENT 	0
#define ONEWIRE_ABSENT 		1

void init();
void delay_ms(unsigned int ui_value);
void beep(unsigned char uc_count);
unsigned char reset();
void write(char WRT);
unsigned char read();
void nibble(unsigned byte);

/*******************************************************************************
* MAIN FUNCTION                                                                *
*******************************************************************************/
int main(void)
{
	unsigned temp, val;
	unsigned short tempL, tempH, fraction;
	unsigned int i = 0;	// declare a variable to store   

	init();

	while(1) 	// create an infinite loop
	{		
		if (reset() == ONEWIRE_PRESENT)
		{
			write(Skip_ROM);
			write(Convert_T);		
			delay_ms(DS18B20_CONV_TIME);
			
			reset();
			write(Skip_ROM);		
			write(Read_scratchpad);	
			
			tempL = read();			//read low temp value
			tempH = read();			//read high temp value
			
			//put both value in one variable
			nibble(tempH);
			delay_ms(WAIT1);
			nibble(0);
			delay_ms(WAIT2);
			
			temp = tempH >> 4;
			nibble(temp);
			delay_ms(WAIT1);
			nibble(0);
			delay_ms(WAIT2);

			nibble(tempL);
			delay_ms(WAIT1);
			nibble(0);
			delay_ms(WAIT2);

			temp = tempL >> 4;
			nibble(temp);
			delay_ms(WAIT1);
			nibble(0);
			delay_ms(WAIT2);
		} else {
			break;
		}
	}

	// Solid LED pattern to indicate we're somewhere we shouldn't be.
	RC0 = 1;
	RC1 = 0;
	RC2 = 1;
	RC3 = 0;

	while (1) continue;
}

void init()
{
	ANSEL = 0;		//Initialize A/D ports off 
	ANSELH = 0;		//Initialize A/D ports off 
	CM1CON0 = 0;	//Initialize comp 1 off 
	CM2CON0 = 0;	//Initialize comp 2 off 
	PORTA = 0x00;	// Clears PORTA
	PORTB = 0x00;	// Clears PORTB
	PORTC = 0x00;	// Clears PORTC
	TRISA = 0x00;	// Sets PORTA to all output
	TRISB = 0x00;	// Sets PORTB to all output
	TRISC = 0x00;	// sets PORTC to all output. 

	// We want 8MHz
	OSCCON = INT_OSC_8MHZ;

	// Wait for clock to stabilise.
	delay_ms(10);
}

void nibble(unsigned byte)
{
	PORTC = (unsigned)(byte & 0x0f);
	return;
}

void delay_ms(unsigned int ui_value)
{
	while (ui_value-- != 0) {
		__delay_ms(1);					// macro from HI-TECH compiler which will generate 1ms delay base on value of _XTAL_FREQ in system.h
	}	
}

unsigned char reset()
{
	Tx_18B20;							// Tris = 0 (output)
	Port_18B20 = 0;						// set pin# to low (0)
	__delay_us(DS18B20_RESET_PULSE);	// 1 wire require time delay
	Rx_18B20;							// Tris = 1 (input)
	__delay_us(DS18B20_WAIT_TIME);		// 1 wire require time delay

	if (Port_18B20 == 0) 				// if there is a presence pluse
	{ 
		__delay_us(DS18B20_RESET_PULSE);// Reset and return
		return ONEWIRE_PRESENT;			// return 0 ( 1-wire is presence)
	}

	__delay_us(DS18B20_RESET_PULSE);	// Reset and return
	return ONEWIRE_ABSENT;				// return 1 ( 1-wire is NOT presence)
}

void write(char WRT)
{
	char i,Cmd;
	Cmd = WRT;
	Rx_18B20; // set pin# to input (1)
	for(i = 0; i < 8; i++)
	{
		if((Cmd & (1<<i))!= 0) 
		{
			// write 1
			Tx_18B20; // set pin# to output (0)
			Port_18B20 = 0; // set pin# to low (0)
			__delay_us(DS18B20_PULLUP_TIME); // 1 wire require time delay
			Rx_18B20; // set pin# to input (release the bus)
			__delay_us(DS18B20_WAIT_TIME); // 1 wire require time delay
		} else  {
			//write 0
			Tx_18B20; // set pin# to output (0)
			Port_18B20 = 0; // set pin# to low (0)
			__delay_us(DS18B20_WAIT_TIME); // 1 wire require time delay
			Rx_18B20; // set pin# to input (release the bus)
		}
	}
}

unsigned char read()
{
	char i,result = 0;
	Rx_18B20; // TRIS is input(1)
	for(i = 0; i < 8; i++)
	{
		Tx_18B20; // TRIS is output(0)
		Port_18B20 = 0; // genarate low pluse for 2us
		__delay_us(DS18B20_PULLUP_TIME);
		Rx_18B20; // TRIS is input(1) release the bus
		if(Port_18B20 != 0) { 
			result |= 1<<i;
		}
		__delay_us(DS18B20_WAIT_TIME); // wait for recovery time
	}
	return result;
}
 

Thread Starter

Litch

Joined Jan 25, 2013
85
I suspect the delay_us and delay_ms may be off, as this would explain the lack of communication between the DS18 and the PIC, it would also explain why it's still seeing the response from the DS18 as the timing on that is large and less specific compared to the read/write timing.

But if I blink an LED at 1000ms it definitely seems like 1 second.../sigh...what I would do for a decent oscilloscope...
 

Thread Starter

Litch

Joined Jan 25, 2013
85
Q: This PIC has an internal timer. How would I go about verifying the delay_ms() time using the LEDs?

Something like:
TMR0 = (Whatever equates to 500ms)
delay_ms(500);
RC0 = 1


(When the Timer interrupt triggers RC1 = 1)

Then I could see which turns on first, or if they're about right.

Sound feasible?
 

ErnieM

Joined Apr 24, 2011
8,415
Q: Sound feasible?
Nah, too much work and too much room for error. Besides, if the line:

Rich (BB code):
#define    _XTAL_FREQ            8000000
accurately reflects the crystal in the hardware then the delays will be correct.

If you flashed the led for a second and it looks good by your watch then you nailed it.
 

Thread Starter

Litch

Joined Jan 25, 2013
85
OMFG

It was a dud breadboard.

The +Ve strip up the side didn't continue past just over 1/3 of the length and the DQ pull up and Vcc for the DS18B20 wasn't even powered.

Just because I made the assumption that the 1-wire was detecting within the PIC code that the temp IC was fine and it was an I/O issue...

Works now, and the LEDS flash:
1000
0000
0110
0101

Which is b'0000 0001 0101 0110'
Which is decimal 378
...23.625 C

I put my finger on it for a few seconds...

1000
0000
1010
0011

Which is b'0000 0001 1100 0101'
...28.3125 C

Which is about right.
 
Top