CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Non-blocking DS18B20 code...

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
ELCouz



Joined: 18 Jul 2007
Posts: 427
Location: Montreal,Quebec

View user's profile Send private message

Non-blocking DS18B20 code...
PostPosted: Fri Mar 25, 2016 7:00 pm     Reply with quote

I usually use TI TMP275 i2c temp sensor because it's faster and i2c bus is easy to control.

But I'm in a situation that the SOIC-8 package won't cut it for precise measurement (shape of the package fitment) vs the TO-92 offered with the DS18B20.

I skipped the DS18B20 because of the code when a sensor fail/1-wire line failure, it freeze the whole PIC on that line:


Code:

 while (busy == 0)
  busy = onewire_read();


from the hansolo code post ---> https://www.ccsinfo.com/forum/viewtopic.php?t=28425


Any idea how to timeout the code properly?

Thanks!
_________________
Regards,
Laurent

-----------
Here's my first visual theme for the CCS C Compiler. Enjoy!
temtronic



Joined: 01 Jul 2010
Posts: 9244
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Mar 25, 2016 8:04 pm     Reply with quote

instead of ...
while (busy == 0)

ADD a 'timeout' conditional to the while()

Have a look at the CCS manual regarding 'waiting for serial ' input yet needing to 'break' if nothing comes in after xx milliseconds.
Can't give you a specific link on wrong computer but I know it's in the manual somewhere!

Jay
jeremiah



Joined: 20 Jul 2010
Posts: 1355

View user's profile Send private message

PostPosted: Sat Mar 26, 2016 8:14 am     Reply with quote

another option might be to pull out the part of the code that checks the busy and put it into another function similar to how uart provides the kbhit method. Then in your main code, you could check and see if it is busy by calling the new function before calling the read routine and if it is busy, then go do something else in your code. You could still implement a timeout that way, but it would be in the calling code rather than the driver (which I prefer when I have drivers honestly).

then your calling code might look like:

Code:

while(timevalue < timeout){
   if (!ds1820_busy()){
      value = ds1820_read();
      break;
   }else{
      //do something else here
   }
}


or if you don't need to do anything else, then just simply

Code:

while(timevalue < timeout){
   if (!ds1820_busy()){
      value = ds1820_read();
      break;
   }
}
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Sat Mar 26, 2016 9:17 am     Reply with quote

Polling an uncommitted system timer could be your friend.
That way you decide when you've waited too long.
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Sat Mar 26, 2016 9:30 am     Reply with quote

I can't post the code I came up with, as it rightfully belongs to my employer, but I can give you some guidelines.

- Dedicate a timer to the task of interfacing with the DS18B20. That timer is used for nothing else.
- If you're using a processor with programmable interrupt priority, you may have to set the priority of this timer to the highest value (higher than any other interrupt you have) if you want completely accurate temperature measurements.
- My projects typically employ a dedicated timer/interrupt to give me a 10ms "system tick." I have a separate counter/flag mechanism as part of that system tick to trigger a temperature reading every 10 seconds.
- To trigger a reading, you first have to take the DS18B20's DQ line low for (I think) > 400 us. When my system tick determines that it's time to trigger a reading, the DQ line is set low and the dedicated timer is enabled and set to expire/fire ~ 500 us later.
- When the dedicated timer expires, it toggles the state of the DQ line, looks up (from a LUT) the next time the line should change state, and sets itself to expire/fire at that time. Writes to the DS18B20 proceed in this manner.
- Reads from the DS28B20 proceed similarly, except there is no advantage to using the timer to do the very timing specific reads of the DQ line. From memory, the general procedure is:
- set DQ line low, wait ~2us, then release the line. ~9us later, read the state of the DQ line (high = 1, low = 0). The process then waits several 10s of us before repeating the process to read the next bit. The underlined section is performed in my dedicated timer's interrupt using delay_us() statements. The reset/wait for the appropriate time to read the next bit is performed by using the dedicated timer.
- When you're done reading the DS18B20, the timer you've dedicated to that task is disabled.

This is a relatively straightforward way of reading a one wire temperature sensor whilst ensuring that your processor can still service other interrupts. This general process is in use on 4 different products. The only one that sometimes reads wonky temperatures is a communications bridge that has to handle very heavy high bit rate traffic. I was not able to set the priority of my temperature reading interrupt higher than everything else because then I'd have dropped packets, which I can't tolerate. An occasional weird temperature is okay though.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group