Pulse Counter (using 18M2+) on an interrupt routine.

HertzHog

Member
Simple question, perhaps the answer is not so simple?
Can you give me an idea of how wide in time a pulse must be to be reliably caught every time by an interrupt routine?
Might a short pulse of 40 microseconds be missed, if the interrupts are polled after each command runs?
My application should not miss any pulses you see, and I can't easily check if some are missed.
HertzHog
 

AllyCat

Senior Member
Hi,

It may depend on what clock frequency you're using and what code is running in the "main" (i.e. interrupted) program. If the main code uses any "blocking" commands then AFAIK interrupts definitely will be missed, but I think 40 us is too short to (reliably) detect interrupts, even with a 32 MHz clock. The interpreter seems to poll some of the more complex instructions (and certainly PE's pseudo commands) several times, but even the simplest commands take more than 40 us to execute with a 32 MHz clock.

However, you might get a reliable response if the main program is "permanently" executing a PAUSE command. But there could still be a small risk of a lost interrupt if it were necessary to put a loop around the Pause.

One solution is to use the on-chip SR Flip-Flop, but I believe that needs 3 pins in all. The FF input is Leg6 and you'd probably need to use the SRQ output (Leg2, the Serial Programming output) because SRNQ is on Leg3 (Serial Programming Input). Generally, reading a PICAxe pin (i.e. polling to generate the interrupt) which is configured as an Output can be problematic, so you'd probably need to externally link the SRQ output to an (interruptable) input pin.

Cheers, Alan.
 

Circuit

Senior Member
I am probably a little out of my depth with this one, but I think that Hippy or Technical might step in with a fuller answer. I would be looking towards using an X2 chip and the hardware interrupt (HINTSETUP). My understanding is that, with the X2 chips, the interrupt occurs instantly on the rising or falling edge and the interrupt flag is set; it is this flag that is then polled by the PICAXE runtime. I would think that the most important aspect of knowing whether you are going to miss any pulses is to firstly understand how frequently these pulses occur. Clearly the determinant here is how long the program takes to process whatever you wish to do with these pulses before resetting the interrupt ready for the next one; obviously this will be affected by the clock speed of the PICAXE. So to help the next respondent, what is the expected frequency of your pulse train?
 

HertzHog

Member
The pulses to monitor are random but 'slow'. I am concerned by their short width. I was hoping not to need extra hardware to stretch them. Hertzhog. There is s lot of pausing in the interrupted section and minimal code in the interrupt handler which I have increased the clock speed in.
 

kranenborg

Senior Member
In my opinion Allycat has the proper solution approach on a M2 device, given the timing info in your last post: the SR-latch, which acts as a memory bit, allowing the polled INT to catch on. Applied in such a way I think it is equally fast as a hardware interrupt on an X2 as suggested by Circuit. The SR-latch can catch a fast spike (you'll have to look at the corresponding PIC datasheet to see what the minimum required spike width is in order to be captured, but I guess this will not be a problem), then the latch output (which can only be connected to an output pin, there is no internal connection sadly) is to be wired to an input pin with polled interrupts enabled. The interrupt routine then can act on it (quickly) and then reset the latch to be ready for the next occurrence ...

I had a very similar but somewhat more complex application for an M2 (a fast spike detector where the SR-latch is set by the internal comparator in order to have a spike detector with a programmable noise canceller), see the first entry at my electronics webpage: http://www.kranenborg.org/electronics/10-picaxe-and-zbasic-code-contributions. You will find a circuit diagram there as well (By the way, the statement there that it is not possible on the 18M2 (but is possible on the 08M2 and 14M2) refers to the comparator+DAC setup for the noise canceller, a comment that does not apply to your case where the SR-latch is driven directly)

BR,
Jurjen
http://www.kranenborg.org/electronics
 
Last edited:

HertzHog

Member
Sorry. As a newbie, I am not sure I understand the SR latch concept. Perhaps I just need to stretch the pulse out with a diode, resistor and capacitor. But how long does it need to be to guarantee it is caught by a routine polled interrupt. That must be known? HertzHog
 

Circuit

Senior Member
The SR latch idea is rather clever and if you are fixed on using an M2 part rather than an X2 part as I suggested earlier then it is a sensible way to go. The idea of the SR latch is, if you like, a semi-independent bit of circuitry within the PICAXE chip. Basically it is a pair of pins; one input, one output. (Actually an inverse output as well on some chips but that does not matter here). The input "listens" for the pulse. As soon as the pulse occurs, regardless of what the rest of the PICAXE is doing, the latch latches. That is, it switches the output pin to high and keeps it that way until you reset the latch within the program. You can program it to catch a very fast pulse as Kranenborg illustrates in his link and no matter what is going on in the rest of the PICAXE chip, the latch will respond to the pulse. Now because the SR latch circuit is not internally connected within the PICAXE chip, you have to use another pin to "read" the SR Latch output pin.
So what is proposed is that you program SRLATCH and apply your pulse to the SRI pin (B.0, leg6 on the 18M2). The SRLATCH output pin will be C.3, leg2 - labelled SRQ). So whenever your very short pulse is applied to B.0, C.3 will latch up until told otherwise by the program. So you have to detect this latching by connecting C.3 to another pin, one with an interrupt. Because you have latched to the pulse, it cannot be missed. This approach is far more certain than pulse-stretching.

I asked about the frequency of your pulse train and you replied that it was "slow but random". Slow is good but random is not. If it is truly random then I presume that two pulses may follow in quick succession; if this is the case then you may miss a pulse because the latch may be locked up and awaiting reset when the second pulse arrives. Of course the same problem would arise if you were pulse-stretching. If there is always a reasonable gap between the pulses then there is not a problem. Perhaps if you would tell us something more about the nature of the project and how the pulses are generated etc. then more help may be available. What are you actually trying to do?
 

hippy

Technical Support
Staff member
Perhaps I just need to stretch the pulse out with a diode, resistor and capacitor. But how long does it need to be to guarantee it is caught by a routine polled interrupt. That must be known?
The PICAXE polls the pins and invokes an interrupt only between commands or during a PAUSE, so an interrupting pulse needs to be present for as long as the command being executed takes to execute. That can vary greatly which is why there is no specific figure to give.

What the HINT pins allow for, and SR-Latch replicates, is detecting the pulse no matter when it occurs, and providing an indication that the pulse occurred when the PICAXE comes to poll the pins and invoke interrupts at the end of commands. Thus a very short pulse, which may no longer be present when polled, will be flagged as having happened, and it's that flag which then causes the interrupt.

The SR-Latch as used as described above works like a diode-resistor-capacitor pulse extender, with infinitely long hold time and only cleared when the interrupt is executed.
 

HertzHog

Member
Thanks. That's much clearer about the independant latch. I'm making a 'Geiger counter' rate meter. So, the pulses really are random in time. Of course, I think I can cope with a known and repeatable 'dead time' after each and every pulse. But a random miss just because the Picaxe is doing some processing is much more problematic! Unless the pulse width needed is known, in practice, it makes the interrupt concept a bit flawed. How long would a pulse need stretching to in order to be caught reliably in milliseconds? That must be known. HertzHog
 

Circuit

Senior Member
Unless the pulse width needed is known, in practice, it makes the interrupt concept a bit flawed. How long would a pulse need stretching to in order to be caught reliably in milliseconds? That must be known. HertzHog
I understand that the PICAXE 18M2 is based upon the Microchip Microcontroller PIC16(L)F1847 (http://ww1.microchip.com/downloads/en/DeviceDoc/40001453E.pdf). The SR Latch is detailed but without any direct figure on response time to a pulse on the SRI leg that I have yet found. The SR Latch also works with two comparators and they appear to have a response time of 150 nanoseconds. Therefore you hardly need stretch your pulse if you use the SR Latch idea or use the hardware interrupt in the X2 series of chips. If you are only using the polled interrupt in the 18M2 chip then I think that there is no direct answer to your question; it entirely depends upon the code that is running when the interrupt occurs.
 

kranenborg

Senior Member
Regarding the minimal pulse width itself (and maximum rise/fall times) I have looked into the PIC datasheets to see whether there are some minimum timing requirements for the spikes to be registered by the latch module. Somewhat surprisingly, there was no info to be found. Maybe a small test with a second Picaxe generating a very fast spike using PULSOUT (and a scope to measure the real signal) would be in place to simulate a Geiger pulse (a 32MHz M2 can generate a pulse of just 1.25 us width)?

EDIT: Parallel post to Circuit ...
 

AllyCat

Senior Member
Hi,

How long would a pulse need stretching to in order to be caught reliably in milliseconds? That must be known.
No, not until you define which instructions are being used in your main program and the clock frequency. For example, AFAIK if you use a SEROUT or SERTXD at 2400 baud, it will be about 5 ms, or nearly double that at 1200 baud. That could be overcome by using HSEROUT on the appropriate pin. But I believe input signals such as SERIN are much more problematic, because they can be fully "blocking". Again HSERIN is possible, but there are major issues, as I described in this recent post.

However, as mentioned above, pulse-stretching does not solve the issue. because the stretched pulse itself will block a second pulse if it occurs shortly after the first. Probably the best that can be done with a PICaxe (at least an M2) is the SR latch which is cleared as soon as the interrupt is entered and then tested again before returning from the interrrupt routine (to avoid the latency of the return and re-interrupt process). That's much what I did in the test code in my post linked above (which also shows a waveform of the typical interrupt latency with carefully chosen "main" code instructions (at 16 MHz).

Cheers, Alan.
 

bpowell

Senior Member
The 08M2 (hardware) has an "Interrupt-on-change new input level time" minimum of 25ns. The 20x2 (hardware) has the same specification...called either "INT Pin Input High or Low time" or "PortB Interrupt-on-change new input level time" both 25ns.

These are hardware specifications...as has already been mentioned, the polled interrupts will take longer, because they have to be checked (polled) while code is executing.
 

HertzHog

Member
Thanks for such long and thoughtful replies!
I just have pauses ifs gosubs highs etc. No need for serial code use. There is a calibadc and maths. No ic2. I am just displaying the current rate and status on a 1 digit single 7 segment display on the project board while waiting for data to acquire. This code has become quite 'sophisticated' as I am leveragIng the capability of a 7 segment display to show lots of information. Count number, battery status, rate of counts etc.
If each pulse has a standard dead time afterwards that is predictable and I can cope with a bit of non linearity at any higher count rates. My pulses are predicted to be mostly quite far apart on average, as I said, but my concern is missing an unknown proportion of them when they do arrive randomly while processing is being done. I had hoped to use a very standard polled interrupt as I think I have debugged that code believing that I was using it as an appropriate 'hammer' to hit my 'nail' with.
The sensor is not very sensitive and background count rates are predicited to be low and prolonged sampling to average out the rate is what I am doing. But, the pulses, when they do come, are predicted to be natively narrow at 40 microseconds pre any stretch.
I found the latch descriptions in the manuals a bit difficult and I would have to see and compare and contrast a matched pair of working programs (which would be a cheeky ask) , one using polled interrupt and the other the latch techniques before I know if my 2 brains can cope with adapting my code.
I had sort of hoped there would we a simple answer to the polling question. I.e. In practice pulses are latched routinely, or need to be more than x micro seconds long to be caught reliably.
I thought it was an important question too that deserved and had an answer.
As the sensor is expensive and so not yet bought, I wanted to check my project feasibility by tapping your experience and knowledge before I buy the sensor. I have written the software bit now. It is too long to share before it has been shown to work. Thanks HertzHog.
 

hippy

Technical Support
Staff member
Another trick for ensuring you don't ever miss pulses is to use an on-chip hardware counter to count them. Let that free-run, take the latest count, subtract the previous and you know how many there have been since you last checked. The on-chip counters can capture multiple sub-microsecond pulses which are sub-microseconds apart so you should not miss any.

The SETTIMER COUNT command is available for that purpose on the 28X2 and 40X2 and it may be possible to implement similar on other PICAXE by carefully controlling things and poking around directly with SFR registers.
 

Circuit

Senior Member
Regarding the minimal pulse width itself (and maximum rise/fall times) I have looked into the PIC datasheets to see whether there are some minimum timing requirements for the spikes to be registered by the latch module. Somewhat surprisingly, there was no info to be found. Maybe a small test with a second Picaxe generating a very fast spike using PULSOUT (and a scope to measure the real signal) would be in place to simulate a Geiger pulse (a 32MHz M2 can generate a pulse of just 1.25 us width)?

EDIT: Parallel post to Circuit ...
I too was surprised that this was not stated anywhere so I raised the issue directly with Microchip. Interestingly, the technician who replied also seemed a little perplexed that their datasheets did not offer this information and he could not find it available. He concludes; "That said, I'd guess the timing to be very short, since this is all digital circuitry. It is essentially just the propagation delay of a handful of digital gates. I'd expect it to be minimal, though I can't guess at a particular number. "
 

hippy

Technical Support
Staff member
I too was surprised that this was not stated anywhere...
There appears to be some related timing in at least some Microchip datasheets. For example the 12F1840 which would apply to 08M2+ has "OS20 - Tinp - INT pin input high or low time" and "OS21 - Tioc - Interrupt-on-change new input level time" both stated as 25ns minimum, "characterized but not tested".
 

Circuit

Senior Member
There appears to be some related timing in at least some Microchip datasheets. For example the 12F1840 which would apply to 08M2+ has "OS20 - Tinp - INT pin input high or low time" and "OS21 - Tioc - Interrupt-on-change new input level time" both stated as 25ns minimum, "characterized but not tested".
Wow, so I guess we are talking figures that really do not matter in any context that we could be working in. I calculate that a 25nS pulse of light is only seven-and-a-half metres long! Yes, that is indeed a pretty brief pulse! Having said that, and thinking laterally as most PICAXE players do I guess, my Leica Laser distance measurer has a resolution in millimetres. I understand that it works on the time-of-flight principle. I just wonder what sort of circuitry is being used to make sub-nanosecond measurements. Also, I guess that we are unlikely to see any PICAXE-based laser rangefinders appearing in the Finished Projects section anytime soon! Bottom line though, and getting back to the original question, is that Hertzhog's 40us pulses will trigger a PICAXE with no problem at all.
 

hippy

Technical Support
Staff member
I just wonder what sort of circuitry is being used to make sub-nanosecond measurements.
The usual trick I believe is gated charging of capacitors. Then all you need to do is leisurely read the capacitor voltage.
 

HertzHog

Member
I really was hoping to implement this pulse counter / rate meter project using The PICAXE-18 Tutorial Board (AXE049) in order to keep it really simple. BUT I think I am going to be frustrated because...
a) The SR SRInput and SRQ output latch pins are fixed in silicon terms to pins which are being used as outputs on this board (and which I am using, in the 7 segment display). These pins are not relocatable programatically?
b) The inputs have on this board also have a 10k resistor hard wired pulling them to ground which seems to be discharging my input capacitors before they trigger and are read by my interrupt routine.
As things stand, I can see the pulses with an optional LED which flashes, but the interrupt routine is not triggered by my pulses at all. However, I can produce pulses by hand to the input C.1 and from the other button pins (I assume because they are wider) which are processed just fine.
Frustrating... Any ideas? or is this just impossible?
 

hippy

Technical Support
Staff member
It may be the sensor output itself is pulling the capacitor down having activated it.

Detail your circuit and exactly how you have things wired and post your code and others can check there are no issues with those.
 

HertzHog

Member
Well I have built a dedicated pulse stretcher to about 5 milliseconds (apparently) and I can now detect the pulses and my code works. I am still tinkering, but at least I have validated my original question. "How long does a pulse have to last to be to be reliably caught by a polled interrupt?" (Leaving out the SR latch concept). And of course same question but with the SR latch. Before stretching I caught no pulses. HertzHog
 

Goeytex

Senior Member
Well I have built a dedicated pulse stretcher to about 5 milliseconds (apparently) and I can now detect the pulses and my code works. I am still tinkering, but at least I have validated my original question. "How long does a pulse have to last to be to be reliably caught by a polled interrupt?" (Leaving out the SR latch concept). And of course same question but with the SR latch. Before stretching I caught no pulses. HertzHog
I would say that what you have validated only applies to your particular code and not to Picaxe polled interrupts in general. It is highly likely that your code could be improved to reduce the time. However, you seem to have no interest in posting your code for others to review. Should you change your mind and decide to post your code I am sure that more help can be provided.
 

HertzHog

Member
I would / will post code but I just feel others would find it long and impenetrable. I thought my question was a hardware one really.
 

HertzHog

Member
Here is edited code to remove the stuff that runs and is interrupted.

OK, on request, here is the code...
FYI I'm happy with the full code in that it responds to button presses calculates and displays my data just fine. The problem is missed very short input interrupt pulses. No blocking commands present. Lots of pausing. No Naps. BUT, when sensor was connected NO pulses were caught at all. However, with a separate CMOS 4001 NOR chip based pulse stretcher and buffer it does now work. It is a shame I do not have access to the pins that can be configured as the SR latch input and outputs. I was hoping to do without the extra logic gates. I failed to stretch the pulses with just diodes and capacitors (might be too high an impedance?).

Code:
' Picaxe project AXE049 board Rate counter, timer, rate meter version 4 11/2014. 
' Much code is removed for clarity!
#picaxe 18m2
#no_data

#Rem
Purpose is to use as a counter, timer or rate meter. Polled interupt routine.
BUT native pulses are short and randomand were likely to be missed by a polled interrupt. 
"Output pulse width 40 µs to 150 µs "
SR latch pins are not available on the board I am using.

Question was how long must the interrupting pulse need to be to be caught by the poll?

Displays all info on a singe digit 7 segment display!
Program to create an interrupt driven counter in a continuous loop.

Buttons trigger interrupt too and Add, Subtract or reset. 
#EndRem

Symbol InterrupState = B1	' Grab the interrupt and freeze it! Test its bits later...


Begin:	' This is where it starts and is called after a reset button push too when time or counts are exceeded.
SetFreq m4	' Normal speed now...
EnableTime	' This is on by default anyway I think. But time may have been disabled before a called reset.
GoSub Interrupt 'Sets up Interrupt routine initially at initiation stage and Interrupt exits.

Main:	' This is the main repetitive loop after the initiation routine.
GoSub NumDisp	' Continuously show the current TallyCount (& RollOver if applicable) or rate.
' This is the bit that can and is designed to display but can be interupted when a new pulse comes in to count.
GoTo Main	' Continuous Loop...
End


Interrupt:'	Increment On a top button press Input6 
Let InterrupState = PinsC	' To capture the pins ASAP and then test at relative leisure...
' Want minimum of processing in here really. Note a interrupt specific tempory word
' InterruptTempWd so does not use or corrupt the alternative TempWord variable.
SetFreq M16 ' 16 MHz. Speed up through Interupt routine. As dead to next pulse till it exits..
Low 0,1,2,3,4,5,6,7	'Blank Display now (While Testing)
Let NewEvent = 1	' New measurement detected...

If Bit15 is On Then 'Input7 is on then ' Increments on TOP Push button (testing works)
	Inc PreScaleCounts ' Increment PreCounter by 1, does not matter if overflows,
	' A bit more stuf is here...
	
ElseIf Bit14 is On Then ' Input6 is on then ' Decrements on BOTTOM Push Button 6 (testing works)
	Dec PreScaleCounts ' Decrement PreCounter, does not matter if underflows,
	' A bit more stuf is here...


ElseIf Bit9 is On Then ' Input1 = SENSOR pulse Pulse! is on then ' Count pulse
	Inc PreScaleCounts ' Increment PreCounter by 1
	' A bit more stuf is here...

ElseIf Bit13 is off then ' Reset. Zero / Resets on RESET Button (Active press is Off unlike 6&7)
	TallyCount = 0	' Reset these three variables
	RollOver = 0
	PreScaleCounts = 0
	CountsToDisplay = 0
	' A bit more stuf is here...

EndIf

Do While Input1 is on or Input7 is on or Input6 is on or Input5 is off	' Must Wait here till button press is released
	Pauseus 10 'Wait till the calling button changes back to normal state.
Loop	' Ready to exit interrupt routine yet?

Let PinsB = 0	' Blanks the display which is on Port B
SetInt Or %11000010,%11100010	' Reset Interupt 7 On or 6 On or 1 On or 5 Off
SetFreq M4	' Back to normal 4MHz speed now
Return	' Back to where it was interrupted from...

' End of Program Code
I thought this was a hardware question and so I have removed most of the bit in the program that does anything useful like calculating and displaying but leaving the skeleton... HertzHog
 

rossko57

Senior Member
The code checks to see what caused the interrupt by reading pins.
This means that no matter how short a pulse might actually invoke the polled interrupt, that pulse also has to remain present for the duration of the interrupt subroutine call and the subsequent pins read. If it doesn't, you won't get the expected path through the If-Elseif code section.

It might be illuminating to end that If-Elseif with a plain Else to trap and somehow indicate an "orphaned" or unidentified pass through your interrupt routing.
 

AllyCat

Senior Member
Hi,

It is a shame I do not have access to the pins that can be configured as the SR latch input and outputs. I was hoping to do without the extra logic gates.
If you're desperate, there are other "spare" gates and latches on the chip, connected to other pins. But completely unsupported by PICaxe Basic and its documentation (except for POKESFR). Here are a few "hints", I won't give any more detail, because if you can't "fill in the gaps" then you'll probably struggle with the overall concept.

First, you would need to consult the "base" PICaxe data sheet (of the 18M2) for the pin (Leg) numbers of the "Digital Signal Modulator". Start with the Table of pin functions (on about page 7) and note the Leg numbers used for the "Modulator", three inputs and one output (MDOUT). If they look "available" in your application, then give yourself a fright by going to the "Simplified Block Diagram" at the start of the DSM section (23 for the 18M2, around page 195).

If you can see the "potential" of that block diagram, then you can start reading how it is configured using its four SFRs, In principle that's not too difficult, because the input multiplexers just need to select the input pins (or maybe the internal flag for the modulation input). The Exclusive-Or gates allow the (active) polarity of the input/output signals to be selected. I must admit that I've only been looking at the "gate" (inverter) possibilities, but the D flip-flops look to be usable as well.

Then you'll need to find how the SFRs are mapped into the PICaxe's pokesfr command (hint: I think they're $FC - $FF), write some test code and see if it works (note it will ONLY work with a real PICaxe, not the simulator).

Cheers, Alan.
 

Goeytex

Senior Member
Definitely not a hardware question IMO. Minimum pulse width that can be detected is determined by clock speed, firmware polling rate and your code.

Consider the following code:
Code:
#Picaxe 08M2
#no_data 

setint %00001000,%00001000   '// int on Pinc.3 high

do
pause 1000   ' waiting for interrupt
loop

interrupt:
    pulsout 2000,C.1       '//LED on Pin C.1 for testing
    setint %00001000,%00001000
return
The program above can reliably detect pulses of 80 us in duration with the Processor clock @ M4. However with the clock @M32 it can reliably detect pulses of 10us in duration. These are 'about' the hardware/ firmware limits as I am not motivated to test to the exact microsecond.

Your code , especially the omitted numdisplay subroutine along with the slow 4MHZ clock in the main sub are the primary reasons that a "pulse stretcher" is needed. Also the interrupt routine is rather bloated. The interrupt routine should be as short as practical. ie increment a variable , set a flag, ... and then move on.

If you will please post the ENTIRE CODE, (not just what you think we need), so that folks here can analyze it and offer specific ways for improvement.

Edit: That being said, I am not convinced that a polled interrupt is the best way to do this. Other have offered general advise about possibly using the SRLATCH/ Comparator, however nothing in the way of practical code examples. Still, it may be worth investigating.
 
Last edited:

HertzHog

Member
The code checks to see what caused the interrupt by reading pins.
This means that no matter how short a pulse might actually invoke the polled interrupt, that pulse also has to remain present for the duration of the interrupt subroutine call and the subsequent pins read. If it doesn't, you won't get the expected path through the If-Elseif code section.
Am I missing something? I thought I had frozen the state that called the interrupt just as soon as I could with my...
"Let InterrupState = PinsC". After that, I thought it should not matter if the calling state fades away, because...
After that I am testing the frozen state with...
"If Bit15 is On"
and it works with the buttons and once I have put in the pulse stretcher.
HertzHog
 

HertzHog

Member
Definitely not a hardware question IMO. Minimum pulse width that can be detected is determined by clock speed, firmware polling rate and your code.

Consider the following code:
Code:
#Picaxe 08M2
#no_data 

setint %00001000,%00001000   '// int on Pinc.3 high

do
pause 1000   ' waiting for interrupt
loop

interrupt:
    pulsout 2000,C.1       '//LED on Pin C.1 for testing
    setint %00001000,%00001000
return
The program above can reliably detect pulses of 80 us in duration with the Processor clock @ M4. However with the clock @M32 it can reliably detect pulses of 10us in duration. These are 'about' the hardware/ firmware limits as I am not motivated to test to the exact microsecond.

Your code , especially the omitted numdisplay subroutine along with the slow 4MHZ clock in the main sub are the primary reasons that a "pulse stretcher" is needed. Also the interrupt routine is rather bloated. The interrupt routine should be as short as practical. ie increment a variable , set a flag, ... and then move on.
OK. Thanks.

I DID try increasing the clock speed, but to no avail.

Re bloated interrupt routine...
As I have posted, I don't mind missing the occasional pulse that might arrive during the interrupt routine. That will introduce a bit of a systematic proportional and predictable error (which I can live with). My problem was the interrupt routine was not getting called at all.

I was hoping this project would do something practical clever and useful. I can't achieve anything useful with the constraints that the interrupt routine has to be 'light' as WELL as the main code that is interrupted! That would make any PicAxe lover weep.

I appreciate specific blocking commands might stop an interrupt call e.g. Nap and going to sleep but hope I have avoided these and the code is quite varied to my eyes. You would surely say the "the omitted numdisplay subroutine" is very bloated too BUT logically it can be interrupted and it just contains a variety of normal, if long and bloated, maths and conditional basic commands. There are lots of pauses too. Please, can you help me by saying what quality in it might stop it from allowing ANY interrupt calls to be generated because that is what would be very helpful to me and others.

I have not posted the entire code here because...
I have written and tested the logic so it can be EITHER a pulse counter, OR an up or down timer, OR a scalable rate meter (free running or one shot), just depending on flags that are set and what I want at the time. That I know would confuse anyone! Besides, I have that all that bit tested tuned tweaked and working. That bit works before the sensor is attached and with the pulse stretcher in place.

"Syntax check successful!

Memory used = 1414 bytes out of 2048"

Yes it is long and you might say bloated but I thought that should not in itself stop it from being interrupted.

The problem is that, I feared and then found, the interrupt routine was just not being called at all by my input pulses which were just not noticed at all till I stretched them. They are described as 'TTL' full voltage pulses so I thought they should have been picked up in terms of voltage rise and impedance (but I admit I am out of my depth here). I could easily see them just with an LED (I do realise a phosphor will extend the pulse as will POV), and taking away the LED to stop voltage being clipped did not help. A transistor buffer did not help either.

If you have tested your measurements above, what happens if you put more varied 'work' e.g. maths and conditional branches into the main program, rather than just pure pauses? If it reliably detects narrow pulses of the width I'm working with then there is indeed a simple answer to the original question. HertzHog

HertzHog
 

AllyCat

Senior Member
Hi,

I don't think any of us (except maybe technical) know what are the longest "uninterruptable" periods of the normal commands. Some commands can take many milliseconds to execute (at 4 MHz), but they are generally PE-created "macros" and probably poll the interrupts several times. However, surprisingly, any RETURN takes over 2 ms, so I would assume at least that period of "blocking" will occur.

If using the DSM module as a latch, the "Set/Reset" input(s) would be on Legs 10 and 13 (interchangeably) using an 18M2, with the output (either Q or /Q) on Leg 9. Are those pins "available" on your hardware?

Cheers, Alan.
 

Goeytex

Senior Member
If you have tested your measurements above, what happens if you put more varied 'work' e.g. maths and conditional branches into the main program, rather than just pure pauses? If it reliably detects narrow pulses of the width I'm working with then there is indeed a simple answer to the original question.
If the interrupt is enabled and a command is called that takes longer than the pulse to execute/complete, and the pulse arriveS and ends during that time, then the pulse will be missed. That means at 4Mhz any pulse less than about 250us. If the pulse is not active between commands, it will be missed. This is bad news for the kind of application you are doing. A Picaxe M2 is simply not adequate.

This is not the case with X2 parts using hardware interrupts (HINTSETUTP/SETINTFLAGS). With hardware interrupts, an interrupt flag bit is set when the pulse arrives, regardless of what is going on. The interrupt flag bit is checked continuously during pauses and between commands, so the pulse will not be missed.

If you want to do this with a Picaxe and interrupts, I would suggest you use either a 20X2 or a 28X2 with hardware interrupts.
 
Last edited:

hippy

Technical Support
Staff member
It should be possible to detect microsecond long digital pulses on any running PICAXE and have the program know they have occurred no matter what it was doing at the time without requiring external pulse stretching. The only pulses which would be missed would be those arriving whilst an existing pulse detection was being handled and that risk can be minimised. It should be possible to catch and handle hundreds and more microsecond pulses per second on any X2 or M2 PICAXE.

Some PICAXE's have HINTSETUP and SETTIMER COUNT commands which make this easier but it can be done by other means though some will require using POKESFR and PEEKSFR to provide for abilities which the PICAXE language does not support directly. Specific hardware pins may be required so it may not be possible with unsuitable hardware designs.

Though not supported by the BASIC language, the 18M2 has the capability to latch pin changes on any of the port B pins. I believe this can be used to flag short pulses, but does require a port B pin to be used as input, and the pulse detected flag has to be polled because it cannot raise an interrupt itself.

The AXE049 Tutorial Board, even though it has a seven segment display attached to all port B pins, should be usable by making the decimal point B.7 pin an input. There is an "OUT7" connection point to allow connecting an input ( or push button for testing ) and it even has the added advantage that the decimal point will flash on input signal going high.

This is obviously not beginner level stuff because it needs a good understanding of the underlying PICmicro hardware and the means to interact with that from a PICAXE program. There are sometimes firmware interactions which means that what might be possible is not in practice but in this case I do not believe there should be any unexpected obstacles but the proof would be in the doing it. If I can find the time I will see if I can produce proof of concept code.
 

hippy

Technical Support
Staff member
This works for me ...

Code:
#Picaxe 18M2
#Terminal 4800
#No_Data

Symbol IOCBP = $F4       ; $394
Symbol IOCBN = $F5       ; $395
Symbol IOCBF = $F6       ; $396

PokeSfr IOCBP, %10000000 ; Enable +Ve change on B.7
PokeSfr IOCBF, 0         ; No changes so far

Do
  SerTxd( #w1, CR, LF )  ; Report count
  Do
    PeekSfr IOCBF, b0    ; Read the change flag register
  Loop While b0 = 0      ; Wait until change
  PokeSfr IOCBF, 0       ; Clear changed flag
  w1 = w1 + 1            ; Count changed
Loop
It even works if you add SLEEP commands before the PEEKSFR, detects input going high on B.7 when sleeping.

The maximum rate of pulses detectable is determined by the rate that the IOCBF SFR is checked. That can be improved upon by increasing the operating speed, optimising the SERTXD to only output a byte at a time, reducing statements to the bare minimum and checking IOCBF more frequently, between every statement...

Code:
#Picaxe 18M2
#Terminal 38400          ; SerTxd at 32MHz
#No_Data

Symbol IOCBP = $F4       ; $394
Symbol IOCBN = $F5       ; $395
Symbol IOCBF = $F6       ; $396

#Macro CountInput
  PeekSfr IOCBF, b0      ; Read the change flag register
  If b0 <> 0 Then        ; Changed
    PokeSfr IOCBF, 0     ; Clear changed flag
    w1 = w1 + 1          ; Count changed
  End If
#EndMacro

SetFreq M32              ; Run as fast as possible

PokeSfr IOCBP, %10000000 ; Enable +Ve change on B.7
PokeSfr IOCBF, 0         ; No changes so far

Do                       : CountInput
  w3 = w2 /  10000       : CountInput
  SerTxd( #w3 )          : CountInput
  w3 = w2 /  1000        : CountInput
  w3 = w3 // 10          : CountInput
  SerTxd( #w3 )          : CountInput
  w3 = w2 /  100         : CountInput
  w3 = w3 // 10          : CountInput
  SerTxd( #w3 )          : CountInput
  w3 = w2 /  10          : CountInput
  w3 = w3 // 10          : CountInput
  SerTxd( #w3 )          : CountInput
  w3 = w2 // 10          : CountInput
  SerTxd( #w3 )          : CountInput
  SerTxd( CR )           : CountInput
  SerTxd( LF )           : CountInput
  Do                     : CountInput
  Loop Until w2 <> w1    : CountInput
  w2 = w1                : CountInput
Loop
Note that with such high speed checking, not having debouncing may cause multiple switch bounce pulses to be counted if a button is used for testing.
 
Last edited:

HertzHog

Member
Thanks. Available input pins are C.0 and C.1 on the Axe049 board this is connected to legs 17 and 18 I think.
Are these any good?
 

HertzHog

Member
Thanks Hippy,

It should be possible to catch and handle hundreds and more microsecond pulses per second on any X2 or M2 PICAXE.
Whilst this will help other's projects, for mine the pulse train is infrequent (I hope!) but random. I am measuring radioactivity you see. The worry is missing pulses because of their randomness and brevity while the program is doing other stuff. I felt this was a classic role for an interrupt routine. I was excited that a Picaxe seemed able to take this in its stride. HertzHog.
 

HertzHog

Member
Am I right in thinking the macro is expanded pre compilation? It appears after every instruction and the compiled program will then be expanded by its numerous copies too?
 

hippy

Technical Support
Staff member
The macro is expanded during compilation so, yes, it will add additional program code after each statement.

There are two ways to implement an application; select the hardware and write the program best suited to that or use less suitable hardware and make the program implement the application. That's often banging a square peg through a round hole so not always as ideal but can work.

I wouldn't use pin change flagging or an interrupt because that could lose pulses while the interrupt is being serviced and the the last change being acknowledged. Using an on-chip counter would be best. That can accept pulses as short and as close together as the physical chip silicon will allow without losing any. As long as you read the counter before 65,536 pulses occur you will never miss any.
 

HertzHog

Member
Thanks. Good advice. It seemed such an obvious use for an interrupt :( on my board.
I think I can re-engineer this project to use different hardware. One way would be to have a proper serial display driven by the second picaxe and then use the SR latch on the first and a spare leg to sense a reset.
But for now pulse stretching works...
I have just noticed some odd behaviour. Separate thread perhaps? Having disabled time with disabletime command (once a pre defined interval has elapsed) the time counter variable seems to increment! but not every second, and quite slowly. Has anyone else noticed that? Is it a 'feature' of a Nap?
 
Top