News:

Let's find out together what makes a PIC Tick!

Main Menu

PROBLEM RTC DS1302 DOES NOT WORK WITHOUT POWER

Started by superpro, Aug 22, 2022, 02:09 PM

Previous topic - Next topic

superpro

USING THE PIC 16F877A, WITH THE DS1302 MODULE, AND ITS BACKUP BATTERY, WHEN IT RUNS OUT OF POWER FROM THE SOURCE, IT RETURNS TO THE PROGRAMMING TIME, AND NOT TO THE UPDATE TIME.
Device = 16F877A
        Xtal = 20
       
LCD_DTPin = PORTD.4
LCD_RSPin = PORTD.0
LCD_ENPin = PORTD.1
LCD_Interface = 4 ' 4-bit Interface
LCD_Lines = 2 ' 2-Line LCD
LCD_Type = 0 ' Alphanumeric LCD type

Dim RTCCMD As Byte

Dim TEMP As Byte
Dim TEMP1 As Byte
Dim TIMEDATA[6] As Byte
Dim OLDSECONDS As Byte
Dim SECONDS As timedata#0
Dim MINUTES As timedata#1
Dim HOURS As timedata#2
Dim DATE As timedata#3
Dim MONTH As timedata#4
Dim YEAR As timedata#5
        TRISB=0
        PORTB=0
'Define registers
Symbol SECREG = %00000
Symbol MINREG = %00001
Symbol HRSREG = %00010
Symbol DATEREG = %00011
Symbol MONREG = %00100
Symbol YRREG = %00110
Symbol CTRLREG = %00111
Symbol BRSTREG = %11111
       
        Symbol CLK = PORTA.0
Symbol DTA = PORTA.1
Symbol RST = PORTA.2

' Time setup data held in eeprom memory
PRST EData $00,$58,$12,$14,$05,$22

All_Digital = True
Cls
       
' Clear Write Protect bit in control register of DS1302
TEMP = $10
RTCCMD = CTRLREG
GoSub DS1302_WRITE

' Pre-set the time registers using a data table stored in eeprom memory
For TEMP1 = 0 To 5
TEMP = ERead PRST + TEMP1
RTCCMD = TEMP1
GoSub DS1302_WRITE
Next

TEMP = $80
RTCCMD = CTRLREG
GoSub DS1302_READ

'Only Displays on the LCD if the seconds have changed
While 1 = 1
GoSub DS1302_READ
If OLDSECONDS <> SECONDS Then
Print At 1,1, "TIME ", Hex2 HOURS,":",Hex2 MINUTES,":",Hex2 SECONDS
Print At 2,1, "DATE ", Hex2 DATE,"/",Hex2 MONTH,"/",Hex2 YEAR


    EndIf

Wend
'-----------------------------------------------------------------------------------
' Write to DS1302 RTC
DS1302_WRITE:
High RST
SHOut DTA, CLK, LsbFirst, [%0\1,RTCCMD\5,%10\2,TEMP\8]
Low RST
Return
'-----------------------------------------------------------------------------------
' Read from the DS1302
DS1302_READ:
High RST
SHOut DTA, CLK, LsbFirst, [%111111\6,%10\2]
OLDSECONDS = SECONDS
SHIn DTA, CLK, LsbPre, [SECONDS,MINUTES,HOURS,DATE,MONTH,YEAR,YEAR]
Low RST
Return

RGV250

#1
Hi,
If I understand you question correctly you need to load the program and run once, then comment out this bit of code
' Time setup data held in eeprom memory
PRST EData $00,$58,$12,$14,$05,$22

All_Digital = True
Cls
       
' Clear Write Protect bit in control register of DS1302
TEMP = $10
RTCCMD = CTRLREG
GoSub DS1302_WRITE

' Pre-set the time registers using a data table stored in eeprom memory
For TEMP1 = 0 To 5
TEMP = ERead PRST + TEMP1
RTCCMD = TEMP1
GoSub DS1302_WRITE
Next
And then download and run it again. What is happening every time you power up you reload these values. There is probably a neater way of doing it but you get the idea.
Probably leave the all digital = true, not sure if that is needed anymore in the latest compiler and the cls.

Bob

superpro

when you write to memory it is the beginning, then it should keep working by itself. Even if you don't have power, that's what the backup battery is for.

RGV250

Maybe I miss-understood, are you only taking the power off the RTC? If you take it off the PIC as well it will run the code and reload the old values to the RTC.

Bob

superpro

without disconnecting the rtc, nor its battery, it does not continue working, when resuming the power supply it starts from what is in the main routine.
now have pic16f877A + rtc with batery 3,3v

RGV250

Hi,
I am still having difficulty with this, are you removing the power from the PIC, if so it will revert back to the time set in the code.

Bob

top204

#6
Bob is correct, in that if the microcontroller is also powered off, it will go through the motions of setting the time and date again when it powers up, regardless if the RTC needs it.

I've worked around that many times by first reading the RTC, and if the Year, Month or Date are not zero, then do not re-set the time and date. However, if they are all zero, then the RTC has lost power or has just been started up, so set the time and date on it, because they always power up with the internal registers set to zero. For example:

'------------------------------------------------------------------------------------------------
' Write the time and date to the DS1302 device if it is required
' Input     : RTC_bSecond holds the seconds value
'           : RTC_bMinute holds the minutes value
'           : RTC_bHour   holds the hour value
'           : RTC_bDay    holds the day of the week value
'           : RTC_bDate   holds the date value
'           : RTC_bMonth  holds the month value
'           : RTC_bYear   holds the year value
' Output    : None
' Notes     : Reads the DS1302 first, and if the year and month and date are all 0, then write the date and time to it.
'
Proc DS1302_SetDateTime_IfReq()
    DS1302_GetDate()                                            ' Read the date from the DS1302 device
    If RTC_bYear = 0 Then                                       ' Is the year value 0?
        If RTC_bMonth = 0 Then                                  ' Yes. So is the month value 0?
            If RTC_bDate = 0 Then                               ' Yes. So is the date value 0?
                DS1302_SetDateTime()                            ' Yes. So set the date and time
            EndIf
        EndIf
    EndIf
EndProc

If the application is not using the date, and only time, do the same, but with the Hour, Minute and Second values, because they will all be zero when the DS1302 is first powered up, and if they are not zero, the RTC is still working so do not re-set the time.

I created a library for the DS1302 RTC device a while ago, so I will tidy it and place it on my web site later today. Below is a screenshot of the DS1302 library working in the simulator. It may help you get a better feel for the device:

DS1302 - RTC.jpg

top204

What compiler version are you using?

In your code, you have the LCD setups, but without the preceding Declare texts, and that has not been valid in the compiler for many years now! They need Declare directives or the compiler gives an error message.

For example:
LCD_DTPin = PORTD.4   
LCD_RSPin = PORTD.0
LCD_ENPin = PORTD.1
LCD_Interface = 4
LCD_Lines = 2
LCD_Type = 0


If not using the latest compiler, it is rather pointless asking questions on the forum, because the answers given will be for the latest Positron compilers and not valid for old compiler versions. For example, the DS1302 library I have created will not work on that compiler at all!


superpro

Hello friends, I have been using several examples, such as the one I upload below, but all of them do not discriminate when the rtc is already working.
Declare Reminders = Off
    Device = 16F877A
    Declare Xtal = 20
    Declare Optimiser_Level = 1

    Declare LCD_DTPin = PORTD.4
    Declare LCD_RSPin = PORTD.1
    Declare LCD_ENPin = PORTD.0
    Declare LCD_Interface = 4               ' 4-bit Interface
    Declare LCD_Lines = 2                   ' 2-Line LCD
    Declare LCD_Type = Alphanumeric         ' Alphanumeric LCD type
'
' Define the pins to use for the DS1302 chip
'
$define DS1302_Clk_Pin PORTA.0              ' Connects to the DS1302 CLK pin
$define DS1302_VO_Pin  PORTA.1              ' Connects to the DS1302 VO pin
$define DS1302_Rst_Pin PORTA.2              ' Connects to the DS1302 RST pin
'
' Define DS1302 registers
'
$define cReg_Seconds $00
$define cReg_Minutes $01
$define cReg_Hours   $02
$define cReg_Date    $03
$define cReg_Month   $04
$define cReg_Year    $05
$define cReg_Ctrl    $07
$define cReg_Brst    $1F
'
' Create some variables for the demo
'
    Dim Global_bRTC_Command As Byte
    Dim Global_bRTC_Value   As Byte
    Dim Global_bOldSeconds  As Byte

    Dim Global_bTimeData[6] As Byte
    Dim Global_bSeconds     As Global_bTimeData#0
    Dim Global_bMinutes     As Global_bTimeData#1
    Dim Global_bHours       As Global_bTimeData#2
    Dim Global_bDate        As Global_bTimeData#3
    Dim Global_bMonth       As Global_bTimeData#4
    Dim Global_bYear        As Global_bTimeData#5

' Time setup data held in flash memory
'
    Dim PRST As Code = $00, $00, $12, $20, $03, $22

'-----------------------------------------------------------------------------------
' Write to DS1302 RTC
' Input     : pCommand holds the command to send to the RTC device
'           : pValue holds the value to send to the RTC device
' Notes     : None
'
Proc DS1302_Write(pCommand As Byte, pValue As Byte)
    High DS1302_Rst_Pin
    SHOut DS1302_VO_Pin, DS1302_Clk_Pin, LsbFirst, [%0\1, pCommand\5, %10\2, pValue\8]
    Clear DS1302_Rst_Pin
EndProc

'-----------------------------------------------------------------------------------
' Read from the DS1302 RTC
' Input     : None
' Output    : Global_bTimeData array is filled with the time values
' Notes     : None
'
Proc DS1302_Read()
    High DS1302_Rst_Pin
    SHOut DS1302_VO_Pin, DS1302_Clk_Pin, LsbFirst, [%111111\6, %10\2]
    Global_bOldSeconds = Global_bSeconds
    SHIn DS1302_VO_Pin, DS1302_Clk_Pin, LsbPre, [Global_bSeconds,_
                                                 Global_bMinutes,_
                                                 Global_bHours,_
                                                 Global_bDate,_
                                                 Global_bMonth,_
                                                 Global_bYear,_
                                                 Global_bYear]
    Clear DS1302_Rst_Pin
EndProc

'-----------------------------------------------------------------------------------
Main:
    Cls
'
' Clear the Write Protect bit in control register of DS1302
'
    DS1302_Write(cReg_Ctrl, $10)
'
' Pre-set the time registers using a data table stored in flash memory
'
    For Global_bRTC_Command = cReg_Seconds To cReg_Year
        Global_bRTC_Value = CRead8 PRST[Global_bRTC_Command]
        DS1302_Write(Global_bRTC_Command, Global_bRTC_Value)
    Next
'
' Only Displays on the LCD if the Seconds have changed
'
    Do
        DS1302_Read()
        If Global_bOldSeconds <> Global_bSeconds Then
            Print At 1, 1, "Time ", Hex2 Global_bHours,":", Hex2 Global_bMinutes, ":", Hex2 Global_bSeconds
            Print At 2, 1, "Date ", Hex2 Global_bDate, "/", Hex2 Global_bMonth, "/", Hex2 Global_bYear
        EndIf
    Loop

superpro

there is another error that is not updating the year, it is still at 00, and the data cannot be saved.

Ivano

#10
Good evening, dear Superpro,
I have used the DS1307 and the DS3231 but the principle of operation is about the same and I have never had any problems.
If you enter the date and time settings in the program, every time you give it power it sets the date and time and time of the
  table.
Use the example of Les checking if the time and date starts from 0 or create a procedure to set the date and time during the execution of the program if you need it, using buttons.
Read the registers in the datasheet carefully.
Sorry google translator.

superpro


superpro

#12
THIS PROGRAM IS SAVING THE DATA
 !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Declare Bootloader = off
Device 16F877A
Config hs_osc,wdt_off,pwrte_on,BODEN_On,LVP_OFF

 
Declare Xtal = 20
Declare Slow_Bus 0
Declare LCD_Type 0
Declare LCD_DTPin PORTD.4
Declare LCD_ENPin PORTD.0
Declare LCD_RSPin PORTD.1
Declare LCD_Interface 4
Declare LCD_Lines 2
All_Digital = true
Symbol Button1   PORTB.1  ; mode
Symbol Button2   PORTB.2   ; settings
Symbol Button3   PORTA.2   ; hour - backlight
Symbol Button4   PORTA.3   ; minute
Symbol Button5   PORTA.4   ; relay 4
Symbol ldr       PORTC.6   ; ldr
Symbol backlight PORTB.1   ; backlight LCD
Symbol Relay1    PORTC.0   ; Relay 1
Symbol Relay2    PORTC.1   ; Relay 2
Symbol Relay3    PORTC.2   ; Relay 3
Symbol Relay4    PORTC.3   ; Relay 4
Declare SDA_Pin  PORTA.0   ; I2C SDA
Declare SCL_Pin  PORTA.1   ; I2C SCL

TRISC=%11110000
TRISB=%10000000

Symbol Cont1 %11010000        ; write adres DS1307
Symbol Cont2 %11010001        ; read  adres DS1307
Dim timer3_on          As Bit ;
Dim relay4_on          As Bit ;
Dim on_screen          As Bit ;
Dim ldr_pin            As Bit ;
Dim ldr_pin_old        As Bit ;
Dim backlight_timer_on As Bit ;
Dim LDR_on             As Bit ;
Dim relay1_activ       As Bit ;
Dim relay2_activ       As Bit ;
Dim relay3_activ       As Bit ;

Dim uur              As Byte  ; Time 10:00:00
Dim minuut           As Byte  ; Time 00:10:00
Dim seconden         As Byte  ; Time 00:00:10
Dim write_uur        As Byte  ; write to eeprom - once a hour
Dim delay            As Byte  ; Delaytime
Dim delay1           As Byte  ; Delay to turn on/off relays
Dim mode             As Byte  ; Menus
Dim settings         As Byte  ; Menus
Dim alarm1_uur       As Byte  ' Alarm time for relay 1/2/3
Dim Alarm1_min       As Byte  ' Alarm time for relay 1/2/3
Dim alarm2_uur       As Byte  ' Alarm time for relay 4
Dim alarm2_min       As Byte  ' Alarm time for relay 4
Dim Alarm1_mode      As Byte  ' start var for delay
Dim timer3_          As Byte
Dim timer_backlight  As Byte
Dim up_min           As Byte
Dim up_uur           As Byte
Dim temp             As Byte
Dim temp_            As Byte
Dim Alarm1_delay     As Byte
Dim x                As Byte
Dim onetime          As Byte
Dim memory           As Byte

'IR variable -------------------------------------------------------------------
Dim RF_Data       As Byte     ' Holds 8-bit data byte
Dim RF_Adres      As Byte     ' Holds 5-bit hardware address
Dim adr3          As Byte     ' Holds "Hardware" address
RF_Data = $FF
RF_Adres = %00000
'-------------------------------------------------------------------------------

adr3               = %11111    ; hardware address
delay              = 2         ; instelbaar~ delay in mode 3/4 licht/donker
delay1             = 2         ;
mode               = 1
settings           = 1
relay4_on          = 0
on_screen          = 1
alarm1_uur         = 0
Alarm1_min         = 0
alarm2_uur         = 0
alarm2_min         = 0
Alarm1_mode        = 0
timer3_            = 0       ; 5 sec pauze na mode
timer3_on          = 0       ;
timer_backlight    = 0       ; backlight lcd
backlight_timer_on = 0       ; backlight lcd timer
ldr_pin_old        = 0       ;
x                  = 0
onetime            = 0
relay1_activ       = 0
relay2_activ       = 0
relay3_activ       = 0
memory             = 0

DelayMS 500              ; wait
;//////////////////////////////////////////////////////////////////////////////
;////// CUSTOM CHAR LCD////////////////////////////////////////////////////////
Print $fe, $40,14,17,17,17,14,10,14,0
Print $fe, $48,14,31,31,31,14,10,14,0
Print $fe, $50,6,12,24,24,24,12,6,0
Print $fe, $58,10,21,14,31,14,21,10,0
Print $fe, $60,3,2,26,10,10,12,8,0

;//////////////////////////////////////////////////////////////////////////////
;////// INIT DS1307 ///////////////////////////////////////////////////////////
BusOut Cont1, $00, [$00] ; sec to zerro
BusOut Cont1, $07, [$00] ; Oscillator enabled
BusOut Cont1, $02, [$00] ; 12/24 hour clock
DelayMS 10               ; wait

;//////////////////////////////////////////////////////////////////////////////
;////// INIT MAINPROGRAM///////////////////////////////////////////////////////
 temp = ERead 0                                   ; read adres 0 eeprom
 If temp = 1 Then                                 ; if 0 first time
   seconden = 0                                   ; put seconds to zero
   GoSub READ_FROM_EEPROM                         ; read from eeprom
   delay1 = delay                                 ; store delay-time
   If mode = 1 Then GoSub RELAY_OFF               ; turn Off relays If mode = 1
   If mode = 2 Then GoSub RELAY_ON                ; turn on relays if mode = 2
   If mode > 2 And LDR_on = 1 Then GoSub RELAY_ON ; and if mode > 2 and when the sun is down
   temp = minuut                                  ; store minute
   GoSub FIX_BCD_OUT                              ; dec to bcd
   BusOut Cont1,$01,[temp]                        ; write to ds1307
   temp = uur                                     ; ''
   GoSub FIX_BCD_OUT                              ; dec to bcd
   BusOut Cont1,$02,[temp]                        ; write to ds1307
   DelayMS 100                                    ; wait
 EndIf
 write_uur = uur + 1                              ; hour + 1 to store in Eeprom

;//
;//////////////////////////////////////////////////////////////////////////////
;////// MAIN SOURCE ///////////////////////////////////////////////////////////
  Cls                                             ; reset lcd
  Low backlight                                   ; backlight off

MAIN:
  If on_screen = 1 Then GoSub GET_TIME                 ; get time ds1307
  If on_screen = 1 Then GoSub TO_SCREEN                ; update LCD
  If settings = 1 And Button1 = 0 Then GoSub MENU_MODE ; button 1 pressed

  ; Relay status after button1 = mode
    If timer3_on = 1 And timer3_ = seconden Then 
      timer3_on = 0
      Alarm1_mode = 0
      If mode = 1 Then GoSub RELAY_OFF
      If mode = 2 Then GoSub RELAY_ON
      If mode > 2 Then
        If LDR_on = 1 Then
  GoSub RELAY_ON
Else
          GoSub RELAY_OFF
EndIf
      EndIf
    EndIf

; button2 pressed
  If Button2 = 0  Then                               
    settings = settings + 1
    Print $fe, 1
    on_screen = 0
    temp = 1
    GoTo MENU_SET
  EndIf

; button 3  - backlight
;           - hour - hour alarm 1 - hour alarm 2 - > pos hardware adres
; button 4  - min -  min alarm 1 - min alarm 2 - delay - hardware adres - memory reset

  If settings > 1 And Button3 = 0 Then GoTo MENU_UUR     
  If settings > 1 And Button4 = 0 Then GoTo MENU_MINUUT   
  If settings = 1 And Button3 = 0 Then GoSub menu_backlight
 
; Relay 4 on/off button 5
  If Button5 = 0 Then                               
    GoSub menu_backlight
    If Relay4 = 1 Then
      Relay4 = 0
      relay4_on = 0
    Else
      Relay4 = 1
      relay4_on = 1
    EndIf
    DelayMS 300
  EndIf

; ldr check in mode 3/4
  If on_screen = 1 Then GoSub ldr_CHECK                   

; Alarm1 on? and time? turnoff relays!
  If alarm1_uur = uur And Alarm1_min = minuut And mode = 4 Then GoSub RELAY_OFF

; delay in mode 3 and 4 - and only when swap between daylight or moonlight
  If Alarm1_mode = 1 And mode > 2 Then
    If Alarm1_delay <> minuut Then
      delay = delay - 1
      Alarm1_delay = minuut
    EndIf
  EndIf
  If delay < 0 Or delay > 20 Then
    Alarm1_mode = 0
    delay = delay1
    If mode = 3 Then
      If LDR_on = 1 Then
        GoSub RELAY_ON
      Else
        GoSub RELAY_OFF
      EndIf
    EndIf
    If mode = 4 And LDR_on = 1 Then
        GoSub RELAY_ON
      EndIf
  EndIf
 
;Alarm 2 on? and time? turn relay 4 off
  If Relay4 = 1 Then
    If alarm2_uur = uur Then
      If alarm2_min = minuut Then
        Relay4 = 0
        relay4_on = 0
      EndIf
    EndIf
  EndIf

; Backlight timer 15 sec
  If backlight_timer_on = 1 Then                 ;backlight
    If timer_backlight = seconden Then
      backlight_timer_on = 0
      Low backlight
    EndIf
  EndIf

' Decode ir signals 
  GoTo RF_Decoder
   
; back to start
  GoTo MAIN
End

'/////////////////////////////////////////////////
'//////writings to LCD

TO_SCREEN:
  Print $fe, 2, Dec2 uur, ":", Dec2 minuut, ":", Dec2 seconden, " ", Dec2 delay, "    "
  If LDR_on = 1 Then
    Print $02
  Else
    Print $03
  EndIf
  Print $fe, $C0, "Mode ", Dec1 mode
;  Print $fe, $C0, DEC1 mode, " ", BIN5 RF_Adres, HEX2 RF_Data
  If Relay1 = 1 Then
    Print $FE, $C0 + 12, $01
  Else
      Print $FE, $C0 + 12, $00
  EndIf
  If Relay2 = 1 Then
    Print $FE, $C0 + 13, $01
  Else
    Print $FE, $C0 + 13, $00
  EndIf
  If Relay3 = 1 Then
    Print $FE, $C0 + 14, $01
  Else
    Print $FE, $C0 + 14, $00
  EndIf
  If Relay4 = 1  Then
    Print $FE, $C0 + 15, $01
  Else
    Print $FE, $C0 + 15, $00
  EndIf
Return

'/////////////////////////////////////////////////
'//////Modes & settings

MENU_MODE:
  GoSub menu_backlight
  temp = mode
  Select Case mode
    Case 1
      mode = 2
  DelayMS 200
    Case 2
      mode = 3
  DelayMS 200
    Case 3
      mode = 4
  DelayMS 200
    Case 4
      mode = 1
  DelayMS 200
  End Select
  timer3_ = seconden + 5
  If timer3_ > 59 Then timer3_ = timer3_ - 59
  timer3_on = 1
Return

MENU_SET:
  GoSub menu_backlight
  Select Case settings
    Case 2
      Print $fe, 2, Dec2 uur, ":", Dec2 minuut
      Print $fe, $C0, "Clock  "
  DelayMS 150
    Case 3
      Print $fe, 2, Dec2 alarm1_uur, ":", Dec2 Alarm1_min
      Print $fe, $C0, "Alarm 1"
  DelayMS 150
    Case 4
      Print $fe, 2, Dec2 alarm2_uur, ":", Dec2 alarm2_min
      Print $fe, $C0, "Alarm 2"
  DelayMS 150
    Case 5
      Print $fe, 2, Dec2 delay, "          "
      Print $fe, $C0, "Delay "
  DelayMS 200
    Case 6
      If onetime = 0 Then
        onetime = 1
        x = 0
      EndIf
      Print $fe, 2, "R1 - R2 - R3"
      If relay1_activ = 1 Then Print $fe, $C0,"On " : Else : Print $fe, $C0,"Off" : EndIf
      If relay2_activ = 1 Then Print $fe, $C0 + 5,"On " : Else : Print $fe, $C0 + 5,"Off" : EndIf
      If relay3_activ = 1 Then Print $fe, $C0 + 10,"On " : Else : Print $fe, $C0 + 10,"Off" : EndIf
      Print $FE, $C0 + x
      Print $FE, $0E
  DelayMS 200
    Case 7
      If onetime = 0 Then
        onetime = 1
        x = 1
      EndIf
      Print $FE, 2, "%", Bin5 adr3, " $", Hex2 adr3
      Print $FE, $C0, "Hardware adress"
      Print $FE, $80 + x
      Print $FE, $0E
  DelayMS 400
     Case 8
      Print $fe, 2, "Reset Memory          "
      If memory = 1 Then Print $fe, $C0, "Yes"
      If memory = 0 Then Print $fe, $C0, "No "
  DelayMS 200
   Case 9
      Cls
      If memory = 1 Then
        Print $fe, 2, "Reset Memory"
        EWrite 0, [0]
        EWrite 1, [0]
        EWrite 2, [0]
        EWrite 3, [0]
        EWrite 4, [0]
        EWrite 5, [0]
        EWrite 6, [0]
        EWrite 7, [1]
        EWrite 8, [0]
        EWrite 9, [0]
        EWrite 10,[0]
        EWrite 11,[0]
        EWrite 12,[0]
        EWrite 13,[relay1_activ]
        EWrite 14,[relay2_activ]
        EWrite 15,[relay3_activ]
        EWrite 16,[adr3]
        Print $fe, $C0, "Turn off power!!"
        Stop
      EndIf
      Print $fe, 1
      on_screen = 1
      settings = 1
      onetime = 0
      Print $FE, $0C
      GoSub Write_to_eeprom
      temp = minuut
      GoSub FIX_BCD_OUT
      BusOut Cont1,$01,[temp]
      temp = uur
      GoSub FIX_BCD_OUT
      BusOut Cont1,$02,[temp]
  DelayMS 400
    End Select
  DelayMS 100
GoTo MAIN

MENU_UUR:
  GoSub menu_backlight
  If settings = 2 Then up_uur = uur
  If settings = 3 Then up_uur = alarm1_uur
  If settings = 4 Then up_uur = alarm2_uur

  Inc up_uur

  If up_uur = 24 Then up_uur = 0
  If settings = 2 Then uur = up_uur   
  If settings = 3 Then alarm1_uur = up_uur
  If settings = 4 Then alarm2_uur = up_uur
  If settings = 6 Then x = x + 5 : Print $FE, $C0 + x : If x > 11 Then x = 0 : EndIf
  If settings = 7 Then x = x + 1 : Print $FE, $80 + x : If x = 6 Then x = 1 : EndIf
  GoTo MENU_SET

MENU_MINUUT:
  GoSub menu_backlight
  If settings = 2 Then
    Inc minuut
    If minuut > 60 Then minuut = 0
  EndIf
  If settings = 3 Then
    Alarm1_min = Alarm1_min + 15
    If Alarm1_min > 45 Then Alarm1_min = 0
  EndIf
  If settings = 4 Then
    alarm2_min = alarm2_min + 15
    If alarm2_min > 45 Then alarm2_min = 0
  EndIf
  If settings = 5 Then
    Inc delay
    If delay > 15 Then delay = 0
    delay1 = delay
  EndIf
  If settings = 6 Then
    If x = 0 Then
      relay1_activ = relay1_activ ^ 1
      If relay1_activ = 0 Then Relay1 = 0
      If relay1_activ = 1 And mode > 1 Then Relay1 = 1
    EndIf
    If x = 5 Then
      relay2_activ = relay2_activ ^ 1
      If relay2_activ = 0 Then Relay2 = 0
      If relay2_activ = 1 And mode > 1 Then Relay2 = 1
    EndIf
    If x = 10 Then
      relay3_activ = relay3_activ ^ 1
      If relay3_activ = 0 Then Relay3 = 0
      If relay3_activ = 1 And mode > 1 Then Relay3 = 1
    EndIf
  EndIf
  If settings = 7 Then
    If x = 1 Then adr3 = adr3 ^ %10000               
    If x = 2 Then adr3 = adr3 ^ %01000               
    If x = 3 Then adr3 = adr3 ^ %00100
    If x = 4 Then adr3 = adr3 ^ %00010
    If x = 5 Then adr3 = adr3 ^ %00001
  EndIf
  If settings = 8 Then
    Inc memory
    If memory > 1 Then memory = 0
  EndIf
  GoTo MENU_SET


'/////////////////////////////////////////////////
'////////BACKLIGHT LCD

menu_backlight:
  High backlight
  backlight_timer_on = 1
  timer_backlight = seconden + 15
  If timer_backlight > 59 Then timer_backlight = timer_backlight - 59
Return

'/////////////////////////////////////////////////
'////////TIME I2C

GET_TIME:
  BusIn Cont2,$00,[temp] ; seconds
  GoSub FIX_BCD_IN
  seconden = temp
  BusIn Cont2,$01,[temp] ; minetes
  GoSub FIX_BCD_IN
  minuut = temp
  BusIn Cont2,$02,[temp] ; hours
  GoSub FIX_BCD_IN
  uur = temp
  If write_uur = uur Then          ; write to eeprom cicle = hour
    write_uur = uur + 1
    GoSub Write_to_eeprom
  EndIf
  DelayMS 10
Return

FIX_BCD_IN:
  temp_=temp & 15
  temp=temp >> 4
  temp=temp_ + 10*temp
Return

FIX_BCD_OUT:
temp_ = temp/$A
temp = temp - (temp_*$A)
temp = temp + (temp_ <<4)
Return

'/////////////////////////////////////////////////
'/////// LDR

ldr_CHECK:
  If ldr = 0 Then
    ldr_pin = 0
    LDR_on = 0
  Else       
    ldr_pin = 1
    LDR_on = 1
  EndIf
  If ldr_pin <> ldr_pin_old Then
    If ldr = 0 Then
      If Alarm1_mode = 0 Then
        Alarm1_mode = 1
        ldr_pin_old = 0
        Alarm1_delay = minuut
      EndIf 
    Else
      If Alarm1_mode = 0 Then
        Alarm1_mode = 1
        ldr_pin_old = 1
        Alarm1_delay = minuut
      EndIf 
    EndIf
  EndIf
Return

'/////////////////////////////////////////////////
'//////// RF DECODER

RF_Decoder:
  SerIn PORTC.7, 16780, 250, MAIN, [RF_Adres, RF_Data]
  If RF_Adres = adr3 Then
    If RF_Data = $EF Then
      If Relay4 = 1 Then
        Relay4 = 0
      Else
        Relay4 = 1
      EndIf
      DelayMS 500
    EndIf
    If RF_Data = $FE Then
      Inc mode
      If mode > 4 Then mode = 1
      timer3_ = seconden + 5
      If timer3_ > 59 Then timer3_ = timer3_ - 59
      timer3_on = 1
      DelayMS 500
    EndIf
    If RF_Data = $FB Then
      settings = settings + 1
      Print $fe, 1
      on_screen = 0
      temp = 1
      GoTo MENU_SET
      DelayMS 500
    EndIf
    If RF_Data = $F7 Then
      If settings > 1 Then GoTo MENU_UUR
      If settings = 1 Then GoSub menu_backlight
      DelayMS 500
    EndIf
    If RF_Data = $FD Then
      If settings > 1 Then GoTo MENU_MINUUT
      DelayMS 500
    EndIf
  EndIf
GoTo MAIN


'/////////////////////////////////////////////////
'//////// RELAY MODES

RELAY_ON:
If mode = 1 Then Return
  If relay1_activ = 1 Then
    Relay1 = 1
    DelayMS 500
  EndIf
  If relay2_activ = 1 Then
    Relay2 = 1
    DelayMS 500
  EndIf
  If relay3_activ = 1 Then
    Relay3 = 1
    DelayMS 500
  EndIf
Return

RELAY_OFF:
  Relay1 = 0
  DelayMS 500
  Relay2 = 0
  DelayMS 500
  Relay3 = 0
  DelayMS 500
Return

'/////////////////////////////////////////////////
'//////// EEPROM

READ_FROM_EEPROM:
uur          = ERead  1
minuut       = ERead  2
alarm1_uur   = ERead  3
Alarm1_min   = ERead  4
alarm2_uur   = ERead  5
alarm2_min   = ERead  6
mode         = ERead  7
delay        = ERead  8
Relay1       = ERead  9
Relay2       = ERead 10
Relay3       = ERead 11
Relay4       = ERead 12
relay1_activ = ERead 13
relay2_activ = ERead 14
relay3_activ = ERead 15
adr3         = ERead 16
Return

Write_to_eeprom:
  EWrite 0, [1]
  EWrite 1, [uur]
  EWrite 2, [minuut]
  EWrite 3, [alarm1_uur]
  EWrite 4, [Alarm1_min]
  EWrite 5, [alarm2_uur]
  EWrite 6, [alarm2_min]
  EWrite 7, [mode]
  EWrite 8, [delay]
  EWrite 9, [Relay1]
  EWrite 10,[Relay2]
  EWrite 11,[Relay3]
  EWrite 12,[Relay4]
  EWrite 13,[relay1_activ]
  EWrite 14,[relay2_activ]
  EWrite 15,[relay3_activ]
  EWrite 16,[adr3]
Return

EData 0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0



         

Ivano

Hello forum,
I am attaching an example of DS1307 rtc management, a program made a long time ago in PBP and subsequently converted into positron.
In the future I will rewrite it using procedures with other improvements.
I hope it will be useful for someone to manage these rtc
Use 4 buttons to set date and time.
If button 1 is pressed for a long time, it enters programming mode.
Pushbuttons 1 or 2, if pressed at start-up, allow to modify the control register of the DS1307 and to compensate via software the delay and advance of the time in a maximum of +/- 50 seconds per day.
The module with DS1307 purchased on Ebay is not very accurate, I had to solder a capacitor of some pF to get close to 32768 hz (now 32768.82 hz) and it has no frequency compensation.
Better to use the DS3231 with internal temperature compensated oscillator and frequency compensation via an internal register. Sorry google translator

Ivano

#14
Hello,
in the file Orologio_rtc_DS1307.zip attached I noticed that in the passage from PBP to Positron with the copy and paste there is some error even if it works.
I attach another file without errors.
I am working on an rtc management file which saves the data in the rtc in UTC format. practically the DS1307 always works in UTC and calculates the local time. It is also possible to set the positive time zone.
It is still being tested but seems to be working.
I attach it if anyone is interested.
Sorry for the Google translation

HAL

Thanks Ivano
I was looking for an example using the DS1307....

Ivano

With these programs it also works with the DS3231 which is better.
However, it has the control register with a different address. The date and time registers are the same and so is the I2c address

Ivano

I reloaded the RTC_DS1307_a file because I reloaded the same file with errors, sorry