The 1-Wire™ Bus and the Digital Serial Number

Summary:  Learn about the 1-Wire™ Bus by building Digital Serial Number that emulates an iButton™

Perhaps you've heard of the the SPI and I²C digital buses.  These are, respectively, 3 wire and 2 wire interconnects that are used to talk to peripheral ICs, such as EEPROMs.  But, did you know there is a digital bus that uses only one wire?  Well, OK, one wire and Ground.  This bus is called, of course, the "1-Wire™" Bus and it was developed many years ago by Dallas Semiconductor (now owned by Maxim.)  The working principle of this 1-Wire interface is elegant in its simplicity.  The signal wire from the master device to the slave device is pulled up by a ~2.2K resistor.  When the bus in inactive, the resistor is used to charge a small capacitor inside the slave device which supplies it power.  Communication from the master to the slave is accomplished by briefly pulling the signal wire low, during which time the slave continues to operate by drawing power from the capacitor. Short pulses to ground are used to signal a "1" bit and slightly long pulses indicate "0" bits.  Reverse communication from the slave to the master is accomplished by the master sending series of even shorter pulses.  The slave responds to these pulses by holding the line low so that it continues to stay low for a longer than the time of the pulse the master.  To send back a "1" bit, the line is held low slightly longer than the pulse sent by the master.  Add, to send back a "0" bit, the line is held low ever longer  Of course, the overall communication protocol is more complicated than this, but it should give you an idea how the 1-wire bus works.  For more details, you should read Application Note AN937 to get the complete picture. 

Dallas/Maxim makes a variety of device that implement the 1-Wire bus, but one the earliest devices they made was a "digital serial number" IC in a plastic TO-92-3 package.  The current version of this device, the DS2401+, is available from Mouser for about $1.71 ($.88 in 1000s.)  These chips are also packaged in metal cans called "iButtons™" that resemble coin cell batteries.  Each device is said to be manufactured with a unique, 48 bit, laser-etched, read-only serial number.  These could be used as a kind of electronic key, or access control mechanism by touching the contact points to a "reader" pad (see below.)  However, in the last few years, imported devices in the iButton form factor have become available that are both writable and readable.  And, to accompany this, small "copier" devices are also available that can read the serial number from one iButton and then copy it to one, or more writable clones.  So, while a digital serial number IC, or iButton would seem like an ideal kind of electronic key, it now suffers from the same duplication problem as other types of keys.  But, fortunately, there's more to the 1-Wire Bus than just making digital serial numbers...

iButton™ (left) and Reader Socket (right)
It's a "Bus" Protocol

It turns out that protocol used to read out the digital serial number actually serves another purpose.  It's the way Dallas invented to discover and selectively identity the presence of multiple devices on the bus (remember, it was designed as a bus, not a point to point interface.)  This protocol, which is called the 1-Wire Search Algorithm, is used to obtain the 48 bit serial number which also acts as the slave device's unique address on the bus.  In addition, the slave device sends back a one byte "family code" that indicates the type of device that's connected so that further communication can take place.  Dallas/Maxim sell a number of more sophisticated devices packaged as iButtons, such as ones with EEPROM, Battery-backed RAM, Temperature loggers, etc.  To read more about these other devices, check out Dallas/Maxim's "Overview of 1-Wire Technology and Its Use" page.

Let's Build Our Own 1-Wire Device!

Just for fun, I started to wonder how hard it would be to create my own 1-wire device that could mimic a DS2401+ using an inexpensive micro-controller, such as the Atmel/Microchip ATTiny10. The SOT-23 version of this chip, the ATTINY10-TSHR is only 33 cents (one piece price), which is significantly cheaper than the $1.71 price of the  DS2401+, so this seemed like an interesting project, just from a cost perspective.  Plus, I'd be able to program in any serial number I wanted.  And, while I could power the ATTiny10 from 5 volts, my plan was to build a circuit, like the following, to see if I could also implement the self-powering aspect of the 1-wire chips. My hope was that, if I could make self-powering work, it would give me the starting point to create other types of custom, 1-Wire devices.

Click image for larger view

To make ATTiny10 function as a 1-Wire device, we need to teach it how to respond correctly to the 1-Wire Search Algorithm.  While the implementation of this algorithm on the master device is rather complex, what the slave device has to do is rather simple and can be described, as follows:
  1. The slave waits for a "reset" which the master sends by pulling the bus low for 480 uS.  This causes all slaves on the bus to wake up.
  2. After a ~50 uS delay, each slave pulls the bus low for ~150 uS, which sends back a "presence" indicator.
  3. If a device responded, the protocol proceeds, otherwise the Master waits and starts again at step 1. 
  4. The master now sends a series of 8 bits that form a "command" byte by pulling the bus low for long (zero) and short (one) durations.
  5. If the slave receives a command byte of 0xF0, it indicates the start of the "1-Wire Search" sequence.
  6. The master now sends a series of 64 groups of 2 read (from slave) pulses followed by 1 write (to slave) pulse.
  7. For the two read pulses, the slave first sends back the value of the LS bit of a 64 byte value.  It sends the complement of this value on the next read pulse.
  8. For the write pulse, the master sends back the value it received in the first read pulse.
  9. If the value the slave receives does not match the value it sent in the first read pulse the slave stops listening and returns to step 1.
  10. Else, it return to step 6 to send the next of the 64 bits
  11. If the slave manages to successfully send all 64 bits, it has been selected as the active device on the bus and can now accept additional commands.
Sounds like to should be fairly easy to code, doesn't it?  Well, I wish I could say this was an easy project, but it took me several days to get the code working and then another day of experimentation to get it working reliably.  This was mostly because I tried to hack the protocol together without first studying all the details.  In particular, the timing of the bits and the wait periods after the bits was rather tricky to get right.  And, while I was able to make the self powered version work, I had to use a more expensive Schottky diode rather than the cheaper 1N4148 diode I tried first as well as a larger capacitor value than I initially thought would be required (I started with a 1 uF cap and increased this to 4.7uF before the circuit would reliably start working on contact.)  Note: 4.7 uF cap seems to work OK when the pull up resistor is 2.2K, but an even larger cap might be needed in systems that use a higher value for the pull up resistor.  The following image shows a trace capture from the Saleae Logic 8 logic analyzer that shows the voltage swings on the signal line (top trace is digital and bottom trace is analog):

Also, I enabled the watchdog timer in the code to help the circuit recover from a slump in the operating voltage.  Since the enabling the watchdog timer can interfere with in-circuit programming, I added a 100 microsecond delay at startup before the watchdog timer is engaged.  This allows time for the programmer to take control should you want to change and reprogram the code.  On my first attempt, I set the WDTON fuse in the ATTiny10, which caused the Watchdog Timer to always be enabled and then later found that I had to resort to using the High Voltage Programming Protocol to reprogram the chip.  BTW, If you decide you want to experiment more with the 1-wire interface, the Saleae Logic Analyzers are very useful because they include a 1-wire decoder option, which you can also see in action in the image above.  Surprisingly, my rather expensive DS4000-series scope from Rigol does not offer a way to decode the 1-Wire protocol.

In summary, even though this project was a lot more work than I initially expected, I was able to create a working, 1-Wire device that responds exactly same was an official digital serial number device.  But, if you decide to duplicate my work, I'll make several suggestions:
  1. Start off by powering the ATTiny10 with 5 volts, as it eliminates any power-related issues.  
  2. Read through the Dallas/Maxim Applications Notes
  3. Use a Logic Analyzer that can decode the 1-Wire protocol.  I'd probably have given up if I hadn't had the Saleae Logic 8 available.

Try It Yourself!

If you want to try making your own digital serial number, I'll show you three ways to duplicate my work.  If you want to compile the code from scratch, you can use my ATTiny10IDE program.  It's an Integrated Development Environment (IDE) I've written in Java as a way to make it easier to work with the ATTiny series of Micro-controllers.  ATTiny10IDE comes with some built-in documentation that explains how to use it so, once you have it installed, you should be able to download the SerialNum.c file (see attachments at the bottom of the page) and get started.  The basic steps are:

1. Compile from Scratch with ATTiny10IDE
  1. Open SerialNum.c using the File Menu.
  2. Use the "Build" command in the "Actions" menu to compile the code (will display a listing in mixed C and assembly code)
  3. Connect an Arduino that running the ATTiny10 Programmer code (more on this below)
  4. Select the Arduino's Port and Baud Rate (115200) in the "Settings" menu.
  5. Select TPI Programmer->Program Device in the "Actions" menu to program the ATTiny10 with the compiled code.
  6. Disconnect the ATTiny10 from the programmer and wire it into the circuit above
  7. Oh, and you'll need a 1-Wire Reader Program to read out the serial number, but about this later...
2. Generate an Arduino Sketch that Can Program an ATTiny10

Alternately, you can use ATTiny10IDE to generate an Arduino Sketch that will act as the programmer you needed in step 3 above.  You can generate this Sketch, like this:
  1. Open SerialNum.c using the File Menu.
  2. Use the "Build" command in the "Actions" menu to compile the code (will display a listing in mixed C and assembly code)
  3. Select "TPI Programmer.>Generate Arduino Programmer Code" in the "Actions" menu and save this file (named "SerialNum-prog.ino") to disk.
  4. Load the Sketch into the Arduino IDE and upload it to a standard Arduino, such as the Arduino UNO.
  5. Open the "Monitor" window and set it to 115200 baud.
  6. The Sketch should print out instructions in how to wire the ATTiny10 to the Arduino's data line, like this:
    • Connect:
    •   Arduino pin D2 to ATtiny10 pin 5
    •   Arduino pin D3 to ATtiny10 pin 3
    •   Arduino pin D4 to ATtiny10 pin 1
    •   Arduino pin D5 to ATtiny10 pin 6
    •   Arduino pin D6 to ATtiny10 pin 2
    • Commands:
    •   P - Program ATtiny10
    •   I - Identify ATtiny10
  7. Verify that the ATTiny10 is properly connected by typing g the letter 'I' into the Monitor's text area pressing the "Send" button.  This should echo back:

  8. Once the ATTiny10 in connected properly (double check) type a 'P' into the Monitor text area at the top and press the "Send" button.
  9. The Sketch should then print "Programming" and then "Done"
  10. Disconnect the ATTiny10 from the programmer and wire it into the circuit above
  11. Oh, and you'll need a 1-Wire Reader Program to read out the serial number, but about this later...
3. Download an Arduino Sketch that Can Program an ATTiny10

Or, finally, you can just down the the "SerialNum-prog.ino" file I've already created for you (see attachments at the bottom of the page) and follow from step 4 in the set of instructions I covet just before this option.  Note: once you've loaded this Sketch into an Arduino, it will also function as the ATTiny10 Programmer in ATTiny10IDE you were requested to use in step 3 in the first set of instructions above.

Changing the Serial Number

If you're compiling the code from scratch (option 1), or generating the Programmer Sketch option 2), you can change the serial number by simply changing the middle 6 bytes (0x57, 0x47, 0xCF, 0x01, 0x00, 0x00) on line 24 in SerialNum.c.  Or, if you downloaded the pre-generated Programmer Sketch (option 3), you can change the same values inside the generated Programmer Sketch, as shown outlined in red below:

Note: the 0x01 byte before the 0x57 value is the "family code" byte and the 0x00 byte to the right of the outlined area is a placeholder for the CRC byte, which is computed automatically by the SerialNum.c program to match the other 7 bytes in the 8 byte, 64 bit sequence.

OK, Now What About the Reader Program?

Download the "One-Wire Serial" file below and, after unzipping it, copy the Sketch into folder with your other Arduino Sketches.  If you need help with this step, see "Adding programs (sketches) to the Arduino IDE".  However, before you can compile and upload this Sketch, you also need to install the OneWire.h Library into the Arduino.  This library can be downloaded from this web page.  If you need help installing a Library into the Arduino IDE, check out this page for complete instructions.  Then, after you've completed the project above (or, if you happen to have an iButton, or other 1-Wire device handy), you can use the following circuit with the One-Wire Serial Reader Sketch to read out the serial number:

Click image for larger view

Here's a picture of my test setup using the connections shown above:

Click image for larger view

To use the Reader, start up the Sketch and then open up the "Monitor" and set it to 115200.  If everything is working correctly, you should see the Sketch print out the following:

DS1990A:    01 57 47 CF 01 00 00 26 
Serial Num: 0x1CF4757 (30361431)

BTW, you can order 3 copies of the ATTiiny10 Breakout Board I used from OSH Park for just 90 cents (includes free postage)!  The resistor and LED are optional, but are designed to work with the "Blink" sketch included with ATTiny10IDE.  The pinout on the board is designed to plug into pins 2-7 (see image below) on an Arduino running the programmer sketch, which works with ATTiny10IDE and uses the low voltage version of the Tiny Programming Interface (TPI) to program ATTiny10 chips.  Then, once you're finished with this project, you can use it to try some of the other examples included with ATTiny10IDE.

Click image for larger view

Below is the complete parts list needed to build the board.  Since you'll get 3 copies of the PCB from OSH park and because the cost of the parts need to build the boards is quite inexpensive you might consider ordering enough parts to build all 3 boards, as that will give you two spares for other projects.

Part Mouser Part NumberPrice
Tiny10 556-ATTINY10-TSHR*$0.33
R1 710-150060RS75000$0.14
LED 71-CRCW02011K00FNED$0.10

Total     $0.57

(*) Note: if the ATTINY10-TSHR is not available at Mouser, try Ordering it from DigiKey at the slightly higher price of $0.34.
One-Wire Serial
Wayne Holder,
Feb 5, 2019, 10:21 PM
Wayne Holder,
Feb 5, 2019, 1:27 AM
Wayne Holder,
Feb 5, 2019, 1:27 AM