From 7d5c63fcdd4c7604a99aec56de4df4ae8a002713 Mon Sep 17 00:00:00 2001 From: angrycompany16 Date: Sat, 2 Mar 2024 12:31:57 +0100 Subject: [PATCH 1/2] It's a bit bruteforced, but stop button, obstruction and better queue management seems to be working well --- skeleton_project/.vscode/settings.json | 3 +- skeleton_project/source/FSM.c | 58 +++++++++++++--------- skeleton_project/source/FSM.h | 7 +++ skeleton_project/source/main.c | 20 ++++---- skeleton_project/source/queue.c | 66 +++++++++++++++++++++++--- skeleton_project/source/queue.h | 15 +++++- skeleton_project/source/request.c | 2 +- skeleton_project/source/request.h | 6 ++- skeleton_project/source/run.c | 25 +++++++++- skeleton_project/source/run.h | 1 + 10 files changed, 156 insertions(+), 47 deletions(-) diff --git a/skeleton_project/.vscode/settings.json b/skeleton_project/.vscode/settings.json index c5acc08..c7c99c1 100644 --- a/skeleton_project/.vscode/settings.json +++ b/skeleton_project/.vscode/settings.json @@ -6,6 +6,7 @@ "button.h": "c", "stdio.h": "c", "queue.h": "c", - "stdlib.h": "c" + "stdlib.h": "c", + "cmath": "c" } } \ No newline at end of file diff --git a/skeleton_project/source/FSM.c b/skeleton_project/source/FSM.c index 5d16a81..78263a8 100644 --- a/skeleton_project/source/FSM.c +++ b/skeleton_project/source/FSM.c @@ -8,6 +8,7 @@ FSM* FSM_init(){ if (p_fsm!= NULL) { p_fsm->current_state = CLOSED_EMPTY; p_fsm->current_floor = 2; + p_fsm->direction = DIR_NONE; p_fsm->moving = false; } else { printf("Error allocating memory for button\n"); @@ -21,65 +22,80 @@ void FSM_deinit(FSM* p_fsm) { } void FSM_behaviour(FSM* p_fsm, time_t* p_timer, Queue* p_main_queue){ - - // Ikke tatt hensyn til Stop (timer-cases) og Obstruction enda - switch(p_fsm->current_state) { case UP_EMPTY: p_fsm->moving = true; + p_fsm->direction = DIR_UP; elevio_motorDirection(DIRN_UP); elevio_doorOpenLamp(0); break; case UP_UNEMPTY: p_fsm->moving = true; + p_fsm->direction = DIR_UP; elevio_motorDirection(DIRN_UP); elevio_doorOpenLamp(0); break; case DOWN_EMPTY: p_fsm->moving = true; + p_fsm->direction = DIR_DOWN; elevio_motorDirection(DIRN_DOWN); elevio_doorOpenLamp(0); break; case DOWN_UNEMPTY: p_fsm->moving = true; + p_fsm->direction = DIR_DOWN; elevio_motorDirection(DIRN_DOWN); elevio_doorOpenLamp(0); break; case OPEN_EMPTY: if (time_limit(p_timer)){ - printf("timer empty\n"); + printf("Empty elevator, timer ran out\n"); FSM_transition(p_fsm, TIMER, p_main_queue, p_timer); } p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(1); break; case OPEN_UNEMPTY: if (time_limit(p_timer)){ - printf("timer unempty\n"); + printf("Unempty elevator, timer ran out\n"); FSM_transition(p_fsm, TIMER, p_main_queue, p_timer); } p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(1); break; case CLOSED_EMPTY: p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(0); break; case CLOSED_UNEMPTY: p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(0); break; case BLOCKED_EMPTY: + if (time_limit(p_timer)){ + printf("Blocked empty elevator, timer ran out\n"); + FSM_transition(p_fsm, TIMER, p_main_queue, p_timer); + } p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(1); break; case BLOCKED_UNEMPTY: + if (time_limit(p_timer)){ + printf("Blocked unempty elevator, timer ran out\n"); + FSM_transition(p_fsm, TIMER, p_main_queue, p_timer); + } p_fsm->moving = false; + p_fsm->direction = DIR_NONE; elevio_motorDirection(DIRN_STOP); elevio_doorOpenLamp(1); break; @@ -107,11 +123,12 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t switch(trigger){ case STOP: p_fsm->current_state = CLOSED_UNEMPTY; + queue_clear(p_main_queue); break; case ENTERED_FLOOR: queue_remove_all(p_main_queue, elevio_floorSensor()); - if (queue_has_off_requests(p_main_queue)){ + if (queue_query(p_main_queue, -1, ANY, TRUE)){ reset_timer(p_timer); p_fsm->current_state = OPEN_UNEMPTY; } else { @@ -122,7 +139,8 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t break; default: p_fsm->current_state = UP_UNEMPTY; - }reset_timer(p_timer); + } + // reset_timer(p_timer); break; case DOWN_EMPTY: @@ -143,11 +161,12 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t switch(trigger){ case STOP: p_fsm->current_state = CLOSED_UNEMPTY; + queue_clear(p_main_queue); break; case ENTERED_FLOOR: queue_remove_all(p_main_queue, elevio_floorSensor()); - if (queue_has_off_requests(p_main_queue)){ + if (queue_query(p_main_queue, -1, ANY, TRUE)){ reset_timer(p_timer); p_fsm->current_state = OPEN_UNEMPTY; } else { @@ -164,15 +183,13 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t case OPEN_EMPTY: switch(trigger){ case OBSTRUCTION: - // do something + p_fsm->current_state = BLOCKED_UNEMPTY; break; case TIMER: - // TODO: implement waiting for stop-button release before starting timer p_fsm->current_state = CLOSED_EMPTY; break; default: p_fsm->current_state = OPEN_EMPTY; - // reset_timer(p_timer); } break; @@ -180,11 +197,12 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t switch(trigger){ case STOP: p_fsm->current_state = OPEN_EMPTY; + queue_clear(p_main_queue); reset_timer(p_timer); break; case OBSTRUCTION: - // do something + p_fsm->current_state = BLOCKED_UNEMPTY; break; case TIMER: p_fsm->current_state = CLOSED_UNEMPTY; @@ -213,11 +231,12 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t } break; - case CLOSED_UNEMPTY: + case CLOSED_UNEMPTY: switch(trigger){ case STOP: if (elevio_floorSensor()!=-1){ p_fsm->current_state = OPEN_EMPTY; + queue_clear(p_main_queue); reset_timer(p_timer); } break; @@ -240,11 +259,7 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t case BLOCKED_EMPTY: switch(trigger){ case TIMER: - // waits for obstr release - // start_timer(time); - // if (time_limit(time)){ - // p_fsm->current_state = CLOSED_EMPTY; - // } + p_fsm->current_state = CLOSED_EMPTY; break; default: p_fsm->current_state = BLOCKED_EMPTY; @@ -254,11 +269,8 @@ void FSM_transition(FSM* p_fsm, FSM_Trigger trigger, Queue* p_main_queue, time_t case BLOCKED_UNEMPTY: switch(trigger){ case TIMER: - // waits for obstr release - // start_timer(time); - // if (time_limit(time)){ - // p_fsm->current_state = CLOSED_UNEMPTY; - // } + printf("lolz"); + p_fsm->current_state = CLOSED_UNEMPTY; break; default: p_fsm->current_state = BLOCKED_UNEMPTY; diff --git a/skeleton_project/source/FSM.h b/skeleton_project/source/FSM.h index 600c921..06d7e6f 100644 --- a/skeleton_project/source/FSM.h +++ b/skeleton_project/source/FSM.h @@ -34,9 +34,16 @@ typedef enum { STAY } FSM_Trigger; +typedef enum { + DIR_NONE = -1, + DIR_DOWN, + DIR_UP, +} ELEVATOR_DIRECTION; + typedef struct { FSM_State current_state; int current_floor; + int direction; bool moving; } FSM; diff --git a/skeleton_project/source/main.c b/skeleton_project/source/main.c index 6d8fcbd..baa0d6e 100644 --- a/skeleton_project/source/main.c +++ b/skeleton_project/source/main.c @@ -18,16 +18,13 @@ int main() { Queue* p_main_queue = queue_init(); int target_floor = -1; - Button* up_buttons[] = { button_init(), button_init(), button_init(), button_init() }; - Button* down_buttons[] = { button_init(), button_init(), button_init(), button_init() }; - Button* cab_buttons[] = { button_init(), button_init(), button_init(), button_init() }; + Button* pp_up_buttons[] = { button_init(), button_init(), button_init(), button_init() }; + Button* pp_down_buttons[] = { button_init(), button_init(), button_init(), button_init() }; + Button* pp_cab_buttons[] = { button_init(), button_init(), button_init(), button_init() }; + Button* p_stop_button = button_init(); while(1) { - run(&target_floor, p_main_queue, p_fsm, p_timer, up_buttons, down_buttons, cab_buttons); - - if (elevio_stopButton()) { - break; - } + run(&target_floor, p_main_queue, p_fsm, p_timer, p_stop_button, pp_up_buttons, pp_down_buttons, pp_cab_buttons); nanosleep(&(struct timespec){0, 20*1000*1000}, NULL); } @@ -36,10 +33,11 @@ int main() { FSM_deinit(p_fsm); timer_deinit(p_timer); for (int i = 0; i < 4; i++) { - button_deinit(up_buttons[i]); - button_deinit(down_buttons[i]); - button_deinit(cab_buttons[i]); + button_deinit(pp_up_buttons[i]); + button_deinit(pp_down_buttons[i]); + button_deinit(pp_cab_buttons[i]); } + button_deinit(p_stop_button); return 0; diff --git a/skeleton_project/source/queue.c b/skeleton_project/source/queue.c index e6fd7d0..d4cdfc2 100644 --- a/skeleton_project/source/queue.c +++ b/skeleton_project/source/queue.c @@ -3,7 +3,6 @@ Queue* queue_init() { Queue* p_queue = (Queue*)malloc(sizeof(Queue)); - // maybe not necessary? if (p_queue == NULL) { printf("Queue object could not be made\n"); exit(EXIT_FAILURE); @@ -44,6 +43,13 @@ void queue_remove_all(Queue* p_queue, int floor) { } } +void queue_clear(Queue* p_queue) { + for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { + queue_remove(p_queue, i); + i--; + } +} + void queue_print(Queue* p_queue) { printf("Printing queue...\n"); for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { @@ -51,24 +57,72 @@ void queue_print(Queue* p_queue) { } } -bool queue_has_off_requests(Queue* p_queue) { +// bool queue_has_off_requests(Queue* p_queue) { +// for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { +// if (p_queue->queue[i].off == true) { +// return true; +// } +// } +// return false; +// } + +bool queue_query(Queue* p_queue, int floor, QueueQueryItem direction, QueueQueryItem off) { + if (floor == -1) { + if (direction == ANY) { + return queue_query_off(p_queue, off); + } else { + if (off == ANY) { + return queue_query_direction(p_queue, direction); + } else { + return queue_query_off(p_queue, off) && queue_query_direction(p_queue, direction); + } + } + } else { + if (direction == ANY) { + if (off == ANY) { + return queue_query_floor(p_queue, floor); + } else { + return queue_query_floor(p_queue, floor) && queue_query_off(p_queue, off); + } + } else { + if (off == ANY) { + return queue_query_floor(p_queue, floor) && queue_query_direction(p_queue, direction); + } else { + return queue_query_floor(p_queue, floor) && queue_query_off(p_queue, off) && queue_query_direction(p_queue, direction); + } + } + } + return false; +} + +static bool queue_query_floor(Queue* p_queue, int floor) { for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { - if (p_queue->queue[i].off == true) { + if (p_queue->queue[i].floor == floor) { return true; } } return false; } -bool queue_query(Queue* p_queue, bool up, bool off) { +static bool queue_query_direction(Queue* p_queue, bool direction) { for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { - if (p_queue->queue[i].off == off && p_queue->queue[i].up == up) { + if (p_queue->queue[i].direction == direction) { return true; - } + } } return false; } +static bool queue_query_off(Queue* p_queue, bool off) { + for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { + if (p_queue->queue[i].off == off) { + return true; + } + } + return false; + +} + Request* queue_find_first_off_request(Queue* p_queue) { for (size_t i = 0; i < p_queue->youngest_queue_element; i++) { if (p_queue->queue[i].off == true) { diff --git a/skeleton_project/source/queue.h b/skeleton_project/source/queue.h index 5276c5c..eb7b74b 100644 --- a/skeleton_project/source/queue.h +++ b/skeleton_project/source/queue.h @@ -11,6 +11,12 @@ typedef struct { size_t youngest_queue_element; } Queue; +typedef enum { + FALSE, + TRUE, + ANY, +} QueueQueryItem; + Queue* queue_init(void); void queue_deinit(Queue* p_queue); @@ -21,10 +27,15 @@ void queue_remove(Queue* p_queue, size_t pos); void queue_remove_all(Queue* p_queue, int floor); +void queue_clear(Queue* p_queue); + void queue_print(Queue* p_queue); -bool queue_has_off_requests(Queue* p_queue); +// bool queue_has_off_requests(Queue* p_queue); -bool queue_query(Queue* p_queue, bool up, bool off); +bool queue_query(Queue* p_queue, int floor, QueueQueryItem direction, QueueQueryItem off); +static bool queue_query_floor(Queue* p_queue, int floor); +static bool queue_query_direction(Queue* p_queue, bool direction); +static bool queue_query_off(Queue* p_queue, bool off); Request* queue_find_first_off_request(Queue* p_queue); diff --git a/skeleton_project/source/request.c b/skeleton_project/source/request.c index 9bce817..e3f26f9 100644 --- a/skeleton_project/source/request.c +++ b/skeleton_project/source/request.c @@ -2,6 +2,6 @@ void print_request(Request* request) { printf("Floor: %d, ", request->floor); - printf("Going up?: %s, ", request->up ? "yes" : "no"); + printf("Going up?: %s, ", request->direction ? "yes" : "no"); printf("Exiting?: %s\n", request->off ? "yes" : "no"); } diff --git a/skeleton_project/source/request.h b/skeleton_project/source/request.h index efab0d6..6cf7323 100644 --- a/skeleton_project/source/request.h +++ b/skeleton_project/source/request.h @@ -3,9 +3,13 @@ #include #include +// NOTE: `direction` boolean has two meanings. When a button is pressed outside the elevator, `direction` refers to whether the +// pershon pressed the direction or down button. However, when a button is pressed inside the elevator, `direction` refers to +// whether the current floor is less than or greater than the floor that the person wants to go to. +// The case where a user enters the elevator and presses the button corresponding to the current floor is not handled. typedef struct { int floor; - bool up; + bool direction; bool off; } Request; diff --git a/skeleton_project/source/run.c b/skeleton_project/source/run.c index dadac19..91335fe 100644 --- a/skeleton_project/source/run.c +++ b/skeleton_project/source/run.c @@ -5,17 +5,34 @@ void run( Queue* p_main_queue, FSM* p_fsm, time_t* p_timer, + Button* p_stop_button, Button** pp_up_buttons, Button** pp_down_buttons, Button** pp_cab_buttons ) { + button_update(p_stop_button, elevio_stopButton()); + for (size_t i = 0; i < 4; i++) { button_update(pp_up_buttons[i], elevio_callButton(i, BUTTON_HALL_UP)); button_update(pp_down_buttons[i], elevio_callButton(i, BUTTON_HALL_DOWN)); button_update(pp_cab_buttons[i], elevio_callButton(i, BUTTON_CAB)); } + if (p_stop_button->was_just_pressed) { + FSM_transition(p_fsm, STOP, p_main_queue, p_timer); + // queue_query_floor(p_main_queue, 2); + } + + if (p_stop_button->pressed) { reset_timer(p_timer); } + + if (elevio_obstruction()) { + reset_timer(p_timer); + FSM_transition(p_fsm, OBSTRUCTION, p_main_queue, p_timer); + } + for (int i = 0; i < 4; i++) { + if (p_stop_button->pressed) { continue; } + if (pp_down_buttons[i]->was_just_pressed) { queue_add(p_main_queue, (Request) {i, false, false}); queue_print(p_main_queue); @@ -38,7 +55,7 @@ void run( } if (!p_fsm->moving) { - if (queue_has_off_requests(p_main_queue)) { + if (queue_query(p_main_queue, -1, ANY, TRUE)) { *target_floor = queue_find_first_off_request(p_main_queue)->floor; } else { if (p_main_queue->youngest_queue_element != 0) { @@ -61,16 +78,20 @@ void run( // printf("Floor sensor: %d\n", elevio_floorSensor()); if (elevio_floorSensor() != -1) { p_fsm->current_floor = elevio_floorSensor(); + if (queue_query(p_main_queue, elevio_floorSensor(), p_fsm->direction, ANY)) { + FSM_transition(p_fsm, ENTERED_FLOOR, p_main_queue, p_timer); + } } if (*target_floor == elevio_floorSensor()) { // TODO: also make elevator stop when someone enters in the same direction FSM_transition(p_fsm, ENTERED_FLOOR, p_main_queue, p_timer); } + } FSM_behaviour(p_fsm, p_timer, p_main_queue); // queue_print(p_main_queue); - printf("Current state: %d\n", p_fsm->current_state); + // printf("Current state: %d\n", p_fsm->current_state); } \ No newline at end of file diff --git a/skeleton_project/source/run.h b/skeleton_project/source/run.h index 23b4568..ae5a9bb 100644 --- a/skeleton_project/source/run.h +++ b/skeleton_project/source/run.h @@ -13,6 +13,7 @@ void run( Queue* p_main_queue, FSM* p_current_state, time_t* p_timer, + Button* p_stop_button, Button** pp_up_buttons, Button** pp_down_buttons, Button** pp_cab_buttons From 3c4fc7fc2e3cf9b1efb09105543025490a4c36ba Mon Sep 17 00:00:00 2001 From: David Persson <81249185+angrycompany16@users.noreply.github.com> Date: Sat, 2 Mar 2024 12:39:22 +0100 Subject: [PATCH 2/2] Created README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..0f93251 --- /dev/null +++ b/README.md @@ -0,0 +1,6 @@ +# Lab work for TTK4235 + +In this lab we implemented a basic system for controlling an elevator in accordance with some pre-specified system requirements. The elevator was also required to pass a FAT test. + +The assignment: +https://github.com/ITK-TTK4235/lab_2/