Puzzling DS18B20 problem

Jeremy Harris

Senior Member
I've been using DS18B20 sensors in lots of projects for a couple of years now, with no problems at all. Suddenly I find myself puzzling over an odd problem that I can't quite understand. I'm currently working on a heating/cooling control system and wish to modify it slightly to use an extra port that I didn't allow for when I made the PCB. This uses a 20M2 Picaxe, driving an LCD display, some thermal actuators (via solid state relays) and controls an air source heat pump (via a couple of normal relays). There's no problem at all with the circuit driving these things, it's been up and running for months without a glitch.

The problem is that I've no spare ports and wanted to add a manual offset adjustment capability, using a pot and a switch. The circuit shares a port that one of the DS18B20 sensors uses, like this:

DS18B20 problem.JPG

The DPDT switch uses a spare input only port (C.6) to indicate whether the code should run a short loop to read the pot voltage with an ADC and convert it to a useful numeric value, or run the normal sensing code that I've had running for months. If the switch is sensed as being low then a short loop runs to measure the voltage, and store the set offset as a byte variable. This loop checks to see if the switch has changed state and if so switches the programme back to the proven code that I know works fine (I can't post all the code as it's too long, but it's the standard way of reading DS18B20 sensors and getting numeric data out).

The problem is this. If the switch is in the run mode when the circuit is powered up it works exactly as before, sensing temperatures correctly with all the right outputs happening as they should. When I switch to "set" mode that loop works fine also, and reads the ADC voltage and allows me to store an offset that's used elsewhere in the programme (previously I'd hard coded this offset, this mod was to allow me to adjust it, so the offset code is also well proven).

This is the odd thing. When I switch back to run mode the circuit works exactly as it did before, with the single exception that the output of the switched DS18B20 now always returns zero. I've checked and double checked the wiring, and the only way I can get the code to run properly is to execute a reset command on exiting the set loop. This gets back to everything working as it should, but loses the set offset (at the moment I'm working around that by writing it to EEPROM and recovering it after the reset).

Now, I can work with the circuit doing this, but am puzzled as to why the Picaxe seems unable to switch a port that had been reading a DS18B20 to reading an ADC and then back to reading a DS18B20 again. The odd thing seems to be that it works one way, in that I can switch this port from reading a DS18B20 to reading an ADC, but cannot then switch it back. It's almost as if there's something that prevents the port being reconfigured to read/write to a DS18B20 after the port has been used to read an ADC.

Before anyone asks, there are debounce delays and state checks after the change of state of C.6 is first detected and there is decoupling everywhere. The same behaviour exists when the code is run on a 20M2 in the AXE091 with no relays or external paraphernalia attached, so I am pretty confident it's not related to decoupling, spikes etc.

My best guess is that it has something to do with the way the ADC command leaves the state of port C.1, which then stops that port from working as an in/out port for a DS18B20, but if this is the case then perhaps it's something one of those with in-depth knowledge of what the Picaxe interpreter is really doing at the code level might be best equipped to answer.


Well-known member
Way beyond my experience with this hardware, but I would guess (as if you hadn't already) that after you switch back to "run" mode re-initialize the DS18B20 port (C.1) the same way that it is being set up when you perform the reset.

Jeremy Harris

Senior Member
I think you're spot on. I have a feeling that something in the Picaxe firmware/interpreter changes the way the port works when the ADC command is used, and this then needs to be reset back somehow. I may try just doing a dirsC command to set this port back to being the initial set of inputs/outputs after executing the adc routine and see if that does the trick, as it'd be neater than doing a complete reset.

EDITED to add:

It seems that doesn't do the trick, so it must be something buried a bit deeper in the hardware/firmware, I think. I just tried re-issuing the dirsC command that I use in init: to set the port up as an input, immediately before leaving the ADC routine, and the thing is still returning zero from subsequent DS18B20 reads.
Last edited:


Senior Member
Hi Jeremy,

Have you tried setting the pin as an OUTPUT, since it's used as a bidirectional bus ?

It might be possible to examine all the relevant SFRs of the PICaxe, both "before" and "after", but don't forget that the Port/Pins are "remapped" within the 20M2 (the "raw" ports A, B and C are all used).

Cheers, Alan.

Jeremy Harris

Senior Member
Thanks, I tried that too, by issuing a dirsC to set C.1 as an output after the adc routine but that didn't work either.

I strongly suspect that it has to be something that's done during initialisation that isn't reversible within any subsequent code, except by using the reset command (which I'm guessing runs the internal initialisation sequence).

The idea of looking at the SFRs is a good one, and I may try peeking at them to try and see what's going on. If it is a change to an SFR, then I could, perhaps, fix things by just poking the SFR back to the state it was originally, and avoiding a complete reset.

At the moment I can live with it, as a reset is no different to a power cut, and the unit is designed to retain settings over a power cut. I only need to adjust the offset very rarely, it was really just a way of allowing some fine tuning without having to plug a PC into the thing and change the code (which is what I've been doing up to now).


Technical Support
Staff member
The odd thing seems to be that it works one way, in that I can switch this port from reading a DS18B20 to reading an ADC, but cannot then switch it back. It's almost as if there's something that prevents the port being reconfigured to read/write to a DS18B20 after the port has been used to read an ADC.
Exactly. When you use the readadc command the pin is automatically set as an analogue input. Internally within the silicon when a pin is set as an analogue input the 'digital' silicon input circuit is disconnected. Hence anything that tries to use that pin digitally such as readtemp will no longer work.

It is rare to use a pin like this, normally an adc pin is just an analogue input all the time.

The solution is to use adcsetup to reset that pin to digital status after the adc section of code is finished.

Jeremy Harris

Senior Member
Brilliant! Thanks very much for solving this puzzle, and on a Sunday afternoon, too!

Thanks also for the workaround using adcsetup, easy and neater than me resetting the whole programme.

I appreciate that what I'm doing is unusual; I'm only doing this to avoid a PCB redesign and build - what I should have done is use a 28 pin variant to give me room for expansion like this without needing to share a pin!

Edited to add: I replaced the reset with an appropriate adcsetup command to reset c.1 to an ordinary digital in/out pin and it works like a charm - many thanks again.
Last edited: