1 Wire reset... can't seem to figure it out....

Hi to all... I'm a first time poster and Arduino noob, and I have what I think is probably a simple question about interfacing my Uno to a Maxim DS18B20. I'm starting from the ground up, trying to write my first routine, a 1-Wire reset. Here's the entire program:

int My_Pin = 2; // Switch connected to digital pin 2

void setup() // run once, when the sketch starts { Serial.begin(9600); // start serial port } void loop() { byte status=0; Serial.print("Reset returns: "); status=OneWire_Reset(My_Pin); Serial.println(status); delay(2000); }

int OneWire_Reset(int pin) { int result;

pinMode(pin, OUTPUT); // sets the digital pin as output delayMicroseconds(10); digitalWrite(pin, LOW); // pull the bus LOW delayMicroseconds(600); // Hold it low for at least 480us pinMode(pin, INPUT); // let go of the bus delayMicroseconds(60); // bus comes back HIGH... delayMicroseconds(150); // DS18B20 pulls it low, so make sure we are within 60-240us reply window result = digitalRead(pin); // Sample for presence pulse from slave delayMicroseconds(300); // wait until the window closes return (result); // LOW = reset, HIGH = no reset } My circuit to the DS18B20 is very straightforward... ground to pin 1, pin 2 connected to Digital 2 of the Arduino and connected to a 4.7K pullup w/+5V, and +5 on the pin 3. Switching jumpers around to put it in parasitic power mode make no difference. This always returns HIGH, which means that the 1 Wire bus is not getting pulled low (which = reset acknowledge). I've varied the timings a bit, but that seem to have no effect. I suspect I'm doing something obviously wrong here, but not sure what.... Thanks for any help, Dan PS I know there is a complete 1 wire library out there, but I really want to learn how to do this....

This is the way the OneWire library does it. I think the main difference is using direct register access rather than the Arduino pinMode(), digitalWrite(), and digitalRead(). Another difference is that it waits only 80 microseconds between releasing the line and checking for the acknowledge pulse. You wait 210 (60+150) microseconds and you are using slower I/O functions so maybe you are missing the pulse. Try using a shorter delay before reading the line.

uint8_t OneWire::reset(void)
{
    uint8_t mask=bitmask;
    volatile uint8_t *reg asm("r30") = baseReg;
    uint8_t r;
    uint8_t retries = 125;

    cli();
    DIRECT_MODE_INPUT(reg, mask);
    sei();
    // wait until the wire is high... just in case
    do {
        if (--retries == 0) return 0;
        delayMicroseconds(2);
    } while ( !DIRECT_READ(reg, mask));

    cli();
    DIRECT_WRITE_LOW(reg, mask);
    DIRECT_MODE_OUTPUT(reg, mask);  // drive output low
    sei();
    delayMicroseconds(500);
    cli();
    DIRECT_MODE_INPUT(reg, mask);   // allow it to float
    delayMicroseconds(80);
    r = !DIRECT_READ(reg, mask);
    sei();
    delayMicroseconds(420);
    return r;
}

John, Thanks for the reply. I made the change you suggested, and now it works, thanks! Strangely enough, I then experimented to see how long I could delay before missing the pulse, so I put it back to 210us, and it still works. ??? Weird. Dan