c_room/task01.c or py_room/task01.py) and include the library.The elevator has 3 floors. When the simulation starts (or when you click Restart Sim in the menu) the cabin is at floor 3 and all doors are closed. Next to each floor there are ▲ (up) and ▼ (down) call buttons; the Cabin Buttons panel has the cabin display and the buttons 1, 2, 3. A button reads 1 only while it is held down; turning button lights on and off and remembering which buttons were pressed is your program's job. The Manual Control panel (toggled from the menu) lets you drive the cabin motor (Up / Stop / Down) and the door of every floor (Close / Stop / Open) by hand.
The cabin needs about 4.7 seconds from one floor to the next; a door opens fully in about 0.65 seconds. If the cabin goes above floor 3 or below floor 1, or a door keeps opening after it is fully open or keeps closing after it is fully closed, the error flag becomes 1 and ERROR appears in the menu bar. So do not put Sleep in a waiting loop that must stop a motor at a sensor. Motors run until you stop them: if a motor is still running when your program ends (or when you stop it with Ctrl+C), the cabin keeps moving; click Stop in Manual Control or Restart Sim. The simulation does not stop the cabin from moving while a door is open; making sure of that is your program's job. The Python library prints a line starting with [SIM] for door, light and display commands.
Start the elevator simulation. Write a program that connects to the simulation, prints a message (e.g. Connected to the elevator!) when the connection works, then disconnects and ends.
Then close the simulation and run your program again: what happens?
sim_connect() returns 0 on success and 1 on failure. Call sim_disconnect() at the end of the program.Show the numbers 1, 2 and 3 one after another on the display in the Cabin Buttons panel. Each number stays on the display for 1 second. When the program ends the display must show 3.
cabin_display(number) writes to the display. To wait, use Sleep(1000) (milliseconds) in C and time.sleep(1) (seconds) in Python.Turn on the lights of the buttons 1, 2 and 3 in the Cabin Buttons panel (the buttons turn orange), wait 3 seconds and turn all three off.
cabin_button_light(floor, state): state 1 turns it on, 0 turns it off.Turn on the lights of the call buttons that make sense in a real building: ▲ on floor 1, ▲ and ▼ on floor 2, ▼ on floor 3. After 3 seconds turn them all off. (The ▼ button on floor 1 and the ▲ button on floor 3 must stay dark.)
floor_button_light(floor, direction, state); use DIR_UP or DIR_DOWN for the direction.First click Restart Sim in the menu (the cabin goes to floor 3). Move the cabin down for 2 seconds and stop it. Wait 1 second, then move it up for 1 second and stop it again. The cabin must stop somewhere between floor 3 and floor 2.
CABIN_DOWN, CABIN_UP and CABIN_STOP with cabin_motor(). The motor runs until you stop it.Click Restart Sim. Open the floor 3 door for 0.3 seconds and stop its motor (the door opens about halfway). Wait 2 seconds, then close the door for 0.3 seconds and stop the motor.
Watch whether the door closes completely and whether ERROR appears in the menu bar. Run it a few times (click Restart Sim before each run).
door(floor, command); the command can be DOOR_OPEN, DOOR_CLOSE or DOOR_STOP.Read the three floor sensors, keep each one in its own variable and print the three values (e.g. Floor 1: 0, Floor 2: 0, Floor 3: 1).
Run it after Restart Sim. Then move the cabin down with Down in the Manual Control panel, click Stop between two floors and run the program again. What do you see?
cabin_sensor_read(floor) returns 1 if the cabin is at that floor, otherwise 0. A variable in C: int s1 = cabin_sensor_read(1);Find out at which floor the cabin is. If it is at a floor, show the floor number on the cabin display and print it. If the cabin is between floors, show 0 on the display and print that it is between floors.
if / else if and store the floor number in the variable. If it is still 0 at the end, the cabin is between floors.Print the state of the floor 3 door: fully closed, fully open or partly open.
Try it after Restart Sim (closed) and after clicking Open for floor 3 in Manual Control and then Stop while the door is halfway (partly open). Stopping the door exactly at its limit by hand is very hard (if you are late, ERROR appears); you will see the fully open state from a program in Task 19.
door_sensor_read(3) is 0 when the door is fully closed, otherwise 1; door_open_read(3) is 1 when the door is fully open. Use both.First the program prints a message and then waits 5 seconds. During this time press the button 2 in the Cabin Buttons panel and keep it held down. When the 5 seconds are over the program reads the button: if it is pressed, it turns on the light of button 2 for 2 seconds and prints that it was pressed; otherwise it prints that it was not pressed.
Also try pressing the button and releasing it before the 5 seconds are over. What happens, and why?
cabin_button_read(2) returns 1 if the button is held down at that moment.Click Restart Sim; the floor 3 door is closed. Make a mistake on purpose: try to close the closed door for 0.1 seconds. Read the error flag right before you stop the motor, then stop the motor and print the result. Wait 1 second, read the flag again and print it.
Watch ERROR in the menu bar. Click Restart Sim when you are done.
get_error() returns 1 if a limit was exceeded, otherwise 0. The flag clears itself after a short time.Click Restart Sim. Start the cabin moving down, after 0.5 seconds read the state of the cabin motor and print its meaning (stopped, up or down). Then stop the motor, read the state once more and print it as a number.
cabin_motion_read() returns 0 (CABIN_STOP), 1 (CABIN_UP) or 2 (CABIN_DOWN). Compare it with the constants.The elevator is ready to move only if the cabin is at a floor AND the door of that floor is fully closed. The program checks both conditions: if both are true it prints that it is ready and the floor number and shows the floor on the display; otherwise it prints that it is not ready.
Try it after Restart Sim, then again after opening the floor 3 door a little with Manual Control (Open, then Stop).
&& in C and and in Python.Count from 1 to 9 on the cabin display; each number is visible for 0.5 seconds. This time use a loop instead of writing 9 separate commands.
for (int i = 1; i <= 9; i++) { ... } Python: for i in range(1, 10):Write a program that runs forever: when the cabin reaches a floor, it shows that floor's number on the display and prints it once. While the cabin is between floors the display keeps showing the last floor. It must not print the same floor again and again.
While the program runs, move the cabin with the Manual Control panel (Up / Stop / Down). Stop the program with Ctrl+C.
while (1) / while True: is an endless loop. Keep the number currently on the display in a variable; update the display only when the new floor is different. Put a short Sleep(10) at the end of the loop.While button 2 in the Cabin Buttons panel is held down its light is on; when it is released the light goes off. Send the light command only when the button's state changes, and print pressed / released. Stop with Ctrl+C.
When one of the cabin buttons (1, 2, 3) is pressed briefly, its light turns on and stays on. When the cabin reaches that floor the light goes off. Print one line for each request and each arrival.
While the program runs, press the buttons and move the cabin between floors with Manual Control. Stop with Ctrl+C.
int lit[4] = {0}; in C, lit = [0, 0, 0, 0] in Python (indexes 1..3 are used). Inside the loop walk over the three floors with for.Click Restart Sim (the cabin is at floor 3). Send the cabin down and wait until the floor 2 sensor is 1; stop the motor at that moment. Show 2 on the display and print that floor 2 was reached. The cabin must stop exactly level with the floor and no ERROR may appear.
while (cabin_sensor_read(2) == 0) { } in C, while cabin_sensor_read(2) == 0: pass in Python. Do not put Sleep in this loop.After Task 18 the cabin is at floor 2. The program first checks that the cabin is at floor 2; if not, it prints a message and ends. If it is there: open the floor 2 door until it is fully open and stop it, keep it open for 3 seconds, then close it until it is fully closed and stop it. ERROR must never appear (compare with Task 6).
door_open_read(2) is 1; while closing, wait until door_sensor_read(2) is 0. Do not put Sleep in either waiting loop.Wherever the cabin is (at floor 3, at floor 2 or between floors), bring it down to floor 1, stop it exactly level and show 1 on the display. If the cabin is already at floor 1, do not start the motor at all; just print that.
Try it a few times after moving the cabin to different places with Manual Control.
if whether it is already at floor 1.Run it while the cabin is at a floor (if it is between floors the program prints a message and ends). The program waits until a cabin button (1, 2 or 3) is pressed. Turn on the pressed button's light, send the cabin in the right direction and stop it at that floor, turn the light off, show the floor on the display and print it. If the pressed floor is the current floor the cabin must not move.
target is 0. (3) Choose the direction by comparing target with the current floor and wait as in Task 18.Write two functions: current_floor() returns the floor where the cabin is (0 between floors); go_to_floor(target) takes the cabin to the target floor, stops it, shows the floor on the display and prints it. If the cabin is between floors, go_to_floor first goes down to the floor below and then to the target.
Use them for this tour: go to floor 1, wait 2 seconds, go to floor 3, wait 2 seconds, go to floor 2.
int current_floor(void) { ... return f; } and void go_to_floor(int target) { ... }. Python: def go_to_floor(target):. Move the code of Task 20 and Task 21 into them.Add two more functions to those of Task 22: open_door(floor) opens the door until it is fully open and stops it, close_door(floor) closes it until it is fully closed and stops it. If the door is already fully open (or fully closed) the function must not start the motor at all.
Do this tour: go to floors 1, 2 and 3 in order; at each floor open the door, keep it open for 2 seconds and close it.
if (door_open_read(f) == 1) return; at the start of the function avoids a needless motor start (which would cause an error). Use a for loop for the tour.A real elevator never moves while any floor door is open. Change the go_to_floor function of Task 23: before moving the cabin it checks all three doors; if a door is open (not fully closed) it prints a warning and closes that door first.
Main program: go to floor 1, wait 1 second, go to floor 3. Test: before running, click Open for the floor 2 door in Manual Control and Stop when the door is halfway.
for loop over the three floors at the very start of go_to_floor and use the close_door function. In C a function must be defined before it is used.Write an elevator that runs forever. When a cabin button or a floor call button (▲ or ▼) is pressed, turn on that button's light, take the cabin to that floor, open the door, keep it open for 3 seconds, close it and turn off all button lights of that floor. Then wait for a new call. Use the functions of Task 24. Stop with Ctrl+C.
target. A function lights_off(floor) that turns off all lights of a floor makes it easier.Improve the elevator of Task 25 so that several calls can wait at the same time. Store the request of every button in arrays (three arrays: cabin buttons, ▲ buttons, ▼ buttons); the light shows that the request is stored. When the elevator is idle it goes to the waiting call NEAREST to its current floor; when the door opens it clears that floor's requests and lights, and after 3 seconds it closes the door.
Test: while the elevator is idle quickly press 1 and 2 (with the cabin at floor 3 it must go to 2 first). What happens to buttons pressed while the cabin moves?
scan_buttons() stores pressed buttons in the arrays and turns on their lights, has_call(floor) tells whether that floor has a request, clear_calls(floor) clears that floor's requests and lights. To find the nearest one, compare the distances between floors.In the elevator of Task 26 presses made while the cabin moved or the door was open were lost. Change the program so that buttons are also read during every wait: the pressed button's light turns on at once and the request is served when its turn comes.
Test: while the cabin goes from floor 3 to floor 1, press 2 and the ▼ button of floor 3; both lights must turn on at once and both calls must be served later.
scan_buttons(); in the body of the empty loops that wait for sensors. Instead of the 3 second Sleep, write a function wait_ms(ms) that waits in short steps and reads the buttons at every step. Read the elapsed time from the clock: GetTickCount() in C (milliseconds), time.monotonic() in Python (seconds).On every floor there are up and down arrow lights that show which way the cabin is going. The library has no ready function for them; their addresses are the constants ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3 (up) and ADR_GOS_DWN1, ADR_GOS_AS2, ADR_GOS_AS3 (down), and they are written with write_mem(address, value).
Write the function show_arrows(direction): for CABIN_UP it turns on the up arrows on all three floors, for CABIN_DOWN the down arrows, and for CABIN_STOP it turns them all off. Inside go_to_floor of Task 27 the right arrows must be on while the cabin moves and go off when it stops.
int up_arrow[4] = {0, ADR_GOS_UP1, ADR_GOS_YUK2, ADR_GOS_YUK3}; The result of a comparison (dir == CABIN_UP) is 1 or 0 and can be written directly.Rewrite the elevator of Task 28 without waiting loops, using a single main loop and a state variable. States: IDLE, MOVING, OPENING (door opening), OPEN (door open), CLOSING (door closing). Each round the main loop reads the buttons and does only the job of the current state. Measure the 3 seconds the door stays open by reading the clock, not with Sleep.
The behaviour must be the same as in Task 28: go to the nearest call, open the door, clear the requests, wait 3 seconds, close; while moving the arrows and the display must be right. At the start, close all doors first and, if the cabin is between floors, bring it down to the floor below.
#define IDLE 0 ...). Clock: GetTickCount() in C (milliseconds, type DWORD), time.monotonic() in Python (seconds). Store the clock in a variable when the door has opened; close it when the difference to the current clock reaches 3000 ms. Do not use Sleep in the loop in states that must stop a motor (MOVING, OPENING, CLOSING).Make the state machine of Task 29 work like real elevators:
• While the elevator is going in one direction, it keeps that direction as long as there are calls waiting in that direction; when there are none left, it turns to the other direction.
• On the way it stops at every floor it passes that has a call (e.g. going from floor 1 to floor 3 with a call on floor 2, it stops at floor 2 first).
• At every stop it opens the door, clears that floor's requests and closes the door after 3 seconds. The display and the arrows are always right; the cabin never moves with a door open.
Test: with the cabin at floor 1 press cabin button 3; before the cabin reaches floor 2 press the ▼ button on floor 2. The cabin must stop at floor 2 first and then at floor 3.
target, keep the last travel direction (dir). Write the functions calls_above(floor) and calls_below(floor). Choosing the direction in IDLE: the old direction if it has calls, otherwise the other one, and stop if there are no calls. In MOVING, at every new floor: stop if it has a call or if it is the top / bottom floor.In real elevators, if someone presses a button of the same floor while the door is closing, the door opens again. Add this to the controller of Task 30:
• If a button of the current floor is pressed while the door is open (OPEN), the request is cleared at once and the 3 second time starts again.
• If a button of the current floor is pressed while the door is closing (CLOSING), the door starts opening again at once.
Test: while the cabin is closing its door at a floor, press that floor's ▲ button or the cabin button of that floor.
if (has_call(floor)) in the OPEN state and one in the CLOSING state. To reverse the door you can give door(floor, DOOR_OPEN) directly while it is closing.Most people enter the building at the ground floor (floor 1). Add this to the controller of Task 30: if the elevator stays IDLE for 10 seconds without any call and it is not at floor 1, it goes down to floor 1 without opening its door and waits there. If a call comes meanwhile, it is served as usual.
Test: start the program after Restart Sim and press nothing; after about 10 seconds the cabin must go down to floor 1.
idle_since and store the clock in it every time you enter IDLE (at the start, when the cabin stops, when the door has closed). In IDLE, if there is no call and the time is up, send the cabin down. MOVING already stops at floor 1.A safe controller must notice when something goes wrong and stop everything. Add this to the controller of Task 30:
• At the start, wait until an old error flag (if any) has cleared.
• In every round of the main loop, if get_error() is 1, do an emergency stop.
• If the moving cabin does not reach a new floor within 7 seconds (normally a floor takes about 4.7 seconds), treat it as a fault too and do an emergency stop.
Emergency stop: stop the cabin motor and the three door motors, turn the arrows off, show 0 on the display, print the reason and end the program.
Test 1: while the cabin moves, click Stop for the cabin motor in Manual Control (timeout after 7 seconds). Test 2: while the program runs, click Open in Manual Control for the door of a floor where the cabin is not, and wait (error when the door is fully open and keeps going).
emergency_stop(reason). Store the clock in a variable last_floor_time when the movement starts and whenever a new floor is reached; check the difference in the MOVING state. Do not forget to call sim_disconnect() before ending the program.To measure how well an elevator works, add statistics to the controller of Task 30:
• how many stops opened the door (number of services),
• how many floors the cabin travelled in total,
• for each floor, the waiting time from the first button press until the door at that floor is fully open, and the average of these times.
After 5 services, once the door has closed and the elevator is idle, print these three values (the average waiting time in seconds, with one decimal), turn the arrows off and end the program cleanly.
press_time[4] hold the first press time of each floor: inside scan_buttons, if a floor had no request and gets a new one, store the clock. Increase the floor count by one at every new floor in the MOVING state.