Help with Elevator Code

thecomprachico

New Member
Hello,

I am very new to Picaxe (read: picked it up yesterday) and am doing this as my first project. I must mention that I have no prior programming experience. I'm trying to code an elevator, operational for 3 levels. This is a University project, but we've basically been left to wander by ourselves-- nothing significant in terms of guidance other than the Picaxe manuals-- so any and all help is truly, greatly appreciated. The header code was provided and according to instructions, is not to be changed (apart from designating unused slots). I'm having trouble finding the right structure for the code since I'm not sure how to program certain functionality -- e.g. how to make the lift go to the highest demanded floor before reversing direction and stopping at lower demanded floors. Herein attached is my very pathetic attempt at code (having been a math student, this doesn't look elegant at all to me). Needless to say it doesn't work-- it's only here to give the reader an idea of my level of inexperience and where I need help most.

Thanks for any help you can provide.
 

Attachments

Circuit

Senior Member
A lot to plough through... but starting from main: you subroutine to idle: and that contains a "loop" without a "do" - see DO - LOOP page 60 manual 2. I guess that is just a starter for ten...
 

thecomprachico

New Member
A lot to plough through... but starting from main: you subroutine to idle: and that contains a "loop" without a "do" - see DO - LOOP page 60 manual 2. I guess that is just a starter for ten...
Thanks for the heads up. I know it's a complete mess-- the entire point of posting the code was just to give the reader an idea of what I'm trying (pathetically) to achieve.

Oh well, everyone has to start somewhere I guess. Thanks again, will look it up.
 

hippy

Technical Support
Staff member
Lift control control can prove to be quite complicated despite appearing deceptively simple and without any prior programming experience it could be quite a challenge - Or is that simply a lack of experience with using PICAXE devices rather than having not programmed before ?

I would suggest getting to grips with the basics to start with; reading button pushes and floor sensors, moving the lift body, understanding how they all work.
 

thecomprachico

New Member
I literally have zilch programming experience. While I honestly don't think this is the way to go about learning anything, our instructors seem to think that throwing us into the deep end is the way to go. I think I understand most of the hardware involved, but the syntax with Basic is becoming a problem because a) I'm not used to programming, b) I'm not used to Picaxe. This makes expressing even simple functions formally very difficult for me. There are still a few weeks until submission, but right now I feel pretty pessimistic and daunted. If y'all could nudge me as to the best resources for this purpose, I'd be very grateful.

P.S. edited the 'arrived' subroutine, although it's still quite awful, it's now consistent with the rest of the non-functional code.


Code:
arrived: 

	if demandreg = positionreg 
	then  pwmout CarPWM, 249, 0 
		pwmout DoorPWM, 249, 700 until DoorOpen = 1
		pwmout DoorPWM, 249, 0
		pause 1000
		pwmout DoorPWM, 249, 700 until DoorClose = 1
return
 

lbenson

Senior Member
As hippy says, you will need to break things down into smaller pieces to climb the big hill you have in front of you (to mix metaphors).

One thing which might be helpful would be to test small snippets of code in the simulator. That way you can make progress in small steps without being overwhelmed by error after error in a big program.

For instance, to test your posted "arrived" subroutine, you would need to include your register and pin definitions, but then you could just copy the code into the Programming Editor and click to run the simulator. You might have less to learn if you start with the latest version of the older Programming Editor, V 5.5.6. If you start with your posted code, without adding the symbols, you get this:
Code:
 if demandreg = positionreg 
                ^

Error: Unknown symbol - positionreg
So go ahead and add the needed symbols:
Code:
#picaxe 40x2
symbol DoorClose     = A.2 'Analogue Sensor for door closed.
symbol DoorOpen      = A.3 'Analogue Sensor for door open.
symbol DoorPWM       = C.1 'PWM output pin to control door motor drive speed.
symbol CarPWM        = C.2 'PWM output pin to control lift motor drive speed.(Hpwm A).
symbol positionreg = b2 'Stored current digital floor sensor values (portD).
symbol demandreg   = b3 'Stores current floors requiring a visit

arrived: 
  if demandreg = positionreg then
    pwmout CarPWM, 249, 0 
    pwmout DoorPWM, 249, 700 until DoorOpen = 1
    pwmout DoorPWM, 249, 0
    pause 1000
    pwmout DoorPWM, 249, 700 until DoorClose = 1
  return
I also moved the "then" up to the "if" line, since I knew the PE would complain. I also reduced indentation to two spaces, since a program as complex as this one is likely to become will wrap lines if 8-space tabs are used for block indentation.

Now you continue to get complaints:
"until" requires a starting condition--added "do" & "loop" twice
"if" requires "endif"
"return" requires some place to return to, so added "main" routine calling "arrived"

Code:
#picaxe 40x2
symbol DoorClose     = A.2 'Analogue Sensor for door closed.
symbol DoorOpen      = A.3 'Analogue Sensor for door open.
symbol DoorPWM       = C.1 'PWM output pin to control door motor drive speed.
symbol CarPWM        = C.2 'PWM output pin to control lift motor drive speed.(Hpwm A).
symbol positionreg = b2 'Stored current digital floor sensor values (portD).
symbol demandreg   = b3 'Stores current floors requiring a visit

main:
 do
   gosub arrived
   pause 5000
 loop

arrived: 
  if demandreg = positionreg then
    pwmout CarPWM, 249, 0 
    do pwmout DoorPWM, 249, 700 loop until DoorOpen = 1
    pwmout DoorPWM, 249, 0
    pause 1000
    do pwmout DoorPWM, 249, 700 loop until DoorClose = 1
  endif
  return
Still complaining about this line.
Code:
    do pwmout DoorPWM, 249, 700 loop until DoorOpen = 1
                                     ^
Error: Syntax error in this line!
So look at the definition of "DoorOpen"--A.2. The comment for the symbol definition says this is an analogue sensor, but it's being used as a digital pin which will have a logic level of "1" or "0", so picaxe syntax requires that you define it as pinA.2 (this confuses many--the best I can say is remember by brute force that "if" "while", "until" tests of the logic level of a pin require the pinX.# syntax).

So try again.
Code:
#picaxe 40x2
symbol DoorClose     = pinA.2 'Analogue Sensor for door closed.
symbol DoorOpen      = pinA.3 'Analogue Sensor for door open.
symbol DoorPWM       = C.1 'PWM output pin to control door motor drive speed.
symbol CarPWM        = C.2 'PWM output pin to control lift motor drive speed.(Hpwm A).
symbol positionreg = b2 'Stored current digital floor sensor values (portD).
symbol demandreg   = b3 'Stores current floors requiring a visit

main:
 do
   gosub arrived
   pause 5000
 loop

arrived: 
  if demandreg = positionreg then
    pwmout CarPWM, 249, 0 
    do pwmout DoorPWM, 249, 700 loop until DoorOpen = 1
    pwmout DoorPWM, 249, 0
    pause 1000
    do pwmout DoorPWM, 249, 700 loop until DoorClose = 1
  endif
  return
This passes the syntax check. Now if you simulate it, it stops on the first "do ... until" line. Click A3 (DoorOpen) in the simulation panel and it will move down to the second "do ... until" line. Click A2 (DoorClose) in the simulation panel and it will finish the subroutine and return back to the "main" loop. You can click off the A3 and A2 pins to repeat this test. You can single-step through the code to see exactly what is happening.

Debug other snippets of code similarly, then paste together.

Hope this helps to get you started.
 
Last edited:

thecomprachico

New Member
As hippy says, you will need to break things down into smaller pieces to climb the big hill you have in front of you (to mix metaphors).

One thing which might be helpful would be to test small snippets of code in the simulator. That way you can make progress in small steps without being overwhelmed by error after error in a big program.

For instance, to test your posted "arrived" subroutine, you would need to include your register and pin definitions, but then you could just copy the code into the Programming Editor and click to run the simulator. You might have less to learn if you start with the latest version of the older Programming Editor, V 5.5.6. If you start with your posted code, without adding the symbols, you get this:
This is incredibly helpful. Thank you so very much for putting in the time. I'll post my progress as I debug segments of the code.
 

flyingnunrt

Senior Member
Although it is not popular with this forum, I find the Logicator for picaxe app quite useful at times.
If you are more comfortable with flow charts it is worth a quick look.
You can see how the program is stepping through the various blocks of code in a fashion not too dissimilar to the simulator in PE5/6
It does have limitations with some commands but it is just another tool you can use.
Once you are more familiar you can then revert back to straight basic code.
Just my opinion.
 

geoff07

Senior Member
You might find it helpful to make a clear documented design before you restart coding. You will also need to try some of the practice coding suggested above for when you do that.

But for the design you might find it helpful to learn about finite-state-machine coding. Having been a maths student you probably know what they are. The idea is to define all the possible states that the system can be in, and all the valid things that can happen in each state. So, for a lift (elevator to you), each car can be at a particular floor, and at each floor there are only certain things it can do (go up/down/open/close etc.). The code cycles round looking for events (call button pushed for floor x, door obstructed, etc) and, based on the state of the relevant car executes a transition to another state (move to next floor, reopen door etc.).

Using this approach you separate the coding structure from the problem structure, the behaviour of the code being defined by a state/transition diagram. There is a generic FSM program structure on my forum blog that you might find useful. It is then easy to change the states, events, and transitions without major changes to the program. For simple problems this approach can be overkill but for complex problems it greatly helps reduce the coding effort, as the system behaviour is largely defined by select statements rather than structural code, and all inputs are scanned in one place (the event monitor procedure) so getting it to work reliably and not messing up the program when changing the system behaviour is much easier. A lift is not a simple problem!

Once you have a basic FSM code structure, and a good state/transition diagram (try qfsm), then the actual implementation can be quite straightforward, even in a very complex system.
 

lbenson

Senior Member
I didn't really note the logic of some of the commands. On looking back, I see that you'll probably not want to do this command this way:
Code:
do pwmout DoorPWM, 249, 700 loop until DoorOpen = 1
I assume the pwmout is opening the door, and pwm is supposed to stop once the DoorOpen signal is received. So re-arrange things thus:
Code:
pwmout DoorPWM, 249, 700 
do loop until DoorOpen = 1
You might well get chatter if the pwmout command is repeated; once started, pwm will run until altered (Note Manual 2 for pwmout: "This command is different to most other BASIC commands in that the pwmout runs continuously (in the background) until another pwmout command is sent.").

Since this is for a grade, you may in the future get more hints and questions about logic from the forum than direct solutions. Personally I feel that advice regarding correct syntax should be permitted--but you might do best to note to your instructor any contributions from online sources.

And questions: how do you know when you've reached the desired floor? Does the same motor open and close the door (if so, I'm interested in knowing how the reversal occurs).
 

thecomprachico

New Member
Although it is not popular with this forum, I find the Logicator for picaxe app quite useful at times.
If you are more comfortable with flow charts it is worth a quick look.
You can see how the program is stepping through the various blocks of code in a fashion not too dissimilar to the simulator in PE5/6
It does have limitations with some commands but it is just another tool you can use.
Once you are more familiar you can then revert back to straight basic code.
Just my opinion.
I have been fiddling about with Logicator since the moment I started with this project (alongwith scribbling a lot of flowcharts on paper) and it really has helped to get the structure right. :)
 

thecomprachico

New Member
And questions: how do you know when you've reached the desired floor? Does the same motor open and close the door (if so, I'm interested in knowing how the reversal occurs).
Well, there are floor and approach sensors which tell us the position of the lift.

And yes, the same motor opens and closes the door. It is a single sliding door with a single motor. The motor is attached to the center of a circle which has a lever-arm on one end. The motor rotates the lever which pushes the door left-to-right emulating an opening and closing sequence. There are infrared sensors lined up on the bottom panel of the lift, such that when the door is open one of the sensors is blocked, and when the door is closed the other one is blocked; this tells us the state of the door.
 

lbenson

Senior Member
And yes, the same motor opens and closes the door..
Ah, I think I understand--clever. So, for a door moving left to close, the lever attached to the circle (disk) is at the far right; when it reaches the far left (180 degrees of rotation), the door is closed, and the sensor tells us to stop turning the disk; to open the door, continue turning in the same direction another 180 degrees until the lever attachment is back on the right and the sensor reports that the door is open.
 

thecomprachico

New Member
Ah, I think I understand--clever. So, for a door moving left to close, the lever attached to the circle (disk) is at the far right; when it reaches the far left (180 degrees of rotation), the door is closed, and the sensor tells us to stop turning the disk; to open the door, continue turning in the same direction another 180 degrees until the lever attachment is back on the right and the sensor reports that the door is open.
Yes, exactly. :)
 

thecomprachico

New Member
Could anyone please tell me why I'm getting a syntax error here? Trying to set up bitmasks for the floor-register and demand-register.

Code:
symbol demandreg   = b3
symbol pinreg = pinsD
symbol floor1reg = pinreg &%00000010
symbol floor2reg = pinreg &%00000100
symbol floor3reg = pinreg &%00001000
symbol demand = pinreg &demandreg
 

hippy

Technical Support
Staff member
Could anyone please tell me why I'm getting a syntax error here?
symbol demand = pinreg &demandreg

expands to -

symbol demand = pinsD & b3

and Programming Editor knows that's not a single variable nor a constant value.

You need to use #DEFINE rather than SYMBOL, for example ...

Code:
[color=Blue]symbol [/color][color=Purple]demandreg [/color][color=DarkCyan]= [/color][color=Purple]b3[/color]
[color=Blue]symbol [/color][color=Purple]pinreg    [/color][color=DarkCyan]= [/color][color=Purple]pinsD[/color]

[color=Navy]#define [/color][color=Black]demand [/color][color=Purple]pinreg [/color][color=DarkCyan]& [/color][color=Purple]demandreg

b0 [/color][color=DarkCyan]= [/color][color=Black]demand[/color]
 

thecomprachico

New Member
symbol demand = pinreg &demandreg

expands to -

symbol demand = pinsD & b3

and Programming Editor knows that's not a single variable nor a constant value.

You need to use #DEFINE rather than SYMBOL, for example ...

Code:
[color=Blue]symbol [/color][color=Purple]demandreg [/color][color=DarkCyan]= [/color][color=Purple]b3[/color]
[color=Blue]symbol [/color][color=Purple]pinreg    [/color][color=DarkCyan]= [/color][color=Purple]pinsD[/color]

[color=Navy]#define [/color][color=Black]demand [/color][color=Purple]pinreg [/color][color=DarkCyan]& [/color][color=Purple]demandreg

b0 [/color][color=DarkCyan]= [/color][color=Black]demand[/color]
Thank you.

Trying out this approach since my simplistic if-statements didn't seem to be cutting it. Let's see how this goes. Will hopefully put up a finished version by the end of this week.

Wouldn't be possible without your guidance! (Goes to everyone who responded here)
 

thecomprachico

New Member
Hello all, here's my code so far. So the lift seems to work in rudimentary way. However, I don't know how to go about assigning preference to the order of floors, i.e. so that it logs multiple demands and plays them out in the correct sequence. I also haven't been able to get the LEDs on the up and down arrow buttons working. If anyone can give me any pointers, that would be great.
 

Attachments

geoff07

Senior Member
However, I don't know how to go about assigning preference to the order of floors
I suggest you keep lists of floors with an outstanding up or down call, and continually resort the lists according to where a car is and which direction it is going. The sorting would implement your strategy for responding to calls, which might depend on how long they have been waiting, which floor has the executive offices (really), which is nearest, etc. Then you take the preferred destination from the list. It isn't simple!

I recall visiting an MD in a tall office block somewhere in Africa. When the meeting was over he said he would call the lift for us. It turned out that he had rung the phone in the lift, and the attendant had stopped the car, emptied out everyone in it, and then come to pick us up!
 

thecomprachico

New Member
Well, I figured out my first mistake. It's the demandreg = 0 bit in the arrived subroutine. That's causing it to clear the registry every time it reaches a floor, basically making it a goldfish without memory. However, without this bit of code it was not able to clear the demand for the floor once it had reached it, and so would continuously keep opening and closing the door while at the floor (without any new demand for it). I'm a bit stumped how to fix this. Help!
 

thecomprachico

New Member
I suggest you keep lists of floors with an outstanding up or down call, and continually resort the lists according to where a car is and which direction it is going. The sorting would implement your strategy for responding to calls, which might depend on how long they have been waiting, which floor has the executive offices (really), which is nearest, etc. Then you take the preferred destination from the list. It isn't simple!
Doesn't sound simple at all. *sigh*
 

lbenson

Senior Member
I don't remember how many floors you have, but if it's no more than 8, you could use the bits in a couple of byte variables to indicate whether you have a call from other floors. So perhaps something like this (note that I didn't attend to your variable usage, so you may have to adjust the symbols).
Code:
symbol downCall = b30 ' bits 0-7 indicate a "down" call for that floor (1-8) was made
symbol upCall   = b31 ' bits 0-7 indicate an "up" call for that floor (1-8) was made
symbol currentFloor = b32 ' values 0-7

symbol currentDirection = bit31 ' bit value 0=down, 1=up

if currentDirection = 1 then ' direction is up
  do while currentFloor < 7  ' note "0" is first floor
    inc currentFloor 
    if upCall bit currentFloor set then ' this floor called for, in or out of elevator
      clearbit upCall, currentFloor 
      '  now do what is necessary to move to new current floor
      '  ...
      exit ' leave do loop
    endif
  loop
else ' direction is down
  do while currentFloor > 0  ' note "0" is first floor
    dec currentFloor 
    if downCall bit currentFloor set then ' this floor called for, in or out of elevator
      clearbit upCall, currentFloor 
      '  now do what is necessary to move to new current floor
      '  ...
      exit ' leave do loop
    endif
  loop

endif
Untested and incomplete, but perhaps a move in the right direction.
 
Top