Need Help with simple programming (beginner)
CelestialDemon
Posts: 20
ok, I will make this simple and straightforward. I am new to programming and its hard to find exact information on how to do exactly what i want to do. My project is a 4-way stop sign stop where, using mini photocells, program 4 lights that are attached to the stop signs (1 for each stop sign) that detect when a car is stopped at the sign and if multiple cars approach the intersection simultaneously, which one gets to go first. This has to be like a real life situation, where once a car leaves, its light will go off and the person who's 2nd in line to go, their light will go on etc. Im not sure how to loop all of these together in the program or how to make it "remember" which sensor was detected 2nd and so on.
This is all i had so far to start, which made 1 light go on when the sensor was covered and the light would go off when the sensor was uncovered. (using basic stamp editor 2.5.3 and stamp bs2 and version 2.5)
input 1
output 2
RUN:
if in1 = 0 then RUN
high 2
OFF:
if in1 = 1 then OFF
low 2
goto RUN
or something along those lines..i cant remember for sure, but any help on this matter would be greatly appreciated.. i dont know all the commands and stuff so I know there is something someone out their knows that will help. thank you!
This is all i had so far to start, which made 1 light go on when the sensor was covered and the light would go off when the sensor was uncovered. (using basic stamp editor 2.5.3 and stamp bs2 and version 2.5)
input 1
output 2
RUN:
if in1 = 0 then RUN
high 2
OFF:
if in1 = 1 then OFF
low 2
goto RUN
or something along those lines..i cant remember for sure, but any help on this matter would be greatly appreciated.. i dont know all the commands and stuff so I know there is something someone out their knows that will help. thank you!
Comments
This is a school project, so we really can't do it for you, but we can give you advice and answer specific questions.
Programs like this usually end up being what's called a "finite-state machine" (do a Google search for this) where you have several loops and each represents what's called a state. The program sits in a state until something happens, then it goes to one of several other states or stays in the same state depending on what happened. When it goes to another state, the program may make something happen (like turn LEDs on or off). The state represents the memory. In the example you posted, you've got two states, RUN and OFF.
In your case, this is a bit more complicated since you might have cars waiting in turn for something to happen and you may want to remember the order in which they arrived. You can do this with a finite-state machine with 16 states (4 potential cars, each with 4 possible arrival positions) or more depending on how you control the lights. There are other ways where you can simplify the number of states needed, like having a 4 element array with numbers 0-4 in each element with 0 meaning no car and 1-4 indicating a car and the number giving the priority.
Are you using a BS1 or BS2 Stamp? If it's a BS2, you can use DO / LOOP and a different form of IF (IF THEN / ELSE / ENDIF)
But as Mike suggests, a state machine is your best bet to finding a solution.
Reference:
http://en.wikipedia.org/wiki/All-way_stop
Oh, Welcome to the forums!
Man, how I wish I had juicy problems like that back in school. Me, I had to use flashlight bulbs, batteries and colored cellophane to make an "electric map" of the population of the Scandinavian countries. No doubt inspired by the famous Gettysburg Electric Map, an all-too familiar field trip to gradeschool kids in northern Virginia. Whatever happened to that? http://www.savetheelectricmap.com
I just wish someone could give me an example statement that looped two photocells together (in1 and in2) with led lights (output 3 and output 4) so that a light would light up if a car reaches the intersection but the other wouldn't unless the first car is gone and the second is still there (so as to not cause an accident) and from there I could figure out how to loop 4 of them. I learn well by examples, and its hard to find good ones like this.
CelestialDemon,
Here is an example of a state machine in pseudo code to your Two input Two output request:
Bummer, dude. Maybe you better set him straight, one way or the other.
Here's a good tutorial on the basic stamp http://www.parallax.com/Portals/0/Downloads/docs/article/SIUApplicationMicros.pdf
Really pay attention to the section on flowcharting which will help you map out program. Once you have the flowchart, go find the appropriate pbasic commands to do what you want. I try to do this on all of my projects, it saves a lot head scratching and rewriting.
One is by way of modes, where you will have interlinking program loops, each of which handles one possible state of the system and has conditions for entry and exit. For example, the short program Beau posted has three modal loops with simple conditions for remaining in the loop and for exiting the loop. This can get quite complicated as you add different possible states and conditions, and the code ends up with a lot of IFs and GOTOs. You can draw something like that out with a bunch of circles and arrows connecting them. It can work if the system is symmetrical and simple, but it comes to resemble a plate of spaghetti if there are a lot of special cases.
Another approach is to use state variables instead of modes. In that approach there is one main mode where the program execution spend most of its time, and it takes short side trips to act on changes in the state variables. Here is a little example:
Think of the arrival of cars as a queue, and you have to line up who gets to go next. In a state variable formulation, that would be an array of numbers with a head and a tail, and arrivals put a number on the queue at the head and departures take a number off at the tail. You also have to account for the possibility that two cars arrive at the same time.
INPUT 5
INPUT 6
OUTPUT 2
OUTPUT 3
start:
IF IN6 = 1 THEN ST2 ;;;; since this statement is first my LED attatched to pin 3 will turn on perfectly when i push the lever
HIGH 3
GOTO ST2
IF IN5 = 1 THEN ST1
HIGH 2
GOTO ST1
ST1:
IF IN5 = 1 THEN ST1
HIGH 2
basic:
IF IN5 = 0 THEN basic
LOW 2
GOTO start
ST2:
IF IN6 = 1 THEN ST2
HIGH 3
yea:
IF IN6 = 0 THEN yea
LOW 3
GOTO start
and --->>> THIS IS MPORTANT
MAKE BACKUP COPIES
of your program file as you work on it (give yourself a naming scheme like ver1, ver2, ver3 etc.) as you go forward.
Few things are as disappointing as getting something working, then changing it making it all break and having no way to get back to where you were.
wondering if you are "infinite loop" ... must play computer... in6=1 is true, so I go to ST2, where as long as in6 is still one I will stay there forever but when in6 is false then I will spin around on yea yea yea (which is a great beatles refrain but likely not what you want)....hmmmm....
On the face of it, the action you describe just here can be done with a very simple loop:
Low state of buttons is transferred directly to high state of leds. The squiggle symbol ~ is an operator that means NOT, so input 0 input becomes output 1, and vice versa. In this program, both lights can be on at once when both buttons are pressed.
When you revisit your program in post #11, think it through like a computer. The program starts, finds the button at in6 up, jumps to ST2, waits there until the button is down, then turns on the led, waits at yea until the button is up, then goes back to start where it jumps right back to ST2. It never gets to ST1.
Here is a quick example in which the start loop tests both buttons until one or the other is pressed. Unlike the program above, only one light can be on at a time.
INPUT 5
INPUT 6
INPUT 7
INPUT 8
OUTPUT 0
OUTPUT 1
OUTPUT 2
OUTPUT 3
START:
LOW 0
LOW 1
LOW 2
LOW 3
IF IN8 = 0 THEN ST3
IF IN7 = 0 THEN ST2
IF IN6 = 0 THEN ST1
IF IN5 = 0 THEN ST0
GOTO start
st0:
HIGH 0
PAUSE 3000
IF IN5=0 THEN st0
GOTO start
st1:
HIGH 1
PAUSE 3000
IF IN6=0 THEN st1
GOTO start
st2:
HIGH 2
PAUSE 3000
IF IN7 = 0 THEN st2
GOTO start
st3:
HIGH 3
PAUSE 3000
IF IN7 = 0 THEN st3
GOTO start
To answer your question, there are ways to keep track of the order of arrival, such as a queue or list. But they will require significant modification to your program to implement. For example, right now in the start routine, you jump to the state based on the first input that is zero. To preserve the order, you would have to scan each input, and if it is zero, save it in a queue or list (which is really just a variable array). Then after all the inputs have been scanned, you would then have to go through the queue by going to each state in the order it was placed in the queue. Once that car leaves, you take it off the queue, go back and see if any more cars arrived, adding them to the end of queue, and then take the next one from the head of the queue. Study up on variables first because you will need at least 4 of them to do this, probably more.
What you need to keep the arrival order isn't in the manual. It's a programming concept called a list or queue. You would have to understand that first abstractly, then translate it into code, and then put it in your program. That's a tall order for only a few days if this is your first programming exercise. It is not a trivial task.
If you choose to do it, here are some hints that may help:
1. You will need at least 4 variables for the arrival queue (or list, I use the terms interchangeably)
2. You will need to know how to set these variables to unique values representing each approach with an occupied sensor
3. You will need to know how to read these variables from the top to the bottom of the queue
4. You will need to determine which state to go to next based on the the value at the top of the queue
5. You will need to remove the top item from the queue after the car leaves the approach and move the others up
list VAR Byte(3)
pressedA VAR Byte
pressedB VAR Byte
pressedC VAR Byte
pressedD VAR Byte
index VAR Byte
INPUT 5
INPUT 6
INPUT 7
INPUT 8
OUTPUT 0
OUTPUT 1
OUTPUT 2
OUTPUT 3
START:
LOW 0
LOW 1
LOW 2
LOW 3
IF IN8 = 0 THEN intersectionA
IF IN7 = 0 THEN intersectionB
IF IN6 = 0 THEN intersectionC
IF IN5 = 0 THEN intersectionD
' 'IF IN8 = 0 THEN st0 '' these are my initial starting lines, i dont think i need them anymore but ill keep them for now
' 'IF IN7 = 0 THEN st1
' 'IF IN6 = 0 THEN st2
' 'IF IN5 = 0 THEN st3
GOTO start
st0:
HIGH 0
PAUSE 3000
IF IN5=0 THEN st0
GOTO start
st1:
HIGH 1
PAUSE 3000
IF IN6=0 THEN st1 '''basically in these sections is where i need to implement my array in a way so that it plays the order out correctly, im just confused as to what to put, i know i need things like "IF in6 = some variable in queue or idk.."
GOTO start
st2:
HIGH 2
PAUSE 3000
IF IN7 = 0 THEN st2
GOTO start
st3:
HIGH 3
PAUSE 3000
IF IN7 = 0 THEN st3
GOTO start
intersectionA:
IF pressedA = 1 THEN start
list(index)= 1
index = index + 1
pressedA = 1
GOTO start
intersectionB:
IF pressedB = 1 THEN start
list(index) = 2
index = index + 1
pressedB = 2
GOTO start
intersectionC:
IF pressedC = 1 THEN start
list(index) = 3
index = index + 1
pressedC = 3
GOTO start
intersectionD:
IF pressedD = 1 THEN start
list(index) = 4
index = index + 1
pressedD = 4
GOTO start
1. The declaration list VAR Byte(3) should be list VAR Byte(4) since there are 4 inputs. Although the index goes from 0 to 3, the array has to be defined as 4 bytes.
2. The place where you will decide which state to go to is right before the first GOTO start, just after the IF IN5=0 THEN intersectionD. You need to do it there, and not in the state itself.
3. To figure out which state to go to, just look at the first element in the array, list(0). You can do this with a BRANCH statement like this:
BRANCH is like GOTO but based on the value of list(0). Note that if the value is zero, the the program will go back to start. Otherwise it will go to one of the four states.
4. Lastly, you will have to do a few things when you exit each of the four states. You have to clear the pressedX variable (X=A to D) since that state has now been served. And you have to shift the list because the top item list(0) is now done and decrement the index (so it doesn't point past the end of the list).
All but the fist instruction above are the same for all states, so ideally they should go into their own routine. I'll let you think about how to do that.
As you put this all together, I suggest you add a few DEBUG statements to show the index, the list and where the program is going until you have it working right.
pressedA=0 ' clear the flag
list(0)=list(1) ' shift the list
list(1)=list(2)
list(2)=list(3)
list(3)=0 ' clear the last entry
index = index-1 ' decrement the index
i know i need 4 of them for each pressedA through pressedD but was confused when u said that this code needs to go into or at the end of each of my four states, which im guessing are st0 - st3? or.. idk and also do i need need lines or not anymore?
'IF IN8 = 0 THEN st0 i guessing i dont need them because i have a list that determines where my program goes
' 'IF IN7 = 0 THEN st1
' 'IF IN6 = 0 THEN st2
' 'IF IN5 = 0 THEN st3
' {$STAMP BS2}
' {$PBASIC 2.5}
list VAR Byte(4)
pressedA VAR Byte
pressedB VAR Byte
pressedC VAR Byte
pressedD VAR Byte
index VAR Byte
INPUT 5
INPUT 6
INPUT 7
INPUT 8
OUTPUT 0
OUTPUT 1
OUTPUT 2
OUTPUT 3
START:
LOW 0
LOW 1
LOW 2
LOW 3
IF IN8 = 0 THEN intersectionA
IF IN7 = 0 THEN intersectionB
IF IN6 = 0 THEN intersectionC
IF IN5 = 0 THEN intersectionD
BRANCH list(0), [start,st0,st1,st2,st3]
GOTO start
st0:
HIGH 0
PAUSE 3000
IF IN8=0 THEN st0
pressedA=0 ' clear the flag
list(0)=list(1) ' shift the list
list(1)=list(2)
list(2)=list(3)
list(3)=0 ' clear the last entry
index = index-1 ' decrement the index
GOTO start
st1:
HIGH 1
PAUSE 3000
IF IN7=0 THEN st1
pressedB=0
list(0)=list(1)
list(1)=list(2)
list(2)=list(3)
list(3)=0
index = index-1
GOTO start
st2:
HIGH 2
PAUSE 3000
IF IN6 = 0 THEN st2
pressedC=0
list(0)=list(1)
list(1)=list(2)
list(2)=list(3)
list(3)=0
index = index-1
GOTO start
st3:
HIGH 3
PAUSE 3000
IF IN5 = 0 THEN st3
pressedD=0
list(0)=list(1)
list(1)=list(2)
list(2)=list(3)
list(3)=0
index = index-1
GOTO start
intersectionA:
IF pressedA = 1 THEN start
list(index)= 1
index = index + 1
pressedA = 1
GOTO start
intersectionB:
IF pressedB = 1 THEN start
list(index) = 2
index = index + 1
pressedB = 2
GOTO start
intersectionC:
IF pressedC = 1 THEN start
list(index) = 3
index = index + 1
pressedC = 3
GOTO start
intersectionD:
IF pressedD = 1 THEN start
list(index) = 4
index = index + 1
pressedD = 4
GOTO start