diff simple_ds18b20.c @ 0:8705acff2494

lots of stuff
author Matt Johnston <matt@ucc.asn.au>
date Sat, 01 Jun 2013 01:38:42 +0800
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/simple_ds18b20.c	Sat Jun 01 01:38:42 2013 +0800
@@ -0,0 +1,192 @@
+// Matt Johnston 2012
+// Based on ds18x20.c by Martin Thomas, in turn based on code by 
+// Peter // Dannegger and others.
+//
+#include <stdio.h>
+#include <avr/pgmspace.h>
+
+#include "ds18x20.h"
+#include "onewire.h"
+#include "crc8.h"
+
+#include "simple_ds18b20.h"
+
+uint8_t 
+simple_ds18b20_start_meas(uint8_t id[])
+{
+	uint8_t ret;
+
+	ow_reset();
+	if( ow_input_pin_state() ) { // only send if bus is "idle" = high
+		ow_command_with_parasite_enable(DS18X20_CONVERT_T, id);
+		ret = DS18X20_OK;
+	} 
+	else { 
+		ret = DS18X20_START_FAIL;
+	}
+
+	return ret;
+}
+
+static uint8_t 
+read_scratchpad( uint8_t id[], uint8_t sp[], uint8_t n )
+{
+	uint8_t i;
+	uint8_t ret;
+
+	ow_command( DS18X20_READ, id );
+	for ( i = 0; i < n; i++ ) {
+		sp[i] = ow_byte_rd();
+	}
+	if ( crc8( &sp[0], DS18X20_SP_SIZE ) ) {
+		ret = DS18X20_ERROR_CRC;
+	} else {
+		ret = DS18X20_OK;
+	}
+
+	return ret;
+}
+
+int16_t 
+ds18b20_raw16_to_decicelsius(uint16_t measure)
+{
+	uint8_t  negative;
+	int16_t  decicelsius;
+	uint16_t fract;
+
+	// check for negative 
+	if ( measure & 0x8000 )  {
+		negative = 1;       // mark negative
+		measure ^= 0xffff;  // convert to positive => (twos complement)++
+		measure++;
+	}
+	else {
+		negative = 0;
+	}
+
+	decicelsius = (measure >> 4);
+	decicelsius *= 10;
+
+	// decicelsius += ((measure & 0x000F) * 640 + 512) / 1024;
+	// 625/1000 = 640/1024
+	fract = ( measure & 0x000F ) * 640;
+	if ( !negative ) {
+		fract += 512;
+	}
+	fract /= 1024;
+	decicelsius += fract;
+
+	if ( negative ) {
+		decicelsius = -decicelsius;
+	}
+
+	if ( decicelsius == 850 || decicelsius < -550 || decicelsius > 1250 ) {
+		return DS18X20_INVALID_DECICELSIUS;
+	} else {
+		return decicelsius;
+	}
+}
+
+uint8_t 
+simple_ds18b20_read_decicelsius( uint8_t id[], int16_t *decicelsius )
+{
+    uint16_t reading;
+	uint8_t ret;
+
+    ret = simple_ds18b20_read_raw(id, &reading);
+    if (ret == DS18X20_OK)
+    {
+        *decicelsius = ds18b20_raw16_to_decicelsius(reading);
+    }
+    return ret;
+}
+
+uint8_t 
+simple_ds18b20_read_raw( uint8_t id[], uint16_t *reading )
+{
+	uint8_t sp[DS18X20_SP_SIZE];
+	uint8_t ret;
+	
+	if (id)
+	{
+		ow_reset();
+	}
+	ret = read_scratchpad( id, sp, DS18X20_SP_SIZE );
+	if ( ret == DS18X20_OK ) {
+        *reading = sp[0] | (sp[1] << 8);
+	}
+	return ret;
+}
+
+static void 
+printhex_nibble(const unsigned char b, FILE *stream)
+{
+	unsigned char  c = b & 0x0f;
+	if ( c > 9 ) { 
+		c += 'A'-10; 
+	}
+	else {
+		c += '0';
+	}
+	fputc(c, stream);
+}
+
+void 
+printhex_byte(const unsigned char b, FILE *stream)
+{
+	printhex_nibble( b >> 4, stream);
+	printhex_nibble( b, stream);
+}
+
+void
+printhex(uint8_t *id, uint8_t n, FILE *stream)
+{
+	for (uint8_t i = 0; i < n; i++)
+	{
+		if (i > 0)
+		{
+			fputc(' ', stream);
+		}
+		printhex_byte(id[i], stream);
+	}
+}
+
+
+uint8_t 
+simple_ds18b20_read_all()
+{
+	uint8_t id[OW_ROMCODE_SIZE];
+	for( uint8_t diff = OW_SEARCH_FIRST; diff != OW_LAST_DEVICE; )
+	{
+		diff = ow_rom_search( diff, &id[0] );
+
+		if( diff == OW_PRESENCE_ERR ) {
+			printf_P( PSTR("No Sensor found\r") );
+			return OW_PRESENCE_ERR; // <--- early exit!
+		}
+		
+		if( diff == OW_DATA_ERR ) {
+			printf_P( PSTR("Bus Error\r") );
+			return OW_DATA_ERR;     // <--- early exit!
+		}
+
+		int16_t decicelsius;
+		uint8_t ret = simple_ds18b20_read_decicelsius(NULL, &decicelsius);
+		if (ret != DS18X20_OK)
+		{
+			printf_P(PSTR("Failed reading\r"));
+			return OW_DATA_ERR;
+		}
+
+		printf_P(PSTR("DS18B20 %d: "), diff);
+		if (crc8(id, OW_ROMCODE_SIZE))
+		{
+			printf_P(PSTR("CRC fail"));
+		}
+		printhex(id, OW_ROMCODE_SIZE, stdout);
+		printf_P(PSTR(" %d.%d ÂșC\n"), decicelsius/10, decicelsius % 10);
+	}
+	printf_P(PSTR("Done sensors\n"));
+	return DS18X20_OK;
+}
+