Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : Micromite: Measuring the Width of a Pulse
Page 1 of 2 | |||||
Author | Message | ||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
I got my PIC32MXF150 chips today and successfully loaded the firmware. Now I need to write a short program that measures the positive width of an incoming pulse. The pulse width will range from 10us to ~ 100us However to my dismay there is no "Pulsin" or related command in MMBASIC. I looked through the MMBASIC manual and found nothing related to measuring the width of a pulse. Certainly there is a way ? Any help or guidance would be appreciated. Bill |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
Yeah, you can pulse an output pin, but not sure if there is an equivalent pulse-in type command for an input. You are probably right - the most likely is a way - but I am not sure of it. Others will no doubt chime in here... I am guessing that you could setup an interrupt or other loop thus: DO If Pin(1)=1 then X=1 If X<>1 then Timer=0 Loop until Pin(1)=0 Print Timer This will measure how long it takes for the input pulse to go low again, and store it in the timer. However, this may not work if the pulse period is shorter then the code's ability to measure it.... If it DID work, you could make expand-and-perfect this sample code, and make it a sub or function. EDIT: I have bugs in my loop above... I am playing with it now. Smoke makes things work. When the smoke gets out, it stops! |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
OK, try this: SetPin 1,2 X=0 Start: DO If Pin(1)=1 then If X=0 then Timer=0 X=1 Endif Loop until Pin(1)=0 X=0 Print Timer Do:Loop until Pin(1)=1 Goto start UNTESTED - I will have a go on the MM now with this. This should work, but it depends on how narrow the pulse-width is, and the fact that this code has to run may actually mean that the returned result is meaningless.(because it takes time to run the code, which will probably mean that the returned result won't be EXACTLY right - all speculation. I need to run some tests.) EDIT: Code edited, and this is working fine for button-press type testing, but again - depending on the pulse period, this idea might not be any use. Kinda depends on how much accuracy you need. The next test I will do, will be using a MicroMite chip, to pulse the MaxiMite in place of the switch, as I can have a pulsout kind of command of a known length, and then see what the MM comes back with. Smoke makes things work. When the smoke gets out, it stops! |
||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
Hi Grogster, I see that with "setpin" that frequency(FIN) and Period(PIN) can be measured, and with (CIN) that pulses can be counted. However, nothing in the manual even suggests a command or function that can read the width of a single pulse like other BASICS that usually include a PULSIN or similar command. And unfortunately the manual only lists the commands and offers little to nothing in the way of code examples for each command. It seems that using the MMBASIC "timer" for short pulses will be fruitless as the timer resolution is 1ms. I simply cannot imaging a having really nice 32-Bit Processor operating at 40Mhz and it not being able to measure the width of a pulse from 10us to 100us with a resolution of 1 - 2us. Certainly there is a way that I am missing ? Even the lowly Picaxe 08M2 "Pulsin" can read the width of a pulse with a resolution of 1.25us. |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
Perhaps Geoff will chime in here....(although, I think he is on holiday at the moment) Might be something that could be added to the language in the next release? Copy that. Smoke makes things work. When the smoke gets out, it stops! |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3196 |
Yes, that sounds like a good idea. I presume that the PICAXE pauses while it is waiting for the leading edge and is measuring the length of the pulse. On the Micromite/Maximite that would disable interrupts during that time - but other than that I cannot see any issues. Geoff Geoff Graham - http://geoffg.net |
||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
[quote]I presume that the PICAXE pauses while it is waiting for the leading edge and is measuring the length of the pulse. On the Micromite/Maximite that would disable interrupts during that time - but other than that I cannot see any issues.[/quote] Yes, it is a blocking command. A nice feature would be to allow the programmer to define the timeout period to improve program flow and eliminate long waits. variable = pulsin (pin,state,timeout) Where state either high (1), or low (0), and timeout is in ms Example: x = pulsin (11,1,5) Measure the width of the next high pulse (in microseconds) on Pin 11. If no edge detected within 5ms then return a value of zero and continue. Thanks Bill |
||||
WhiteWizzard Guru Joined: 05/04/2013 Location: United KingdomPosts: 2817 |
In your example, how would you see best to deal with a high edge being detected within 5ms but then doesn't drop to low (0) again for a 'long' time? Do you need another timeout? As a coder I can appreciate that you need to cover all possible scenarios otherwise the firmware could get 'stuck' in an endless loop. x = PulseIn (11,1,5,100) gets 'messy' but the 100 parameter to mean 100mS timeout once leading edge detected. WW For everything Micromite visit micromite.org Direct Email: whitewizzard@micromite.o |
||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
[quote]In your example, how would you see best to deal with a high edge being detected within 5ms but then doesn't drop to low (0) again for a 'long' time? Do you need another timeout?[/quote] I can tell you how the Picaxe does it. The timeout is fixed and based upon processor speed. With the default CPU Speed of 4Mhz each pulsin unit is 10us. The timeout is (65535 * 10us = .655 seconds). This same timeout period is used if no edge is detected, or if the timer overflows after the edge is detected (pulse is > .655 seconds). If the CPU speed is increased to 32Mhz each pulsin unit becomes 1.25us and the fixed timeout period is reduced to 1.25us * 65535 or about 82ms. The timeouts could be: 1. Fixed (as with the Picaxe) 2. A single user definable value for both timeouts 3. Two user definable values as you indicated 4. A user definable value for waiting and a fixed value if the pulse too long. The problem with a single fixed timeout value as with the Picaxe, Is that if an expected pulse does not come when it is supposed to, the program is halted for up to .655 seconds. For example, reading a servo signal. We know that the frame is ~20ms. If the receiver fails and there is no positive pulse, the program will stop execution for .65 seconds before it returns a fault (value of zero). If a timeout of 30 is used then program execution is not unnecessarily halted and can move on to other tasks. Ideally I would have the command as: x = pulsin (pin,state,[t1,t2]) where t1 and t2 are the optional timeouts, and if omitted, a reasonable fixed timeout is automatically implemented. However, this is more complicated to implement in firmware. In any case, any Pulsin type command/function would be a welcome addition to MMBasic. Not being able to read the width of a pulse with reasonable accuracy & resolution is a deal killer for me, as many of my projects depend upon it. |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
Don't despair! Looks like Geoff will add this to a future MMBasic update so it would seem, although, I am not sure of how long that will take, as Geoff is a busy boy. I'm surprised, actually, that this pulse-in type of command has not been found and discussed before now.... Generally speaking, if you have a pulse-out command(which MMBasic does have), then usually you have the matching pulse-in, but it obviously just was not thought about or seen as necessary before now. It's good you came along and wanted it, cos it will then become an extra feature once it is implemented. For the record, I also like your command syntax with the options idea. It just remains to see how involved those extra options are to implement. Smoke makes things work. When the smoke gets out, it stops! |
||||
robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2350 |
geoff: would it not be possible to make use of one of the 32-bit timers (timer2/3 or timer4/5) with an external gate input for timing pulse lengths? so when pin x is high the counter counts up at a set rate (8MHz perhaps, giving a maximum interval of a little over 2 seconds); while when pin x is low counting is inhibited. this would provide the basic functionality of measuring a pulse width, without making the code too task-specific and closing off other uses. i am looking at "FIGURE 13-2: TIMER2/3, TIMER4/5 BLOCK DIAGRAM (32-BIT)" on page 156 of the revision F datasheet. as far as how to implement the code: simply create a procedure thus: FastCount gate_pin, polarity [,prescaler] where gate_pin is the number of an input pin (already assigned as a digital input using SETPIN), polarity is either 'H' or 'L' to indicate when counting should be enabled), and prescaler is an optional prescaler for a slower count rate. allow reading of the counter using the pseudo-variable FastCountX. using the above scheme, the fast counter could be used across several pins, just not more than one at once, much like the A/D converter is multiplexed. if there is not a free 32-bit timer, the use of FastCount could be made mutually exclusive with other functions that clash. the syntax "FastCount OFF" could be used to restore the previous functions when finished with timing. such a functionality would also make for a neat way to implement a stopwatch. rob :-) |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3196 |
There are no spare timers but the timing would be easy to do using the core timer as a counter. This is how other timing (such as the DISTANCE function) works and the same principal can be used for PULSIN. Geoff Geoff Graham - http://geoffg.net |
||||
robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2350 |
what functions are the various timers used for at the moment? rob :-) |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3196 |
Timers...................................................... .....
TIMER NBR DESCRIPTION INTERRUPT core Used by the uSec() macro no 1 IR Decoder no 2 Used by PWM channel 1 no 3 Used by PWM channel 2 no 4 MMBasic clocks and timers yes 5 COM2 serial interface yes Request the source, it is all in there. Geoff Graham - http://geoffg.net |
||||
Geoffg Guru Joined: 06/06/2011 Location: AustraliaPosts: 3196 |
I experimented with adding the PULSIN command to the Micromite and it was quite simple, so attached is V4.5D Beta 1 which includes the command. I have to do some more work on the firmware before I can make a general release but I thought that the readers of this thread would appreciate having access to this command before then. 2014-05-19_090008_Micromite_V4.5D_Beta_1.zip This is identical to V4.5C with the addition of PULSIN. The manual entry is: a = PULSIN( pin, polarity [, t1 [, t2]] )
Measures the width of an input pulse from 1uS to 1 second with 0.1uS resolution. 'pin' is the I/O pin to use for the measurement, it must be previously configured as a digital input. 'polarity' is the type of pulse to measure, if zero the function will return the width of the next negative pulse, if non zero it will measure the next positive pulse. 't1' is the timeout applied while waiting for the pulse to arrive, 't2' is the timeout used while measuring the pulse. Both are in microseconds (uS) and are optional. If 't2' is omitted the value of 't1' will be used for both timeouts. If both 't1' and 't2' are omitted then the timeouts will be set at 100000 (ie, 100mS). This function returns the width of the pulse in microseconds (uS) or -1 if a timeout has occurred. With a CPU speed of 40MHz the measurement is accurate to +/-0.5% and +/-0.5uS. At other speeds the measurement is slightly less accurate. Note that this function will cause the running program to pause while the measurement is made and interrupts will be ignored during this period. Thanks @Goeytex for the suggestion, as you can see, I implemented it as you proposed. Geoff Geoff Graham - http://geoffg.net |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
Wow - yet AGAIN, Geoff, you amaze us all....... I bet Goeytex will be happy to read this thread. Are you still on holiday, or are you back home now? Smoke makes things work. When the smoke gets out, it stops! |
||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
@Geoff Based upon my experience with other vendors/platforms, I was expecting months or weeks or even nothing at all, instead of a day or two. Your response to this is unexpected and very much appreciated. Having a Pulsin command allows the Micromite to be used in a multitude of applications where it could not be used before. For example, with a single hall sensor on a flywheel, the pulse width can be measured and the velocity (RPM) can be determined within < 1 rotation of the flywheel. (Ignition system / rev limiter / PID Control). Another might be a servo mixer. There are many many more. Having such good resolution/accuracy along with user control of the timeouts makes the MMbasic Pulsin command better than any other out there. Many thanks, Bill |
||||
Grogster Admin Group Joined: 31/12/2012 Location: New ZealandPosts: 9308 |
Geoff is very proactive - it never ceases to amaze me....(and others, no doubt) Smoke makes things work. When the smoke gets out, it stops! |
||||
robert.rozee Guru Joined: 31/12/2012 Location: New ZealandPosts: 2350 |
good work geoff! any chance this might mark the beginning of a few other small tweaks? i'd love to see the option to select the internal band-gap reference for analog inputs - easiest bet would be to return the raw A/D value (0..1023) when using the internal reference, with -1 being returned if an overflow, and "OPTION REF 3V3 | INT" to select between reference sources (defaulting to 3V3 on powerup). it would then be up to the programmer to handle scaling and any calibration when using the band-gap. please, please, please :-) i'm after being able to use the analog inputs in a useful way while running on 2x AA batteries. rob :-) |
||||
Goeytex Regular Member Joined: 12/05/2014 Location: United StatesPosts: 74 |
I loaded the V4.5D Firmware and ran a simple PULSIN test. A Picaxe was programmed to generate a short positive pulse. Results: [code] $2000 TEK Scope: 13.02us Saleae Logic: 13.0625us Micromite Pulsin: 13.3us [/code] This is excellent! The Microcmite code can be easily modified to provide a resolution of 1us which should be adequate for most applications. Sample Test Code: [Code] '========================= 'PULSIN TEST '========================= CPU 48 do a = cint(pulsin(15,1) print a pause 1000 loop [/code] Bill |
||||
Page 1 of 2 |
Print this page |