OneWire support

I can’t post specifics, but if you want to post your basic DS2482 code (or PM it) I can take a look.

If you’re getting null responses, that sounds rather like you’re not using the right i2c address?

I have an 1-wire imp master complete with code available. More info here.

There are some app notes around from Atmel and Maxim using a standard UART for this purpose. It should be possible to just use a low forward voltage sckotty diode on TX to make it like an open collector output and a pullup resistor on the DQ bus wire. The advantage is over bit banging is that the UART is doing all the timing, but a disadvantage is this approach is using two IO pins.

I have not done any testing, but below the code that should do the trick using the UART on pin 1 and 2 and only one wire device on the bus.

`
function owReset()
{
// configure UART for OneWire RESET timing
hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
hardware.uart12.write(0xF0);
hardware.uart12.flush();

if ( hardware.uart12.read() == 0xF0 )
{
    server.log("owDevice not present");
    return 0;
} else {    
    server.log("owDevice present");
    // Switch UART to OneWire data speed timing
    hardware.uart12.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
    return 1;
}

}
function owWrite(byte)
{
// Writebit: 1 = TX 0xFF = RX else error, 0 = TX 0x00 = RX
local bit = 0x00;
for (local b=0; b<8; b++, byte=byte>>1)
{
bit=byte&0x01?0xFF:0x00;
hardware.uart12.write(bit);
hardware.uart12.flush();
if (hardware.uart12.read() != bit) server.log(“owDevice write error”);
}
}
function owRead()
{
// Readbit: TX 0xFF, RX != TX = 0, RX = TX = 1
local byte = 0x0;
for (local b=0; b<8; b++)
{
hardware.uart12.write(0xFF);
hardware.uart12.flush();
if (hardware.uart12.read() != 0xFF) byte += 0x01 << b;
}
return byte;
}

if (owReset())
{
server.log(“Try reading 18B20”);
owWrite(0xCC); // SKIP ROM
owWrite(0x44); // CONVERT_T DS18B20

imp.sleep(0.750); //wait for conversion to finish

owReset();
owWrite(0xCC); // SKIP ROM
owWrite(0xBE); // READ_SCRATCHPAD DS18B20
server.log(owRead()); //temp LSB
server.log(owRead()); //temp MSB
// owReset(); // issue reset if you want stop reading here
server.log(owRead());
server.log(owRead());
server.log(owRead());
server.log(owRead());
server.log(owRead());
server.log(owRead());
server.log(owRead());
}
`

The SEARCH_ROM function could be done in the same way if there are more devices on the bus.

Hi,

Has anyone tried the code that @theo shared?

I currently have two RHT-03s, which I’m dying to read with my Imp!

Anyone?

No not yet. I have ordered some sckotty diodes and 3k3 resistors.
Theoretically it should work but if it does not work the first time I’am pretty sure we can fix the code. Just give it a try !

Any new timing for the “Bit-banger scheduler”?

@theo - Would you please elaborate on the schematic and the components used?

I’d be willing to try this and see if it works.

I have just tried it. I get the 1wire presence pulse back OK. But reading and writing shows a lot of pulses on the bus but i always read 0xFF. So something is wrong. I just have my oscilloscope but need a protocol analyzer to debug.

diode: 1N5189, resistor 3k3 (tried 4k7 but makes no difference) , TX: pin 1, RX pin2.

Thanks for trying this out!

I’d really love to get OneWire going since I have a couple of sensors collecting dust, which I’d have to interface via external hardware ATM…

I really hate to complicate things for no good reason.

Thanks for your help!

Hi,
will there not be a bit-banger scheduler?

Still on the list MiKi, but still no date. Lot of other things going on!

I just made another attempt and this time i got 1-wire working through the serial port. I have connected a DS18B20 temperature sensor to the 1-wire bus and supply voltage 3.3V. I used a Schottky diode 1N5189 with a low forward voltage drop, resistor 2k2 , TX: pin 1, RX pin2. This resistor value can supply 1.5mA ‘parasite power’ during the conversion of one DS18B20.

A simple piece of code reports the temperature every 30 seconds.

10-7-2013 20:36:28: Temperature: 30.3
10-7-2013 20:36:57: Reading 18B20
10-7-2013 20:36:58: Temperature: 30.3
10-7-2013 20:37:27: Reading 18B20
10-7-2013 20:37:28: Temperature: 30.3

The code listing:

`// oneWire Test program
imp.configure(“oneWire”, [], []);

function owReset()
{
// configure UART for OneWire RESET timing
hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
hardware.uart12.write(0xF0);
// hardware.uart12.flush();

if ( hardware.uart12.read() == 0xF0 )
{
    server.log("owDevice not present");
    return 0;
} else {

// server.log(“owDevice present”);
// Switch UART to OneWire data speed timing
hardware.uart12.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
return 1;
}
}
function owWrite(byte)
{
// Writebit: 1 = TX 0xFF = RX else error, 0 = TX 0x00 = RX
local bit = 0x00;
for (local b=0; b<8; b++, byte=byte>>1)
{
bit=byte&0x01?0xFF:0x00;
hardware.uart12.write(bit);
// hardware.uart12.flush();
if (hardware.uart12.read() != bit) server.log(“owDevice write error”);
}
}
function owRead()
{
// Readbit: TX 0xFF, RX != TX = 0, RX = TX = 1
local byte = 0x0;
for (local b=0; b<8; b++)
{
hardware.uart12.write(0xFF);
// hardware.uart12.flush();
if (hardware.uart12.read() == 0xFF) byte += 0x01 << b;
}
return byte;
}

// Wake up and write to the server

function awake()
{
local tempL = 0;
local tempH = 0;
local temp = 0;

imp.wakeup(30.0, awake);

server.log(“Reading 18B20”);

owReset();
owWrite(0xCC); // SKIP ROM
owWrite(0x44); // CONVERT_T DS18B20
imp.sleep(0.8); // wait min 750 msec for temperature conversion to finish

owReset();
owWrite(0xCC); // SKIP ROM
owWrite(0xBE); // READ_SCRATCHPAD DS18B20

tempL = owRead();
tempH = owRead()*256;
owReset(); // use reset to stop reading the rest of the scratchpad

temp = (tempL + tempH)/16.0; // calculate temperature from LSB and MSB

server.log(format(“Temperature: %3.1f”, temp));
server.show(format(“Temperature: %3.1f”, temp));
}

// Setup to read temperature for the first time
imp.wakeup(5.0, awake);`

@theo: I edited your post to wrap the code in a < code> </ code> block :slight_smile:

Yeah sorry, i was just looking how to do that . Thanks

GREAT! So we’ve had OneWire support all along? (be it through a workaround)

Would someone please write a complete tutorial as I’d love to get this working with my RHT-03s?

Thanks in advance!

should be challenging to write it yourself :wink:

DS2482 is $1.57 from Digikey in 1’s

I did some more testing on the one wire bus using a uart. I have added a bit read/wite function to support the search algorithm that i have added. I have setup a bus with twelve DS18B20’s and one DS2406 (single channel PIO extender in a 3 legged TO-92).

The code below will trigger all DS18B20’s to do the temperature conversion at the same time, and will then loop through all individual found devices on the bus to read the temperature. When the DS2406 is found it will read the PIO-A pin and toggle the output which has a led connected to it.

`// oneWire Test program
imp.configure(“oneWire”, [], []);

function owReset()
{
// configure UART for OneWire RESET timing
hardware.uart12.configure(9600, 8, PARITY_NONE, 1, NO_CTSRTS);
hardware.uart12.write(0xF0);

if ( hardware.uart12.read() == 0xF0 )
{
    server.log("owDevice not present");
    return 0;
} else {
    // Switch UART to OneWire data speed timing
    hardware.uart12.configure(115200, 8, PARITY_NONE, 1, NO_CTSRTS);
    return 1;
}

}

function owWrite(byte)
{
for (local b=0; b<8; b++, byte=byte>>1) owBit(byte&0x01);
}

function owRead()
{
local byte = 0;
for (local b=0; b<8; b++) byte=(byte>>1)+0x80*owBit(1);
return byte;
}

// Write/Read bit
function owBit(bit)
{
bit=bit?0xFF:0x00;
hardware.uart12.write(bit);
return hardware.uart12.read()==0xFF?1:0;
}

function owSearch(next)
{
local Y = 0; // last found fork point

// Reset the bus and exit if no device found
if(owReset())
{

// OW_SEARCH_ROM readies all 1-Wire devices to begin the search and
// simultaneously sending the first least significant bit on the next read
owWrite(0xF0);

// Reading 64 bits romcode LSB: family code (8 bits), serialnummber (48 bits), MSB: CRC (8 bits)

    for (local i=64; i>0; i--) {
          local byte = (i-1)/8;
          local b = owBit(1);   // read bit from bus
          if(owBit(1))          // read inverse bit
          {
            if(b) { Y=0; break } // read 1+1, bus error, no response
          } else if(!b) {       // read 0+0, found 2 devices with opposite bits
                if( next > i || ( next != i && (id[byte] & 1) ) ) // or take the same path as in the previous ID
                {
                    b = 1;    // take the '1' direction on this point
                    Y = i;    // store last found fork point
                }                
          }

// select only devices on the bus with the same bit valvue, other devices go offline and no longer participate in the search until next search
owBit(b);
// shift out the previous path bits, add on the msb side the new choosen path bits
id[byte] = (id[byte] >> 1) + 0x80 * b;
}
}
// return the last fork point for next search
return Y;
}

// Wake up every 30 seconds and write to the server

function awake()
{
id <- [0,0,0,0,0,0,0,0]; // OW device ID array
next <- 65;

local tempL = 0;
local tempH = 0;
local temp = 0;

imp.wakeup(30.0, awake);

server.log(“Trigger all devices to do temperature conversion”);

owReset();
owWrite(0xCC); // SKIP RO to select all devices on the bus
owWrite(0x44); // CONVERT_T DS18B20 start conversion on all devices

imp.sleep(0.75); // wait 750 msec for temperature conversion to finish

local dev = 0;

while(next)
{
dev++;
next = owSearch(next);

if (id[7] == 0x28)
{
owReset();
// MATCH ROM to select device for reading temperature
owWrite(0x55);
for (local i=7; i>=0; i–) owWrite(id[i]);
// READ_SCRATCHPAD DS18B20
owWrite(0xBE);

tempL = owRead();
tempH = owRead()*256;
owReset(); // stop reading the rest of the scratchpad

temp = (tempL + tempH)/16.0; // calculate temperature from LSB and MSB

server.log(format("#%02d: Family: %02x (DS18B20), Serial: %02x%02x%02x%02x%02x%02x, CRC: %02x, Temp: %3.1f", dev, id[7],id[1],id[2],id[3],id[4],id[5],id[6],id[0],temp));
}

if (id[7] == 0x12)
{
owReset();
owWrite(0x55); // MATCH ROM to select device for reading temperature
for (local i=7; i>=0; i–) owWrite(id[i]);
// CHANNEL_ACCESS followed by 2 channel control bytes
owWrite(0xF5);
// first channel control byte: no crc, set CHS0 = select PIO-A only, b6=IM=0=writing-reading
owWrite(4); // 00000100
// write dummy channel control byte
owWrite(0xFF);
// read channel info byte
local pioA = owRead() & 5; // PIO-A bits 00000101
owBit(!pioA); // toggle output PIO-A

server.log(format("#%02d: Family: %02x (DS-2406), Serial: %02x%02x%02x%02x%02x%02x, CRC: %02x, pioA: %02x", dev, id[7],id[1],id[2],id[3],id[4],id[5],id[6],id[0],pioA));
}
}
}

// Start the loop
imp.wakeup(2.0, awake);
`

Output from the server log:

14-7-2013 15:56:12: Trigger all devices to do temperature conversion
14-7-2013 15:56:12: #01: Family: 12 (DS-2406), Serial: 0000007d2d03, CRC: f9, pioA: 05
14-7-2013 15:56:13: #02: Family: 28 (DS18B20), Serial: 000003fa9237, CRC: cc, Temp: 28.6
14-7-2013 15:56:13: #03: Family: 28 (DS18B20), Serial: 000003fabd2d, CRC: cf, Temp: 28.5
14-7-2013 15:56:13: #04: Family: 28 (DS18B20), Serial: 000003faa3f9, CRC: 09, Temp: 28.7
14-7-2013 15:56:13: #05: Family: 28 (DS18B20), Serial: 000003fac8c9, CRC: 85, Temp: 28.4
14-7-2013 15:56:13: #06: Family: 28 (DS18B20), Serial: 000003fa9b1e, CRC: 1f, Temp: 28.6
14-7-2013 15:56:13: #07: Family: 28 (DS18B20), Serial: 000003face76, CRC: 3a, Temp: 28.5
14-7-2013 15:56:13: #08: Family: 28 (DS18B20), Serial: 000003fac076, CRC: 98, Temp: 28.6
14-7-2013 15:56:14: #09: Family: 28 (DS18B20), Serial: 000003fab236, CRC: 03, Temp: 28.6
14-7-2013 15:56:14: #10: Family: 28 (DS18B20), Serial: 000003faa5aa, CRC: e2, Temp: 28.5
14-7-2013 15:56:14: #11: Family: 28 (DS18B20), Serial: 000003faa08a, CRC: 86, Temp: 28.6
14-7-2013 15:56:14: #12: Family: 28 (DS18B20), Serial: 000003fa8922, CRC: 70, Temp: 28.4
14-7-2013 15:56:14: #13: Family: 28 (DS18B20), Serial: 000003fac66c, CRC: 90, Temp: 28.6
I hope this will be useful for you 1-wire fans.

I cant find a 1N5189 at farnell, or rs components, is there something simular i can use?

Any Schottky diode with a low forward voltage drop should work. I think i got mine from Sparkfun