How to work

  1. Do the tasks in order; each one adds something to the previous one.
  2. For each task, open a new file in the simulation folder next to the library file (e.g. c_room/task01.c or py_room/task01.py) and include the library.
  3. Start the simulation first, then run your program. Stop programs with an endless loop using Ctrl+C.
  4. When you get stuck, check the hint first; open the answer last.

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.

1 Beginner

Connecting, switching outputs and waiting.
01

Connect to the simulation

See answer

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?

Hint
sim_connect() returns 0 on success and 1 on failure. Call sim_disconnect() at the end of the program.
sim_connect()sim_disconnect()printf / print
02

Show numbers on the cabin display

See answer

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.

Hint
cabin_display(number) writes to the display. To wait, use Sleep(1000) (milliseconds) in C and time.sleep(1) (seconds) in Python.
cabin_display()Sleeptime.sleep
03

Cabin button lights

See answer

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.

Hint
cabin_button_light(floor, state): state 1 turns it on, 0 turns it off.
cabin_button_light()Sleep
04

Floor call lights

See answer

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.)

Hint
floor_button_light(floor, direction, state); use DIR_UP or DIR_DOWN for the direction.
floor_button_light()DIR_UPDIR_DOWN
05

Move the cabin a little

See answer

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.

Hint
Use the constants CABIN_DOWN, CABIN_UP and CABIN_STOP with cabin_motor(). The motor runs until you stop it.
cabin_motor()CABIN_STOP
06

Open the door for a time

See answer

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).

Hint
door(floor, command); the command can be DOOR_OPEN, DOOR_CLOSE or DOOR_STOP.
door()DOOR_OPENDOOR_CLOSEDOOR_STOP

2 Basic

Reading sensors, printing and deciding with if/else.
07

Where is the cabin?

See answer

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?

Hint
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);
cabin_sensor_read()değişken / variable
08

Show the floor number on the display

See answer

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.

Hint
Set a variable to 0; check the sensors one by one with if / else if and store the floor number in the variable. If it is still 0 at the end, the cabin is between floors.
if / else if / elsecabin_sensor_read()cabin_display()
09

What state is the door in?

See answer

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.

Hint
There are two sensors: 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.
door_sensor_read()door_open_read()if / else if / else
10

Is the button pressed?

See answer

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?

Hint
cabin_button_read(2) returns 1 if the button is held down at that moment.
cabin_button_read()if / else
11

See the error flag

See answer

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.

Hint
get_error() returns 1 if a limit was exceeded, otherwise 0. The flag clears itself after a short time.
get_error()if / else
12

What is the motor doing?

See answer

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.

Hint
cabin_motion_read() returns 0 (CABIN_STOP), 1 (CABIN_UP) or 2 (CABIN_DOWN). Compare it with the constants.
cabin_motion_read()if / else if
13

Is the elevator ready?

See answer

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).

Hint
Find the floor as in Task 8. To combine two conditions use && in C and and in Python.
&& / anddoor_sensor_read()cabin_sensor_read()

3 Intermediate

Loops, continuous control and tracking state.
14

Count on the display

See answer

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.

Hint
C: for (int i = 1; i <= 9; i++) { ... } Python: for i in range(1, 10):
forcabin_display()
15

Live floor indicator

Your turn

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.

Hint
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.
whiledurum değişkeni / state variableSleep
16

Light while held

See answer

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.

Hint
Keep the button's value from the previous round in a variable. If the new value differs from the old one, something has changed.
değişim algılama / change detectioncabin_button_read()cabin_button_light()
17

Remember the pressed button

See answer

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.

Hint
Use an array that keeps whether each floor's light is on: 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.
dizi / arrayforcabin_button_read()cabin_sensor_read()
18

Stop at floor 2 with the sensor

Your turn

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.

Hint
A 'wait until something happens' loop: while (cabin_sensor_read(2) == 0) { } in C, while cabin_sensor_read(2) == 0: pass in Python. Do not put Sleep in this loop.
while (bekleme / wait)cabin_sensor_read()cabin_motor()
19

Open and close the door with sensors

See answer

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).

Hint
While opening, wait until door_open_read(2) is 1; while closing, wait until door_sensor_read(2) is 0. Do not put Sleep in either waiting loop.
door()door_open_read()door_sensor_read()while
20

Go down to floor 1 from anywhere

Your turn

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.

Hint
The cabin is always above floor 1 or at floor 1, so going down always reaches floor 1. First check with if whether it is already at floor 1.
if / elsewhilecabin_sensor_read()
21

Go to the requested floor

See answer

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.

Hint
Three steps: (1) find the current floor as in Task 8. (2) Write a loop that reads the buttons while the variable target is 0. (3) Choose the direction by comparing target with the current floor and wait as in Task 18.
whileforif / else ifcabin_button_read()

4 Advanced

Functions, timing, state machines and robustness.
22

Function: go to a floor

See answer

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.

Hint
A function gives a job a name. C: 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.
fonksiyon / functionreturnparametre / parameter
23

Function: open and close the door

Your turn

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.

Hint
A check like 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.
fonksiyon / functionreturnfor
24

Safety lock: no moving with an open door

See answer

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.

Hint
Add a 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.
güvenlik / safetyfonksiyon / functiondoor_sensor_read()
25

Answer calls one by one

Your turn

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.

Hint
Each round read the three buttons of the three floors and store the pressed floor in a variable target. A function lights_off(floor) that turns off all lights of a floor makes it easier.
whilefonksiyon / functionfloor_button_read()cabin_button_read()
26

Collect calls, go to the nearest

See answer

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?

Hint
Write three small functions: 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.
dizi / arrayfonksiyon / functionen yakın / nearest
27

Do not miss presses while moving

Your turn

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.

Hint
Put 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).
bloklamayan bekleme / non-blocking waitscan_buttons()GetTickCounttime.monotonic
28

Direction arrows

See answer

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.

Hint
Put the addresses into two arrays that you can index with the floor number: 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.
write_mem()adres dizisi / address arrayADR_GOS_UP1
29

State machine

See answer

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.

Hint
Define constants for the states (C: #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).
durum makinesi / state machineGetTickCounttime.monotonic#define

5 Project

Complete systems that combine everything.
30

Complete 3-floor elevator controller

See answer

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.

Hint
Instead of 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.
durum makinesi / state machinetoplayıcı kontrol / collective controlfonksiyon / function
31

Reopen the door

Your turn

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.

Hint
You only need one 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.
durum geçişi / state transitionhas_call()door()
32

Park at floor 1 when idle

Your turn

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.

Hint
Keep a variable 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.
zaman aşımı / timeoutGetTickCountdurum makinesi / state machine
33

Error watchdog and emergency stop

Your turn

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).

Hint
Write a function 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.
get_error()zaman aşımı / timeoutacil durdurma / emergency stop
34

Service statistics

Your turn

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.

Hint
Let an array 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.
sayaç / counterortalama / averagezaman damgası / timestamp