DH11/22 SoftWare advice

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

hello forum , this time i need an advice regarding the dh11 humidity / temperature sensor using 1 wire protocol .

using atmega128 i have a SW that is collecting data through some sensors , sending them over UART , also some actuators (servos-dc-light) , the atmega will be sending and receiving packets through interrupt driven UART from/to RPi acting as master . 

 

after some reading i've found 2 libraries for the dh11/22 one using delay , another using external interrupt .each one has advantage and disadvantage in my opinion .

 

- 1st , the delay library will consume maximum 5.5ms to complete a single conversion but i must make sure that there are no interrupts will get into way because it will miss up the readings , here the problem arise because , what if the UART rx triggers an interrupt ,this would miss up my readings if i left the global interrupt flag set , if use clear the global interrupt and a packet arrives , it will be either corrupted or lost . 

 

-2nd , external interrupt library is a wise more professional option , but again the external interrupt is higher in the priority , the RX comes after the Exteral interrupts ( 7 external . int. )which will leave me trapped in the same situation .

 

so if maybe there are a way to do this efficiently giving UART  max priority , also a way to ensure that i get the data correctly from sensor . 

 

 

additional notes : i use 4 sensors on the ADC pins using interrupts , a timer start a conversion every 10 seconds ( the ISR continues to start a conversion till it reaches the last channel then it stops till the timer start a new conversion ) , the timer i use comes after the RX interrupt which means that i'm able to make nested interrupts .

 

i'm open for any suggestions , if any thing is not clear please let me know :) 

 

 

This topic has a solution.
Last Edited: Wed. Feb 1, 2017 - 12:57 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Why is there a problem with using both usart and external interrupts? The serial interrupt should not take too long to upset the timing from the dht11. If you're really worried, use the capture feature of the timer and that will remove a interrupt timing problem.

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

If the timing requirements of one wire are a concern, why not use a different T/H sensor with I2C or SPI interface that is more tolerant of timing?

Take a look at the SHT31, adafruit has a break out board to test with. 

 

Jim

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Reviewing 1-wire protocol, it uses 60uSec timing slots, so unless your serial comm is very high speed you should not have any problems disabling interrupt servicing for the few uSec's it takes to send a 1-wire command/data if you keep your ISR short, nesting of interrupts can lead to problems, I would re-think that.

Are you bit-banging or using usart for 1-wire comm?

 

Jim

 

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

 

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

Agreed.

 

I have successfully done two 1-Wire ports with multiple serial ports, TCP/IP, mulriplexed 7-segments, etc on an 8051 - so don't see why an AVR shouldn't cope ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I agree with the above, keep the USART ISR short, (read the data and put it in a buffer for the Main to read), and you shouldn't have a problem.

 

A "1" pulse is < 15 uSec, 60 uSec of a "0", so lots of "guard time".

 

Recall, in case you ever change uC's, that the Xmega series has a priority interrupt controller.

 

JC

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

DocJC wrote:
A "1" pulse is < 15 uSec, 60 uSec of a "0", so lots of "guard time".

and note that it's only the timing within the bit that matters - the timing between bits is unimportant.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do you have control over the rPi (assuming Raspberry PI here) program?  If so then you can have the rPi only send data to the AVR when the AVR is not receiving data from the DHT11.   The AVR sends a pulse to the DHT to start the next conversion.  Before this pulse, it can send a flag to the rPi to not send any UART data until the flag is received again.  Since the data transfer from the DHT is relatively short, the UART data from the rPi will not be buffered for very long.

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

The dht11 uses one wire to report its data but this is not to be confused with Dallas 1wire. The dht11 gets a low going trigger from the host then outputs a bitstream. How many microseconds does the serial comms steal?
I wrote some code for a cortex m0 that did high speed serial and dht11 comms concurrently.

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

is 115200 considered high speed ? i'm communicating with RPi , i managed to do 250000 , so what you're basically saying if i use slow communication ( making the ISR very short ) it wouldn't affect my readings .

 

can you further explain why nesting interrupts would lead to problems , the Timer ISR is really really short 

sei()
	Time_counter ++ ;
	if (Time_counter == 1000) // every 10 seconds  
	{
		ADCSRA |= 1<< ADSC ; // start conversion
		Time_counter = 0 ;
	}

then after 10ms an adc conversion complete ISR is triggered and here is the ADC ISR

switch(ADC_channel_select)
	{
		//---------------------------------------------------------------------- Serving Channel A0 ----------------------------
		case ADC_CHANNEL_0 : // Temprature ADC channel
		{
			ADC_Instant_R[TEMPERATURE_S].u16ADC_Value  = ADC ;
			ADC_Instant_R[TEMPERATURE_S].u8High_val    = ((TEMPERATURE_S<<4)& 0b11110000 ) ;	// shift right 5 times to put the number of the sensor used high_val[7,6,5]
			ADC_Instant_R[TEMPERATURE_S].u8High_val   |= (ADC_Instant_R[TEMPERATURE_S].u16ADC_Value >> 8 ) ;		// saving the last 8,9 bit to high_val[0] high_val[1] 
			ADC_Instant_R[TEMPERATURE_S].u8Low_Val     = (ADC_Instant_R[TEMPERATURE_S].u16ADC_Value & 0xff ) ;		// saving the value of ADC conversion ADCL Reg  to Low_val .
			
		
			
			ADC_channel_select = ADC_CHANNEL_1  ;  // Choosing the next channel
			ADMUX &=~ CHANNELS_MASK ;              //clearing Channel Selector 
			ADMUX |=  ADC_channel_select ;		   // setting up the Channel Selector
			ADCSRA |= 1<< ADSC ; // start conversion
			
		}
		break;

i only copied one case , the rest is similar , except the last channel there is no start conversion .

 

i'm only giving high priority to the USART . i really don't want to miss that start byte :D , 

i built my USART ISR based on this https://www.avrfreaks.net/forum/s... , notice Kartman post #4 , so if i miss the start byte i will remain in state 0 .

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

actually i've just mentioned you , what a chance :D , i built my ISR using your reply in this thread https://www.avrfreaks.net/forum/s... , i really have no idea how to measure my ISR length !! i'm very new to debugging , i used the debugger but it kept me looping in the main , of course this is expected as there are no comm happening in sim , so any idea how can i measure it ? ????

 

i used the debugger to measure the ADC & the Timer ISR and they were really quick .

 

edited .

Last Edited: Fri. Jan 20, 2017 - 12:37 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Simonetta wrote:
Before this pulse, it can send a flag to the rPi to not send any UART data until the flag is received again.  Since the data transfer from the DHT is relatively short, the UART data from the rPi will not be buffered for very long.

 

actually it's not a bad idea (Y) , 

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

Do you really need interrupts for the ADC?
I have three interrupt sources in my app- timer tick at 10ms, serial and input capture. Your serial int should only take a few us - get the char and put it into a buffer., or grab a char from a buffer and send it. Consider how fast you REALLY need to send the data - temperature and humidty aren't going to change too quickly so going for a super fast baud rate isn't going to help. Another consideration is tolerating the error - reafing the dht a few times a second means you can tolerate a number of reads failing.

I used a TDM technique where my system would send a character and each device would delay their response based on their unit number.

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

Kartman wrote:
Do you really need interrupts for the ADC?

actually , i really don't see why not to use it , it makes it easy ( start conversion then update my  ADC struct , then in the main " app layer " the data are waiting for me fresh out of the ADC ) , as u said , 

Kartman wrote:
temperature and humidty aren't going to change too quickly so going for a super fast baud rate isn't going to help
i would bring my baudrate to 38400 or less .

 

 

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

Adding interrupts adds non-determinism to your system - you never know what really happens in all cases. By all means use interrupts, but use them wisely.
http://www.ganssle.com/articles/acodeisr.htm

Last Edited: Fri. Jan 20, 2017 - 07:21 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Just use handshake on the UART

Or use a slow UART speed, so 5.5 ms can't be more than 1 char.(perhaps 2 depending of HW in your AVR UART), so try 1200 baud.

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

Messiry wrote:
is 115200 considered high speed

 

I guess speed is relative!  When I started a teletype ran at 45.45 baud, I can read text scrolling easily at 4800 baud, you may be faster than that!   q:-)

When you said your nested ISR, that says to me you re-enable interrupts within your ISR so new interrupts will be serviced within the current ISR....

This can lead to memory starvation if your not careful, as the stack grows,  but I don't see that in the examples you have shown...

you may be thinking since you have more then one ISR, they are stacked, but they may not be if only one can run at a time.

 

One way to measure your ISR time, is wiggle a spare port pin at the beginning of the ISR and again at the end, then use a scope to measure the time.

Another is use the simulater, set a break point on the first & last instruction, when it breaks, clear the cycle counter (right click the counter value, select clear) and continue.

At the next break point you can see the time and # of cycles.....

 

 

Jim

 

 

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"