Maths Problem

neiltechspec

Senior Member
Following up on my model railway scale speed display, I seem to be having trouble
trying to get my head around the maths required.

The start & stop timing sensors are 100mm apart, N guage scale is 1:148. So I calculated this to be 1 Sec = 33MPH.
The problem I'm having is how calaculate the numbers for example:
at half this speed, 2 sec is 16MPH
twice this, 0.5sec is 66MPH

Shouldn't this be a linear relationship & how do I do the calculations.

Start pulse sets a counter running, Stop pulse stops the counter.
So do I count up or down, obviously the count will be smaller for faster speeds.

What I have so far is good at 33MPH, reads low at 16MPH & reads low at 66MPH.

Code:
main:
    b0 = 0
    pinsC = %01000000
    do
    if sens1 = 0 then goto clockwise
    if sens2 = 0 then goto anticlock    
    loop

clockwise:
    pinsC = %00000000
    high dp
    do
    inc b0
    pause 18
    loop until sens2 = 0
    low dp
    goto display
    
anticlock:
    pinsC = %00000000
    high dp
    do
    inc b0
    pause 18
    loop until sens1 = 0
    low dp
    goto display

display:
    b1 = inv b0
    b2 = b1 / 4
    bintoascii b2,b25,b26,b27
    sertxd("b0:",#b0," b1:",#b1," b2:",#b2,"  MPH :",b25,b26,b27,cr,lf)
    goto main
Any help appreciated.

Neil.
 

Aries

New Member
b1 = inv b0
b2 = b1 / 4
I have to say I can't follow your arithmetic. INV is effectively a NOT function - it changes all the 1-bits to 0 and all the 0-bits to 1. For bytes, this is equivalent to subtracting from 255. So, if b0 = 123, b1 = 132 and b2 = 33 (which is what I imagine you have).

However, if the speed is half, the count is twice, so b0 = 246. This makes b1 = 9 and b2 = 2.25.

You don't want a logical inversion, you need an arithmetic inverse (i.e. the result of dividing one by your value)

What I think you need to do is establish what the count is for 33 mph (say 123 as above). Then what you need to get b2 is:
Code:
b2 = 123*33/b0
 

neiltechspec

Senior Member
Thanks,

You are of course correct, a logical inversion is not what is needed. I was just playing with numbers.
The count for 33mph is 112, 66mph is 55, 16mph is 223.

Your solution of b2 = 112*33/b0 is pretty good - simple really, why couldn't I see that !!!!.
Now gives 67mph for 0.5 sec & 16mph for 2 sec. Plenty accurate enough.

Not much point in going a lot below 16mph, N Guage don't like going much below that anyway.

Neil.
 

AllyCat

Senior Member
Hi,

I did actually tell you that in #3 of your previous thread:
..... to calculate a speed, you need to DIVIDE by the time taken (the longer the time, the slower the speed) and the "best" practical divisor is only a few hundred with PICaxe Basic, so you may need to measure in, say, 10 ms units.
For best accuracy or resolution you need to create a "calibration constant" approaching (but not greater than) 65535 and then divide it by the time taken, so IMHO 123 * 33 is not large enough (perhaps because your time value is too small a number).

Cheers, Alan.
 

neiltechspec

Senior Member
Obviously I missed that bit.

I tried what you suggested & it seemed to make accuracy worse at higher speeds for some reason.

It doesn't actually have to be that accurate (no speed cameras on a model railway !).

So I'll stick with what works, which gives a reading of 16 @ 2sec, 33 @ 1sec and 67 @ 0.5sec, which is fine for steam locos.

Neil.
 

AllyCat

Senior Member
Hi,

If 112 * 33 / period is giving a result of 67, then presumably the timed period is "55". That means that above about 60 mph, a few speeds will never be displayed, for example I believe 65 mph. Or you could "round" the result to the nearest integer, but then some other values will be "missing".

Of course if you do measure the period to higher resolution (and the key word here is "measure", not simply multiply up), or if you want to show speeds below 15 mph, then you will need to record the time period in a Word variable (i.e. > 255).

Cheers, Alan.
 

inglewoodpete

Senior Member
If you have an area of EEPROM that is still not used, set it up as a lookup table. Getting a value out of a lookup table is quicker than mathematical equations, particularly division. This is particularly useful when the calculated values do not conform or the maths starts getting complicated.

I have used a lookup table to provide logarithmic sequences for LED light values so that the LED's brightness to the human eye appears proportional.
 

neiltechspec

Senior Member
I will experiment further in a few days, when my new cheap chinese pulse generator arrives,
replacing the cheap chinese pulse generator that has just died this morning.

Neil.
 

AllyCat

Senior Member
Hi,

The issue here is that the maths is NOT complicated, but the input data is "logarithmic" and the output data is linear, which is not favourable for a lookup table method. I did post a code snippet to do a "Reverse Lookup" to get from a (Log) Word range back to a (Linear) byte value, but that's well outside the scope of this thread. The OP does appear to have limited his measurement data to a single byte value, which is why the minimum measurable speed is 15 mph, but there will be "gaps" between the displayed integer values above 60 mph.

Since the measurement period is (up to) 2 seconds, the computational speed is hardly relevant, but the numerator (112 * 33) can be pre-calculated so the execution time (of 3696 / timedelay) is around 1.5 ms (with a 4MHz setfreq). Even Rounding the result to the nearest integer can be done in less than 4 ms, for example : speed = timedel / 2 + 3696 / timedel, and since all PICaxe internal calculations use 16-bit (Word) values, the resolution could be increased by a factor of 10 (almost 20) with no impact on execution times (except for the display of a "decimal place" if one decided to do so).

Cheers, Alan.
 

Aries

New Member
Let's start by asking what you want to achieve - what is the range of speeds you want to measure, and what is the granularity (do you want to see every speed within a range, or are you prepared to have "gaps" - e.g. 66, 65, 63, 62, 60)?

Assuming you want to measure speeds up to a maximum of 100mph, with a granularity of 1 (i.e. no "missing" values).

You will have a pulse count for a speed of 100mph - let's call it P. Then, for a speed of 99mph, your pulse count will be

P * 100 / 99.

You need this to differ from P by at least 1, otherwise you won't be able to distinguish 99mph from 100mph.

So,

P * 100 / 99 - P >= 1

or

P * 100 - P * 99 >= 99

so P >= 99.

This is the pulse count you have to achieve if you want to measure speeds up to 100mph with a granuarity of 1.

You can increase your pulse count in two ways - by increasing the speed of the Picaxe (use the setfreq command) or by reducing the size of your pause.

Your calculation is then

b2 = 100 * 99 / b0

Picking up on Alan's points - you would be better using a word variable, because your counts will often go over 256. Also - what happens if your train stalls in the measuring section? Your loop will never terminate. I suggest you add something to check if your count has exceeded (say) 10000, and terminate at that point - which, with the numbers I suggested, would give you a speed of zero.
 

neiltechspec

Senior Member
I am already running @ 16Mhz & have already changed to a word and decreased the pause from 18 to 2.

This gives the ability to measure below 16mph for what its worth on the longest straight section of track.

Everybody seems to keep forgetting, it's a N Guage Railway. They don't like running very slowly so
there is very little point in measuring much below about 10mph. Out of the 6 Loco's I have (all steam),
only 1 will run reliably below 16mph anyway.

N Guage are very fussy about how clean the track is, the slightest bit of dust can stop them,
the slower it goes then the worse it is.

Do people have any idea how slowly, in real time, a speed of 16mph / divided by 148 is ??.
It's 0.0108 real mph. A small spider can walk quicker !.

I said from the outset (in another thread) that accuracy is not that critical, it just an approximate guide of the scale speed.
Whether it reads 99 instead of 100 is irrelevant.

A valid point about stalling in the measuring section though, as it's only 100mm the chances of that are remote.
I may alter the code to catch that (w0 = 65535).

Thanks for your input anyway.

Neil.
 

AllyCat

Senior Member
Hi,

Some of the "art" of writing good computer programs is to cover all eventualities (commonly known as making them "bomb proof") and preferably with no need for the user to read an instruction manual (RTFM). Of course that's not "essential", but IMHO something to aspire to, particularly when it's not difficult to achieve. There are of course also people who intentionally try to "break" any program that they encounter. ;)

Here, we presumably have a two-digit display (7 segments?) which can obviously display up to 99. Maybe none of the current locos can achieve that speed, but it doesn't seem unreasonable to make that a target in case you get a faster one in the future. Certainly one might not expect the speed to be accurate to within 1 mph, but a "reasonable person" (who hasn't RTFM) might expect the numbers to "run in sequence". If you read the Microchip Data Sheet for our PIC(axe) chips, they specify that their ADC is "Monotonic" with "No Missing Codes" (i.e. the digits run in sequence); isn't that what most people would expect ?

To cover all eventualities, I would expect a speed of greater than 99 mph (maybe somebody cheated) to display something like: "E5" (Excessive Speed), and of course "E" (Error) codes often indicate that the Program knows that something unexpected has happened. Similarly, you might want to do something if the speed measures unusually low. The problem with waiting until the measured speed has dropped to zero is that you (or the program) won't know that for over 30 seconds (if 33 mph = 1 second). Even worse, waiting for a count of 65535 at 112 pps will take around 10 minutes!

I'm surprised that 16 MHz was needed to measure 112 counts/second; I would expect a 9ms loop to be possible at 4 MHz. If that's pushed to 200 counts/sec, then you can measure 100 mph in half a second (with no missing codes) and 10 mph in 5 seconds (with a count of 1,000 dividing into a calibration constant around 10,000). That's a reasonable time to wait before displaying an "Exception" message such as "<9", or "US" (Under Speed), " 0", or just another Error such as E0.

Cheers, Alan.
 
Top