1-Wire Bus Questions

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

Hey all,

I have a question regarding the 1-Wire Bus. I am using WinAVR and trying to interface a ATMega168 (running at 8Mhz, CLKDIV/8 fuse is not set) with a DS1822 digital temperature sensor. I am attempting to use the library from http://www.sicklinger.com/en/atmel-avr-atmega-ds18x20-library-in-c.html. I am using the timer/counter0 interrupt to detect pulses from another sensor, and also reading an input from an analog temp sensor. I have looked at the 1-wire bus activity on my o-scope and it appears that the timing is in order (although, I had to make a few adjustments to the delays in the code). The issue I am having is when I display the temperature from the DS1822 to my LCD display, it shows -88. I am seeing one odd waveform in the 1-wire bus activity which is shown in the image below:

[img][/img]

I have tried disabling all of the calling functions in my program and also disabling the interrupts using cli()while reading from the DS1822. I believe I have a timing issue, but wanted to confirm. I am also attaching the typical activity I am seeing on the bus:

[img][/img]

Attached is the code that I have so far (Disclaimer: I am far from a "good" C programmer, so be gentle!). I realize there are a lot of global variables called out, which I will be addressing soon.

Thanks in advance for the suggestions.

 /* DataLogger.c	-	Program for collection of data from external sensors.  Data is logged onto SD flash memory. */ 


#include  
#include  
#include  
#include  
#include "lcd.h" 
#include "i2cmaster.h" 

#define DS1307   	0b11010000 
#define DISABLE		0

//***** One-Wire Library Includes
#include "OneWireLibrary/ds18x20lib.h"

//***** ADC Channel Definitions  (Added 12/11/2011)
#define ADC0			0b00000000
#define ADC1			0b00000001
#define ADC2			0b00000010
#define ADC3			0b00000011

//***** ADC-Related Defines (Added 12/11/2011)
#define VREF			5000	// 5V
#define BIT_RES			1024	// Bit resolution of 10-bit ADC

// Variable Declaration for DS1307 Registers 
char ds1307_sec[7];		// DS1307 Seconds Register value (converted to decimal)
char ds1307_min[7];		// DS1307 Minute Register value (converted to decimal)
char ds1307_hour[7];		// DS1307 Hour Register value (converted to decimal)
char ds1307_AmPm[3];		// DS1307 Am/Pm Register value (converted to decimal)
char ds1307_weekday[7];	// DS1307 Day of Week Register value (converted to decimal)
char ds1307_monthday[7];	// DS1307 Day of Month Register value (converted to decimal)
char ds1307_month[7];	// DS1307 Month Register value (converted to decimal)
char ds1307_year[7];		// DS1307 Year Register value (converted to decimal)
volatile uint8_t ReadDS1307Flag, WriteLCDFlag; // volatile variable type, ISR accesses this variable
uint8_t Seconds, DayofWeek, Month, Minutes, Hour, Pm;

// Current Time variables
uint8_t ct_sec = 0;			// Initialize for 0 seconds
uint8_t ct_min = 0;			// Initialize for 0 minutes
uint8_t ct_hour = 12;		// Initialize for the 12th hour
int8_t ct_dayweek = 1;		// Initialize for 1 (Monday)
int8_t ct_daymonth = 1;	// Initialize for the 1st of the Month
int8_t ct_month = 1;		// Initialize for the 1st month (January)
int8_t ct_year = 10;		// Initialize for the 10th year after year 2000 (2010)
uint8_t ct_ampm = 0;		// Initialize for 0 (Am)
char CtHour[3], CtMin[3], CtYear[3], CtMonthday[3];	// Array of characters for string storage of converted unsigned integer values using utoa() function.

// Array of Pointers to input string for decimal value
char *weekday[] = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"};		// Array of Pointers for Week Days
char *month[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};		// Array of Pointers for Months
char *AmPm[] = {"Am", "Pm"};	// Array of Pointers for AM / PM
//char *OnOff[] = {"Off", "On"};	// Array of Pointers for Alarm On / Off
//char *Snooze[] = {"Off", "On"};	// Array of Pointers for Snooze On / Off
char Hours[3], Min[3];

// Anemometer input / calculation variables
uint8_t AnemDebounceFlag = 0;	// shouldn't need to ask what this does
uint8_t AnemPulse = 0;			// collects pulses from anemometer used for calculation of wind speed
volatile uint8_t WindSpeedCalcFlag = 0;		// Flag for calculation of wind speed based on collected pulses from anemometer
char WindSpeed[7];			// holds wind speed value calculated from anenemometer pulses
uint8_t TempStor = 0;

// Analog Temperature Sensor Variables
char STemp[14];				// Stator Temperature (Analog) storage variable
uint8_t ADCSTempFlag = 0;	// Flag in order to start temperature converting function

// Digital Temperature Sensor Variables
int16_t DigTemperature = 0;
volatile uint8_t DigATempFlag = 0;

// One-Wire Variables
unsigned char temp_po_str[8];
float temp_po;

// Flagging function variables
uint8_t FunctionFlag = 0;

//Function Prototypes 
char dec2bcd(char num); 
char bcd2dec(char num); 
void WriteDS1307(void); 
void ReadDS1307(void); 
void WriteLCD(void);
void AnemDebounce(void);
void WindSpeedCalc(void);
void ADCSTempConv(void);		// Function for converting Analog Temperature sensor signal to temperature value (Added 12/11/2011)
uint16_t ReadADC(uint8_t);		// Function used to read ADC registers (Added 12/11/2011)
void TriggerFunctions(void);	// Sets flags within function instead of loading up the ISR (Added 12/11/2011)
void DigATempConv(void);		// Converts digital signal to temperature value


/**************************************************************************************/
/**************************************************************************************/
/*********************           main function          *******************************/
/**************************************************************************************/
/**************************************************************************************/

int main(void) 
{ 
	
	// Init LCD 
   lcd_init(LCD_DISP_ON); 
   i2c_init();
    
   // Write values to DS1307 Registers 
   WriteDS1307();

   // Set Data Direction Register
   DDRB |= 0x02;	// PB1 set to output, all others don't care
   DDRD |= 0x80;	// Set bit 7 of PORTD (PD7) to output, all others left alone
   
   DDRC |= 0x00;	// Set for inputs
   
   PORTB |= 0x3C;	// Enable pullups on bit 2, 3, 4, and 5 of PINB (PB2, PB3, PB4, PB5), other bits don't care
   PORTC |= 0x0E;	// Enable pullups on bit 1 thru 3, all others don't care
   PORTD |= 0x80;	// Enable pullup on bit 7 of PIND (PB7), all others don't care
	
   // Initialize ATMega168 Timer/Counter0 Peripheral 
   TCCR0A = (1 << WGM01);  // Clear Timer on Compare (CTC) mode
   TCCR0B = (1 << CS02) | (1 << CS00);      // prescaler set for fclk/1024
   TCNT0 = 0x00;            // Start Counter at 0
   OCR0A = 0xFF;			// Set CTC compare value to 256 decimal.
   TIMSK0 = (1 << OCIE0A);      // Enable Compare Match A interrupt 
   
   // Initialize ATMega 168 Pin Change Interrupt on PIN 6
   PCICR = (1 << PCIE2);		// Enable Pin Change Interrupt 2
   PCMSK2 = (1 << PCINT23);	// Enable Pin Change Interrupt on PCINT20 (Pin 6, PD4)
   
   // Initialize ATMega 168 ADC Peripheral
   ADMUX =  (1 << REFS0) | (0 << MUX3) | (0 << MUX2) | (0 << MUX1) | (0 << MUX0);	// Enable AVcc Voltage Reference (Approx 5V), Enable ADC0 Input
   ADCSRA = (1 << ADEN) | (1 << ADPS2) | (1 << ADPS1);  							// Enable ADC Operation (ADEN), Division factor set to 64 (gives 125kHz sampling rate).
   ADCSRB = (0 << ADTS2) | (1 << ADTS1) | (1 << ADTS0);								// ADC operation triggered from Timer/Counter0 Compare Match A
   
   cli();	// Disable Interrupts
   
   // Initialize DS182x temperature sensor
	ds1820_init(DS1820_pin_po);              //Initialize DS1820 Buffer oben (top buffer)
   
   sei();	// Enable Interrupts  
    
   for(;;)  // run forever
   { 
	
		// Read DS1307 Registers
		ReadDS1307();
		
		// Write Clock to LCD Display
		WriteLCD();
		
		// Check Anemometer Pulses
		AnemDebounce();
		
		// Check WindSpeedCalc for flagging
		WindSpeedCalc();
		
		ADCSTempConv();		// Check ADCSTempConv() for flagging
		
		DigATempConv();		// Check for flagging
		
		TriggerFunctions();	// Check TriggerFunctions for flagging
		
		//PORTB |= (1 << 1);	// Turn LED on for diagnostics	
  
		
   } 
    
} 

/**************************************************************************************/
/**************************************************************************************/
/*********************           dec2bcd function          ****************************/
/***********     Convert decimal value to binary coded decimal (bcd)       ************/
/**************************************************************************************/
/**************************************************************************************/


// Convert Decimal to Binary Coded Decimal (BCD) 
char dec2bcd(char num) 
{ 
    return ((num/10 * 16) + (num % 10)); 
} 

/**************************************************************************************/
/**************************************************************************************/
/*********************           dec2bcd function          ****************************/
/***********     Convert decimal value to binary coded decimal (bcd)       ************/
/**************************************************************************************/
/**************************************************************************************/


// Convert Binary Coded Decimal (BCD) to Decimal 
char bcd2dec(char num) 
{ 
    return ((num/16 * 10) + (num % 16)); 
} 


/******************* ISR's ***********************************/
/*************************************************************/

ISR(TIMER0_COMPA_vect)       // Continually Interrupt program to update time to LCD display 
{ 

	FunctionFlag = 1;		// Set flag for TriggerFunctions() function
	
} 

ISR(PCINT2_vect)			// Interrupt program to detect pulse on falling edge from anemometer
{

	AnemDebounceFlag = 1;	// Set flag for AnemDebounce() function
	
}


/*------------------ End ISR's ----------------------------*/
/*-----------------------------------------------------------*/

/*------------------------------------------------------------------------------------*/	// Function Added 12/11/2011
/*------------------------------------------------------------------------------------*/
/*--------------------   TriggerFunctions Function         ---------------------------*/
/*------------   Set Flags for polled function is main()   ---------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void TriggerFunctions(void)
{
	if (FunctionFlag == 1)
	{
		// Enable ReadDS1307 Function 
		ReadDS1307Flag = 1;
		
		WindSpeedCalcFlag++;		// Increment flagging variable
		
		ADCSTempFlag = 1;			// Flag ADCSTempConv() Function to start
		
		//ADCCurrentFlag = 1;		// Flag ADCCurrentConv() Function to start
		
		//ADCVoltageFlag = 1;		// Flag ADCVoltageConv() Function to start
		
		//ADCFreqFlag = 1;			// Flag ADCFreqConv() Function to start
		
		DigATempFlag = 1;			// Flag DIGATempConv() Function to start
		
		// Enable WriteLCD Function
		WriteLCDFlag = 1;
		
		//SDWriteFlag = 1;			// Flag SDWrite() Function to start
		
		FunctionFlag = 0;			// Reset FunctionFlag 
	}
	
}

/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*---------------------          WriteLCD function          --------------------------*/
/*---------------------     Write values to LCD screen      --------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/


void WriteLCD(void)
{
	if (WriteLCDFlag == 1)
	{
		// Clear the screen
		lcd_clrscr();
		
		// Display the Day of Week
		lcd_puts(weekday[DayofWeek]);
		lcd_puts(" ");
		
		//Display the Month
		lcd_puts(month[Month]);
		lcd_puts(" ");
		
		// Display the Day of Month
		lcd_puts(ds1307_monthday);
		lcd_puts(" ");
		
		// Display the Year
		lcd_puts("20");
		lcd_puts(ds1307_year);
		lcd_puts("\n");
		
		// Display the clock 
		//lcd_clrscr(); 
		lcd_puts(ds1307_hour); 
		lcd_puts(":");

		if (Minutes < 10)
		{
			lcd_puts("0"); 
			lcd_puts(ds1307_min);
		}
		
		else
		{
			lcd_puts(ds1307_min);
		}
		
		lcd_puts(":");
		
		if (Seconds < 10)
		{
			lcd_puts("0");
			lcd_puts(ds1307_sec); 
		}
		
		else
		{
			lcd_puts(ds1307_sec);
		}
		
		lcd_puts(" ");
		
		if (Pm == 1)
		{
			lcd_puts("Pm");
		}
		
		else if (Pm == 0)
		{
			lcd_puts("Am");
		}
		
		lcd_puts("\n");
		lcd_puts("WS ");
		lcd_puts(WindSpeed);
		
		lcd_puts(" Ta=");
		lcd_puts(STemp);
		
		lcd_puts(" Ts=");
		lcd_puts(temp_po_str);		// --> was temp_po_str
		
		// Reset Flag
		WriteLCDFlag = 0;
		
	}
}



/**************************************************************************************/
/**************************************************************************************/
/*********************        WriteDS1307 function       ******************************/
/********* Write current time, date, year, month to DS1307 Registers      *************/
/**************************************************************************************/
/**************************************************************************************/

void WriteDS1307(void) 
{ 

    // Start the I2C Write Transmission 
   i2c_start(DS1307+I2C_WRITE); 

    // Start from Address 0x00 
    i2c_write(0x00); 
	
	//i2c_write(0x58);   // Set second value to decimal 58 
	//i2c_write(0x59);   // Set minute value to decimal 59 
	//i2c_write(0x72);   // Set hour register to decimal 12 (12-hour format), PM
	
	i2c_write(dec2bcd(ct_sec));   // Set second value
	i2c_write(dec2bcd(ct_min));   // Set minute value 
	
	if (ct_ampm == 1)
	{
		i2c_write(dec2bcd(ct_hour) | 0x60);   // Set hour register
	}
	
	else if (ct_ampm == 0)
	{
		i2c_write(dec2bcd(ct_hour) | 0x40);   // Set hour register
	}
	
	i2c_write(dec2bcd(ct_dayweek));	// Set Day of the week
	i2c_write(dec2bcd(ct_daymonth));	// Set Day of month
	i2c_write(dec2bcd(ct_month));	// Set Month
	i2c_write(dec2bcd(ct_year));	// Set year
    
    // Stop I2C Write 
    i2c_stop(); 
    
} 

/**************************************************************************************/
/**************************************************************************************/
/*********************        ReadDS1307 function       *******************************/
/*********   Read current time, date, year, month from DS1307 Registers  **************/
/**************************************************************************************/
/**************************************************************************************/


void ReadDS1307(void) 
{ 
   
   if (ReadDS1307Flag == 1)
   {
	   uint8_t TempData, TempData1, TempData2; 
		
		i2c_start(DS1307+I2C_WRITE);
		i2c_write(0x00);
	   // Start I2C Read 
		i2c_start(DS1307+I2C_READ); 

		// Read the Second Register, Send Master Acknowledge 
		TempData = i2c_readAck(); 
		TempData = bcd2dec(TempData);
		Seconds = TempData;

		// Convert number to string
				 
	   utoa(TempData,ds1307_sec,10); 

		// Read the Minute Register, Send Master Acknowledge 
		TempData = i2c_readAck(); 
		TempData = bcd2dec(TempData);
		Minutes = TempData;

	   // Convert number to string
	   utoa(TempData,ds1307_min,10); 

		// Read the Hour Register, Send Ack 
		TempData2 = i2c_readAck(); 
		TempData = bcd2dec(TempData2 & 0x1F); 	// AND TempData with 0x1F to get in human-readable format
		TempData1 = (TempData2 & 0x20) >> 5;	// Shift PM / AM bit to bit position 0, making it decimal 0 or 1
		Hour = TempData;
		Pm = TempData1;
		
		// Convert number to string
	   utoa(TempData,ds1307_hour,10);
	   utoa(TempData1,ds1307_AmPm,10);

		// Read the Day of Week Register, Send Ack
		TempData = i2c_readAck();
		TempData = bcd2dec(TempData);
		DayofWeek = TempData;
		
		// Convert number to string
		utoa(TempData,ds1307_weekday,10);
		
		// Read the Day of Month Register, Send Ack
		TempData = i2c_readAck();
		TempData = bcd2dec(TempData);
		
		// Convert number to string
		utoa(TempData,ds1307_monthday,10);
		
		// Read the Month Register, Send Ack
		TempData = i2c_readAck();
		TempData = bcd2dec(TempData);
		Month = TempData;
		
		// Convert number to string
		utoa(TempData,ds1307_month,10);
		
		// Read the Year Register, Send No Ack
		TempData = i2c_readNak();
		TempData = bcd2dec(TempData);
		
		// Convert number to string
		utoa(TempData,ds1307_year,10);
		
	   // Stop I2C Read 
	   i2c_stop(); 
   }
	ReadDS1307Flag = 0;
} 

/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*--------------------        AnemDebounce function        ---------------------------*/
/*--------   When flagged by ISR, debounce input pulses to prevent       -------------*/
/*--------   erronous readings.  Accumlate accepted readings into        -------------*/
/*--------   variable.                                                   -------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void AnemDebounce(void)
{
	
	if (AnemDebounceFlag == 1)
	{
		AnemPulse++;			// Increment Anemometer Pulse Counter
		AnemDebounceFlag = 0;	// Reset Flag
	}
}

/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*---------------------       WindSpeedCalc function       ---------------------------*/
/*--------   Read number of pulses into variable (and SD memory) after   -------------*/
/*--------   a one second interval to determine RPM of anemometer for    -------------*/
/*--------   determination of wind speed                                 -------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void WindSpeedCalc(void)
{
	
	if (WindSpeedCalcFlag >= 40)
	{
	
		// Calculate Wind Speed from AnemPulse Variable
		TempStor = (AnemPulse) * 2.50;		// 2.5 MPH per Hz (1 Hz = 1 Pulse / second)

		//Convert integer to string
		utoa(TempStor,WindSpeed,10);

		AnemPulse = 0;

		// Reset Flag
		WindSpeedCalcFlag = 0;
	
	}
	
}

/*------------------------------------------------------------------------------------*/	// Function Added 12/11/2011
/*------------------------------------------------------------------------------------*/
/*--------------------          ReadADC function           ---------------------------*/
/*----------     Read ADC value on specified channel (Channel variable),   -----------*/
/*----------     start conversion, and return ADC value to calling         -----------*/
/*----------     function                                                  -----------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

uint16_t ReadADC(uint8_t Channel)
{
	// Initialize ATMega 168 ADC Peripheral
	ADMUX |= Channel;	// Enable ADC Input Specified by calling function
		
	// Initialize ADC Conversion Start
	ADCSRA |= (1 << ADSC);
	
	// Wait for conversion flag to clear
	while (! (ADCSRA & (1 << ADIF) ))
	{
		;
	}
	
	// Clear ADIF flag by writing logical one to ADIF bit of ADCSRA register
	ADCSRA |= (1 << ADIF);
	
	// Return value read from ADC pin to calling function
	return (ADCW);	// ADCW is special value used by GCC-AVR which holds value of ADCH and ADCL from ADC registers
	
}
/*------------------------------------------------------------------------------------*/	// Function Added 12/11/2011
/*------------------------------------------------------------------------------------*/
/*--------------------        ADCSTempConv function       ----------------------------*/
/*--------   Read voltage value from Analog Temp Sensor and store value  -------------*/
/*--------   to variable.  The stored value will be sent to SD memory.   -------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/
/*------------------------------------------------------------------------------------*/

void ADCSTempConv(void)		
{
	// Declare temporary storage for Temperature Calculation
	int32_t ADCVal1;
	int32_t VInt1, TempCalc;
	
	if (ADCSTempFlag == 1)
	{
		// Disable Interrupts while data is being processed
		cli();	
		
		// Call ReadADC function and pass ADC0 channel value
		ADCVal1 = ReadADC(ADC0);

		// Convert ADC value to equivalent voltage (value in mV)
		VInt1 = ADCVal1 * VREF;
		VInt1 /= BIT_RES;
		
		// Calculate Temperature using Transfer Function
		TempCalc = VInt1 - 500;
		TempCalc /= 10;
		
		// Convert Temperature value to string for LCD display
		itoa(TempCalc,STemp,10);

		// Enable Interrupts
		sei();
		
		// Reset Flag
		ADCSTempFlag = 0;
		
	}

}

/**************************************************************************************/	// Function Added 12/16/2011
/**************************************************************************************/
/*********************        DIGATempConv function       *****************************/
/*********   Read binary value from Digital Temp Sensor and store value  **************/
/*********   to variable.  Convert Temperature from ºC to ºF.            **************/
/*********                                                               **************/
/**************************************************************************************/
/**************************************************************************************/

void DigATempConv(void)
{
	if (DigATempFlag == 1)
	{
		
		// Read Temperature from DS182x sensor
		temp_po = ds1820_read_temp(DS1820_pin_po);	//Get temperature from DS1820 puffer oben
		
		// Convert Temperature Vals to strings
		itoa(temp_po,temp_po_str,10);
		
		// Reset Flag
		DigATempFlag = 0;
	
	}

}


/*-------------------------REV HISTORY---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
//	-	12/11/2011		>> Removed code for ancilliary peripherals.  Added code back in for wind speed sensor.  Wind speed sensor now registers correctly, and displays correct value on LCD display.        
//						>> Next steps:  1) Interface analog temperature sensor and display temp. on LCD.
//						  				2) Interface digital temperature sensor and display temp. on LCD.
//										3) Interface frequency to voltage converter (which derives the wind turbine rotor RPM) and display correct RPM on LCD.
//										4) Interface voltage sensing from voltage divider circuit (which will be remotely mounted on the to-be-constructed charge controller). 
//										   and display charging voltage on LCD.  This output value will also be used to calculate power produced by wind turbine.
//										5) Interface current sensing from current sensor (which will be remotely mounted on the to-be-constructed charge controller)
//										   and display charging current on LCD.  This output value will also be used to calculate power produced by wind turbine.	
//	  
//	-	12/11/2011		>> Completed including code for step 1).  Need to test hardware and verify code function.	
//	-	12/15/2011		>> Hardware and code verified for step 1).
//	-	12/16/2011		>> Including code for step 2).
//	-	12/17/2011		>> commented-out ds2890 #defines and declarations.  This device is not being used.
//	-	12/18/2011		>> Removed AVR318 #defines / functions.  Using Sicklinger's library instead.

Attachment(s): 

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

How does you code help to demonstrate the problem? Since you've got a digital 'scope, you can manually decode the data coming out of the sensor. Is it correct? Have you dumped the raw data being read from the device? Does the CRC compute? The point here is: are you getting good data from the sensor or are you processing it incorrectly? Also remember that having other interrupts enabled will probably upset the 1wire code. Work logically through the problem and you'll find the answer.

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

Thanks for the reply Kartman:

I believe the data coming from the sensor is accurate when I compare the activity to the datasheet timing diagrams. I don't have much experience decoding the data with the scope, but I am assuming that the pulse train represents the hex values coming from the sensor. I see what you mean now though. I will try decoding the sensor values and figure out what is being read into the scratchpad and go from there. Thanks again.

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

You've got the tools, it's a good time to put them to good use! 1wire is pretty simple, narrow pulses and fat pulses. Get your pencil out and write down the bit stream. After a bit of practice you'll be an expert on 1wire comms. I would suggest you write some code that just does the basics of reading the 1wire temperature sensor - no interrupts (unless the code for the 1wire does use them). Get that working then add in the extras. You should then find out what is causing the 1wire stuff to fail by a process of elimination. Then kick yourself when you do figure out the problem.

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

+100
1 wire is very simple bus. However I had spent little time to understand it, to write working program.
I also recommend you do not use any interrupts, timers and so on.
At first give a presence pulse.
Then look at the datasheet's end. There is one useful diagram. It shows you how to work well.
However I use DS18B20. I don't know if is there such diagram.

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

If you can afford to devote your AVR's on-board UART to acting as a 1-wire bus controller, the trick where you just transmit various carefully-selected byte patterns at clever baud rates to generate and measure the 1-wire pulsewidths works very well (described in a Maxim app note). I wanted to include a sketch showing how to combine the Tx and Rx signals together to serve as the 1-wire control, but my graphic-arts ineptitude defeated MS Paint, OpenOffice Draw, and two free-trial schematic sketching/drawing tools. So, in prose: Connect emitter of jellybean NPN to the AVR UART's Tx line, pull the base of the NPN up to the logic supply via 27Kohms or so, and the collector up to the logic supply via whatever's good for your 1-wire data line (1Kohm, perhaps?). Connect the NPN collector to the UART's Rx line, and use it as your 1-wire bus signal.

As I recall, the magic baudrates were 9600 (for generating reset pulses) and 115200 baud (for sending/receiving data bits). At the high baudrate, '1' and '0' bits result from transmitting 0xFF and 0x00 bytes, respectively. "Receiving" an 0xFF UART byte represents receiving a '1' onewire bit, anything else is a '0' bit. Or something like that.

Also, I noticed that your ISRs follow the advice of many here on the forum, and do nothing besides set flags in RAM that your main() code looks at. Commendable, but once you've achieved that extreme of simplicity, you don't need to put the CPU through the bother of running the interrupt code at all; the RAM flags you're setting only duplicate the hardware interrupt flags. If you just didn't enable the various interrupt sources' interrupts, your main() could just as well test and reset their hardware interrupt flag as it tests and resets your ISR-deposited RAM copies of them.

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

Kartman,

Appreciate the feedback. It's easy to get carried away sometimes and not break the problem down into manageable chunks as you suggest. I have decoded the bus and it appears the sensor is sending the correct series of bits for the temperature of ~25ºC. Who needs a logic analyzer when you have a DSO!?

Levenkay,

That is a good point with the ISR. I could use an IF statement with a counter that would initiate after a number of ticks corresponding to the required time. I would like to keep the UART available for possible interfacing to a PC later down the road, so I would like to try implementing this device via software bit-banging. Thanks for your input!

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

I need some clarification...

Is this waveform displaying 0xCC or 0x33? It looks like 0x33 to me (based on looking at the 1-wire timing diagrams), but I saw an output from a logic analyzer on another thread that was saying this waveform was 0xCC.....am I missing something?

Attachment(s): 

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

According to the datasheet, fat low pulses are logic '0' and the data lsb first. Reading the bits in sequence: 00110011, reverse for lsb first: 11001100. Therefore the sequence shows 0xcc.

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

Ah, the bit sequence bit me (pun intended)! I remember reading it in the datasheet, but apparently slipped my mind in frustration. It is the "big endian" / "little endian" scenario. I only thought that applied to Intel and Motorola architectures such as processors, not lower level hardware such as this temperature sensor. You learn something everyday! Thanks again Kartman.

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

Big/little endian refers to byte order. Bit order varies: uart is lsb first, spi is msb first, can't recall what i2c is so it comes down to reading the spec. If you can read the 1wire serial number then you're nearly there. Follow the sequence on the datasheet and you should have success.

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

Just an update:

I was receiving the correct signals to / from the DS1822 temp sensor (correct reset pulse and presence pulse timing, etc), except the bytes read from the scratchpad were all reading 0xFF. I was suspicious that it may be hardware related and ordered a few new of these sensors, and sure enough, I must have statically shocked the sensor at some point. Tried the new sensor and everything is working great now. I did have to modify a few of the timing parameters to account for code overhead, but only changing from the standard timing values listed DS1822 datasheet by no more than 10𝜇s. At first I thought what a waste of time, but it turns out it was a great way to learn about the 1-wire bus intricacies (As long as I don't have to go through this again!). Thanks everyone (especially Kartman) for your help on this!