Dallas DS2450 Emulation With Tiny AVR
Dallas DS2450 Emulation With Tiny AVR
AVR
This article describes basic approach to building 1-wire slave devices by uC emulation on example of
DS2450 1-Wire Quad A/D Converter. Besides lower cost, emulated device allows to get more precision that
the prototype and more flexibility by adding various extra software options. Also, 12 bit ADC conversion
was realized by oversampling technique.
Vladimir I. Yershov (first price winner in Russian BASCOM contest)
Chloride Rus, Moscow, Russia
The idea to replace standard DS2450 [1] came during the development battery monitoring system, when it became
obvious that declared precision of the DS2450 does not exceed 8 bits.
The Hardware
.
ATTiny45 chip finally was chosen for the emulation although PIC12F675/683 also were tested but failed due to the speed
limitations.
Tiny45 was configured for operation from internal RC clock at 8 MHz with RESET pin configured as analog input. Pin
configuration shown on Fig.1.
A lab sample of the battery measuring board based on Tiny emulator shown below on Fig.2. As galvanic isolation is
mandatory for such applications, there are two optocouplers on the sides of the board. So 1-wire communication is
performed via optical link. But it’s a topic for another article.
Fig.2 Sample board for battery monitoring system. Tiny is in the middle.
The Firmware
Present software version supports most basic operations of DS2450 except output pins control and alarms function. To
achieve 12 bit resolution, a well known over sampling technique [2] was used.
Fig.3 Simplified software flowchart
The design is also allows addressable firmware upgrade via 1-wire network with the Bootloader by Peter Dannegger [3].
To demonstrate the operation of the device a compilation option for Mega32 (Tiny45 is not available for simulation) was
added and Proteus simulation design was made.
Simplified software flowchart shown on Fig.3. The program flow divides into the several stages.
• Main Loop – polling of the state of the 1-wire pin Dq for Reset Pulse from Master. Once the low state of Dq has been
distinguished Timer starts to counts and the program waits for High Dq. On the High Dq Timer stops and the comparison
with the predefined Min and Max intervals made. If the pulse seems to be Reset the program performs output of the
Presence Pulse and the program begin to wait a general command from the Master.
• General commands reception. General commands could be only: Read ROM, Search ROM, Skip ROM or Match
ROM. If received byte corresponds to one of the General Commands the control passed to second command acquisition
block which recognize device specific commands. Oversize flow returns to the Main Loop.
• Device specific commands reception. These commands for this emulator are: Start ADC Conversion, Read
Memory (ADC results and settings), Write Memory (Device Setup) and Firmware Upgrade.
• ADC Conversion, according to the Oversampling Technique Idea executed 64 times with summing conversion results
in word array for each ADC channel with subsequent division by 16 which results in 12 bit value. Resulting conversion time
is similar with the prototype DS2450.
• CRC16 Calculation is necessary for 1-wire protocol requirements almost for any transaction. In this program CRC16
calculated for each sent/received byte on the fly immediately as the byte is available. It’s the task of CRC_Update
subroutine.
• Interrupt Service Routine (ISR) on timer overflow used here to prevent program endless cycling in cases of
transmition errors or if the master sleeps too long. It returns the control to the different points of the Main Loop depending
of the state of Dq.
• Firmware Upgrade performed via 1-wire bus. This design was developed to work with the intermediate PIC uC
which serves as a Master, accumulates, process data and send results to PC. At the beginning of FW Upgrade Master sent
to Slave Bootload command byte. Slave responses with the same byte and jumps to Bootloader. Master come into
transparent mode and translates the Bootloader traffic from PC to Slave and back.
• Tiny programming consists of two steps: 1. Flashing the Bootloader 2. Downloading Firmware via Bootloader.
Results
Testing of the design was performed in virtual and real environments. Real tests were done with 4 Tiny emulator modules,
united in 1-wire net and connected to the 16 x 12V VRLA batteries of the 10 kVA UPS. Also modules based on DS2450
prototype were tested in the same conditions. Monitoring parameters were: battery voltage, charge-discharge current,
measuring accuracy and transmition errors. Tiny modules shows better performance over DS2450 by all parameters except
current consumption which was 1.5 times greater. There were no any power optimization in current version, so it’s
optimistic to think it’ possible to improve in the future releases.
Proteus simulations were helpful for debug and presentation. Below is the screen short of such simulation.
Schematic
Click here for download archive with source code and schematic
Source code:
'****************************************************************
'* Name : Tiny_DS2450.BAS *
'* Author : Vladimir I. Yershov *
'* *
'* Date : 21.12.2008 *
'* Version : 1.0 *
'* Notes : Firmware for Tiny and Mega AVR to emulate Dallas *
'* DS2450 1-Wire Quad A/D Converter *
'* : *
'****************************************************************
'$regfile = "attiny45.dat" : Const Chip = 45 ' Choose chip for compilation by uncomment line
$regfile = "m32def.dat" : Const Chip = 32
$crystal = 8000000
#if Chip = 45
$loadersize = 512 ' bootloader space reservation
Config Clockdiv = 1
#endif
' HW Config
$hwstack = 32
$swstack = 8
$framesize = 16
Config Adc = Single , Prescaler = Auto
Config Timer0 = Timer , Prescale = 64
Const Dqpin = 1
Const Ipin = 0 ' value in DDRB for input
Const Opin = 1 ' value in DDRB for output
Dq Alias Pinb.dqpin
' Commands
Const Search_rom = &HF0
Const Skip_rom = &HCC
Const Match_rom = &H55
Const Read_rom = &H33
Const Writemem = &H55
Const Convert = &H3C
Const Read_mem = &HAA
Const Bootload = &HEE
Const Write_epr = &HE0
' Timings
Dim I As Byte
Dim B As Byte
Dim Inmask As Byte
Dim Readout As Byte
Dim Addrlo As Byte
Dim Adcnum As Byte
Enable Interrupts
Enable Timer0
On Timer0 Isr Nosave
Restore MyromData
For Addrlo = 1 To 8
Read B
Myrom(addrlo) = B
Next Addrlo
Stop Timer0
#if Chip = 45
Admux = &B00100000
Adcsra = &B00000110
Adcsrb = &B00000000
' Didr0 = &B00111101
Didr0 = &B00111100
#endif
Open "comb.0:57600,8,n,1" For Output As #1
Print #1 , "T45.3 18.11.07" ' version info
Waitms 500
'-----------------------------------
Mainloop:
Waitreset:
Disable Interrupts
Timer = 0
Waitfall:
L1:
sbis pinb, DqPin
rjmp L1
L2:
sbic pinb, DqPin
rjmp L2
Start Timer0
Rwaitrise:
L01:
sbic pinb, DqPin
rjmp L01
L02:
sbis pinb, DqPin
rjmp L02
Stop Timer0
Sendpresense:
Waitus Owpause
Ddrb.dqpin = Opin
Waitus Owpresent
Ddrb.dqpin = Ipin
Timer = 0
Enable Interrupts
Readb:
Gosub Readbyte
Readb1:
Isr:
Spl = &H5F
Sph = 1
If Dq = 0 Then
Timer = T1reset
Goto Rwaitrise
Else
Goto Waitreset
End If
Return
'-------------------------------
Readrom:
For B = 1 To 8
Bytedat = Myrom(b)
Gosub Sendbyte
Next B
Goto Readb
'----------------------------------
Matchrom:
For B = 1 To 8
Gosub Readbyte
If Bytedat <> Myrom(b) Then Goto Mainloop
Next B
Funct:
Gosub Readbyte
Goto Readb1
'----------------------------------------
Fwupgrade:
Gosub Sendbyte
jmp 0
Readmem:
Crc16_lo = 0
Crc16_hi = 0
B = 0
Gosub Readbyte
Addrlo = Bytedat
Gosub Crc_update ' ByteDat = AddrLo
Gosub Readbyte
Gosub Crc_update ' ByteDat = AddrHi
Readloop:
Bytedat = Ram(addrlo + 1)
Gosub Sendbyte
Gosub Crc_update
Incr Addrlo
Incr B
Crc16_lo = 0
Crc16_hi = 0
Goto Mainloop
'----------------------------------------
Write_mem:
Crc16_lo = 0 : Crc16_hi = 0
Gosub Readbyte
Addrlo = Bytedat
Gosub Crc_update ' AddrLo
Gosub Readbyte
Gosub Crc_update ' AddrLo
Gosub Readbyte
Ram(addrlo + 1) = Bytedat
Gosub Crc_update ' MemByte
Bytedat = Ram(addrlo + 1)
Gosub Sendbyte
' ====== END OF FIRST PASS ===========
Writememloop:
Incr Addrlo
Crc16_hi = 0
Crc16_lo = Addrlo ' low (Crc16) = Addrlo
Gosub Readbyte
Ram(addrlo + 1) = Bytedat
Gosub Crc_update
Bytedat = Ram(addrlo + 1)
Gosub Sendbyte
Goto Mainloop
' =============
Conversion:
Crc16_lo = 0 : Crc16_hi = 0
Gosub Crc_update 'ByteDat = Convert
#if Chip = 45
Didr0 = &B00111100
Adcsra = &B00000101 ' ADC clock = 250 kHz
Adcsra.7 = 1 ' Enable ADC
Adcsrb = &B00000000
#endif
For Adcnum = 1 To 4
Ramw(adcnum) = 0
Next Adcnum
#if Chip = 45
For Overcount = 1 To Oversample
Admux = &B00000000 ' Righ aligned result
For Adcnum = 1 To 4
Adcsra.6 = 1
While Adcsra.6 = 1 : Wend
Templ = Adcl : Temph = Adch
Ramw(adcnum) = Ramw(adcnum) + Tempw
Incr Admux
Next Adcnum
Next Overcount
#else
Start Adc
For Overcount = 1 To Oversample
For Adcnum = 1 To 4
B = Adcnum - 1
Ad_result = Getadc(b)
Ramw(adcnum) = Ramw(adcnum) + Ad_result
Next Adcnum
Next Overcount
#endif
For Adcnum = 1 To 4
Shift Ramw(adcnum) , Right , Overshift
Shift Ramw(adcnum) , Left , Normshift
Next Adcnum
Exit_case:
#if Chip = 45
Adcsra.7 = 0 ' Disable ADC
#else
Stop Adc
#endif
Goto Mainloop
'======================================================
Crc_update:
Wreg = Bytedat
Wreg = Wreg Xor Crc16_lo
Temp = Wreg
Wreg = Crc16_hi
Crc16_lo = Wreg
Wreg = 0
Crc16_hi = Wreg
Wreg = Wreg And &HF0
Crc16_hi = Crc16_hi Xor Wreg
Crc16_lo = Crc16_lo Xor Wreg
Wreg = 0
Return
'---------------------------------
'================================
Readbyte:
For I = 0 To 7
L11:
sbis pinb, DqPin
rjmp L11
L12:
sbic pinb, DqPin
rjmp L12
Timer = 256 - T1reset
Start Timer0
Bytedat.7 = Dq
Next I
Stop Timer0
Return
'----------------------------------
Sendbyte:
Adcnum = Bytedat
For I = 0 To 7
L21:
sbis pinb, DqPin
rjmp L21
L22:
sbic pinb, DqPin
rjmp L22
Timer = 256 - T1reset
Start Timer0
Next I
Bytedat = Adcnum
Stop Timer0
Return
'-----------------------------------
Sendrom:
' Stop Timer0
For I = 1 To 8
Bytedat = Myrom(i)
For B = 0 To 7
'----------------------------
Sendcbit1:
L31:
sbis pinb, DqPin
rjmp L31
L32:
sbic pinb, DqPin
rjmp L32
L41:
sbis pinb, DqPin
rjmp L41
L42:
sbic pinb, DqPin
rjmp L42
'--------------------------
Readcbit:
L51:
sbis pinb, DqPin
rjmp L51
L52:
sbic pinb, DqPin
rjmp L52
Waitus Owstrobe
Bitdat = Dq
'-------------------------
If Bitdat <> Bytedat.0 Then Goto Mainloop
Rotate Bytedat , Right
Next B
Next I
Goto Readb
End
MyromData:
'Data &H20 , &H0D , &HCB , &H0A , 00 , 00 , 00 , &HEC
'Data &H81 , &H55 , &H22 , &H24 , 00 , 00 , 00 , &H6A
'Data &H20 , &HAC , &HC7 , &H0A , 00 , 00 , 00 , &HA6