Pololu micro timing pulsed inputs on analog input

Will I be able to measure the interval between 1ms wide pulses on an analog input to the pololu micro using the ms timer?
the best accuracy I need is 1ms. the pulses will be from 100ms apart to 1500 ms apart.
thanks.
I’m using the analog input as some of the pulses will be 0.6v down to 0.4v and some will be 0.6v up to 0.8v and by discriminating between them I’ll attribute the input to the appropriate channel. ( ie: v<0.5 time1 v>0.7 time2 )
thanks.

I should mention that the program will have nothing else to do until it determines the two intervals. then it will store the intervals as “servo pulse widths” so they can be read via the usb port. After this a short routine will run to set a servo position based on these values and then it will go about collecting those two numbers again - depending on the individual periods, from between once every 2 seconds to once every second.

Hello,

Are you talking about the Micro Maestro? The Maestro can only execute a few thousand instructions per second and the analog inputs are only sampled a few thousand times per second (less often the more you have enabled, by the way), so it might take you 1ms to test whether your signal is high or low. Also, you can never get 1ms accuracy with a millisecond timer, since the start and end times will each be off by up to 1ms.

You might be able to pull it off if your application does not have strict requirements and you are a clever programmer - but then it would make more sense to use a fully programmable microcontroller board like an Orangutan.

-Paul

yes, the micro servo controller.
well, if the analog inputs are sampled a few thousand times per second - that’s plenty. If it’s sampled a thousand times per second, that’s good enough for me.
the ms timer is a bit marginal. how fast can I execute a simple count loop which also checks the value of the analog input? can I improve the resolution to 0.5 ms?
Like I said - it has nothing else to do until this number is determined. not that I need 0.5 ms resolution, just 1 ms - but to generate an accuracy of 1ms… this is the extreme case however and most of the time 3ms accuracy is enough unless the pulse period gets very short.

Something like this?

sub kmh
1 get_position 100 less_than
return

sub cadence
1 get_position 300 greater_than
return

sub kmprd
5 delay
2000
begin dup while
1 minus
kmh if minus 4 servo return

repeat
return

sub cadprd
5 delay
2000
begin dup while
1 minus
cadence if minus 3 servo return

repeat
return

begin

kmh if kmprd drop

cadence if cadprd drop

# other things I have to do with the information I have collected. Note that 4 and 3 servo are just storing the values so they can be read by the usb port.
# also, the actual ms does not matter, just that I have a number proportional to the period between pulses.

repeat

Please include “Maestro” in the name of the servo controller, or you are likely to get it confused with our older micro serial servo controller or some other product.

Your code includes several loops and various functions, and I do not think it will work as written, but I count about 13 instructions in the loops, so they could take up to several milliseconds to execute. Maybe you can make it a little faster if you rearrange the loops, but the Maestro scripting language is not really designed for the kind of accuracy you are asking for. I would say that 0.5ms is definitely out of the question.

-Paul

By the way, it is probably faster to skip the script and just read the value of your analog input continuously over USB. Also, our USB AVR Programmer includes what we call a “SLO-scope” - a feature for reading analog values on a sub-millisecond timescale, so maybe that would be a better product for you in this case.

-Paul

can you tell me how many instructions per ms it is capable of?
if the timing is that long, I’ll have to go back to the ms timer method…

also, it looks to me like 1 have 7 instructions in a timing loop - which increases only when the conditional branch causes the exit.

decrement the count
test if the input is less than the trigger or branch and exit
repeat

I cannot say any more than “a few instructions per millisecond”, since every instruction is different and there are even differences depending on the values of the arguments. Also, if the processor is busy doing other things like generating servo pulses or communicating over USB, that will slow it down, too.

As for 7 vs. 13 or so - don’t forget to count the instructions within the subroutine - that takes time, too!

-Paul

If I use the ms timer instead, I would use this as a subroutine then:

sub kmprd
get_ms
5 delay

begin
1 get_position 300 greater_than
if get_ms minus 4 servo return endif
repeat

return

what chance does the loop part have of executing at least every 2 ms? ( notice I’m setting my target lower… )

This is the cleaned up code…?

begin
# i am watching two pulses - one increases the voltage from 0.6v the other decreases the voltage from 0.6v and I need to time the interval between same polarity pulses.
# the pulses are in continuous trains, and i will monitor one set, then the other and once i have the two time intervals will do an operation that will set a servo.

1 get_position 100 less_than if kmprd endif

1 get_position 300 greater_than if cadprd endif

# now we use the speed increment to set 5 servo to the correct position

repeat

sub cadprd
get_ms
5 delay
begin
1 get_position 300 greater_than
if get_ms minus 4 servo return endif # the time difference in ms is stored as a servo setting
repeat

sub kmprd
get_ms
5 delay
begin
1 get_position 100 less_than
if get_ms minus 3 servo return endif # the time difference in ms is stored as a servo setting
repeat

Like I said, I cannot specify it better than “a few instructions per millisecond”. Your code has about 6 instructions in the main loop, so it will probably take less than 3ms, but I really cannot promise even that much. It sounds like you should just get one and try it!

-Paul

it should be here on tuesday…

By the way, I can do a limited test tomorrow to see approximately how fast this particular code runs on average, but I will not be able to promise that it will execute the code at this speed consistently, even while the Maestro is doing other things, or that the resulting time resolution is actually good enough for your application.

-Paul

Hey -I’d appreciate that! this is the first code I’ve written for pololu, as you might have guessed.

It works perfectly. I had to increase the initial delay to 60ms as this is the dwell of either the reed switch or the A/D converter. I’m not sure which at this point.

That’s great to hear, and I am sorry I forgot to to the test. I tried this loop just now:

begin
1 get_position 300 greater_than
if get_ms minus 4 servo return endif
repeat

and found that it was able to run in about 400 us on a Micro Maestro and about 550 us on a Mini Maestro 24. What kind of timing precision are you seeing?

-Paul

1ms precision would be ideal, but even 2ms gets me beyond 95% of the conditions I would expect to encounter.

sorry, I misread you - you asked what I was seeing, not what I was seeking.
I am not certain yet. I am comparing it to a digital tachometer, which has quite a lot of latency, as it updates only every couple of seconds.
When I have a helper, then I’ll be able to compare more precisely, but it appears to track pretty well. This is a hand driven thing so I have a hard time keeping it steady
while looking at the computer screen - but I expect certain things to happen with my servos at certain speeds, and I can see those things happening quite accurately - even though I can’t monitor the screen at that time. A rig to simulate a constant speed would be nice. I believe at this point that it is at least as accurate as I need.

I’m using the ms_timer code rather than a counter… but it sounds like a counter could give better granularity - as long as the repeatability is there.