Menu

interrupt guidance

2021-04-25
2021-06-09
1 2 3 4 > >> (Page 1 of 4)
  • Reginald Neale

    Reginald Neale - 2021-04-25

    interrupt guidance

    I want to control the chiming of the hour in a refurbished mantel clock. The primary source of time information is a 30ms once-per-second pulse from a quartz clock module.
    I’m thinking pseudo code something like that below. My question is where to place the interrupt enable and the interrupt flag reset so that the program will recognize the once-per-second interrupt and increment the counter even during the chiming, which takes several seconds. Grateful for any comments and suggestions.

    PSEUDO CODE

    DO
    Enable interrupt on change for pin X
    On interrupt go sub increment counter
    LOOP

    Sub increment counter
    Seconds = Seconds + 1
    If Seconds = 60 Then
    Minutes + Minutes + 1
    Seconds = 0
    End If
    If Minutes = 60 Then
    Hours = Hours +1
    Minutes = 0
    gosub Strike Hour
    End If
    End sub

    Sub Strike Hour
    For numcount to Hours
    output a pulse to strike chime
    Next
    If Hours = 12 Then
    Hours = 1
    End If
    reset interrupt flag
    End sub

     
  • kent_twt4

    kent_twt4 - 2021-04-25

    I would say to pull the On Interrupt stuff out of the loop. Just initialize and forget.

     
  • mmotte

    mmotte - 2021-04-26

    Interrupts are quite easy in GCB. But there still is a couple of basic things to remember.
    1) you want to spend a minimum amount of time in the interrupt routine or you may miss the next interrupt
    2) Use "flag" variable to initiate events in the main routine. This would be like your strike hour "hour" routine
    3) You may want to use ExtInt0 instead of "Enable interrupt on change for pin X". Because you can choose the rising or falling edge and a 30ms pulse will cause more than 1 interrupt.

    So the "On Interrupt" statement needs only to be placed in the initialization before the "Main" loop. Look up the On Interrupt in the help.

    Your "increment counter" is fine except for the "gosub Strike Hour" which is going to take time and you don't want to miss the next second pulse. So here you would use a variable like "hourStrike" and set it to True or 1. Then in the Main you would check with an IF if hourstrike was True then you would call your "StrikeHour" sub. You do not need to reset the interrupt flag but you do need to reset your "hourStrike" variable to False or 0. The interrupt resets the interrupt flag in the background.

    One final comment on the if statements in the "incrementcounter " . "If Seconds = 60 Then" It is usually good practice to use "If Seconds > 59 Then" because it would catch it if something strange happens.

    The Interrupt is automatically enabled when you run the On Interrupt statement and you are not going to shut it off because you want to catch every pulse.

    GL
    Mike

     
    • Reginald Neale

      Reginald Neale - 2021-04-28

      Thanks Mike. You clearly understand that my problem is making sure not to miss any of the once-per-second pulses during a several second chiming sequence. Somehow I am not completely wrapping my head around the logic of how the interrupt works.
      You're right about using >= instead of +, I did run into that problem.

       
  • stan cartwright

    stan cartwright - 2021-04-26

    I would use the quartz clock modude and count the 30ms pulses.
    You could use the millis function.

    #include millis().h
    dim tempmillis as long
    tempmillis=millis()
    do
        if millis()-tempmillis = 3600000 ;milliseconds in an hour
        then chime : tempmillis=millis()
        endif
    loop
    
     

    Last edit: stan cartwright 2021-04-26
  • stan cartwright

    stan cartwright - 2021-04-26

    here's a clock i wrote using every 1ms interrupt https://www.youtube.com/watch?v=kEcN4Zo3Syg

     
  • William Roth

    William Roth - 2021-04-27

    Hi Reginald.

    Attached is example code that should do want it to do. It is well commented so you can understand what is going on. Remove the hserial sections after testing and debugging.

    William

    Note: There was a bug in the original file where it would chime 13 times when the clock hit 1. This has been corrected in the newly attached file.

     

    Last edit: William Roth 2021-04-28
  • stan cartwright

    stan cartwright - 2021-04-28

    I'd go for timer 0 overflow as there's a calculator to get the interrupt time.
    Set it up for mS and use a counter to get the hour.
    I got 328 code if you're interested.

     
    • William Roth

      William Roth - 2021-04-28

      Why?

      The project already receives a 30 ms pulse every second from a crystal clock. There is no need to implement a timer or to count ms.

      As I understand it Reginald already has a clock. He is adding a chiming function to an existing clock that outputs a short pulse every second.

       

      Last edit: William Roth 2021-04-28
      • Reginald Neale

        Reginald Neale - 2021-04-28

        Thanks William, this is very helpful. I'm studying it and trying to make sure I understand it. I need to use the 16F1829 with a 32kHZ clock because this is a battery-operated circuit. So I changed that and also the appropriate chime output pin. For the ON Interrupt line, I need a falling edge on portb.6 . Does that go on the same line replacing portb.0?
        I made those changes and got errors related to the USART. Errors 464 and 466 "Cannot store -1 in the byte variable SPBRG" and same for SPBRGH. When I commented out all the USART related lines it compiles OK.
        I really appreciate your input. The serial output should be very helpful for debugging if I can get it to work.

         
  • stan cartwright

    stan cartwright - 2021-04-28

    I mentioned the 30ms pulse every second first William. Thought Reginald wanted an alternative.
    The timer 0 overflow interrupt is a nice way to start with interrupts. They are surrounded with they're complicated but just not explained properly and are useful.
    Gcb can do a short bit of code in a 1ms interrupt, in fact a counter to make it every 20ms so to use rc servos and stepper motors. I got timer 0 overflow to work with avr and pic.
    someone should do a tutorial. mr Roper has used timer 0 overflow to write the millis function, which is useful but never finished the do every which he gave me a demo to test.
    I mainly use 328 and the interrupts that are in gcb demos/help but they are useful.

     
    • Reginald Neale

      Reginald Neale - 2021-04-28

      Thanks Stan. I think the real problem is I haven't quite wrapped my had around the way the interrupt works. Still studying.

       
  • stan cartwright

    stan cartwright - 2021-04-28

    This is 328 but same for pic

    ;start 1ms interrupt isr
        On Interrupt Timer0Match1 Call valve_isr
        Dim OCR0  AS byte alias OCR0A
        Dim TCCR0 AS  byte alias TCCR0B
        WGM01 = 1
        OCR0 = 249 ;1ms
        TCCR0 = 0x28
        TCCR0 = TCCR0 or 0x03
        do
        loop
    Sub valve_isr ;called every 1mS
        your code every 1mS
    End Sub
    
     
  • stan cartwright

    stan cartwright - 2021-04-28

    It's surprising what code can be done in a 1ms interrupt .. ie before the next interrupt.
    It can be a counter so stuff happens every 20 ms. and still carry on with the main program.
    The millis() funtion is an example of timer 0 overflow and is sorted so it works across pic and avr...no simple feat.
    Try setting up a timer 0 overflow interrupt every 1ms for an experiment .. port b1=not port b1
    scope the output

     
  • mmotte

    mmotte - 2021-04-28

    Reginald,
    I assume the 1 second pulse also runs the clock, so you would not want the program to provide the timer. You already have the precision time from that pulse.

    One additional thing you need is a way to set the chime clock hours and minutes to the right time. You could use 7segment leds but they would kill your battery, so you could turn them on only when a a button is pressed.

    portb.6 can be used for the interrupt using IOC
    The neg edge can be used by setting the IOCBN6 bit in this register:
    REGISTER 13-5: IOCBN: INTERRUPT-ON-CHANGE PORTB NEGATIVE EDGE REGISTER
    (PIC16(L)F1829 ONLY)
    IOCBN7 IOCBN6 IOCBN5 IOCBN4 — — — —

     
    • Reginald Neale

      Reginald Neale - 2021-04-28

      Yes, the external 1/s pulse is the time reference. My plan for setting the time is to provide a SYNC button that sets time to zero and a INCR button that advances the hour counter and confirms the new hour by initiating the chime sequence.

       
  • William Roth

    William Roth - 2021-04-29

    Hi Reginald.

    I just found an 16F1829 that I can throw on a dev board. I would think that using INTO on falling edge on would be more straight forward than IOC. I will try a few things and posts some code to test.

    What stage are you in now? Do you have a chip on a board connected all up and ready to test?
    Have you successfully operated the 16F1829 at 32Khz?
    What is the pulse requirement for the chime output ?
    How much time between consecutive chimes do you want ?

    FYI: This can be done just as easily without using an interrupt. But either will work

     
    • Reginald Neale

      Reginald Neale - 2021-04-29

      Glad to have any ideas. I'm not a sophisticated user.
      I have a breadboard that I use to test clock programs. I have a PicKit 3 that I keep handy. Yes, have used the 16F1829 with the 32kHZ internal oscillator. My previous version of the program is for a circuit that uses a separate dedicated IC to do the counting, so the uchip device gets a square wave input with a one hour period. Plenty of time for even the longest chime sequence. I'm sure it's pretty clunky but it has worked for years. So my immediate goal is to eliminate the separate IC. With a 16LF1829 I was able to reduce the supply current to about 1uA. Battery lasts a long time!
      Another part of the circuit is a transistor interface that takes the quartz module pulse of 1.5 VDC and outputs a 5 VDC output . I see that the 16F1829 has a comparator function, so I'm hoping that it may be possible to use that instead of a discrete transistor, simplifying the circuit even further.
      The solenoid driver pulse length needs to be about 400 ms. GCB doesn't accurately scale the timing with the 32kHZ oscillator, so the the actual time value in the program needs to be larger by a factor of about eleven.
      Again, thanks very much for your help and suggestions. This forum is a great resource!

       
  • William Roth

    William Roth - 2021-04-29

    Ok.

    I think I now have the information I needed to write a good example for you to test.

     
  • William Roth

    William Roth - 2021-04-30

    Reginald.

    Here is a test program that works nicely. It demonstrates how to use the 16f1829 chip at 32Khz and how to generate relatively accurate delays/ pulse times given that GCB timings and delays are not supported at 31Khz.

    I do not recommend using IOC for this application , but instead use the interrupt on the falling edge of the dedicated interrupt pin on PortA.2.

    Enjoy

     

    Last edit: William Roth 2021-04-30
    • Reginald Neale

      Reginald Neale - 2021-04-30

      Preliminary tests look good. Attached is the schematic of my current version with the separate counter chip that I want to eliminate. More in a bit.

       
  • William Roth

    William Roth - 2021-04-30

    The PDF will not open. File format error

     
  • stan cartwright

    stan cartwright - 2021-04-30

    Do you want to eliminate the external timer and use pic interrupts which if using a crystal for the clock should be accurate? I did a clock, albeit analogue, that ran off a timer 0 overflow interrupt every ms. It was mainly to learn trig. There's 1 ms interrupt demos.

     
  • William Roth

    William Roth - 2021-05-01

    Not making a clock here Stan.

    Adding a chime function to an existing clock (Crystal Clock Module) so that it chimes 1 time for every hour of the current time when hours change.

    So for example , when the time changes from 11:59:59 to 12:00;00. the PIC will send 12 chiming pulses of 400 ms each to a solenoid to ring the chime . Chime pulses are spaced apart by 2 seconds (adjustable). And while chiming, the 400 ms pulses cannot be interrupted and the chiming pulse cannot interfere with the seconds counter.

    There is absolutely no need for 1 ms pulses, 1 ms delays, or 1 ms interrupts or for a timer in this application.

    Besides, you cannot get 1 ms accuracy with a PIC operating at 31.25Khz with its internal clock. But you can get precise 1 second accuracy when the Pic is receiving a pulse every second from an external crystal clock module that has an accuracy of 6=10 ppm. The PIC simply needs to sync with the external clock and chime on the hour.

     
    • Reginald Neale

      Reginald Neale - 2021-05-01

      William, I changed "IF seconds >59" to "IF seconds > 5" so that it increments 10x faster. It's been running for several hours with no errors.
      I tried to change Clock_Pulse pin from PORTA.2 to PORTB.6, which was how my breadboard was wired, but that made the program hang.
      I'm trying to think how to use the serial commands. Ideally, there would be a way to do this within the IDE, while the chip is still on the LPC or Curiosity board, just plug in the external 1pps signal.
      Thanks again for your carefully commented program. I'm still absorbing its subtleties.

       
1 2 3 4 > >> (Page 1 of 4)

Log in to post a comment.

Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.