Simülasyona bağlanan, ekrana Hello room! yazan ve bağlantıyı kapatan bir program yazın.
Önce simülasyonu başlatın, sonra programı çalıştırın. Konsolda kütüphanenin [SIM] Connected ve [SIM] Disconnected. mesajlarını da görmelisiniz.
Sonra simülasyonu kapatıp programı yeniden çalıştırın: bağlantı kurulamadığı için program hata mesajıyla bitmelidir.
Her program aynı iskeletle başlar: kütüphaneyi ekle, sim_connect() ile bağlan, işini yap, sim_disconnect() ile ayrıl.
Simülasyon açık değilse sim_connect() 1 döndürür. Bu durumda devam etmenin anlamı yoktur; program 1 koduyla biter. Bu iskeleti sonraki tüm görevlerde kullanacaksınız.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1; // simulation not running
printf("Hello room!\n");
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1) # simulation not running
print("Hello room!")
sim_disconnect()
Odadaki lambayı yakan bir program yazın. Program lambayı yaktıktan sonra bitsin.
Program bittiğinde lamba yanmaya devam ediyor mu? Gözlemleyin. Sonra lambayı elle kontrol panelindeki Lamba Kapat düğmesiyle söndürün.
lamp(LAMP_ON) paylaşılan belleğe 1 yazar; simülasyon bu değeri sürekli okur ve ışığı çizer. Program bitince bellekteki değer silinmez, bu yüzden lamba yanık kalır. Elle kontrol panelindeki düğmeler de aynı belleğe yazar.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
lamp(LAMP_ON); // the light appears in the room
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1)
lamp(LAMP_ON) # the light appears in the room
sim_disconnect()
Lambayı yakın, 2 saniye bekleyin ve söndürün. Lamba simülasyonda 2 saniye yanık görünmeli, program bittiğinde sönük kalmalı.
Bilgisayar komutları çok hızlı çalıştırır. Bekleme olmadan lamba mikrosaniyeler içinde yanıp söner ve hiçbir şey göremezsiniz. Sleep(2000) / time.sleep(2) programı 2 saniye durdurur; bu sırada lamba yanık kalır.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
lamp(LAMP_ON);
Sleep(2000); // 2000 ms = 2 s
lamp(LAMP_OFF);
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
lamp(LAMP_ON)
time.sleep(2) # 2 seconds
lamp(LAMP_OFF)
sim_disconnect()
Şu sırayı uygulayan bir program yazın:
1. Lambayı yakın.
2. 3 saniye sonra klimayı açın (odada klimanın rüzgârı görünür).
3. 5 saniye sonra lambayı ve klimayı kapatın.
Klima açıkken sıcaklık göstergesini izleyin: yaklaşık 1 saniye sonra düşmeye başlar.
Program yukarıdan aşağıya satır satır çalışır; buna sıralı akış denir. ac(AC_ON) lambadan 3 saniye sonra çalışır çünkü önündeki Sleep(3000) bitmeden sıra ona gelmez.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
lamp(LAMP_ON);
Sleep(3000);
ac(AC_ON); // wind appears, room starts cooling
Sleep(5000);
lamp(LAMP_OFF);
ac(AC_OFF);
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
lamp(LAMP_ON)
time.sleep(3)
ac(AC_ON) # wind appears, room starts cooling
time.sleep(5)
lamp(LAMP_OFF)
ac(AC_OFF)
sim_disconnect()
Perde kapalıyken (en aşağıda) başlayın. Perdeyi yukarı çalıştırın, 6 saniye bekleyin, sonra aşağı çalıştırın ve programı bitirin.
Perde en üste gelince kendiliğinden durmalı; program bittikten sonra da aşağı inmeye devam edip en altta durmalı.
curtain() perdeyi bir anda taşımaz, motoru bir yönde çalıştırır. Motor, perde uca gelene kadar döner ve uçta kendiliğinden durur. Komut bellekte kaldığı için program bittikten sonra da perde inmeye devam eder. 6 saniyelik bekleme, 4,5 saniyelik tam açılmaya yetecek kadar uzundur.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
curtain(CURTAIN_UP); // motor stops by itself at the top
Sleep(6000);
curtain(CURTAIN_DOWN); // keeps moving after the program ends
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
curtain(CURTAIN_UP) # motor stops by itself at the top
time.sleep(6)
curtain(CURTAIN_DOWN) # keeps moving after the program ends
sim_disconnect()
Perde kapalıyken başlayın. Perdeyi 2 saniye boyunca yukarı çalıştırıp durdurun. Perde pencerenin yaklaşık yarısında kalmalı.
Sonra süreyi 1 saniye ve 3 saniye yapıp farkı gözlemleyin (her denemeden önce perdeyi Perde Aşağı düğmesiyle kapatın).
Perdenin konumunu okuyamayız ama motorun ne kadar süre çalıştığını biz belirleriz. Tam açılma yaklaşık 4,5 saniye olduğu için 2 saniye yaklaşık yarıya denk gelir. Süreyle konum ayarlamak basit ama tam hassas değildir.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
curtain(CURTAIN_UP);
Sleep(2000); // about half of the 4.5 s full travel
curtain(CURTAIN_STOP);
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
curtain(CURTAIN_UP)
time.sleep(2) # about half of the 4.5 s full travel
curtain(CURTAIN_STOP)
sim_disconnect()
Perde kapalıyken başlayın. Her adımdan önce ekrana ne yapıldığını yazan bir sabah senaryosu hazırlayın:
1. Good morning! yazın, lambayı yakın, 2 saniye bekleyin.
2. Opening the curtain yazın, perdeyi yukarı çalıştırın, 5 saniye bekleyin.
3. Fresh air yazın, lambayı söndürün, klimayı açın, 3 saniye bekleyin.
4. Klimayı kapatın ve Ready for the day. yazın.
Oda sıcaklığını bir değişkene okuyun ve ekrana Temperature: 24 C biçiminde yazın.
Programı birkaç kez çalıştırın ve yazılan değeri simülasyondaki sıcaklık göstergesiyle karşılaştırın. Sonra Klima Aç düğmesine basıp tekrar çalıştırın.
Değişken, bir değeri saklayan isimli bir kutudur. read_temp() o anki sıcaklığı döndürür, biz de onu t değişkenine koyarız. C'de %d tam sayıyı metnin içine yerleştirir; Python'da {t} aynı işi yapar. Sıcaklık sürekli değiştiği için her çalıştırmada farklı bir değer görebilirsiniz.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
int t = read_temp();
printf("Temperature: %d C\n", t);
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1)
t = read_temp()
print(f"Temperature: {t} C")
sim_disconnect()
Odanın bütün değerlerini okuyup alt alta yazan bir rapor programı yazın:
Temperature: .., Lux: .., AC: .., Lamp: .., Curtain motor: ..
Elle kontrol panelinden lambayı yakın, Gün Işığını Değiştir sürgüsünü 500'e getirin, perdeyi yukarı çalıştırın ve perde hareket ederken programı çalıştırın. Rapordaki sayılar yaptığınız değişiklikleri göstermeli.
Sıcaklık ve lüks simülasyonun ölçtüğü sensör değerleridir. read_ac(), read_lamp() ve read_curtain() ise çıkışlara en son ne yazıldığını gösterir (sizin programınız veya paneldeki düğmeler). Lamba yanıyorsa 1, perde yukarı gidiyorsa 1, duruyorsa 0 görürsünüz.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
printf("Temperature: %d C\n", read_temp());
printf("Lux: %d\n", read_lux());
printf("AC: %d\n", read_ac());
printf("Lamp: %d\n", read_lamp());
printf("Curtain motor: %d\n", read_curtain());
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1)
print(f"Temperature: {read_temp()} C")
print(f"Lux: {read_lux()}")
print(f"AC: {read_ac()}")
print(f"Lamp: {read_lamp()}")
print(f"Curtain motor: {read_curtain()}")
sim_disconnect()
Dış ışığı okuyun. Değer 100 lüksten azsa lambayı yakıp Dark (.. lux): lamp on yazın; değilse lambayı söndürüp Bright (.. lux): lamp off yazın.
Deneme: Gün Işığını Değiştir sürgüsünü 50'ye getirip programı çalıştırın, sonra 800'e getirip tekrar çalıştırın.
if programın karar vermesini sağlar: koşul doğruysa ilk blok, yanlışsa else bloğu çalışır; ikisi birden asla çalışmaz. 100 lüks bir eşik değeridir; siz değiştirerek lambanın ne zaman yanacağını belirleyebilirsiniz.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
int lux = read_lux();
if (lux < 100) {
lamp(LAMP_ON);
printf("Dark (%d lux): lamp on\n", lux);
} else {
lamp(LAMP_OFF);
printf("Bright (%d lux): lamp off\n", lux);
}
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1)
lux = read_lux()
if lux < 100:
lamp(LAMP_ON)
print(f"Dark ({lux} lux): lamp on")
else:
lamp(LAMP_OFF)
print(f"Bright ({lux} lux): lamp off")
sim_disconnect()
Sıcaklığı okuyun. 26 °C'den yüksekse klimayı açıp Hot (.. C): AC on yazın; değilse klimayı kapatıp Not hot (.. C): AC off yazın.
Deneme: klima kapalıyken oda birkaç saniyede ısınır; programı çalıştırın, klima açılmalı. Sonra 5 saniye bekleyin (oda soğur) ve programı tekrar çalıştırın: klima kapanmalı.
Perde motorunun durumunu okuyup sayı yerine yazıyla gösterin: 0 ise Curtain stopped, 1 ise Curtain moving up, 2 ise Curtain moving down, başka bir değerse Unknown value.
Deneme: perde dururken çalıştırın; sonra Perde Yukarı (veya Perde Aşağı) düğmesine basıp perde hareket ederken hemen çalıştırın.
else if zinciri koşulları yukarıdan aşağıya dener ve ilk doğru olanı çalıştırır; hiçbiri doğru değilse en sondaki else çalışır. CURTAIN_UP gibi sabitler kodu okunur yapar: c == 1 yerine c == CURTAIN_UP ne demek istediğinizi açıkça söyler. = atama, == karşılaştırmadır.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
int c = read_curtain();
if (c == CURTAIN_STOP) {
printf("Curtain stopped\n");
} else if (c == CURTAIN_UP) {
printf("Curtain moving up\n");
} else if (c == CURTAIN_DOWN) {
printf("Curtain moving down\n");
} else {
printf("Unknown value: %d\n", c);
}
sim_disconnect();
return 0;
}
from room import *
if sim_connect() != 0:
exit(1)
c = read_curtain()
if c == CURTAIN_STOP:
print("Curtain stopped")
elif c == CURTAIN_UP:
print("Curtain moving up")
elif c == CURTAIN_DOWN:
print("Curtain moving down")
else:
print(f"Unknown value: {c}")
sim_disconnect()
Lamba yanıyorsa VE dışarısı 600 lüksten aydınlıksa lambayı söndürüp Lamp was on in daylight: turned off yazın. Aksi halde hiçbir komut göndermeden Nothing to do yazın.
Deneme: Lamba Aç düğmesine basın, ışık sürgüsünü 800'e getirip programı çalıştırın (lamba sönmeli). Sonra sürgüyü 300'e getirip lambayı yakın ve tekrar çalıştırın (lamba yanık kalmalı).
Görev 11'i geliştirin: komut göndermeden önce read_ac() ile klimanın durumuna bakın.
• Sıcaklık 26 °C'den yüksekse: klima zaten açıksa AC already on, kapalıysa klimayı açıp AC turned on yazın.
• Değilse: klima zaten kapalıysa AC already off, açıksa klimayı kapatıp AC turned off yazın.
Deneme: menüden Animasyon Hızını en düşüğe alın. Oda sıcakken programı arka arkaya iki kez çalıştırın: önce AC turned on, sonra AC already on görmelisiniz.
Lambayı 5 kez yakıp söndürün: her seferinde 1 saniye yanık, 1 saniye sönük. Her yanışta ekrana Blink 1, Blink 2 ... Blink 5 yazın.
Kodu 5 kez kopyalamak yerine döngü kullanın.
for döngüsü içindeki blok, sayaç i 1'den 5'e kadar her değer için bir kez çalışır. Yanıp sönme sayısını değiştirmek için tek bir sayıyı değiştirmeniz yeter. Python'da range(1, 6) 1, 2, 3, 4, 5 üretir (6 dahil değildir).
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
for (int i = 1; i <= 5; i++) {
printf("Blink %d\n", i);
lamp(LAMP_ON);
Sleep(1000);
lamp(LAMP_OFF);
Sleep(1000);
}
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
for i in range(1, 6):
print(f"Blink {i}")
lamp(LAMP_ON)
time.sleep(1)
lamp(LAMP_OFF)
time.sleep(1)
sim_disconnect()
Perde kapalıyken başlayın. Ekrana her saniye bir sayı yazarak 10'dan 1'e geri sayın. Sayım bitince Go! yazın, lambayı yakın ve perdeyi yukarı çalıştırın.
Klima kapalıyken oda ısınsın, sonra programı çalıştırın. Program klimayı açsın, her 200 ms'de bir toplam 20 ölçüm alıp her birini 1: 44 C biçiminde yazsın. Sonunda klimayı kapatsın ve ölçümlerin en düşüğünü ve en yükseğini yazsın: Lowest: .. C, highest: .. C.
Önce perdeyi aşağı çalıştırın ve motor durana kadar bekleyin (perde tamamen kapanır). Sonra perdeyi yukarı çalıştırın ve motor kendiliğinden durana kadar her 100 ms'de bir sayaç artırın. Sonunda Opened in about .. ms yazın (yaklaşık 4500 ms görmelisiniz).
Sabit bir süre beklemeyin; motorun durduğunu read_curtain() ile anlayın.
Görev 10'u hiç bitmeyen bir döngüye koyun: her 100 ms'de dış ışığı okuyun; 100 lüksten azsa lambayı yakın, değilse söndürün.
Programı çalıştırıp ışık sürgüsünü 50 ile 500 arasında oynatın; lamba kendiliğinden yanıp sönmeli. Konsolu da izleyin: ne görüyorsunuz? Programı Ctrl+C ile durdurun.
Kontrol programları genellikle sonsuz döngüdür: oku → karar ver → uygula → biraz bekle → tekrar. 100 ms'lik bekleme işlemciyi boşuna yormaz ama değişikliklere hızlı tepki verir.
Konsolda her 100 ms'de bir [SIM] Lamp -> ... satırı akar: program lamba zaten doğru durumdayken bile komutu tekrar tekrar gönderiyor. Bunu Görev 20'de düzelteceğiz.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
while (1) { // stop with Ctrl+C
if (read_lux() < 100) {
lamp(LAMP_ON);
} else {
lamp(LAMP_OFF);
}
Sleep(100);
}
sim_disconnect(); // not reached, see Task 29
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
while True: # stop with Ctrl+C
if read_lux() < 100:
lamp(LAMP_ON)
else:
lamp(LAMP_OFF)
time.sleep(0.1)
sim_disconnect() # not reached, see Task 29
Görev 19'u düzeltin: lambaya sadece durumunun değişmesi gerektiğinde komut gönderin. Lamba her değiştiğinde ekrana bir kez Lux 85: lamp on veya Lux 120: lamp off yazın.
Sürgüyü oynatın: konsolda artık sadece değişiklik anlarında satır görünmeli.
want lambanın olması gereken durumudur. Sadece want şimdiki durumdan farklıysa komut gönderilir. Böylece saniyede 10 komut yerine yalnızca gerçek değişikliklerde birer komut gider. Bu "değişince gönder" kalıbını bundan sonraki bütün kontrol görevlerinde kullanacağız.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
while (1) { // stop with Ctrl+C
int lux = read_lux();
int want = LAMP_OFF;
if (lux < 100) want = LAMP_ON;
if (want != read_lamp()) { // only on change
lamp(want);
if (want == LAMP_ON) printf("Lux %d: lamp on\n", lux);
else printf("Lux %d: lamp off\n", lux);
}
Sleep(100);
}
sim_disconnect(); // not reached, see Task 29
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
while True: # stop with Ctrl+C
lux = read_lux()
want = LAMP_OFF
if lux < 100:
want = LAMP_ON
if want != read_lamp(): # only on change
lamp(want)
if want == LAMP_ON:
print(f"Lux {lux}: lamp on")
else:
print(f"Lux {lux}: lamp off")
time.sleep(0.1)
sim_disconnect() # not reached, see Task 29
Sürekli çalışan bir termostat yazın: her 100 ms'de sıcaklığı okuyun; 26 °C'den yüksekse klima açık, değilse kapalı olsun. Görev 20'deki gibi sadece değişiklikte komut gönderin ve 27 C: AC on / 26 C: AC off biçiminde yazın.
Çalışırken klimanın ne sıklıkla açılıp kapandığını izleyin (rahat izlemek için Animasyon Hızını düşürebilirsiniz).
Elle kontrol panelindeki lamba düğmelerini bir giriş gibi kullanın. Program lambanın kaç kez yakıldığını saysın: lamba her sönükten yanığa geçtiğinde Press 1, Press 2 ... yazsın. 5. yakıştan sonra klimayı açsın, 5 presses: AC on yazsın ve bitsin.
Deneme: lamba sönükken programı başlatın, sonra Lamba Aç ve Lamba Kapat düğmelerine sırayla basın.
Sadece "lamba yanık mı?" diye bakarsak, lamba yanık kaldığı sürece her döngüde sayarız. Önceki ve şimdiki değeri karşılaştırarak yalnızca değişim anını (0'dan 1'e geçişi, "yükselen kenar") yakalarız. Döngü koşulu sayaca bağlı olduğu için 5. yakışta döngü kendiliğinden biter.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
int presses = 0;
int prev = read_lamp();
printf("Press Light On / Light Off in the panel\n");
while (presses < 5) {
int now = read_lamp();
if (prev == LAMP_OFF && now == LAMP_ON) { // rising edge
presses++;
printf("Press %d\n", presses);
}
prev = now;
Sleep(50);
}
ac(AC_ON);
printf("5 presses: AC on\n");
sim_disconnect();
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
presses = 0
prev = read_lamp()
print("Press Light On / Light Off in the panel")
while presses < 5:
now = read_lamp()
if prev == LAMP_OFF and now == LAMP_ON: # rising edge
presses += 1
print(f"Press {presses}")
prev = now
time.sleep(0.05)
ac(AC_ON)
print("5 presses: AC on")
sim_disconnect()
Lambayı times kez, her seferinde ms milisaniye yanık ve ms milisaniye sönük olacak şekilde yakıp söndüren bir blink(times, ms) fonksiyonu yazın.
Ana programda önce blink(3, 200) (hızlı), 1 saniye ara, sonra blink(3, 1000) (yavaş) çağırın.
Fonksiyon, bir işe isim verip onu farklı değerlerle tekrar tekrar kullanmamızı sağlar. Parametreler (times, ms) her çağrıda farklı olabilir. Ana program artık kısa ve okunur: ne yapıldığını söylüyor, nasıl yapıldığı fonksiyonun içinde.
#include "room.h"
void blink(int times, int ms) {
for (int i = 0; i < times; i++) {
lamp(LAMP_ON);
Sleep(ms);
lamp(LAMP_OFF);
Sleep(ms);
}
}
int main(void) {
if (sim_connect() != 0) return 1;
blink(3, 200); // fast
Sleep(1000);
blink(3, 1000); // slow
sim_disconnect();
return 0;
}
from room import *
import time
def blink(times, ms):
for i in range(times):
lamp(LAMP_ON)
time.sleep(ms / 1000)
lamp(LAMP_OFF)
time.sleep(ms / 1000)
if sim_connect() != 0:
exit(1)
blink(3, 200) # fast
time.sleep(1)
blink(3, 1000) # slow
sim_disconnect()
move_curtain(dir) fonksiyonu yazın: perdeyi verilen yönde çalıştırsın ve motor durana kadar beklesin. Motor 8 saniye içinde durursa 1 döndürsün. Durmazsa motoru durdurup 0 döndürsün (zaman aşımı).
Ana program: perdeyi kapatın ve Closed yazın, 2 saniye bekleyin, perdeyi açın; sonuç 1 ise Opened, 0 ise Timeout! yazın.
Zaman aşımını denemek için perde açılırken menüden Sim Durdur'a basın: 8 saniye sonra Timeout! görmelisiniz.
Görev 21'deki termostatı iki eşikle yazın: sıcaklık 28 °C'nin üstüne çıkınca klimayı açın, 20 °C'nin altına inince kapatın; arada hiçbir şey yapmayın. Klimanın kaç kez açıldığını sayın ve her değişiklikte 29 C: AC on (switch 3) gibi yazın.
Görev 21 ile karşılaştırın: klima ne kadar sık açılıp kapanıyor?
Görev 25'teki termostat her 100 ms'de çalışmaya devam etsin. Aynı döngüye bir uyarı ışığı ekleyin: perde hareket ederken lamba yarım saniyede bir durum değiştirsin (0,5 s yanık, 0,5 s sönük); perde durunca lamba sönsün.
Deneme: Perde Yukarı veya Perde Aşağı düğmesine basın. Lamba yanıp sönerken termostat da klimayı kontrol etmeye devam etmeli.
Sleep(500) kullanmayın; o zaman termostat da yarım saniye bekler.
Sleep beklerken program başka hiçbir şey yapamaz ("bloklayan" bekleme). Bunun yerine döngü hep 100 ms'de bir döner ve her iş kendi zamanının gelip gelmediğine sayaçla bakar. Böylece termostat ve uyarı ışığı aynı anda, birbirini bekletmeden çalışır. % bölümden kalanı verir: ticks % 5 0, 1, 2, 3, 4, 0, ... diye döner.
#include "room.h"
int main(void) {
if (sim_connect() != 0) return 1;
int ticks = 0;
while (1) { // stop with Ctrl+C
// job 1: thermostat (every tick)
int t = read_temp();
if (t > 28 && read_ac() == AC_OFF) ac(AC_ON);
else if (t < 20 && read_ac() == AC_ON) ac(AC_OFF);
// job 2: warning light (every 5 ticks = 0.5 s)
if (read_curtain() != CURTAIN_STOP) {
if (ticks % 5 == 0) {
if (read_lamp() == LAMP_ON) lamp(LAMP_OFF);
else lamp(LAMP_ON);
}
} else if (read_lamp() == LAMP_ON) {
lamp(LAMP_OFF); // curtain stopped
}
ticks++;
Sleep(100); // one tick = 100 ms
}
sim_disconnect(); // not reached, see Task 29
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
ticks = 0
while True: # stop with Ctrl+C
# job 1: thermostat (every tick)
t = read_temp()
if t > 28 and read_ac() == AC_OFF:
ac(AC_ON)
elif t < 20 and read_ac() == AC_ON:
ac(AC_OFF)
# job 2: warning light (every 5 ticks = 0.5 s)
if read_curtain() != CURTAIN_STOP:
if ticks % 5 == 0:
if read_lamp() == LAMP_ON:
lamp(LAMP_OFF)
else:
lamp(LAMP_ON)
elif read_lamp() == LAMP_ON:
lamp(LAMP_OFF) # curtain stopped
ticks += 1
time.sleep(0.1) # one tick = 100 ms
sim_disconnect() # not reached, see Task 29
Perdeyi gün ışığına göre otomatik kontrol edin. Perdenin dört durumu olsun: CLOSED, OPENING, OPEN, CLOSING.
• Başlangıçta perdeyi tamamen kapatın (Görev 24'teki fonksiyon) ve CLOSED durumundan başlayın.
• CLOSED iken lüks 600'ün üstüne çıkarsa perdeyi yukarı çalıştırın → OPENING.
• OPENING iken motor durursa → OPEN.
• OPEN iken lüks 300'ün altına inerse perdeyi aşağı çalıştırın → CLOSING.
• CLOSING iken motor durursa → CLOSED.
Her durum değişikliğinde yeni durumun adını yazın. Deneme: ışık sürgüsünü 800 ile 100 arasında oynatın.
Simülasyon henüz açık değilse programın hemen pes etmesi yerine bağlanmayı 10 kez, 1 saniye arayla denemesini sağlayın (Attempt 1/10 failed...). 10 denemede de bağlanamazsa Could not connect, giving up. yazıp 1 koduyla bitsin.
Bağlandıktan sonra kısa bir kendi kendini test yapsın: lambayı ve klimayı açsın, 200 ms beklesin, read_lamp() ve read_ac() ile komutların gerçekten yazıldığını kontrol edip Lamp OK / Lamp FAILED ve AC OK / AC FAILED yazsın. Sonra ikisini de kapatıp bağlantıyı kapatsın.
Deneme: önce programı çalıştırın, birkaç saniye sonra simülasyonu başlatın.
Sağlam bir program hataları öngörür: simülasyon geç açılabilir, bir komut yerine ulaşmayabilir. Yeniden deneme geçici sorunları tolere eder, sınırlı deneme sayısı ise sonsuza kadar beklemeyi önler. Çıkış kodu (0 başarı, 1 hata) programı başka programların veya betiklerin de anlayabileceği şekilde bitirir. Komut sonrası durumu geri okumak, komutun gerçekten uygulandığını doğrular.
#include "room.h"
int connect_retry(int tries) {
for (int i = 1; i <= tries; i++) {
if (sim_connect() == 0) return 0;
printf("Attempt %d/%d failed, retrying in 1 s\n", i, tries);
Sleep(1000);
}
return 1;
}
int main(void) {
if (connect_retry(10) != 0) {
printf("Could not connect, giving up.\n");
return 1;
}
lamp(LAMP_ON);
ac(AC_ON);
Sleep(200);
if (read_lamp() == LAMP_ON) printf("Lamp OK\n");
else printf("Lamp FAILED\n");
if (read_ac() == AC_ON) printf("AC OK\n");
else printf("AC FAILED\n");
lamp(LAMP_OFF);
ac(AC_OFF);
sim_disconnect();
return 0;
}
from room import *
import time
def connect_retry(tries):
for i in range(1, tries + 1):
if sim_connect() == 0:
return 0
print(f"Attempt {i}/{tries} failed, retrying in 1 s")
time.sleep(1)
return 1
if connect_retry(10) != 0:
print("Could not connect, giving up.")
exit(1)
lamp(LAMP_ON)
ac(AC_ON)
time.sleep(0.2)
print("Lamp OK" if read_lamp() == LAMP_ON else "Lamp FAILED")
print("AC OK" if read_ac() == AC_ON else "AC FAILED")
lamp(LAMP_OFF)
ac(AC_OFF)
sim_disconnect()
Şimdiye kadar sonsuz döngülü programları Ctrl+C ile kestik; lamba, klima ve perde o anki durumda kaldı ve sim_disconnect() hiç çalışmadı. Görev 20'deki gece lambasını öyle değiştirin ki Ctrl+C'ye basıldığında döngüden düzgünce çıksın, lambayı ve klimayı kapatsın, perdeyi durdursun, sim_disconnect() çağırsın ve Bye! yazsın.
Ctrl+C programa bir kesme sinyali gönderir. Python bunu KeyboardInterrupt hatası olarak fırlatır; biz yakalayıp temizlik koduna geçeriz. C'de sinyal fonksiyonu sadece bir bayrağı değiştirir, döngü bir sonraki turda bayrağı görüp kendiliğinden biter. Böylece program her durumda odayı güvenli bir durumda bırakır. Bundan sonraki projelerde bu kalıbı kullanacağız.
#include "room.h"
#include <signal.h>
static volatile sig_atomic_t running = 1;
static void on_ctrl_c(int sig) {
(void)sig;
running = 0; // only set a flag here
}
int main(void) {
if (sim_connect() != 0) return 1;
signal(SIGINT, on_ctrl_c);
while (running) {
int want = LAMP_OFF;
if (read_lux() < 100) want = LAMP_ON;
if (want != read_lamp()) lamp(want);
Sleep(100);
}
// cleanup: leave the room in a safe state
lamp(LAMP_OFF);
ac(AC_OFF);
curtain(CURTAIN_STOP);
sim_disconnect();
printf("Bye!\n");
return 0;
}
from room import *
import time
if sim_connect() != 0:
exit(1)
try:
while True:
want = LAMP_OFF
if read_lux() < 100:
want = LAMP_ON
if want != read_lamp():
lamp(want)
time.sleep(0.1)
except KeyboardInterrupt: # Ctrl+C
pass
# cleanup: leave the room in a safe state
lamp(LAMP_OFF)
ac(AC_OFF)
curtain(CURTAIN_STOP)
sim_disconnect()
print("Bye!")
Odayı tamamen otomatik yöneten bir program yazın. Her alt sistem kendi fonksiyonunda olsun ve hepsi aynı 100 ms'lik döngüde çalışsın:
• Lamba: dış ışık 100 lüksten azsa yanık, değilse sönük.
• Klima: 28 °C üstünde aç, 20 °C altında kapat (Görev 25).
• Perde: Görev 27'deki durum makinesi (600 lüks üstünde aç, 300 lüks altında kapat).
• Komutlar sadece değişiklikte gönderilsin ve her değişiklik ekrana yazılsın.
• Ctrl+C ile temiz kapanış (Görev 29).
Deneme: ışık sürgüsünü 50, 400, 800 ve tekrar 50 yapın; her adımda lambanın ve perdenin ne yaptığını izleyin. Ya da bekleyin: dış ışık zaten kendiliğinden değişir.
Hiçbir şeyi kontrol etmeyen, sadece izleyen bir enerji sayacı yazın. Lambayı ve klimayı elle kontrol panelinden (veya aynı anda çalışan başka bir programla) açıp kapatın; sayaç şunları ölçsün:
• lambanın ve klimanın toplam kaç saniye açık kaldığı,
• klimanın kaç kez açıldığı.
Her 5 saniyede bir Lamp 12.3 s, AC 4.0 s, AC started 2 times gibi bir satır yazsın. Ctrl+C ile çıkınca enerji tüketimini hesaplasın: lamba 60 W, klima 1500 W. Enerji (Wh) = güç (W) × süre (s) / 3600. Örnek: Energy: lamp 0.21 Wh, AC 1.67 Wh.
Otomatik sistemler kullanıcıyı dinlemelidir. Lamba (100 lüks altında yanık) ve klima (28/20 °C histerezis) otomatik çalışsın. Ama kullanıcı elle kontrol panelinden lambanın veya klimanın durumunu değiştirirse, program o cihaza 30 saniye boyunca dokunmasın ve Lamp: manual for 30 s (veya AC: ...) yazsın. 30 saniye dolunca Lamp: back to automatic yazıp otomatiğe dönsün. Ctrl+C ile temiz kapanış olsun.
Deneme: ışık sürgüsünü 50'ye getirin (lamba yanar), sonra Lamba Kapat'a basın: lamba 30 saniye sönük kalmalı, sonra yeniden yanmalı.
Odanın bir gününü yöneten bir durum makinesi yazın. Durumlar: NIGHT, DAY, EVENING.
• Başlangıç: lüks 300 veya üstündeyse perdeyi tamamen açıp DAY, değilse tamamen kapatıp NIGHT durumundan başlayın.
• NIGHT → lüks 300'ün üstüne çıkınca sabah rutini: Good morning! yazın, lambayı hızlıca 3 kez yakıp söndürün (300 ms), perdeyi adım adım açın (1 s yukarı, 2 s bekle, 1 s yukarı, 2 s bekle, sonra sonuna kadar), DAY durumuna geçin.
• DAY → lüks 100'ün altına inince: Good evening! yazın, perdeyi aşağı çalıştırın, lambayı yakın, EVENING durumuna geçin.
• EVENING → 10 saniye sonra lambayı söndürün, Good night! yazın, NIGHT durumuna geçin. Bu 10 saniye beklenirken döngü bloklanmasın (tick sayacı).
• Ctrl+C ile temiz kapanış.
Deneme: ışık sürgüsüyle günü hızlandırın (50 → 500 → 50) ya da yaklaşık 3 dakika bekleyip kendiliğinden değişen gün ışığını izleyin.