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.
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.
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
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.
····· 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)
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.
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.
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;
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.
Comments
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
Very much thanks for all the explanations and codes.
Johnny
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
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
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
····· 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
This was also one of my points that i wanted to investigate.
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
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
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
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
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
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
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
may be added.
regards peter