OWC #190 Serial One Wire Controller

Seven Channel Dallas 1-W, Analog to Digital and Output


(Last update Sept 29, '07).

Introduction.

The OWC #190 provides the capability of data acquisition and output control logic by any PC or similar capable of RS232 serial communication at 9600 baud (8 bits, no parity, 1 or more stop bits, no flow control) . For PCs not having a traditional COM port, a USB to serial adaptor may be used.

The module provides seven channels. Each of these channel may be used for any of the following

Thus, the user might use this module as simply seven A/D converters, seven digital outputs or to interface with seven Dallas DS18B20 temperature sensors. Or, in any combination. Two channels might be used to measure temperature using Dallas DS18B20s, two other channels might be used as A/D inputs to measure the output of a Honeywell HIH-4000 relative humidity sensor and the remaining three channels might be used as outputs for controlling a fan, humidifier or alarm.

The idea of this module is to provide the user with the capability of doing many powerful things using a PC or similar. I offer some examples using the free Bloodshed C++ Compiler, but these are only examples. Please note that I do not do custom sofware development.

Sample C++ Code


Note that this design permits the hobbyist to use the Dallas 1-W capability to interface with any Dallas 1-wire device including DS18S20, DS18B20, DS1822 temperature sensors, DS2438 temperature and A/D, DS2423 dual 32-bit counter and DS2450 Quad 16-bit A/D. Note that a channel dedicated to interfacing with Dallas 1-W devices will accommodates one Dallas 1-W device. This design does not support multiple devices on the same channel.



The module consists of an assembled printed circuit board with a 7805 +5 VDC regulator, a MAX232 level shifter, a programmed PIC16F688 or similar, screw terminal terminal blocks, four nylon standoffs, a compatible wall power unit and a six foot serial cable. With the assembled unit, I have wired a DS18B20 temperature sensor to Channel 0.

Detailed Description.

The command set consists of a letter followed by the channel designation in the range of 0 through 6. An optional newline may be sent to terminate the command. However, the module ignores the carriage return and line feed characters.

Analog to Digital Voltage Measurement

The command "A1" causes the module to perform a 10-bit A/D measurement on channel 1 and the module then returns the result in three digit hexadecimal followed by a newline;
   0c2
Note that this is in the range of 0x000 to 0x3ff (0 - 1023). The voltage at the input of the A/D is calculated as;
   Vad = ADVal / 1024 * Vref
where Vref is the nominal 5.0 VDC supply voltage.

The specified channel will be configured as an A/D input on receipt of the first A# command and it will remain so until a non A/D command is issued for the channel.

Consider the following function;

float meas_v(int ch)
{
    char s[25], line[25];
    int num_chars, ad_val;
    float volts;

    rs_flush();
    sprintf(s, "A%1d", ch);
                // A followed by the channel

    rs_putstr(s);

    num_chars = rs_getline(line, 250);


    // printf("%d %s\n", num_chars, line);
    if(sscanf(line, "%x", &ad_val) != 1)
    {
        return(-1.0);
    }
    else
    {
       volts = (float) ad_val * 5.0 / 1024.0;
       return(volts);
    }
}

Digital Output.

After making the specified channel high or low, the processor reads the state of the specified channel and sends either a 0 or a 1 followed by a new line. The idea here is to assure the host that the action was performed by the processor.

The source and sink capability of each channel is 15 mA.

When the module is booted, either by a powerup, a manual reset or a watchdog timeout, all channels are configured as input high impedances (or floating). Thus, the user may wish to install either a pullup or pull down resistor as appropriate to avoid erroneously operating a FET or relay.

The user must use care when issuing the H# or L# commands. If the user has a sensor attached to the specified channel intending to use the A/D command, the accidental application of +5 VDC or GRD to the sensor may damage the sensor and perhaps the processor.

Consider the following code;

int output_state(int ch, int state)
{
    char s[25], line[25];
    int num_chars, relay_state;
    rs_flush();

    if (state == 1)
    {
        sprintf(s, "H%1d", ch);  // H followed by the channel
    }
    else
    {
        sprintf(s, "L%1d", ch); // L followed by the channel
    }

    rs_putstr(s);

    num_chars = rs_getline(line, 250);
    sscanf(line, "%d", &relay_state);
    return(relay_state);
}

Dallas 1-W Commands.

The command set for interfacing with Dallas 1-W devices is minimal;

These commands are then used to interface with virtually any Dallas 1-W device.

For example, consider the Dallas DS18B20 temperature sensor.

The simple measurement sequence is to send a a presence (or reset) pulse, followed by 0xcc (skip ROM) followed 0x44 (perform temperature measurement) followed by one second of strong pullup.

The PC sends the following;

   "P0W0CCS044"
Note the presence pulse on channel 0, followed by a write of the byte "CC" followed by a write of the byte "44" followed by one second of strong pullup. The "S" command is functionally the same as the "W" command, except that after sending the byte, the processor immediately brings the DQ lead to a strong logic one for one second.

The sequence continues with a presence pulse, 0xcc (skip ROM), followed by 0x44 (send temperature). This is easily done by sending the string;

   "P0W0CCW044"
The data is then read by sending the command "R0" and then reading a byte (hexadecimal).

Consider the following function;

float meas_temp_0(void)
{
    char s[25], line[25];
    int num_chars, high, low, word;
    float Tc;

    sprintf(s, "P0W0ccS044");
                // presence, 0xcc, 0x44 followed by one second of strong pullup

    rs_putstr(s);
    delay_ms(1200); // wait for the strong pullup to end

    sprintf(s, "P0W0ccW0be");
              // presence,, 0xcc, 0xbe
    rs_putstr(s);
    delay_ms(200);

    rs_flush();  // clear anything that may be in the buffer
    sprintf(s, "R0");
    rs_putstr(s);

    delay_ms(50);
    num_chars = rs_getline(100);
    sscanf(line, "%x", &low);

    rs_flush();  // flush buffer
    sprintf(s, "R0");
    rs_putstr(s);

    delay_ms(50);
    num_chars = rs_getline(line, 100);

    sscanf(line, "%x", &high);
    word = (high << 8) | low;
    if (word & 0x8000)
    {
        word = (word ^ 0xffff) + 1;
        Tc = -0.0625 * (float) word;
    }
    else
    {
         Tc = 0.0625 * (float)(word);
    }
    return(Tc);
}
Note that in the more general case where the channel is passed to the function, the sprintf's appear a bit more cryptic


float meas_temp_ds18b20(int ch)
{

   ....
   sprintf(s, "P%1dW%1dccS%1d44", ch, ch, ch);
                   // presence, 0xcc, 0x44 followed by one second of strong pullup
   ....
   sprintf(s, "P%1dW%1dccW%1dbe", ch, ch, ch);
              // presence,, 0xcc, 0xbe

   ....
   sprintf(s, "R%1d", ch);
   ....
}