Go Down

Topic: SOLVED: Trying to read OneWire ds18b20 without disabling interrupts (Read 681 times) previous topic - next topic

RobvdVeer

Nov 26, 2013, 03:55 pm Last Edit: Nov 29, 2013, 08:02 pm by RobvdVeer Reason: 1
As the subject says. I'm running a 328p without crystal @8mhz. I'm manually multiplexing a 4 digit 7-segment display using timer2 interrupt. Also, i,m trying to read the ds18b20 with the OneWire library and Dallas library for conversion. Problem is that the I/O with the temp sensor is disrupting the display routine. I tried removing the 'nointerrupts()' and pairing 'interrupts()' in the OneWire library but then it doesn't work anymore (display is good, but i/o fails).

Any suggestions?
Rob
Follow my progress on http://simplicate.weebly.com

gardner

Running two bit bashing algorithms simultaneously is a challenge, and the one-wire bus requires some fairly sensitive timing.  It's likely that you will not be able to resolve the conflict.  Best bet is to purposely blank the display during the one-wire bus activity.

RobvdVeer

Thanks gardner. I know it's a tricky thing. The i/o with the ds18b20 takes about 50 msec in total and that's too long not to notice. I'm sure theres a concurrency bug in there somewhere, my interrupt is only 5 lines of code, there must be a way.

A logic analyser (saleae knockoff) is on its way to find the real problem without too much hassle.
Rob
Follow my progress on http://simplicate.weebly.com

gardner

If you can use your logic analyzer to measure the actual timing of your display updates, then perhaps you could modify the timing in the one-wire bus protocol logic to use display updates as part of the timing.  For example in OneQire:read_bit you could change

Code: [Select]
uint8_t OneWire::read_bit(void)
{
IO_REG_TYPE mask=bitmask;
volatile IO_REG_TYPE *reg IO_REG_ASM = baseReg;
uint8_t r;

noInterrupts();
DIRECT_MODE_OUTPUT(reg, mask);
DIRECT_WRITE_LOW(reg, mask);
delayMicroseconds(3);
DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
delayMicroseconds(10);
r = DIRECT_READ(reg, mask);
interrupts();
delayMicroseconds(53);
return r;
}


to

Code: [Select]

DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise
delayMicroseconds(10);
r = DIRECT_READ(reg, mask);
interrupts();

// delayMicroseconds(53);
        displayUpdate();             // measured 22 microsecs with logic analyzer
        delayMicroseconds(53 - 22);  // shortened to allow display update

return r;


Just as a for-instance.

RobvdVeer

Thanks to the analyser, i found out my interrupt was not firing when a 1-wire data was being written. As it turned out, the service vector enabled/disabled the interrupts as well, with the effect that the disable/enable pairing went out of sync.

I removed the enabling/disabling from my timer interrupt. This fixed the problem.
Rob
Follow my progress on http://simplicate.weebly.com

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy