Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 09:42 29 Nov 2024 Privacy Policy
Jump to

Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.

Forum Index : Microcontroller and PC projects : DS3231 code mmbasic

     Page 1 of 3    
Author Message
atmega8

Guru

Joined: 19/11/2013
Location: Germany
Posts: 722
Posted: 06:55am 07 Mar 2014
Copy link to clipboard 
Print this post

Hello,

has anyone a working DS3231 code for micromite?

Would be nice if you could post it here.


Thanks
 
jwettroth

Regular Member

Joined: 02/08/2011
Location: United States
Posts: 71
Posted: 09:05am 07 Mar 2014
Copy link to clipboard 
Print this post

I'm working on one. Should have it done over the weekend and will post.
John Wettroth
 
jman

Guru

Joined: 12/06/2011
Location: New Zealand
Posts: 711
Posted: 09:53am 07 Mar 2014
Copy link to clipboard 
Print this post

Hi
The DS3231 has the same address and register layout as the DS1307
there is code in the forums to use the DS1307
I have attached code that will run on the uMite

Regards
Jman2014-03-07_195259_umiteDs1307.zip Edited by jman 2014-03-08
 
jwettroth

Regular Member

Joined: 02/08/2011
Location: United States
Posts: 71
Posted: 10:09am 07 Mar 2014
Copy link to clipboard 
Print this post

jman- this is partially true- the first 6 registers for basic time are the same. The configuration registers, alalmr registers and all the other special goodies are different. Bascially, all the things that make the DS3231 unique over the DS1307 are at higher addresses (these are just RAM in the 1307 which isn't present in the DS3231).

I will start with that 1307 code but plan to expand on it signficantly. I'm especially looking forward to using the alarms- I want to put the micromite to sleep and have an alarm or timer tick wake it up.

Another cool feature is that the DS3231 has an internal temperature register in it. I'm going to read out and display that value and use a DS18B20 for external temp. The project is just sort of a battery operated desk clock with internal and external temp that never needs setting.

Thanks for the link- the DS3231 is a pretty cool part. Stay tuned. Edited by jwettroth 2014-03-08
John Wettroth
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 10:55am 07 Mar 2014
Copy link to clipboard 
Print this post

Here is some code to read and interpret the temperature and Aging Offset register functions of the DS3231
If RTCdata(17) < &h80 Then
Temperature = RTCdata(17) + (RTCdata(18) / 256)
Else
Temperature = -(((RTCdata(17) Xor &hFF) + 1) + (RTCdata(18) / 256))
EndIf
t$=Format$(Temperature,"%+6.2f")
Print "Temperature is "; T$; "degrees Celsius"

If RTCdata(16) < &h80 then
Offset = RTCdata(16)
Else
Offset = -((RTCdata(16) Xor &hFF) +1)
Endif
Print "The Aging Offset data is "; Offset


disclaimer: This is Maximite code written several years back. It may be different for MicroMite.


Edited by BobD 2014-03-08
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 01:15pm 07 Mar 2014
Copy link to clipboard 
Print this post

My 3231 + EEPROM modules arrived last week, so I must hook one up and try it.
It will be a chance to play with both devices on the I2C bus, and also test out Beta 10, where Geoff removed the slew rate to fix a bug, and see if this causes any problems. However, I would be inclined to second-guess any faults, as I am only a novice with I2C.

I will see if I can find time to do this over the weekend some time.
Smoke makes things work. When the smoke gets out, it stops!
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 01:40pm 07 Mar 2014
Copy link to clipboard 
Print this post

I also have the DS3231 with EEPROM and I intend to store the Aging Offset in the EEPROM with the idea to retrieve it and reload it if necessary. I hope to experiment to see if a correction can be applied to achieve better accuracy. I have a bit of work ahead, my MM has been powered off for about 18 months and I am not (yet) into the MicroMite.
 
jwettroth

Regular Member

Joined: 02/08/2011
Location: United States
Posts: 71
Posted: 01:44pm 07 Mar 2014
Copy link to clipboard 
Print this post

Bob,
Let me know what you learn and if you run into problems.

John
John Wettroth
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 09:18pm 07 Mar 2014
Copy link to clipboard 
Print this post

I'm lost already with the I2C.
How do you specify the read-write address in the device?
This is NOT the slave-address for the device, but the actual registers that you want to alter within the device?

Do I just send two bytes?
Byte 1 is the register, and byte 2 is the data to be written to that register?


At this stage, just trying to write $00(h00) into address $0E on the 3231, which is the square-wave output. By default and without battery, it is 32kHz, but if you write $00 into address $0E on the 3231, this output changes to 1Hz, which I have an LED connected to.

I DID get this working in PICAXE basic a year or two ago, but not sure how to port this to the uM...

PICAXE code was:

'DS3232 tester 1A

#picaxe 40x2
#no_table
#no_data

symbol x=b1
symbol key=b2
symbol video=D.2

hi2csetup i2cmaster,%11010000,i2cfast,i2cbyte 'Configure I2C for RTC communications

wait 5 'Allow LCD screen to fire up

serout video,T9600_8,("Talking to clock...",CR,CR)
hi2cout $0E,($00) 'Set RTC to pulse LED at 1Hz
serout video,T9600_8,("Done.",CR)


end


Things don't jive here. With PICAXE, you specify the start read/write address within the device, then the byte(s) to write. MMBasic does not allow for specifying a read/write address within the device for your data, so how do you specify that?

Hello MOBI. Yes, confused already...

EDIT: Have been reading through the code example for MM posted in the link above, but still can't see how you can specify a register address to read or write to within any given device. This MUST be possible, I am just not seeing it, as EEPROM memory is a fine example of needing to read/write to different memory addresses.Edited by Grogster 2014-03-09
Smoke makes things work. When the smoke gets out, it stops!
 
TassyJim

Guru

Joined: 07/08/2011
Location: Australia
Posts: 6102
Posted: 09:54pm 07 Mar 2014
Copy link to clipboard 
Print this post

  Grogster said   I'm lost already with the I2C.
How do you specify the read-write address in the device?


It all depends on the device.

For the BMP085 pressure transducer, I do the following:

I2C write BMP085address, 0, 2, BMP085control, BMP085temp
pause 5
I2C write BMP085address, 0, 1, BMP085reading
I2C read BMP085address, 0, 2, BMPData(0)


The first line sends the 'control byte' followed by the control I want to send
we wait for the conversion to happen
then send the message that we want to read

Finally we read the two bytes of data into the array.

I haven't tried an EEPROM yet but usually you will send 1 or 2 bytes for the address followed by one or more data bytes. The EEPROM usually auto increments the write address.

The ones I will be playing with allow 64 bytes to be written at once.

Jim
VK7JH
MMedit   MMBasic Help
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 09:58pm 07 Mar 2014
Copy link to clipboard 
Print this post

WORKING!

I have my 1Hz blinking LED on the SQW output pin.

Will post code etc in a moment......

EDIT: OK, here is a screenshot of the code on the uM:



I started reading my way through the datasheet for the 3231, and naturally enough - it was all explained there - funny that....

In the case of the 3231, you send the slave address byte, followed by a register address byte, followed by the data you want to read or write to that register.

Above code sets register $0E to $00, which causes the SQW output to oscillate at 1Hz for my "Ticking" LED.
Edited by Grogster 2014-03-09
Smoke makes things work. When the smoke gets out, it stops!
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 10:20pm 07 Mar 2014
Copy link to clipboard 
Print this post

Hi Grogster,

=====
edit-
it looks like we were working in parallel
======

one step at a time.

First thing to remember is the device address for MM Basic is a 7 bit address not 8 bit like the picaxe. MM i2c uses bits 1 to 7 only and leaves bit 0 as a data direction bit called read/write, where a 0 is write to slave and a 1 is read from the slave. So, as far as the device address is concerned, call bit 1 bit 0 and so on. You will probably find it easier to use binary address form e.g. &b0011100 in MM would have been &b00111000 (8 bits) in PICaxe.

The next thing to remember is that the i2c slave has a number of internal registers or addresses usually starting at zero. Each register has a device specific function.
In the RTC, address 0 is the seconds register that you can read from or write to (set time).

If we want to read the seconds data, we first have to write a start address of zero. Subsequent reads will read from the next address (minutes) etc. MaxiMite allowed us to specify the start address as part of the read routine, but not in uMite.

To do anything on the i2c bus, you first must activate or open the i2c function. You do this by the command i2c open,100,100. Never mind the reason for now, just use it.

So, if you want to read the seconds, first point to the seconds (zero) register:

i2c write device_address,0,1,0

where i2c write specifies data direction (master to slave).
device_address is the 7 bit address,
0 is a special MM control. Just use it, don't try and understand yet,
1 says you have 1 byte to send, and
0 is the device register byte you want to access (in this case RTC seconds)

i2c read device_address,0,1,value

where i2c read specifies the data direction (slave to master)
device_address is the same 7 bit address,
0 is the same MM control,
1 is the number of bytes to receive, and
value is the variable you want the received data to appear in. In this case, it could be Secs.

There is a special MM value called MM.i2c which returns a 1 if the i2c function failed or a 0 if it worked, so...

Try and write a simple programme to read the seconds data and after each i2c read/write command, include "print MM.i2c" (not the quotes) and followed by an END

See what you get. (I think I got the above right I'm being pounded by wind turbines at the moment and thinking is not easy)
Edited by MOBI 2014-03-09
David M.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 10:27pm 07 Mar 2014
Copy link to clipboard 
Print this post

  MOBI said  So, if you want to read the seconds, first point to the seconds (zero) register:

i2c write device_address,0,1,0

where i2c write specifies data direction (master to slave).
device_address is the 7 bit address,
0 is a special MM control. Just use it, don't try and understand yet,
1 says you have 1 byte to send, and
0 is the device register byte you want to access (in this case RTC seconds)


...but opening I2C for writing, at address zero, writing one byte, and that byte is zero, would that not reset the seconds register? If you want to READ from the device, how come you have to open for WRITE first?
Smoke makes things work. When the smoke gets out, it stops!
 
MOBI
Guru

Joined: 02/12/2012
Location: Australia
Posts: 819
Posted: 10:45pm 07 Mar 2014
Copy link to clipboard 
Print this post

  Quote  
...but opening I2C for writing, at address zero, writing one byte, and that byte is zero, would that not reset the seconds register? If you want to READ from the device, how come you have to open for WRITE first?


If you want to read from an i2c slave, you can do it two ways. If you just send the code:

i2c read,0,1,value

it will read the value of the register last pointed to, so it you had previously just read the seconds (reg 0), your read pointer would now be at register 1.

If you want to specify the register to start reading from, you must send (write) just the register number.

All i2c write commands send a start address first e.g.

i2c write device_address,0,start_register,number _of Bytes_to _send...bytes to send
David M.
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 10:53pm 07 Mar 2014
Copy link to clipboard 
Print this post

OK, trying to write your suggested routine, for the purposes of experimentation and learning.

This is what I have:



How come A$, which should be the value of whatever seconds is, is always zero?
Should it not be incrementing each time I read it?
Smoke makes things work. When the smoke gets out, it stops!
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 11:07pm 07 Mar 2014
Copy link to clipboard 
Print this post

Grogster,
val(A$) is 0 because there is not a valid numeric in that variable. You have to format the data from the clock. The data in the time registers is two 4 bit numbers which each have to be converted to decimal and added together.
I will post some code when I can find it but I think one of the Johns posted some a couple of days back which will have the details.
Bob
 
BobD

Guru

Joined: 07/12/2011
Location: Australia
Posts: 935
Posted: 11:11pm 07 Mar 2014
Copy link to clipboard 
Print this post

I have found some code to interpret the RTC time and date data. This does not apply to all data in the DS3231. Read the datasheet.
Seconds = (RTCdata(0) and &h70)\16*10 + (RTCdata(0) and &h0f)
Minutes = (RTCdata(1) and &h70)\16*10 + (RTCdata(1) and &h0f)
Hours = (RTCdata(2) and &h70)\16*10 + (RTCdata(2) and &h0f)
DoW = RTCdata(3) and &h07
Date = (RTCdata(4) and &h30)\16*10 + (RTCdata(4) and &h0f)
Month = (RTCdata(5) and &h10)\16*10 + (RTCdata(5) and &h0f)
Year = (RTCdata(6) and &hf0)\16*10 + (RTCdata(6) and &h0f)

 
jman

Guru

Joined: 12/06/2011
Location: New Zealand
Posts: 711
Posted: 11:21pm 07 Mar 2014
Copy link to clipboard 
Print this post

I2C write I2caddr, 0, 1, 0
I2C Read i2caddr, 0, 8, RTCbuff(0)

This will set the address to start reading at 0
then read the contents of 0 thru 7 to RTCbuff(0)


Regards

Jman
 
Grogster

Admin Group

Joined: 31/12/2012
Location: New Zealand
Posts: 9308
Posted: 11:44pm 07 Mar 2014
Copy link to clipboard 
Print this post

OK, tried a little more on this - reading into an array is rejected.



I suspect that this is perhaps because there was mention that the RTC code supplied in the zip was meant for a MM, not a uM, so that might explain why it does not want to behave as expected.

EDIT: I might have a play with the EEPROM chip now - getting frustrated with the RTC.
This is not to say I am ready to give up on it - far from it - just want to try the other chip on the same module. Edited by Grogster 2014-03-09
Smoke makes things work. When the smoke gets out, it stops!
 
JohnS
Guru

Joined: 18/11/2011
Location: United Kingdom
Posts: 3816
Posted: 11:55pm 07 Mar 2014
Copy link to clipboard 
Print this post

  Grogster said   OK, trying to write your suggested routine, for the purposes of experimentation and learning.

This is what I have:



How come A$, which should be the value of whatever seconds is, is always zero?
Should it not be incrementing each time I read it?


Try ASC(A$) or if A$ is an array then ASC(A$(index)) where index is the element number you want.

By way of example, suppose A$ was a space. VAL(A$) would be 0. ASC(A$) would be 32 (because the ASCII value of a space is 32).

JohnEdited by JohnS 2014-03-09
 
     Page 1 of 3    
Print this page
© JAQ Software 2024