Shop OBEX P1 Docs P2 Docs Learn Events
Calculation goes wrong (Float32) - Page 2 — Parallax Forums

Calculation goes wrong (Float32)

2»

Comments

  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-22 12:12
    but why calculate the distance to update through the speed? why can't it be statically?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-22 12:43
    So no output to the lcd, all over the place, as you said?

    You calculate the distance by assuming that the speed in adjacent loops
    is constant, that is, if you miss a pulse, you assume the speed is the
    same as the next pulse that you don't miss. That way the distance is
    more accurate.

    If you increase the distance by a fixed amout for every pulse you see,
    then the distance is not increased for·missed·pulses, so distance falls behind.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-22 13:09
    Ah oke, I get it, what you've written is quite a piece of code! But I think it missed the pulses when the buffers where too big, so it took some time to print the whole buffer, this is why it missed the pulses. I will ask my teached if it's nessary to add the security to it. This is my first project and working with javelin so not very good at it. It's not supposed to be very accurate and precise so i will get back to you on this.

    Very much thanks for all the explanations and codes.

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-22 13:18
    Correct me if I am wrong, but in an other thread
    http://forums.parallax.com/showthread.php?p=581618
    where you tested your sensor,
    the output of the sensor was a low going pulse, with a fixed high level width of three 8.68 uSec ticks,
    and a variable low level width that was proportional to speed.
    So I would think that speed = K * passed rather than speed = K/passed.
    Or do you have another sensor now?

    regards peter

    Post Edited (Peter Verkaik) : 5/22/2006 1:22:01 PM GMT
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-23 12:32
    Hey Peter,

    I use the same sensor as before, every time a new low pulse is detected the passedMS is meassured.

    You know now that the bike moved 1 (circumference of wheel).

    I used a static 2 meters as circumference, lets assume the passedMS is 250 ms.

    (2/250)*3600 gives the speed in km/hr. (28.8Km/hr)

    (4 pulses in 1 second gives 4x2 8m/s > 8/1000*3600 = 28.8 Km/hr)

    So why should I use k*passed?

    It works fine

    Thanks Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 12:55
    In the other post you got large values for pulseIn() at high speed
    while getting low values for pulseIn() at low speeds.
    Since pulseIn() measured the time of the low period of a pulse,
    that should yield the same result as manually waiting for
    high->low->high using the Timer().
    With pulseIn() longer time corresponded to higher speed (see other thread).
    With manually timer you say smaller time corresponds to higher speed.

    The easy test is to drive your bike wheel at a low speed for a few seconds and noting the
    calculated speed. Then drive your bike wheel at a higher speed for a few seconds
    and see if the calculated speed increases or decreases. If it decreases at the
    higher speed, then you must use k * passed, because it must increase.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-23 13:14
    I did that and the speed increased when the passedMS got smaller.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 14:17
    In that case you could replace

    ····· while (CPU.readPin(SensorPIN)); //wait for pin low
    ····· t.mark();
    ····· while (!CPU.readPin(SensorPIN)); //wait for pin high
    ····· passed = t.passedMS(); //retrieve ms between pulses

    by

    ····· int r·= CPU.pulseIn((short)0xFFFF,SensorPIN,false); //measure time pin is low
    ······passed·= r/115; //115 ticks in 1 msec
    ····· if (r<0) passed += 569;·· // r is really unsigned, so if r<0 (0x8000-0xFFFF) then
    ······································· // r/115 equals ((65536+r)/115) = 569 + r/115

    The pulseIn is more accurate because the time is measured by a native method.
    Also, the pulseIn() allows to specify a timeout value, so this method always
    returns even if the speed drops to 0 without generating a pulse (the while not pin high will
    then hang, the pulseIn will timeout)

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-23 14:29
    is this timeout not possible in the while loops?

    This was also one of my points that i wanted to investigate.
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 14:42
    Sure, but that creates even more overhead (and thus time) between
    detecting the low edge and the high edge, so that makes your
    timing measurement less accurate.

    Lets calculate what pulseIn() yields:
    If pulseIn() times out, it returns -1 (eg. 0xFFFF) so passed = 569 or speed = 12.6 km/h
    This shows you cannot use pulseIn·because the lowest speed measured is 12.6

    So, it·looks you do indeed need to check for timeout during the while loops.
    You can use another timer for that.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-23 21:09
    So how do i get out of a loop, not all loops?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 21:47
    You can do that as in the attached program.
    Note that the display is only updated if a valid pulse
    has been detected. It uses the distance calculation
    that allows for missed pulses.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-23 22:19
    I also need to add the time to the bikecomputer. My first idea was to do it like this:

    adding passedMS when certain ms is reached the seconds will be increased and the ms -. and so on with minutes and hours.

    Is there another way or is this the only way, it seems very inaccurate with my first test with this code:


    int timerMS;
    int timerS;
    int timerM;
    int timerH;


    timerMS = timerMS+t.passedMS();

    if (timerMS >= 2000){
    · timerMS = timerMS - 1000;
    · timerS – timerS + 2;}
    if (timerS == 60) {
    · timerS = 0;
    · timerM++;}
    if (timerM == 60) {
    · timerM = 0;
    · timerH++;}


    The 2000 let me have pulses to 2000 ms apart. So it won't meassure below 3.6Km/h.

    thanks Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 22:59
    There is a software realtime clock class here (SoftwareRTC.java)
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/peripheral/rtc/

    From the SoftwareRTC class:
    ·* In a tyical application, implementation might look like this:
    ·*
    ·* <code>
    ·*·· public static void main() {
    ·*···· int time,prevTime,baseTime,intervalYime;
    ·*···· Calendar cal = new Calendar(hundredth, seconds, minutes, hours,
    ·*································ day, month, int year);
    ·*···· SoftwareRTC sysClock = new SoftwareRTC();
    ·*···· sysClock.setClock(cal);
    ·*···· Timer tics = new Timer();
    ·*···· tics.mark();
    ·*···· prevTime = tics.tickLo();
    ·*
    ·*···· while (true) {
    ·*······ baseTime = (short)49671;
    ·*······ if (tics.timeout(1,basetime)) { //timeout 1000 millisec
    ·*········ tics.mark();
    ·*········ time = tics.tickLo();
    ·*········ intervalTime = (time-prevTime)>>>2;
    ·*········ baseTime >>>= 2;
    ·*········ prevTime = time;
    ·*········ sysClock.update(baseTime,intervalTime);
    ·*······ }
    ·*······ // ... other main loop code
    ·*···· }
    ·*·· }
    ·* </code>

    The public integers cal.seconds, cal.minutes and cal.hours keep the passed realtime.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-23 23:55
    The problem with SoftwareRTC is that its update method must be called
    every second. You may not be able to do that due to the pulse count.
    An alternative is the ScaledTimer16 class that operates like the Timer class
    but uses a userdefined timeunit.
    http://groups.yahoo.com/group/JavelinCode/files/Javelin%20Stamp%20IDE/lib/stamp/core/

    For example:
    static ScaledTimer16 realtime = new ScaledTimer16(120,(short)50000); //timeout=1min, timeunit=0.5sec

    realtime.passedTime() then returns the number of timeunits since the last call
    to realtime.mark()

    static void main() {
    · realtime.mark(); //start global time
    · hours=minutes=seconds=0;
    · while (true) { //the mainloop
    ··· //your code inserted here

    ··· //now calculate hours,minutes,seconds from passed seconds
    ··· passedSeconds = realtime.passedTime()>>>1; //number of seconds passed
    ·························································· //unsigned so max time = 32767 sec = 9.1 hours
    ··· realtime.mark();
    ··· hours +=·passedSeconds/3600;
    ····passedSeconds %= 3600;
    ··· minutes += passedSeconds/60;
    ····passedSeconds %= 60;
    ··· seconds += passedSeconds;
    ··· if (seconds > 59) {
    ····· minutes++;
    ······seconds -= 60;
    ··· }
    ··· if (minutes > 59) {
    ····· hours++;
    ······minutes -= 60;
    ··· }
    ··· if (hours > 23) {
    ····· hours -= 24;
    ··· }
    ··· //display HH:MM:SS

    · }//end while
    }//end main

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-24 12:26
    Hmm it inaccurate too, with higher speeds it is a disaster.

    My idea is better in this case don't you think? It must be accurate my way, I meassure the time betweern pulses for speed, why not use that for time also? the pulses are 3 ticks that means theoratical, the time is off by·0.013 second on every Km. (3*8.68=26us => 26*500(pulses for 1KM by circumference 2M)·= 13000 / 1000000 = 0.013s). So it must be quite accurate, why do i get on my stopwatch 1 minute and the first test on the bikecomputer 1.3 minute? I still use this code? Is there some inaccurate programming or something else, this should work wright?

    int timerMS;
    int timerS;
    int timerM;
    int timerH;


    ··· passed = t.passedMS(); //retrieve ms between pulses
    ··· timerMS = timerMS + passed;


    if (timerMS >= 2000){
    · timerMS = timerMS - 1000;
    · timerS – timerS + 2;}
    if (timerS == 60) {
    · timerS = 0;
    · timerM++;}
    if (timerM == 60) {
    · timerM = 0;
    · timerH++;}


    Thanks Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-24 13:13
    The problem with my ScaledTimer16 example is that if realtime.passedTime()
    returns an odd number, then 0.5 seconds are lost in the timekeeping. This could
    be corected but that requires more code.

    The problem with using the time between pulses is that it does not include the
    time·occupied by the other code.

    The solution is to use another loopTime (loopTime2).
    I placed·loopTime2 outside the if (validPulse) so it gets calculated for each loop.
    looptime2 is in msec units, so we need to add looptime2 until we cross 1000
    and then increment seconds.

    Now even if there is not a valid pulse, the running time (your realtime)
    keeps getting·updated.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-24 13:34
    Updated the timekeeping. If the pulse timeouts, then up to 10 seconds
    may be added.

    regards peter
Sign In or Register to comment.