Reading output from DS18B20 to USART on ATMEGA128 ?

Go To Last Post
25 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Guys,

I tried to read DS18B20...
but the output in USART is

Temperature : ?

What should I change in this code ? thanks

 

	double d = 0;
	int d1 = d; 
		
	usart_init(BAUD_PRESCALE);
	usart_pstr("TEST DS18B20 \n" );
	//init interrupt
	sei();
	
	while(1)
	{
		d = ds18b20_gettemp();
		//printf(printbuff,"%d",d1);
		
		sprintf(printbuff, "%.2f", d);
		usart_pstr("Temperature:");
		usart_pstr(printbuff);
		usart_pstr("\r\n");
		_delay_ms(500);
		
	}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Go on. You have been a member here for some time now.
You know that the full fat printf () function needs you to tick a box in AS6.
Where did you get your ds18b20_gettemp () function? Does it return a double?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What is the declaration of printbuff ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To David,

 

double ds18b20_gettemp() , and

Is it the one you mean ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
char printbuff[100];

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I ticked :

and get

 

Temperature : - 0.06, what do I miss now ???

Last Edited: Sun. Jun 28, 2015 - 09:45 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I do not see how you can link with both printf_min and printf_flt. Just use printf_flt.
I have no idea about your code or ds18b20_xxxx () functions. Where did they come from?
Surely there will be a ds18b20_init () of some description.
It is winter in Australia. Is it a cold day today?
Otherwise it looks as if you have a pretty straightforward program.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To David

Yes it's cold now 8 degree

Here's the function

/*
 * get temperature
 */
double ds18b20_gettemp() {
	uint8_t temperature_l;
	uint8_t temperature_h;
	double retd = 0;

	#if DS18B20_STOPINTERRUPTONREAD == 1
	cli();
	#endif

	ds18b20_reset(); //reset
	ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
	ds18b20_writebyte(DS18B20_CMD_CONVERTTEMP); //start temperature conversion

	while(!ds18b20_readbit()); //wait until conversion is complete

	ds18b20_reset(); //reset
	ds18b20_writebyte(DS18B20_CMD_SKIPROM); //skip ROM
	ds18b20_writebyte(DS18B20_CMD_RSCRATCHPAD); //read scratchpad

	//read 2 byte from scratchpad
	temperature_l = ds18b20_readbyte();
	temperature_h = ds18b20_readbyte();

	#if DS18B20_STOPINTERRUPTONREAD == 1
	sei();
	#endif

	//convert the 12 bit value obtained
	retd = ( ( temperature_h << 8 ) + temperature_l ) * 0.0625;

	return retd;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0




 
#define DS18B20_PORT PORTC
#define DS18B20_DDR DDRC
#define DS18B20_PIN PINC
#define DS18B20_DQ PC0

//commands
#define DS18B20_CMD_CONVERTTEMP 0x44
#define DS18B20_CMD_RSCRATCHPAD 0xbe
#define DS18B20_CMD_WSCRATCHPAD 0x4e
#define DS18B20_CMD_CPYSCRATCHPAD 0x48
#define DS18B20_CMD_RECEEPROM 0xb8
#define DS18B20_CMD_RPWRSUPPLY 0xb4
#define DS18B20_CMD_SEARCHROM 0xf0
#define DS18B20_CMD_READROM 0x33
#define DS18B20_CMD_MATCHROM 0x55
#define DS18B20_CMD_SKIPROM 0xcc
#define DS18B20_CMD_ALARMSEARCH 0xec
uint8_t ds18b20_reset() {
	uint8_t i;

	//low for 480us
	DS18B20_PORT &= ~ (1<<DS18B20_DQ); //low
	DS18B20_DDR |= (1<<DS18B20_DQ); //output
	_delay_us(480);

	//release line and wait for 60uS
	DS18B20_DDR &= ~(1<<DS18B20_DQ); //input
	_delay_us(60);

	//get value and wait 420us
	i = (DS18B20_PIN & (1<<DS18B20_DQ));
	_delay_us(420);

	//return the read value, 0=ok, 1=error
	return i;
}

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I wanted to see a link to proven library code.    I did not want to see some random paste job.

 

I Googled "dsb20_gettemp" and found https://github.com/mkschreder/avr-ultimate-driver-pack/blob/master/ds18b20.c

It looks perfectly respectable.    It also looks as if the author nicked code from Davide Girone.

 

Of course,  it is your responsibility to disable interrupts during the onewire primitive calls.    And your responsibility to buy a real DS18B20 and real 4k7 pull-up resistor.    As well as connect it to the PC0 pin.

 

Somehow the Arduino approach is more foolproof.

 

David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here we go again..........

 

To localise the problem, I would output the raw values from the ds1820 and see if they make sense. That answers the question of whether you are getting garbage from the ds1820 code or the problem is further on.

 

Having said that, this line looks suspect:

retd = ( ( temperature_h << 8 ) + temperature_l ) * 0.0625;

Since we're dealing with floating point and shifting left doesn't make much sense:

retd = ( ( temperature_h * 256.0 ) + temperature_l ) * 0.0625;

Might yield a better result.

With all the time you spent pissing around with this, you could've had yourself an electronic or software engineering degree. How many years??

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Yes it was from this library...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To Kartman:

 

Let me see about your solution

retd = ( ( temperature_h * 256.0 ) + temperature_l ) * 0.0625;

Is there a relation between degree and this matter? and yourself is an electronic and software engineer ?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To Kartman :

Here's the output now :

 

Temperature:4095.937500

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

To David, I've tested with arduino and it's ok....now I moved on to my ATMEGA128...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The relation is one of education - how many years have you been fiddling with this stuff and still making rookie errors?

 

I suggested you output the raw data. You seemed to have missed this critical suggestion. It seems the values are 0xff and 0xff. At least one problem is solved. Look at your ds1820 code.

 

You've got a logic analyser - use it to see what is happening on the one wire bus.

Last Edited: Sun. Jun 28, 2015 - 11:41 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Kartman wrote:

The relation is one of education - how many years have you been fiddling with this stuff and still making rookie errors?

 

I suggested you output the raw data. You seemed to have missed this critical suggestion. It seems the values are 0xff and 0xff. At least one problem is solved. Look at your ds1820 code.

 

You've got a logic analyser - use it to see what is happening on the one wire bus.

 

Ok, thanks for the suggestion...I have logic analyzer and osciloscope but I don't have much time for it now....it's just for fun and filling my free time...like filling a puzzle...

If it's 0xFF and 0xFF it's 65535 isn't it ?

 

I'll continue later on...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

/*debug with usart*/
	usart_pstr("Low byte value:")
	sprintf(printbuff_temp, "%2d", temperature_l);
	usart_pstr("\r\n");
	sprintf(printbuff_temp, "%2d", temperature_h);
	usart_pstr("\r\n");
/*debug with usart*/

Perhaps this one can show something ? every helps from you guys are very appreciated...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I think it makes sense if the temperature is 22.75 on high byte value, but it's empty on low byte value...why ????

 

Output at UART :

Low byte value:
High byte value:
Temperature:22.750000

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The idea was that you test your code. But we've already determined the values you're getting. Why not put those debug tools you paid good money for to good use and use them to debug your problem. Its probably something simple like a port problem or timing. 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I put on my notebook exhaust fan, it's showing :

 

High byte value:
Temperature:36.250000

 

I reckon it's working as it's supposed to be...isn't it ? so I don't need my logic analyzer,

 

Thanks to Kartman and David, I appreciate your comments...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Something just doesn't sound right - you were getting 0xffff as a response, now you're getting correct data - on the wrong registers. 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You will need to print the contents of printbuff_temp to see useful information.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The real intent of the left-shift is to create a 16-bit value that is then scaled by the 0.0625
(the fractional-portion of the conversion is in the first 4-bits of the low-byte)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seems like one should expect to keep the fractional part of the temperature if one is passing a floating point result.

 

Imagecraft compiler user