1_Wire RTC problems DS1994

cravenhaven

Senior Member
This is driving me crazy, I've spent hours on it and cant figure out whats wrong.
I have simplified the program to just focus on what the problem is and inserted it below (I think?).
I have also copied in the circuit and the output from the program.

This section of the program is to write the correct time to the clock.
The root of the problem seems to be that when I setup the variables to write out to the RTC, the DataByte variable seems to get changed and I cant see why.

Hopefully someone can point out the error of my ways!.


Code:
#PICAXE 20X2
;
;EEPROM messages. 20 bytes per message
EEPROM 1, ("DS1994 NOT found")
EEPROM 20,("Time out of range")
EEPROM 40,("Write Time wrong")
EEPROM 60,("Byte sent <> recv'd")
EEPROM 80,("Date conv. Wrong")
;
;Constants
;
SYMBOL OW_ReadRom 	=$33
SYMBOL OW_SkipRom 	=$CC
SYMBOL OW_SearchRom 	=$F0
SYMBOL OW_ReadMem		=$F0
SYMBOL OW_Writescr	=$0F
SYMBOL OW_Readscr		=$AA
SYMBOL OW_Copyscr		=$55
SYMBOL OW_Startclock	=$50	;Osc on, Stop counter
SYMBOL OW_lo_ctrl_buf	=$01	;Control register lo_byte
SYMBOL OW_lo_rtc_buf	=$03	;RTC Register lo_byte
SYMBOL OW_hi_tkr_buf	=$02	;Time Keeping Registers hi_byte
SYMBOL OW_Net		=B.0

;
;Variables
;

SYMBOL errors		=b2
SYMBOL errormsg		=b3
SYMBOL message		=b4
SYMBOL errormsgno		=b5
SYMBOL DataByte		=b5
SYMBOL OW_TA1		=b7		; Target address low byte to be issued to the 1-Wire DS1994
SYMBOL OW_TA2		=b8		; Target address high byte to be issued to the 1-Wire DS1994
SYMBOL OW_ES		=b9		; Target ending address status register for the 1-Wire DS1994
SYMBOL index		=b10		; general index used with FOR...NEXT blocks


SYMBOL Time1	= w11		;Holds latest date&time
SYMBOL   Time1_1	= b22 
SYMBOL   Time1_2	= b23
SYMBOL Time2	= w12		;Holds latest date&time
SYMBOL   Time2_1	= b24
SYMBOL   Time2_2	= b25		
SYMBOL hundr	=b26
SYMBOL tens		=b27
SYMBOL units	=b28

;Temporary variables
SYMBOL Temp1	= b40
SYMBOL Temp2	= b41
SYMBOL Temp3	= b42
SYMBOL Lookup_result=w23
SYMBOL TempW0	= w24
SYMBOL   TempW0_1	= b48
SYMBOL   TempW0_2	= b49		
SYMBOL TempW1	= w25
SYMBOL   TempW1_1	= b50
SYMBOL   TempW1_2	= b51		
SYMBOL TempW2	= w26	
SYMBOL   TempW2_1	= b52
SYMBOL   TempW2_2	= b53		
SYMBOL TempW3	= w27	
SYMBOL   TempW3_1	= b54
SYMBOL   TempW3_2	= b55		

;
; -----( Start Program )--------------------------------------------------
;
main:
	PAUSE 10000
	Time2=$4E2E			;Date/Time in seconds
	Time1=$916A			;Date/Time=26/07/2011 10:05:30 referenced to 1/1/1970 00:00:00
	GOSUB OW_Time_init
	GOSUB Check_Time_Registers

	PAUSE 10000
	Time2=$BA9B			;Date/Time in seconds
	Time1=$B80B			;Date/Time=15/03/2006 17:21:17 referenced to 1/1/1970 00:00:00
	GOSUB OW_Time_init
	GOSUB Check_Time_Registers

	GOTO main
END

OW_Time_init:		;Set the time (in seconds) on the DS1994
	SERTXD(CR,LF,"Time_init",CR,LF)
	
	OW_TA2=OW_hi_tkr_buf

	SERTXD(CR,LF,CR,LF,"Time_Init loop, Writing Time2_2")
	OW_TA1=OW_lo_ctrl_buf+3		
	DataByte=Time2_2
	SERTXD(CR,LF,"Time2_2=",#Time2_2," DataByte=",#DataByte)
	GOSUB OW_WriteByte
	SERTXD(CR,LF,"Time_Init loop, Address and status registers. OW_TA2= ",#OW_TA2,"   OW_TA1= ",#OW_TA1,"   E/S= ",#OW_ES)

	SERTXD(CR,LF,CR,LF,"Time_Init loop, Writing Time2_1")
	OW_TA1=OW_lo_ctrl_buf+2		
	DataByte=Time2_1
	SERTXD(CR,LF,"Time2_1=",#Time2_1," DataByte=",#DataByte)
	GOSUB OW_WriteByte
	SERTXD(CR,LF,"Time_Init loop, Address and status registers. OW_TA2= ",#OW_TA2,"   OW_TA1= ",#OW_TA1,"   E/S= ",#OW_ES)

	SERTXD(CR,LF,CR,LF,"Time_Init loop, Writing Time1_2")
	OW_TA1=OW_lo_ctrl_buf+1		
	DataByte=Time1_2
	SERTXD(CR,LF,"Time1_2=",#Time1_2," DataByte=",#DataByte)
	GOSUB OW_WriteByte
	SERTXD(CR,LF,"Time_Init loop, Address and status registers. OW_TA2= ",#OW_TA2,"   OW_TA1= ",#OW_TA1,"   E/S= ",#OW_ES)

	SERTXD(CR,LF,CR,LF,"Time_Init loop, Writing Time1_1")
	OW_TA1=OW_lo_ctrl_buf	
	DataByte=Time1_1
	SERTXD(CR,LF,"Time1_1=",#Time1_1," DataByte=",#DataByte)
	GOSUB OW_WriteByte
	SERTXD(CR,LF,"Time_Init loop, Address and status registers. OW_TA2= ",#OW_TA2,"   OW_TA1= ",#OW_TA1,"   E/S= ",#OW_ES)

	SERTXD(CR,LF,"*******Time_init EOS ********",CR,LF)
RETURN


OW_WriteByte:			;Called with target address hi & lo bytes in OW_TA2 & OW_TA1 and the subject byte
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Writescr,OW_TA1,OW_TA2,DataByte) ;now start the clock running
	OWOUT OW_Net,ownoreset,(OW_SkipRom,OW_Readscr)		;Tell the device to read the scratch register back
	OWIN  OW_Net,owresetafter,(TempW0_1,TempW0_2,OW_ES,TempW1_1)	;read scratch address vectors
	errors=0
	IF TempW0_1=OW_TA1 AND TempW0_2=OW_TA2 THEN 			;If the scratch registers are wrong then dont write the data
			IF  TempW1_1=DataByte THEN
				OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Copyscr,TempW0_1,TempW0_2,OW_ES)	;copy scratch to RTC registers (inlude authorisation codes)
			ELSE LET errors=1
			ENDIF	
		ELSE LET errors=1
	ENDIF	
	SERTXD(CR,LF,"---------------------------TempW0_1=OW_TA1: ",#TempW0_1,"=",#OW_TA1," TempW0_2=OW_TA2: ",#TempW0_2,"=",#OW_TA2," TempW1_1=DataByte: ",#TempW1_1,"=",#DataByte," OW_ES: ",#OW_ES,CR,LF)

RETURN

OW_Read_Byte:			; call with OW_TA1,OW_TA2 set to lo&hi address registers
      OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_ReadMem,OW_TA1,OW_TA2)
     	OWIN OW_Net,owresetafter,(DataByte)
	
RETURN

Check_Time_Registers:	
	SERTXD(CR,LF,"Main loop, Time registers from RTC")
	OW_TA2=OW_hi_tkr_buf
	FOR OW_TA1=0 to 6
		GOSUB OW_Read_Byte
		Temp2=DataByte
		GOSUB Display_Reg
	NEXT OW_TA1
RETURN
	
Display_Reg:		;Display a register value. Modifies Temp1, Called with register in Temp2
	Temp1=Temp2 AND $F0 /$10 + $30
	IF Temp1 > $39 THEN LET Temp1=Temp1+7
	ENDIF
	SERTXD(" $",Temp1)
	Temp1=Temp2 AND $0F + $30
	IF Temp1 > $39 THEN LET Temp1=Temp1+7
	ENDIF
	SERTXD(Temp1)
RETURN


Output from circuit when running the above code


Code:
Time_init


Time_Init loop, Writing Time2_2
Time2_2=78 DataByte=78
---------------------------TempW0_1=OW_TA1: 4=4 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 76=78 OW_ES: 4

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 4   E/S= 4

Time_Init loop, Writing Time2_1
Time2_1=46 DataByte=46
---------------------------TempW0_1=OW_TA1: 3=3 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 44=46 OW_ES: 3

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 3   E/S= 3

Time_Init loop, Writing Time1_2
Time1_2=145 DataByte=145
---------------------------TempW0_1=OW_TA1: 2=2 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 145=145 OW_ES: 2

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 2   E/S= 2

Time_Init loop, Writing Time1_1
Time1_1=106 DataByte=106
---------------------------TempW0_1=OW_TA1: 1=1 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 104=106 OW_ES: 1

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 1   E/S= 1
*******Time_init EOS ********

Main loop, Time registers from RTC $F8 $50 $54 $FC $4D $31 $4C
Time_init


Time_Init loop, Writing Time2_2
Time2_2=186 DataByte=186
---------------------------TempW0_1=OW_TA1: 4=4 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 184=186 OW_ES: 4

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 4   E/S= 4

Time_Init loop, Writing Time2_1
Time2_1=155 DataByte=155
---------------------------TempW0_1=OW_TA1: 3=3 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 153=155 OW_ES: 3

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 3   E/S= 3

Time_Init loop, Writing Time1_2
Time1_2=184 DataByte=184
---------------------------TempW0_1=OW_TA1: 2=2 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 184=184 OW_ES: 2

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 2   E/S= 2

Time_Init loop, Writing Time1_1
Time1_1=11 DataByte=11
---------------------------TempW0_1=OW_TA1: 1=1 TempW0_2=OW_TA2: 2=2 TempW1_1=DataByte: 9=11 OW_ES: 1

Time_Init loop, Address and status registers. OW_TA2= 2   OW_TA1= 1   E/S= 1
*******Time_init EOS ********

Main loop, Time registers from RTC $F8 $50 $7C $08 $50 $31 $4C
View attachment OW_troubles.dsn
 

westaust55

Moderator
Sorry but a bit busy to look through your code right now (about to leave and "battle" through the heavy rain and storms around here).

Have a look through this thread on 1-Wire and in particular posts 39 + 74 for a “Time” chip and post 78 for the DS1993 memory chip (memory access same as DS1994)
http://www.picaxeforum.co.uk/showthread.php?15306-One-Wire-Devices-Networks.

Will look back later (this evening West Aust time )to see if you have found a solution in this way.
 

cravenhaven

Senior Member
Thanks Westaust,
I am about 150k's east of you and am glad I'm not in the city today. Have studied most of your stuff to be able to get this far but this has just got me beat.
 

hippy

Senior Member
The root of the problem seems to be that when I setup the variables to write out to the RTC, the DataByte variable seems to get changed and I cant see why.
There's a lot of code and diagnostic messages to work through when not familiar with what you are doing. Is it possible to indicate exactly where the DataByte variable is changing from what you expect, where that is in the code and in the diagnostics ?

Is it possible to simplify the code even further, to just a few lines, which demonstrates it not working as expected ?

Most people ( me included ) won't have used a DS1994, won't be familiar with how it works, what it expects, what it outputs, and I would guess most haven't much experience with OWIN and OWOUT commands either. The simpler you can make it to see the problem the easier it will be for people to help, even those without that experience.
 

westaust55

Moderator
Your code extract is incomplete (some symbol/alias names not defiend) so will not simulate without effort.

The problem may be that you are generating a reset after some write commands when you need to leave the comms open ready to read back, or delay the reset and give the DS1994 time to copy the data. Try changing the OW_WriteByte: subroutine as follows:

Code:
OW_WriteByte:			;Called with target address hi & lo bytes in OW_TA2 & OW_TA1 and the subject byte
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Writescr,OW_TA1,OW_TA2,DataByte) ;now start the clock running
[COLOR="#008080"]; change next to owresetbefore - do not reset after as we want to leave comms open ready to read back[/COLOR]
	OWOUT OW_Net,[COLOR="#FF0000"]owresetbefore[/COLOR],(OW_SkipRom,OW_Readscr)		;Tell the device to read the scratch register back from DS1994
	OWIN  OW_Net,owresetafter,(TempW0_1,TempW0_2,OW_ES,TempW1_1)	;read scratch address vectors
	errors=0
	IF TempW0_1=OW_TA1 AND TempW0_2=OW_TA2 THEN 			;If the scratch registers are wrong then dont write the data
			IF  TempW1_1=DataByte THEN
[COLOR="#008080"]; change next to owresetbefore - do not reset too early after write  - give time to copy from scratchpad to DS1994 register[/COLOR]
				OWOUT OW_Net,[COLOR="#FF0000"]owresetbefore[/COLOR],(OW_SkipRom,OW_Copyscr,TempW0_1,TempW0_2,OW_ES)	;copy scratch to RTC registers (inlude authorisation codes)
			ELSE LET errors=1
			ENDIF	
		ELSE LET errors=1
	ENDIF	
	SERTXD(CR,LF,"---------------------------TempW0_1=OW_TA1: ",#TempW0_1,"=",#OW_TA1," TempW0_2=OW_TA2: ",#TempW0_2,"=",#OW_TA2," TempW1_1=DataByte: ",#TempW1_1,"=",#DataByte," OW_ES: ",#OW_ES,CR,LF)

RETURN
 

cravenhaven

Senior Member
Is it possible to simplify the code even further, to just a few lines, which demonstrates it not working as expected ?
Hi Hippy,
The problem is in the parts shown.
I call the write routine from the Init routine and set 3 variables to be used: The 2 address bytes "OW_TA2 and OW_TA1", and the byte of data to be written is in 'DataByte'.

********When I check the value of DataByte after the Write routine returns it is intermittently changed. The address bytes never change however. **********
Oops pretend I never wrote that last paragraph.

What I meant to say is that when I compare what is in the scratch register with what I wrote there, it is intermittently different. The address bytes always read back OK however.

This is shown in the output where 'TempW1_1=DataByte: 76=78'. Not very clear I guess but it is meant to indicate that TempW1_1 and DataByte should be the same but the returned data shows them as different.


Code:
OW_Time_init:
	OW_TA2=OW_hi_tkr_buf
	OW_TA1=OW_lo_ctrl_buf+3		
	DataByte=Time2_2
	GOSUB OW_WriteByte
RETURN


OW_WriteByte:
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Writescr,OW_TA1,OW_TA2,DataByte) 
	OWOUT OW_Net,ownoreset,(OW_SkipRom,OW_Readscr)	
	OWIN  OW_Net,owresetafter,(TempW0_1,TempW0_2,OW_ES,TempW1_1)
RETURN
 
Last edited:

cravenhaven

Senior Member
That's strange Westaust. The code I put into the original post was a full copy/paste of what I ran to get the sample output that I also posted. I'll copy it back and compare.
I tried a few variants of the reset sequences but nothing seemed to work, but will try your suggestion.
The protocol is a bit confusing wrt resets.
 

hippy

Senior Member
What I meant to say is that when I compare what is in the scratch register with what I wrote there, it is intermittently different.
That makes sense if I've got it right; what's read from the chip isn't what was written to the chip previously.

That's always a nightmare problem, like posting a letter and it not arriving at the destination; you just don't know what went wrong - did it go wrong when the letter was being picked up or when it was being delivered - and it's always hard to tell what's going on when it sometimes works and sometimes doesn't, it may depend on the address or data or maybe not, could be hardware, software or something else.

The best approach is to write the simplest test code, a simple loop which writes to a register and then reads it back, checks what's read is what's written, identify the frequency of any mis-match and see if anything those which work and those that don't have in common.

The best result is finding a case which should always work but always fails, though sometimes works and sometimes fails is useful. The minimum number of things changing between a works and doesn't is best; for example, same address, same data.

One pre-test I'd do is write a program to READOWSN the serial number, keep repeating that and checking the result to see that it does return the same data every time. Then retest with OWIN and OWOUT instead of READOWSN to check the results are the same.
 

cravenhaven

Senior Member
Tried your suggestion Westaust but no improvement.

When looking at the output data however I noticed that the problem is with bit 2 of the data byte. ie an 'E' becomes 'C'an 'A' becomes '8' a 'B' becomes '9'.

I have 2 of these chips and they both do the same.
 

zebulon

Member
Hi cravenhaven,

Just a suggestion because english is not my mother language and perhaps I don't understand all that things ...

In the "Copy Scratchpad [55h]" section of the datasheet, it is written : "A logic 0 is transmitted after the data has been
copied until the user issues a reset pulse. Any attempt to reset the part is ignored while the copy is in
progress. Copy typically takes 30microseconds
."

Are you sure there is a delay of 30 microseconds between the writing of the 3 bytes TempW0_1,TempW0_2,OW_ES and the final reset pulse ( in OWOUT command in the OW_WriteByte function after the two IF ) ? If not, the datas are perhaps not written because not validated by the final reset pulse.

Just an idea ...

Guillaume
 
Last edited:

Technical

Technical Support
Staff member
Note that when OW_ES = 2 the values are correct, any other time and they are wrong. That may tell you something...
 

cravenhaven

Senior Member
Thanks Guillaume,
I think what this means is that the device will ignore any other communications until the copy is complete.
My code doesnt allow the copy scratch to take place because the comparisons in the 'IF' statements fail.
 

cravenhaven

Senior Member
Thanks all for your effort.
After recognising that it was losing bit2 of the databyte, I ran a simple test of writing an incrementing series of numbers to EEPROM on the device and then read them back all with no error checking. The result was that bit2 is always '0'.
Strange though that both devices behave identically.
I assume it is a write error but havent been able to prove that yet.
 

boriz

Senior Member
"Is it possible to simplify the code even further, to just a few lines, which demonstrates it not working as expected ?"

This is a bugbear of mine. Posting a large program, saying it's faulty and expecting people here to wade through, reverse engineering it and trying to re-construct the logic and find the fault. It's hard work, and requires more motivation than I usually have. Perhaps a note in the 'read me first' forum etiquette sticky to the tune of Hippys statement above? Something like 'Please post a small code sample of the minimum size that demonstrates the problem'.

No offense intended to OP.
 

cravenhaven

Senior Member
Well its a bit of a dilemma. If I just put in a couple of bits where I think the problem is, then potential helpers respond with "give me the actual code you are working with".
With Westaust's attempt to help, he copied the code and ran it on the simulator, he wouldnt have been able to do this if I had only put in a partial piece of code.
As it was in this case, I had already cut out all the unnecessary modules from my program, tested it to verify the problem still existed, and copied up what I considered a simple version
 

westaust55

Moderator
Programs to test a DS1994

@cravenhaven,

just in case it is a bug in your code, though from your latest reports it seems hardware orientated, try the following:

1. Run the attached program "1-wire network improved device search" it should search for your DS1994 and any other 1-Wire device conencted and save the serial numbers into PICAXE internal EEPROM and display on the PE terminal window.
Note that YOU will need to change the #PICAXE 40X1 directive at the start of the program.

See if the numbers match those on the front of the actual DS1994 chip.

2. Run the second program. "DS1994 NV RAM 1-wire writing and reading example"
This should write data to most of the DS1994 EEPROM locations and read it back so you can verify.

I have tested tonight with an actual DS1994 and they are working.


Did you try the READOWSN command as suggested by hippy?
That effectively does much the same as the first program but only works for 1 device connected at a time and does not save the serial numbers to EEPROM.

I would need to rework you actual code to try here as my minimum 1-Wire network always has 3 devices conencted and thus I cannot use the SKIPROM command.
 

Attachments

cravenhaven

Senior Member
Thanks so much Westaust,
Your code seemed to work perfectly so what is wrong with mine.
I had observed today that if I set the clock running, some of the time registers counted all the way through without error, but others didnt (consistently). This caused me even more concern about my diagnosis.
You have now proved my suspicions correct, but what am I doing wrong?.


Code:
A DS1994 NV RAM Exists in Device List

Writing data for NV RAM page 0 to DS1994 Scratchpad

>DS2401 Silicon Serial Number   <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 1 to DS1994 Scratchpad

>DS2405 1-Chan Programmable GPIO<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 2 to DS1994 Scratchpad

>DS2406 2Ch GPIO & 128Byte EPROM<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 3 to DS1994 Scratchpad

>DS2437 Smart Battery Monitor   <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 4 to DS1994 Scratchpad

> DS2450 4-Chan  2 to 16 bit ADC <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 5 to DS1994 Scratchpad

>#DS1994 512 Byte 16 Page EEPROM <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 6 to DS1994 Scratchpad

>£DS1994 512 Byte 16 Page EEPROM <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 7 to DS1994 Scratchpad

>&DS2438 Smart Battery Monitor   <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 8 to DS1994 Scratchpad

>'DS2417 TimeClock with Interrupt<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 9 to DS1994 Scratchpad

>(DS18B20Temperature Sensor      <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 10 to DS1994 Scratchpad

>)DS2408 8-Chan Programmable GPIO<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 11 to DS1994 Scratchpad

>,DS2890 256-Step Digital Potent.<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 12 to DS1994 Scratchpad

>-DS2431 128 Byte 04 Page EEPROM <

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 13 to DS1994 Scratchpad

>:DS2413 2-Chan Programmable GPIO<

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 14 to DS1994 Scratchpad

><

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Writing data for NV RAM page 15 to DS1994 Scratchpad

><

All data now sent to Scratchpad

Retrieving and Checking Target Address and Error Register

Error Register indicates no errors.
Now reading data back for verification.

>
NV RAM indicates Valid copy from scratchpad to EEPROM memory

Reading back from NV RAM
DS2401 Silicon Serial Number   
DS2405 1-Chan Programmable GPIO
DS2406 2Ch GPIO & 128Byte EPROM
DS2437 Smart Battery Monitor   
 DS2450 4-Chan  2 to 16 bit ADC 
#DS1994 512 Byte 16 Page EEPROM 
£DS1994 512 Byte 16 Page EEPROM 
&DS2438 Smart Battery Monitor   
'DS2417 TimeClock with Interrupt
(DS18B20Temperature Sensor      
)DS2408 8-Chan Programmable GPIO
,DS2890 256-Step Digital Potent.
-DS2431 128 Byte 04 Page EEPROM 
:DS2413 2-Chan Programmable GPIO
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO
øP(o½„¼„

ALL DONE !  :-)
 
Last edited:

cravenhaven

Senior Member
Sorry, I forgot to answer your questions.
Yes the numbers match. I was already using part of your code to verify that the right chip was connected and it read the serial number without a problem. I assumed (but havent checked) that the READOWSN did the same thing.

The only changes I had to make to your code was the 40x1-20x2, and you had a CRC hard coded into your verification routine so it reported a "Wrong Device: error.

I wrote a little test routine to read through the ram and incorporated your 'strong' pullups without any success. I then changed it to set up the read before the FOR NEXT loop and then read the databytes one-at-a-time with no resets and this worked. WHY?.
Thanks
Allan
 

westaust55

Moderator
Okay, so we know the DS1994 iButtons are generally (at least the EEPROM part) working correctly.

Yes, the READOWSN reads the 8 bytes of the device serial number and stores the data in byte variables b6 to b13 inclusive.

Will not have a chance straight away but will look at your code again later over the weekend. Strip out all the debug commands so I am looking at the basic 1-Wire code and see if I can spot where things are going wrong.
 

cravenhaven

Senior Member
Thanks very much for your help Westaust, I think it is working now.
Could I get you to have a look at the 'OW_Write_Byte' routine with a view to minimising the commands. There seems to be an excess but I'm not sure which ones I should be able to combine.
I have changed the code considerably and I think it is much better and more flexible and would welcome any comments on the subroutines (the main is just for debugging).

Code:
#PICAXE 20X2
;
;EEPROM messages. 20 bytes per message
;Constants
;
SYMBOL Start_Scr_Arry	= 0
SYMBOL End_Scr_Arry	=63
SYMBOL OW_ReadRom 	=$33
SYMBOL OW_SkipRom 	=$CC
SYMBOL OW_SearchRom 	=$F0
SYMBOL OW_ReadMem		=$F0
SYMBOL OW_Writescr	=$0F
SYMBOL OW_Readscr		=$AA
SYMBOL OW_Copyscr		=$55
SYMBOL OW_Startclock	=$50	;Osc on, Stop counter
SYMBOL OW_lo_ctrl_buf	=$01	;Control register lo_byte
SYMBOL OW_lo_rtc_buf	=$03	;RTC Register lo_byte
SYMBOL OW_hi_tkr_buf	=$02	;Time Keeping Registers hi_byte
SYMBOL OW_Net		=B.0

;
;Variables
;

SYMBOL FirstByte		=b3
SYMBOL lastbyte		=b4
SYMBOL DataByte		=b5
SYMBOL OW_TA1		=b7		; Target address low byte to be issued to the 1-Wire DS1994
SYMBOL OW_TA2		=b8		; Target address high byte to be issued to the 1-Wire DS1994
SYMBOL OW_ES		=b9		; Target ending address status register for the 1-Wire DS1994
SYMBOL index		=b10		; general index used with FOR...NEXT blocks
SYMBOL Time1	= w11		;Holds latest date&time
SYMBOL   Time1_1	= b22 
SYMBOL   Time1_2	= b23
SYMBOL Time2	= w12		;Holds latest date&time
SYMBOL   Time2_1	= b24
SYMBOL   Time2_2	= b25		
;Temporary variables
SYMBOL Temp1	= b40
SYMBOL Temp2	= b41
SYMBOL Temp3	= b42
SYMBOL Temp4	= b43
SYMBOL Temp5	= b44
SYMBOL Temp6	= b45
SYMBOL Temp7	= b46
SYMBOL Temp8	= b47
SYMBOL TempW0	= w24
SYMBOL   TempW0_1	= b48
SYMBOL   TempW0_2	= b49		
SYMBOL TempW1	= w25
SYMBOL   TempW1_1	= b50
SYMBOL   TempW1_2	= b51		
SYMBOL TempW2	= w26	
SYMBOL   TempW2_1	= b52
SYMBOL   TempW2_2	= b53		
SYMBOL TempW3	= w27	
SYMBOL   TempW3_1	= b54
SYMBOL   TempW3_2	= b55		

;
; -----( Start Program )--------------------------------------------------
;
main:
	PAUSE 1000
	;set time
	Time2=$4e33
	Time1=$f5c4
loopmain:	
	ptr = Start_Scr_Arry		; set the pointer to the start of the scratchpad array
	@ptrinc=Time1_1			; create the data array
	@ptrinc=Time1_2
	@ptrinc=Time2_1
	@ptrinc=Time2_2

	OW_TA1=OW_lo_rtc_buf		; Set the RTC address
	OW_TA2=OW_hi_tkr_buf
	lastbyte=Start_Scr_Arry+3	; Setup data array access pointers for 4 bytes
	FirstByte=Start_Scr_Arry
	GOSUB OW_WriteByte

	SERTXD(CR,LF,"Reading Data from RTC",CR,LF)
	FOR index=1 to 5
		SERTXD(CR,LF)
		OW_TA1=OW_lo_rtc_buf-3	; read all time keeping registers incl status&control
		FirstByte=OW_lo_rtc_buf-3
		lastbyte=FirstByte+7
		GOSUB Display_read_data
		PAUSE 1000
	NEXT index
	random Time2
	random Time1
	SERTXD(CR,LF,CR,LF)
	GOTO loopmain
END


	; call with OW_TA1,OW_TA2 set to lo&hi address & first/lastbyte set to start end of data array
OW_WriteByte:
	SERTXD(CR,LF,"Writing Data to EEPROM",CR,LF)
	OWOUT OW_Net,%1001,(OW_SkipRom) 
	OWOUT OW_Net,%1000,(OW_Writescr,OW_TA1,OW_TA2)
	DEC lastbyte				; To allow for final write to incl reset
	FOR ptr=FirstByte to lastbyte
		DataByte=@ptr
		OWOUT OW_Net,%1000,(DataByte)
	NEXT ptr
	DataByte=@ptr				; Write last byte and reset after with pullup
	Temp2=DataByte:GOSUB Display_Reg
	OWOUT OW_Net,%1010,(DataByte)

	OWOUT OW_Net,%1001,(OW_SkipRom,OW_Readscr)		; read the scratch register back
	OWIN  OW_Net,%1000,(TempW0_1,TempW0_2,OW_ES)	;read scratch address vectors
	OWOUT OW_Net,%1001,(OW_SkipRom) 
	OWOUT OW_Net,%1010,(OW_Copyscr,TempW0_1,TempW0_2,OW_ES)	;copy scratch to RTC
RETURN

	; call with OW_TA1,OW_TA2 set to lo&hi address & first/lastbyte set to start end of data array
OW_Read_Byte:
      OWOUT OW_Net,%1001,(OW_SkipRom,OW_ReadMem,OW_TA1,OW_TA2)
	DEC lastbyte				; To allow for final Read to incl reset
	FOR ptr=FirstByte to lastbyte
		OWIN OW_Net,%1000,(DataByte)
		@ptr=DataByte
	NEXT ptr
	OWIN OW_Net,%1010,(DataByte)
	@ptr=DataByte				; Read last byte and reset after with pullup
RETURN
	
Display_Reg:		;Display a register value. Modifies Temp1, Called with register in Temp2
	Temp1=Temp2 AND $F0 /$10 + $30
	IF Temp1 > $39 THEN LET Temp1=Temp1+7
	ENDIF
	SERTXD(Temp1)
	Temp1=Temp2 AND $0F + $30
	IF Temp1 > $39 THEN LET Temp1=Temp1+7
	ENDIF
	SERTXD(Temp1)
RETURN

	
Display_read_data:	
	GOSUB OW_Read_Byte
	FOR ptr=FirstByte to lastbyte
		SERTXD(" $")
		Temp2=@ptr
		GOSUB Display_Reg
	NEXT ptr
RETURN
 
Last edited:

westaust55

Moderator
DS1994 code snippets

Hi cravenhaven.

Passing through home at the moment.
Below is a revised set of subroutines that combine some code lines and restructure others.
Saves around 25 bytes - 1-Wire control is quite "hungry" on program space.

See the couple of notes included as remarks for you.
Syntax is correct in the PE simulator but untested on an actual DS1994 as about to dash out the door again soon . . . .

Code:
; call with OW_TA1,OW_TA2 set to lo & hi address & first/lastbyte set to start end of data array
OW_WriteByte:
	SERTXD(CR,LF,"Writing Data to EEPROM",CR,LF)
	OWOUT OW_Net, %1001, (OW_SkipRom,OW_Writescr,OW_TA1,OW_TA2) 
	DEC lastbyte
	ptr = FirstByte				
	DO 
		DataByte = @ptrinc
		OWOUT OW_Net, %1000, (DataByte)
	LOOP UNTIL ptr > lastbyte
; NOTE: no need to perform a "reset after" in above loop as we do a "reset before" command in the next line	
	OWOUT OW_Net,%1001,(OW_SkipRom,OW_Readscr)		; read the scratch register back
	OWIN  OW_Net,%1000,(TempW0_1,TempW0_2,OW_ES)	;read scratch address vectors
	OWOUT OW_Net,%1001,(OW_SkipRom,OW_Copyscr,TempW0_1,TempW0_2,OW_ES)	;copy scratch to RTC
      RETURN

	; call with OW_TA1,OW_TA2 set to lo&hi address & first/lastbyte set to start end of data array
OW_Read_Byte:
      OWOUT OW_Net,%1001,(OW_SkipRom,OW_ReadMem,OW_TA1,OW_TA2)
; NOTE - consider moving this DEC comamnd in next line to calling code then you always enter Write and Read with required value for Lastbyte
      DEC lastbyte
	ptr = FirstByte				
	DO
		OWIN OW_Net, %1000, (DataByte)
		@ptrinc = DataByte
	LOOP UNTIL ptr > lastbyte
	OWIN OW_Net, %1001, (DataByte) ; just read anything if you seek to issue a reset command
; NOTE the above is not really essential/mandatory as while it leaves the current device "open"
; we should always issue a "reset before"	to get the attention of ALL devices when starting a new operation
; in case you later work with multiple devices on the 1-Wire network
      RETURN
 
Last edited:

cravenhaven

Senior Member
Thanks Westaust,
All working now and I even gained a bonus in learning how to use the scratchpad.
I still dont understand why any of it works better than in the first place;
eg. Originally I had:


Code:
OW_Write_Time:	
      OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Writescr,OW_lo_rtc_buf,OW_hi_tkr_buf,Time1_1,Time1_2,Time2_1,Time2_2)
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Readscr)						
	OWIN  OW_Net,owresetafter,(OW_TA1,OW_TA2,OW_ES,TempW0_1,TempW0_2,TempW3_1,TempW3_2)	
	IF TempW3<>Time2 OR TempW0<>Time1 THEN 			
				LET errors=1
				errormsgno=40
				GOSUB Display_Error
			ELSE 
				OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Copyscr,OW_TA1,OW_TA2,OW_ES)
				LET errors=0
	ENDIF	
RETURN
I had tried various combinations for the resets including a 'resetbefore' on the first line followed by 'noresets' and a 'resetafter' on the last line.
But whatever I tried resulted in a non-match of the data written to scratch compared to that read from scratch. Hence a failure to 'copyscratch' the data.
In essence the working solution only differs from my attempts in 2 ways:
1. I am using pullups on all commands
2. Instead of including the data in a series of variables within the OWOUT, OWIN commands, they are accessed through a stream within a do-while loop.

On both these points I see examples of where they apparently work as I originally did them.
1. I gather that the additional pullups are only required for some chips such as the DS18B20, shouldnt be required for the DS1994
2.In your code you use a string of variables when using the 'Matchrom' command.

What is it that I am not understanding?
 

westaust55

Moderator
1-wire network pull-ups and MATCHROM command use

I gather that the additional pullups are only required for some chips such as the DS18B20, shouldnt be required for the DS1994
I am not aware of any specific 1-wire devices specifically needing the use of micro-controller internal pull-up even though I use it.
My network has a fairly low pull-up resistor (around 2k2 from memory)and is a more active arrangement so I can occassionally program DS2406 EPROM (as opposed to EEPROM) chip memory.
Using the pull-up after command bit helps to pull the signal/data line high more rapidly after a data transfer by inserting some parallel resistance and thus increasing the "drive current".
Mind you the PIC/PICAXE pull-ups are relatively "weak" so the effect may be marginal.
Tentatively this (use of micro-controller pull-ups) is of more value for longer cable lengths when cable capacitance may slow the rise time to the supply voltage level.

While 4k7 as a pull up resistor is recommended for a single DS18B20, lower values can be neccessary for multiple devices and longer cable lengths.
Also some chips required more current and thus use of a lower value of external 1-Wire data line pull-up resistor can be required. Some of this is covered in my 1-Wire tutorial (thread link given previously).




In your code you use a string of variables when using the 'Matchrom' command.

What is it that I am not understanding?
The MATCHROM command allows you to select a specific 1-Wire chip/device when you have multiple devices on the 1-Wirenetwork (and in which case the SKIPROM cannot be used).
For the MATCHROM command you must send the full set of 8 bytes equal to the serial number of the desired device.

My 1-Wire demo network cosists of a base box/module and around 5 other modules that I can plug into the network.
The base module and each of the other modules each contain typically 3 1-Wire devices and the same device exists in several modules. So I have a total of up to ~25 devices including up to 4 assorted ibutton devices that can be connected at any one time.
Hence I do not use the SKIPROM command in any program I write but must use the MATCHROM command to specifically select a device.
My experience, and likely true for most folks, would be that a check for the family type and the CRC code will be sufficient to identify a particular device but this CANNOT be guaranteed under all circumstances.

Some of my programs using mutliple devices. To find the required devices the program actively sets up pointers to the serial numbers for the desired devices so I can point to the desired serial number, from multiple serial numbers, in PICAXE EEPROM as the need arises.
 

cravenhaven

Senior Member
Lost communication just as I pressed the send button, so will try again.

The info about the pullup was in the AN937 1-wire standards document and was in reference to the DS1920 which has no battery and so requires strong pullup to maintain communications. (page 81). It is a temperature sensor which is why I related it to the 18b20.

The other question which I posed badly was not meant to question your setup, but was comparing the success of your commands to the failure of mine when they look similar.
eg
Code:
      OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_ReadMem,OW_lo_rtc_buf,OW_hi_tkr_buf)
     	OWIN OW_Net,owresetafter,(Time1_1,Time1_2,Time2_1,Time2_2)
 OR

      OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Writescr,OW_lo_rtc_buf,OW_hi_tkr_buf,Time1_1,Time1_2,Time2_1,Time2_2)
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Readscr)
	OWIN  OW_Net,owresetafter,(OW_TA1,OW_TA2,OW_ES,TempW0_1,TempW0_2,TempW3_1,TempW3_2)

compared to your:

	  OWOUT OW_Net, %1001, ($55, b6, b7, b8, b9, b10, b11, b12, b13 )
They all involve transferring multiple bytes from within the one OWIN/OWOUT command but mine arent successful.
 

westaust55

Moderator
Lost communication just as I pressed the send button, so will try again.

The info about the pullup was in the AN937 1-wire standards document and was in reference to the DS1920 which has no battery and so requires strong pullup to maintain communications. (page 81). It is a temperature sensor which is why I related it to the 18b20.

The other question which I posed badly was not meant to question your setup, but was comparing the success of your commands to the failure of mine when they look similar.
eg
Code:
      OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_ReadMem,OW_lo_rtc_buf,OW_hi_tkr_buf)
     	OWIN OW_Net,owresetafter,(Time1_1,Time1_2,Time2_1,Time2_2)
 OR

      OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Writescr,OW_lo_rtc_buf,OW_hi_tkr_buf,Time1_1,Time1_2,Time2_1,Time2_2)
	OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Readscr)
	OWIN  OW_Net,owresetafter,(OW_TA1,OW_TA2,OW_ES,TempW0_1,TempW0_2,TempW3_1,TempW3_2)

compared to your:

	  OWOUT OW_Net, %1001, ($55, b6, b7, b8, b9, b10, b11, b12, b13 )
They all involve transferring multiple bytes from within the one OWIN/OWOUT command but mine aren't successful.
The line from my code:
OWOUT OW_Net, %1001, ($55, b6, b7, b8, b9, b10, b11, b12, b13 ) ; send MatchROM and device Serial number to get the attention of a specific device​

while sending a control and 8 bytes of data is in effect the same as (when a single device on the network):
OWOUT OW_Net,owresetboth,(OW_SkipRom) ; Open a comms channel to the only device on the 1-wire network​

I will have a closer look at your code and come back later . . . .
 

westaust55

Moderator
The info about the pullup was in the AN937 1-wire standards document and was in reference to the DS1920 which has no battery and so requires strong pullup to maintain communications. (page 81). It is a temperature sensor which is why I related it to the 18b20.
Okay, AN937 covers iButton standards.
in that context, iButtons are always 2 wire parasically powered devices. The DS18B20 can be operaqed as parasically powered or separately powered.
I did cover some of the concepts for max current / min voltage during conversions, writing to memory, etc, in my tutorial with a table indicating current/voltage requirements and the equivalent pull up resistor to ensure proper operation.
As already mentioned, the pull-ups in PIC/PICAXE chips are nominally "weak" (ie inferred relatively high resistance values) and thus while they may help and I do frequently use them in my code I would be considering a lower value of external 1-Wire network pull-up resistor.



With respect to your code, I had a further look but could not sight anything obvious.

You indicate your code at post 20 is working.
I tried that with a few adjustments (eg using MATCHROM in lieu of SKIPROM) and I can see the data from the DS1994 increasing as the Timer counters advance.

You code at post 1 has too many variables (as allowed with X2 parts) and thus not easily reworked to operated with a 40X1.
You had also restructured the subroutines and main loop significantly between Post 1 and Post 20 so I could not just drag the 1-Wire read and write routines into the code from post 20 and have it work properly but it did appear to be reading data back in.

For the code in post 1, I did note that you have the error flag addigned to variable b5 as is the databyte varioable.
Whethee that is/was the casue of your grief I did not pursue since my 40X1 has insufficient variables available to fully try the Post 1 code.
 

Technical

Technical Support
Staff member
There is a subtle difference that can affect one-wire operation - this code

OWOUT OW_Net,owresetboth,(OW_SkipRom,OW_Writescr,OW_lo_rtc_buf,OW_hi_tkr_buf,Time1_1,Time1_2,Time2_1,Time2_2)
OWOUT OW_Net,owresetbefore,(OW_SkipRom,OW_Readscr)

gives

reset - data bytes - reset - reset - data bytes

whilst this code is

OWOUT OW_Net, %1001, (OW_SkipRom,OW_Writescr,OW_TA1,OW_TA2)
OWOUT OW_Net, %1000, (DataByte)
OWOUT OW_Net, %1001,(OW_SkipRom,OW_Readscr) ; read the scratch register back

reset - data bytes - reset - data bytes
 

cravenhaven

Senior Member
Thats the 3rd time this thing has 'lost' my post. GRRRR!
As I said, (but in summarised form this time)
You should be able to send any number of resets provided they dont occur in the middle of a command.
If the picaxe 1-Wire command routines comply correctly with the 1-Wire timing protocols then a command issued with all-in-one should have a better chance of success than one executed in pieces
ie
OWOUT Ownet,%1011,(skiprom,writescratch, data1,data2,......datax)

should be more reliable than
OWOUT Ownet,%1001,(skiprom,writescratch)
FOR X=1 TO N
OWOUT Ownet,%1000,(datax)
NEXT X

Which is the point I'm trying to understand.
 

westaust55

Moderator
You should be able to send any number of resets provided they dont occur in the middle of a command.
Understand what you are trying to do however your comment (above) is not correct.

If you want to read from a 1-Wire device, there are several steps:
1. Generate a reset and select the device (SKIPROM or MATCHROM)
2. Send (OWOUT) the address or other data to set up the pointer or action
3. Read back (OWIN) the data.
4. Generate a new reset if desired - not essential

You cannot perform a reset after the start of set 1 and before the end of step 3 otherwise you have closed the comms channel to the desired device and data will not be sent/received.

You can put steps 1 and 2 above into a single OWOUT command line if desired.
 

cravenhaven

Senior Member
For the code in post 1, I did note that you have the error flag addigned to variable b5 as is the databyte varioable.
Whethee that is/was the casue of your grief I did not pursue since my 40X1 has insufficient variables available to fully try the Post 1 code.
Hmmm! that was definitely an error, they should have used different variables but I dont think it would have caused an error. It would have made the debugging more confusing though, because I compare the databyte with a memory read after I have sent an error message.
 
Top