Ok, have it working on 4 sensors with 4 cogs, but needed an extra cog to handle the tv method (aswell as the object).
It is not done well but works, now I just need to try codemonkeys way to make it bi-directional, will post up the code later so you can see where I can improve.
I am glad to hear you got it working DJH82UK. In a short amount of time you have come a long ways in understanding the Prop. Lets see some code when you get a moment.
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter tdswieter.com
One little spark is all it takes for an idea to explode
Well, it's very very messy, not efficient whatsoever (look at the var block), and ignore any comments for the most part.
I have learnt a lot on this project and still have a way to go, my next effort is to make it bi-directional, then make the code use more efficient, then add "max" speed which is stored in the free space of the eeprom, then finally see what recources are left to make the display a bit sexier, maybe use the graphics object. What I should probably do next tho is sort out the sensors, i am still using your example to simulate them, I want to use photo emitters and receivers, but I am yet to figure out how to wire them, do I need pull-ups? Pull-downs?.
If anyone has any comments on getting rid of some of those Var's or to make it bi-directional I would very much appreciate it.
Thanks for all your help so far.
heres the code:
Somebody said...
CON
_clkmode = xtal1 + pll16x 'Using the Parallax Demo Board Rev C
_xinfreq = 5_000_000 'The crystal is 5MHz. and the Propeller will run at 80MHz.
'Pin Definitions, change the pin numbers to match the desired output pins, on Demo Board Rev C these are LEDs
Trigger1 = 16 'This pin is the output of Trigger 1, should attach to Sensor1
Trigger2 = 17 'This pin is the output of Trigger 2, should attach to Sensor2
long one_ms 'Amount of clock cycles to wait for 1ms, calculated based on clock frequency
long cog 'Value of Cog's ID
long stack[noparse][[/noparse]15]
long stack1[noparse][[/noparse]50]
long stack2[noparse][[/noparse]30]
long stack3[noparse][[/noparse]30]
long stack4[noparse][[/noparse]30]
long pincheckstart
long starttime
long endtime
long finaltime
long finaltime2
long finaltime3
long speed100
long whole
long remainder
long starttime2
long endtime2
long finaltime_2
long finaltime22
long finaltime32
long speed1002
long whole2
long remainder2
long starttime3
long endtime3
long finaltime_3
long finaltime23
long finaltime33
long speed1003
long whole3
long remainder3
long starttime4
long endtime4
long finaltime_4
long finaltime24
long finaltime34
long speed1004
long whole4
long remainder4
PUB Init
text.start(12)
'text.str(string(13," Train Speed Detector",13,13))
'StartSpeedChecker(Trigger1,Trigger2)
one_ms := clkfreq / 1_000 'Setup one millisecond based on clk frequency
cognew(SpeedChecker(Trigger1,Trigger2), @stack)
cognew(tv(0, 0, 1), @stack1)
waitcnt((500 * one_ms) + cnt)
'repeat
'wait for the pin on sensor 1 to equal the desired state, read up on waitpeq to get it right, check examples
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime := EndTime - StartTime
Finaltime := Finaltime -1248
FinalTime3 := (finaltime / 800000)
FinalTime2 := (distvar/finaltime3)
Speed100 := finaltime2 * 10
Whole := Speed100 / 100
Remainder := Speed100 // 100
'Where // means Mod, ie the remainder.
waitcnt((500 * one_ms) + cnt)
'repeat
'wait for the pin on sensor 1 to equal the desired state, read up on waitpeq to get it right, check examples
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime2 := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime2 := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime_2 := EndTime2 - StartTime2
Finaltime_2 := Finaltime_2 -1248
FinalTime32 := (finaltime_2 / 800000)
FinalTime22 := (distvar/finaltime32)
Speed1002 := finaltime22 * 10
Whole2 := Speed1002 / 100
Remainder2 := Speed1002 // 100
'Where // means Mod, ie the remainder.
waitcnt((500 * one_ms) + cnt)
'repeat
'wait for the pin on sensor 1 to equal the desired state, read up on waitpeq to get it right, check examples
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime3 := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime3 := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime_3 := EndTime3 - StartTime3
Finaltime_3 := Finaltime_3 -1248
FinalTime33 := (finaltime_3 / 800000)
FinalTime23 := (distvar/finaltime33)
Speed1003 := finaltime23 * 10
Whole3 := Speed1003 / 100
Remainder3 := Speed1003 // 100
'Where // means Mod, ie the remainder.
waitcnt((500 * one_ms) + cnt)
'repeat
'wait for the pin on sensor 1 to equal the desired state, read up on waitpeq to get it right, check examples
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime4 := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime4 := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime_4 := EndTime4 - StartTime4
Finaltime_4 := Finaltime_4 -1248
FinalTime34 := (finaltime_4 / 800000)
FinalTime24 := (distvar/finaltime34)
Speed1004 := finaltime24 * 10
Whole4 := Speed1004 / 100
Remainder4 := Speed1004 // 100
'Where // means Mod, ie the remainder.
'TV (sensor1, sensor2, sensornum)
pub TV (sensor1, sensor2, sensornum)
repeat
text.str(string(13," Train Speed Detector",13,13))
'pincheckstart := Ina[noparse][[/noparse]sensor1] 'check to see if sensor has been triggered
'waitpeq(0,|< sensor1,0)
text.out(13)
'text.dec(finaltime)
text.out(13)
'text.dec(finaltime_2)
'text.out(" ")
'text.dec(finaltime22)
'text.out(" ")
I have made some new progress, but have also found a new problem. I now have it saving the highest recorded speed to the boot eeprom, and check it against each new speed, and writes the higher value (or leaves it alone).
This has however shown up a problem, i cannot get the sensing code to repeat, if I put a repeat above the code shown below, it simply does not get a reading, after a bit of debugging it seems that it just ignores the waitpeq and carries on as if triggering, causign the counter to not increase enough to register a speed.
Any Ideas how I can get this code to always repeat?
Somebody said...
repeat
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime0 := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime0 := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime := EndTime0 - StartTime0
Finaltime := Finaltime -1248
FinalTime3 := (finaltime / 800000)
FinalTime2 := (distvar/finaltime3)
Speed100 := finaltime2 * 10
Whole := Speed100 / 100
Remainder := Speed100 // 100
'Where // means Mod, ie the remainder.
waitcnt((500 * one_ms) + cnt)
'repeat
'wait for the pin on sensor 1 to equal the desired state, read up on waitpeq to get it right, check examples
waitpeq(0,|< Sensor1,0) 'Assumes Off or 0 is the state when the sensor sees the train
StartTime := cnt 'Grab the current value of the timer
waitpeq(0,|< Sensor2,0) 'Assumes Off or 0 is the state when the sensor sees the train
EndTime := cnt 'Grab the current value of the timer
'Calculate the speed and the values as needed
FinalTime := EndTime - StartTime
Finaltime := Finaltime -1248
FinalTime3 := (finaltime / 800000)
FinalTime2 := (distvar/finaltime3)
Speed100 := finaltime2 * 10
Whole := Speed100 / 100
Remainder := Speed100 // 100
'Where // means Mod, ie the remainder.
'TV (sensor1, sensor2, sensornum)
Maybe i can offer a bit with the var issue. Unless you need all the intermediate results (FinalTime, FinalTime2, etc) outside the routine you can just have them as local variables. You might have to increase·the stack a bit, if things start not working so well. For example:
pri start1 (sensor1, sensor2, sensornum) | FinalTime, FinalTime2, FinalTime3
Of course, you could gang everything together to dispense of those local variables·but that sometimes makes debugging a bit more difficult. To wit:
Assuming that start1, start2, start3, etc are identical, except for the particular set of sensors and "return" values, you could easily make one routine to do all of them, and pass where you want the results to be stored. The general routine could become:
pri startX (sensor1, sensor2, sensornum, result) | FinalTime, FinalTime2, FinalTime3
...waitpeq code here and the answer is returned by...
Long[noparse][[/noparse]result] := (distvar / (((EndTime - StartTime) - 1248) / 800000)) * 10
...saving the whole and remainder calculations for your output routines. Or if you want, you could do them here and return them instead of "result"
called by:
StartX(1, 2, 1, @Speed100)
I'm assuming, of course, that all your indents are proper.
Uh, i just looked a bit more carefully. The repeat is commented out--that would certainly put somewhat of a damper on the waitpeqs repeating. Also, you probably already know to watch your beginning-of-line indent spacing.
yeh, it is only commented out so I could test it, sorry should have said,
everything under the repeat was included (indented 2 spaces)
After a bit of debugging, is seems like it just does not bother waiting for an input, it just skips the waitpeq completley, If i put a delay between the two then a speed registers on the screen, in accordance to the delay.
You have to strictly distinguish between numbers and strings - this is not TK or Perl
So there are two options:
1. Covert both numbers to strings and copy one after the other with MOVEBYTES (or maybe you can even give a destination address just behind the first string when converting the second number)
2. you can use simple math: var3 := 10 * var1 + var2
When you are not shure of the "size" of var2 (which of course determines the factor, here assumed as "10"), run this simple loop:
well the only reason I was asking is because I just cannot get it to store a number larger than 255 in the eeprom using the basicI2C Driver Object..
I am using the PageWrite and ReadWrite functions, as the WriteLong and WriteWord seem to mess the number up, say it tries to write 122 it actually writes 156.
Rather confusing, make Mike or anyone else could advise?
I am using the BasicI2c driver to store words and longs and it works fine. I don't see any code above that uses the driver to store variables. Maybe it is just something in your code. Here is what works for me:
eebase is a con with a value of $8000, because I am using a 512kbit eeprom. Nav_delay is the offset to the desired location above eebase. Navfactor is the name of the variable that I am storing.
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
the Method in the basic i2c driver for reading a long is this:
PUB ReadLong(SCL, devSel, addrReg) : data
I know what all the variables are within the brackets, but how do I access the data? I am presuming this is some sort of "result", so would I need something like
readeeprom := readlong etc etc?
How should I format it?
The same goes for the WriteLong Method
My problem is that I just cannot get it to store/read a number over 255
I have tried read and write long but when I do it I get strange numbers that do not match any of the variables.
but perhaps it is the write long causing the problem I don't know how to tell
if i2c.WriteLong(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer)
abort ' an error occured during the write
startTime := cnt ' prepare to check for a timeout
repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress)
if cnt - startTime > clkfreq / 10
abort ' waited more than a 1/10 second for the write to finish
What happens if you read areas of your code? Does it match what you see in the editor? I can't see any reason why your code isn't working, are you sure you are using a valid eeprom address?
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
I found I had to use an address above $7FFFF. Try using $8000 as your starting address for storage. Each long is 4 bytes, so your second long should be stored at $8004.
HTH,
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔ www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
The graphics driver does have methods for adding text to a graphics screen, but it's really intended for labeling, not for a scrolled text field. The text is effectively painted on the graphics bitmap. Have a look at the comments for the "textXXX" methods in the source code. The TV_text driver uses the same bitmapped TV I/O driver as the graphics driver and it's possible to modify the TV_text driver to allow embedded graphics windows combining the two, but I'm not aware of any easy examples.
ok, im still struggling a bit on the bi-directional part, how can I figure out which pin has been activated, and only get it to check the other pin for the 2nd trigger, for instance if pin 2 is triggered, i want it to start counting and only be checking pin 1 to be triggered and then stop counting, and vice versa
hmm, ok it seems to be binary, but only displays on the screen (newwatchpinstate) if I use text.bin with the number of digits set to 22
I then get either 100000000000000000000
or
0010000000000000000000
or 1010000000000000000000 if neither sensors are triggered, i have been testing it with the below code, how can i get the program to tell which pin has been activated?
Fred Hawkins said...
djh, I think we've lost the context of your question.
That's exactly what I thought
@DJH: What I understand is, that you are working with two independent input streams and get confused about the states they are in. As your code consists of basic initialization only, there is no hint to anything at all....
In general one uses a "state machine" for problems of that kind: You have four STATES:
0: Both switches off
1: First on, second off
2: First off, second on
3: both on
The numbering in this situation reflects the pin polarity but this is just good luck that can be utilized. Generally "states" are more complex..
When the pins change, you simply update the STATE and act accordingly:
0 1 2 3 <- new state
0 . ? ? ?
1 ? . ? ?
2 ? ? . ?
3 ? ? ? .
|
old state
The ? mark YOUR actions for this situation
You can keep the STATE in a variable, or you can have different sections in your program. The latter technique is mainly used when you have JUMP or GOTO instructions, which SPN has not.
A minor problem is that there is no WAIT instruction for an arbitrary pins change in the Propeller; thus you have to "poll" the pins using a small (!) WAITCNT inbetween - you can consider this as a kind of "low pass filter"
Comments
It is not done well but works, now I just need to try codemonkeys way to make it bi-directional, will post up the code later so you can see where I can improve.
DJH
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
Timothy D. Swieter
tdswieter.com
One little spark is all it takes for an idea to explode
I have learnt a lot on this project and still have a way to go, my next effort is to make it bi-directional, then make the code use more efficient, then add "max" speed which is stored in the free space of the eeprom, then finally see what recources are left to make the display a bit sexier, maybe use the graphics object. What I should probably do next tho is sort out the sensors, i am still using your example to simulate them, I want to use photo emitters and receivers, but I am yet to figure out how to wire them, do I need pull-ups? Pull-downs?.
If anyone has any comments on getting rid of some of those Var's or to make it bi-directional I would very much appreciate it.
Thanks for all your help so far.
heres the code:
I have made some new progress, but have also found a new problem. I now have it saving the highest recorded speed to the boot eeprom, and check it against each new speed, and writes the higher value (or leaves it alone).
This has however shown up a problem, i cannot get the sensing code to repeat, if I put a repeat above the code shown below, it simply does not get a reading, after a bit of debugging it seems that it just ignores the waitpeq and carries on as if triggering, causign the counter to not increase enough to register a speed.
Any Ideas how I can get this code to always repeat?
pri start1 (sensor1, sensor2, sensornum) | FinalTime, FinalTime2, FinalTime3
Of course, you could gang everything together to dispense of those local variables·but that sometimes makes debugging a bit more difficult. To wit:
FinalTime := EndTime - StartTime
Finaltime := Finaltime -1248
FinalTime3 := (finaltime / 800000)
FinalTime2 := (distvar/finaltime3)
Speed100 := finaltime2 * 10
might become:
Speed100 :=·(distvar / (((EndTime - StartTime) - 1248) / 800000)) * 10
Assuming that start1, start2, start3, etc are identical, except for the particular set of sensors and "return" values, you could easily make one routine to do all of them, and pass where you want the results to be stored. The general routine could become:
pri startX (sensor1, sensor2, sensornum, result) | FinalTime, FinalTime2, FinalTime3
...waitpeq code here and the answer is returned by...
Long[noparse][[/noparse]result] := (distvar / (((EndTime - StartTime) - 1248) / 800000)) * 10
...saving the whole and remainder calculations for your output routines. Or if you want, you could do them here and return them instead of "result"
called by:
StartX(1, 2, 1, @Speed100)
I'm assuming, of course, that all your indents are proper.
DJH
everything under the repeat was included (indented 2 spaces)
After a bit of debugging, is seems like it just does not bother waiting for an input, it just skips the waitpeq completley, If i put a delay between the two then a speed registers on the screen, in accordance to the delay.
DJH
for instance
var1 = 64
var2 = 5
So I want Var3 to equal 645.
Any operators that can do this?
DJH
So there are two options:
1. Covert both numbers to strings and copy one after the other with MOVEBYTES (or maybe you can even give a destination address just behind the first string when converting the second number)
2. you can use simple math: var3 := 10 * var1 + var2
When you are not shure of the "size" of var2 (which of course determines the factor, here assumed as "10"), run this simple loop:
Typo edited..
Post Edited (deSilva) : 7/14/2007 7:20:32 PM GMT
I am using the PageWrite and ReadWrite functions, as the WriteLong and WriteWord seem to mess the number up, say it tries to write 122 it actually writes 156.
Rather confusing, make Mike or anyone else could advise?
DJH
I am using the BasicI2c driver to store words and longs and it works fine. I don't see any code above that uses the driver to store variables. Maybe it is just something in your code. Here is what works for me:
i2c.initialize(eeScl)
i2c.start(eeScl)
i2c.writeword(eeScl,eeAdr,eeBase+Nav_delay,navfactor)
HTH,
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
What are those last 2 variables you are using?
DJH
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
the Method in the basic i2c driver for reading a long is this:
PUB ReadLong(SCL, devSel, addrReg) : data
I know what all the variables are within the brackets, but how do I access the data? I am presuming this is some sort of "result", so would I need something like
readeeprom := readlong etc etc?
How should I format it?
The same goes for the WriteLong Method
My problem is that I just cannot get it to store/read a number over 255
I have tried read and write long but when I do it I get strange numbers that do not match any of the variables.
DJH
temp := i2c.ReadLong(i2c#BootPin, i2c#EEPROM, eepromAddress)
but perhaps it is the write long causing the problem I don't know how to tell
if i2c.WriteLong(i2c#BootPin, i2c#EEPROM, eepromAddress, @buffer)
abort ' an error occured during the write
startTime := cnt ' prepare to check for a timeout
repeat while i2c.WriteWait(i2c#BootPin, i2c#EEPROM, eepromAddress)
if cnt - startTime > clkfreq / 10
abort ' waited more than a 1/10 second for the write to finish
indents are as they should be
navWait := i2c.readlong(eeScl,eeAdr,eeBase+nav_delay)
What happens if you read areas of your code? Does it match what you see in the editor? I can't see any reason why your code isn't working, are you sure you are using a valid eeprom address?
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
What eeprom addresses would you say I should use for 2 longs?
I have one as $7000 and one as $6000
My code is quite small
HTH,
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
working now [noparse]:)[/noparse]
Thanks a lot
Byte Buffer2[noparse][[/noparse]32]
changed it to:
Long Buffer2
before it would work.
Just got to tidy up the code and make the display look pretty now [noparse]:)[/noparse]
Can you use TV text aswell as the graphics objects? Or how easy is it to do text with the graphics object?
DJH
Great! Glad it is finally working. As the the TV text and graphics, I have no idea, never used these.
Jonathan
▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
www.madlabs.info - Home of the Hydrogen Fuel Cell Robot
DJH
hex, Bin or Dec?
I guess this is aimed at codemonkey, but help from anyone would be great
thanks
DJH
I then get either 100000000000000000000
or
0010000000000000000000
or 1010000000000000000000 if neither sensors are triggered, i have been testing it with the below code, how can i get the program to tell which pin has been activated?
I think we've lost the context of your question. Try posting a question with your spin file(s) attached.
Fred
@DJH: What I understand is, that you are working with two independent input streams and get confused about the states they are in. As your code consists of basic initialization only, there is no hint to anything at all....
In general one uses a "state machine" for problems of that kind: You have four STATES:
0: Both switches off
1: First on, second off
2: First off, second on
3: both on
The numbering in this situation reflects the pin polarity but this is just good luck that can be utilized. Generally "states" are more complex..
When the pins change, you simply update the STATE and act accordingly:
The ? mark YOUR actions for this situation
You can keep the STATE in a variable, or you can have different sections in your program. The latter technique is mainly used when you have JUMP or GOTO instructions, which SPN has not.
A minor problem is that there is no WAIT instruction for an arbitrary pins change in the Propeller; thus you have to "poll" the pins using a small (!) WAITCNT inbetween - you can consider this as a kind of "low pass filter"
EDIT: Tried to make it more explicite
Post Edited (deSilva) : 8/5/2007 8:41:53 AM GMT