Go Down

Topic: SOLVED: Trying to read OneWire ds18b20 without disabling interrupts (Read 556 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