Help with programming for interrupt from RTC

parto

Member
Hi, I am having trouble putting together the code for programming the 14M2 and the DS3231 to set and use alarm interrupts. I've been searching all over for examples to use; perhaps I'm overlooking a source of information but presently I'm just stuck.

I need to have the 14M2 sleep until it receives an alarm interrupt every 90 minutes from the DS3231. Then the 14M2 wakes up, performs a variety of tasks, resets the alarm, and goes back to sleep. This goes on for four months, so I am trying to conserve power as much as possible.

I know how to set the clock's time using Picaxe commands. I have some knowledge of the commands used for setting up the 14M2 for the interrupt (SETINT). I have looked at this information: https://picaxeforum.co.uk/threads/getting-started-with-the-ds3232-rtc-and-a-brief-comparison-of-some-other-rtc-chips.23739/ . But I seem to need very basic examples or other learning material. Can anyone steer me toward some?

Thank you!
 
Last edited:

AllyCat

Senior Member
Hi,

AFAIK the M2 chips only support "polled" interrupts (i.e. the program must be running), an input signal cannot "wake up" the PICaxe from Sleep. However, this is not a serious problem, the PICaxe (program) just needs to wake up occasionally (which could be set as low as 2 seconds or as much as 40 hours ! ), check if any action is required, and go back to sleep if not. The "check" could be reading the RTC time directly, or testing if an interrupt pulse has been generated.

I don't know if the RTC interrupt pulse has a fixed width or if it is only cleared by program control, but even if the interrupt level does automatically "disappear", there are at least 3 ways to latch the event, so that the PICaxe program can check if a pulse occurred whilst it was Sleeping: Firstly, there is the Set-Reset Latch which is directly supported by PICaxe Basic on the dedicated pin(s). Or there are two methods which need PEEKSFR commands, there is the "Timer 1 Gate" hardware (on a dedicated pin) for which I wrote a Code Snippet, or the "Interrupt on (pin) Change Flags" register which can record a change on any input pin(s).

Cheers, Alan.
 

parto

Member
So I've misinterpreted the HINTSETUP documentation? It seemed to say that the interrupt would wake the PICAXE from sleep:

"The X2 parts have up to 3 hardware interrupts pin (INT0, INT1, INT2) which are activated/deactivated by the hintsetup command. The hardware interrupt pins constantly background monitor for an edge based trigger. As they operate in the background the PICAXE program does not have to poll the input to detect a change in state.

The hardware interrupts are triggered and processed extremely quickly. Therefore be aware of, for instance, switch contact bounce, which may give unexpected results if not debounced by software and/or hardware.

The hardware interrupt pins can also wake a PICAXE microcontroller from sleep / doze mode.

The hardware interrupt pins cause an instant change in the hardware interrupt flags upon input pin condition change.. If a setintflags command has also been issued, a PICAXE program interrupt may then occur."
 

AllyCat

Senior Member
Hi,
"The X2 parts have up to 3 hardware interrupts.....
Yes, the X2 parts can be put to sleep and woken up, but the M2 chips cannot. You didn't read on to the bit that says: "Applies To: 20X2, 28X2, 40X2".

From the Sleep Command description: "On non-X2 parts the command 'sleep 0' is ignored..." which suggests that the M2 chips behave "differently" to the X2s.

Cheers, Alan.
 
Last edited:

parto

Member
Oops, I mistook "X2" for "M2". Probably I should have gone with the X2 but I just purchased 7 of the M2 boards and chips.

I wonder what the polling will do to the power consumption. I'll try with your information to set up the polling. Any more help with getting started on this would be greatly appreciated!
 

AllyCat

Senior Member
Hi,

The average power consumption of the PICaxe if it needs to wake up for just a short time (say) every few minutes could be very low.

The Interrupt on Change Latch register is probably the "best" method, but there are a number of complications which need a careful examination of the "base PIC" data sheet. Also, I don't know of any detailed descriptions on the forum, but with time we should be able to help you.

However, I did describe the "Timer 1 Gate" hardware method in post #10 of this thread, so take a look at that first.

Cheers, Alan.
 

hippy

Technical Support
Staff member
The DS3321 uses its SQW output as an active low INT flag signal which will indicate when an alarm has been activated. So even without a permanent sleep that should be near achievable with -
Code:
Do
  Sleep 1
Loop Until pinSQW = 0
It should be possible to extend the SLEEP period as the alarm signal will be latching or be present for at least a minute.

Probably best to make pinSQW a pin with a pull-up as that's open-collector and needs a pull-up. Interrupts don't need to be used. The amount of power saved if an interrupt were used is likely minimal.

Using a polling loop which is mostly sleeping is probably a good idea anyway as it allows waking up even if the alarm for some reason fails to go off -
Code:
w0 = 2860 ; (100 mins * 60 secs ) / 2.1 secs
Do
  Sleep 1
  w0 = w0 - 1
Loop Until pinSQW = 0 Or w0 = 0
If w0 = 0 Then
  Gosub AlarmFailed
End If
I would approach the project by getting alarms to work first, interrupting every 5 minutes or so without worrying about power consumption, so it's easier to prove it's working reliably. Then make it sleep between alarms. And finally extend to 90 minutes.
 

hippy

Technical Support
Staff member
This wpuld be my starting pint, untested -
Code:
#Picaxe 14M2
#Terminal 4800
#No_Data

Symbol reserveW0   = w0 ; b1:b0
Symbol mins        = b2
Symbol hour        = b3

Symbol pinSQW      = pinC.0

;                     CCCCCCCCBBBBBBBB
;                     7654321076543210
Symbol PULLUP_MASK = %0000000100000000

#Define ToBin(bcd) bcd / 16 * $FA + bcd
#Define ToBcd(bin) bin / 10 * 6 + bin

Test:
  HI2cSetup I2CMASTER, $D0, I2CSLOW, I2CBYTE
  PullUp PULLUP_MASK
  Pause 2000
  SerTxd( "Started", CR, LF )
  hour = 0 : mins = 0
  Gosub SetTime
  Do
    Gosub SetAlarmFiveMinutesFromNow
    Do
      Sleep 1
    Loop Until pinSQW = 0
    Gosub ReadTime
    SerTxd( "Alarm at ", #hour,":", #mins, CR, LF )
  Loop

SetTime:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  ;              s  m  h  dow  d   m   y
  HI2cOut $00, ($00,b0,b1,$01,$01,$01,$00)
  HI2cOut $0E, ($80,$00)
  Return

ReadTime:
  HI2cIn $01, (b0,b1)
  mins = ToBin(b0)
  hour = ToBin(b1)
  Return

SetAlarmFiveMinutesFromNow:
  b0 = 5  ; In minutes
  b1 = 0  ; In hours
  Goto SetNextAlarm

SetAlarmAnHourAndHalfFromNow:
  b0 = 30 ; In minutes
  b1 = 1  ; In hours
  Goto SetNextAlarm

SetNextAlarm:
  b0 = mins + b0
  b1 = b0 /  60 + b1 // 24
  b0 = b0 // 60
  b0 = ToBcd(b0)
  b1 = ToBcd(b1)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

SetAlarm:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

EnableAlarm:
  HI2cOut $0E, ($86,$00)
  Return

DisableAlarm:
  HI2cOut $0E, ($80,$00)
  Return
 

olegb1423

New Member
This wpuld be my starting pint, untested -
Code:
#Picaxe 14M2
#Terminal 4800
#No_Data

Symbol reserveW0   = w0 ; b1:b0
Symbol mins        = b2
Symbol hour        = b3

Symbol pinSQW      = pinC.0

;                     CCCCCCCCBBBBBBBB
;                     7654321076543210
Symbol PULLUP_MASK = %0000000100000000

#Define ToBin(bcd) bcd / 16 * $FA + bcd
#Define ToBcd(bin) bin / 10 * 6 + bin

Test:
  HI2cSetup I2CMASTER, $D0, I2CSLOW, I2CBYTE
  PullUp PULLUP_MASK
  Pause 2000
  SerTxd( "Started", CR, LF )
  hour = 0 : mins = 0
  Gosub SetTime
  Do
    Gosub SetAlarmFiveMinutesFromNow
    Do
      Sleep 1
    Loop Until pinSQW = 0
    Gosub ReadTime
    SerTxd( "Alarm at ", #hour,":", #mins, CR, LF )
  Loop

SetTime:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  ;              s  m  h  dow  d   m   y
  HI2cOut $00, ($00,b0,b1,$01,$01,$01,$00)
  HI2cOut $0E, ($80,$00)
  Return

ReadTime:
  HI2cIn $01, (b0,b1)
  mins = ToBin(b0)
  hour = ToBin(b1)
  Return

SetAlarmFiveMinutesFromNow:
  b0 = 5  ; In minutes
  b1 = 0  ; In hours
  Goto SetNextAlarm

SetAlarmAnHourAndHalfFromNow:
  b0 = 30 ; In minutes
  b1 = 1  ; In hours
  Goto SetNextAlarm

SetNextAlarm:
  b0 = mins + b0
  b1 = b0 /  60 + b1 // 24
  b0 = b0 // 60
  b0 = ToBcd(b0)
  b1 = ToBcd(b1)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

SetAlarm:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

EnableAlarm:
  HI2cOut $0E, ($86,$00)
  Return

DisableAlarm:
  HI2cOut $0E, ($80,$00)
  Return
This wpuld be my starting pint, untested -
Code:
#Picaxe 14M2
#Terminal 4800
#No_Data

Symbol reserveW0   = w0 ; b1:b0
Symbol mins        = b2
Symbol hour        = b3

Symbol pinSQW      = pinC.0

;                     CCCCCCCCBBBBBBBB
;                     7654321076543210
Symbol PULLUP_MASK = %0000000100000000

#Define ToBin(bcd) bcd / 16 * $FA + bcd
#Define ToBcd(bin) bin / 10 * 6 + bin

Test:
  HI2cSetup I2CMASTER, $D0, I2CSLOW, I2CBYTE
  PullUp PULLUP_MASK
  Pause 2000
  SerTxd( "Started", CR, LF )
  hour = 0 : mins = 0
  Gosub SetTime
  Do
    Gosub SetAlarmFiveMinutesFromNow
    Do
      Sleep 1
    Loop Until pinSQW = 0
    Gosub ReadTime
    SerTxd( "Alarm at ", #hour,":", #mins, CR, LF )
  Loop

SetTime:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  ;              s  m  h  dow  d   m   y
  HI2cOut $00, ($00,b0,b1,$01,$01,$01,$00)
  HI2cOut $0E, ($80,$00)
  Return

ReadTime:
  HI2cIn $01, (b0,b1)
  mins = ToBin(b0)
  hour = ToBin(b1)
  Return

SetAlarmFiveMinutesFromNow:
  b0 = 5  ; In minutes
  b1 = 0  ; In hours
  Goto SetNextAlarm

SetAlarmAnHourAndHalfFromNow:
  b0 = 30 ; In minutes
  b1 = 1  ; In hours
  Goto SetNextAlarm

SetNextAlarm:
  b0 = mins + b0
  b1 = b0 /  60 + b1 // 24
  b0 = b0 // 60
  b0 = ToBcd(b0)
  b1 = ToBcd(b1)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

SetAlarm:
  b0 = ToBcd(mins)
  b1 = ToBcd(hour)
  HI2cOut $0B, (b0,b1,$81)
  HI2cOut $0E, ($86,$00)
  Return

EnableAlarm:
  HI2cOut $0E, ($86,$00)
  Return

DisableAlarm:
  HI2cOut $0E, ($80,$00)
  Return
 

olegb1423

New Member
hippy,



I tried to replicate your (not tested!) code above for 14M2 using both old PICAXE compiler 5.5.5 and the new 6.1.0.0.

Both editors came up with the different errors which I need some help to to understand and fix:



1. editor 5.5.5 indicated an errors in the lines 15,16



#Define ToBin(bcd) bcd / 16 * $FA + bcd

#Define ToBcd(bin) bin / 10 * 6 + bin



2. editor 6.1.0.0 passed #Define lines above however indicated an errors on the lines 35, 36 further down:



b0 = ToBcd(mins)

b1 = ToBcd(hour)



Refer to the attached screenshot for more.



Is it possible to test your code to make sure that we are not facing another compiler’s bugs here?



Thank you for your help!
 

Attachments

hippy

Technical Support
Staff member
Programming Editor 5 will not understand the code so one needs to use PICAXE Editor 6.

That should work so I think it is how you have launched PE6 which is the issue. At the top of the Editor in the screenshot it shows "Blockly for PICAXE 6.1.0.0" which I recall means Blockly for PICAXE was launched, and this is disabling capabilities the code relies upon.

From the Start Menu / Programs / Revolution Education / PICAXE Editor 6 you should see a plain "PICAXE Editor 6" alongside the "Blockly for PICAXE" item. Launch the "PICAXE Editor 6" and I think everything should be fine.

If not, Options / Compilers / Enable pre-processor should fix things - it is that from what I recall which is not selectable from the Blocky version -- Well, you can select it, but it gets cleared as soon as OK is clicked.
 

olegb1423

New Member
that's was exactly an issue! I have Blockly Editor6 and old editor 5.5.5 deinstalled just left only pure PICAXE Editor 6 instead. Everything is looks good now. Thank you, hippy!
 
Top