Исправления мелких багов

This commit is contained in:
VladislavOstapov 2023-01-13 11:00:35 +03:00
parent 0fb2f3b007
commit 92d40847b3
4 changed files with 262 additions and 265 deletions

View File

@ -18,7 +18,6 @@ void scheduler_main();
// Флаги, которые есть в оригинальной программе на ПЛК, в "C global variables" // Флаги, которые есть в оригинальной программе на ПЛК, в "C global variables"
// Кнопки с панели // Кнопки с панели
extern char hla_auto_mode;
extern char hla_night_mode; extern char hla_night_mode;
extern char hla_correct_command; extern char hla_correct_command;

View File

@ -11,87 +11,73 @@ struct scheduler_task {
short scheduler_find_task(const struct scheduler_task* tasks, const short curr_pos) { short scheduler_find_task(const struct scheduler_task* tasks, const short curr_pos) {
if (hla_night_mode) { // для начала надо найти максимальный приоритет у операций
// надо просто найти самый левый барабан short max_priority = -1;
short b = -1; // собсна барабан, который можно переместить for (short i = 0; i < BARRELS_COUNT; i++) {
short z = ZONE_UNLOAD; // зона, ищем минимальную поэтому ставим максимальную - зону выгрузки if (tasks[i].dest_zone >= 0) {
for (short i = 0; i < BARRELS_COUNT; i++) { if (tasks[i].priority > max_priority) {
if (tasks[i].dest_zone >= 0 && tasks[i].start_zone <= z) { max_priority = tasks[i].priority;
b = i;
z = tasks[i].start_zone;
} }
} }
}
return b; if (max_priority < 0) {
} else { return -1; // тасков нет
// для начала надо найти максимальный приоритет у операций }
short max_priority = -1;
for (short i = 0; i < BARRELS_COUNT; i++) { // ищем первый барабан слева, и ближайший справа
if (tasks[i].dest_zone >= 0) { short left = -1, right = -1;
if (tasks[i].priority > max_priority) { for (short i = 0; i < BARRELS_COUNT; i++) {
max_priority = tasks[i].priority; short target = tasks[i].start_zone; // фактическая зона откуда тащить барабан
} if (tasks[i].dest_zone < 0) {
} continue;
} }
if (max_priority < 0) { // чтобы не получилось перемещать барабаны с приоритетом ниже
return -1; // тасков нет if (tasks[i].priority < max_priority) {
continue;
} }
// ищем первый барабан слева, и ближайший справа if (curr_pos <= target) {
short left = -1, right = -1; // это таск справа, надо найти ближайший
for (short i = 0; i < BARRELS_COUNT; i++) { if (right == -1) {
short target = tasks[i].start_zone; // фактическая зона откуда тащить барабан right = i;
if (tasks[i].dest_zone < 0) {
continue;
}
// чтобы не получилось перемещать барабаны с приоритетом ниже
if (tasks[i].priority < max_priority) {
continue;
}
if (curr_pos <= target) {
// это таск справа, надо найти ближайший
if (right == -1) {
right = i;
} else {
if (barrels[right].zone > target) {
right = i;
}
}
} else { } else {
// таск слева, ищем максимально дальний (с минимальной зоной) if (barrels[right].zone > target) {
if (left == -1) { right = i;
}
}
} else {
// таск слева, ищем максимально дальний (с минимальной зоной)
if (left == -1) {
left = i;
} else {
if (barrels[left].zone > target) {
left = i; left = i;
} else {
if (barrels[left].zone > target) {
left = i;
}
} }
} }
} }
}
// итого есть результат: есть ли таски, которые надо тащить вперед (и если надо то какой ближний), и есть первый таск // итого есть результат: есть ли таски, которые надо тащить вперед (и если надо то какой ближний), и есть первый таск
if (left < 0) { if (left < 0) {
return right; // вернем таск справа (если его нет, в переменной будет -1) return right; // вернем таск справа (если его нет, в переменной будет -1)
} }
if (right < 0) { if (right < 0) {
return left; // если вдруг задачи справа не оказалось, вернем задачу слева если есть return left; // если вдруг задачи справа не оказалось, вернем задачу слева если есть
} }
// вычисляем что ближе // вычисляем что ближе
short ld = curr_pos - left; // левая дельта short ld = curr_pos - left; // левая дельта
short rd = right - curr_pos; // правая дельта short rd = right - curr_pos; // правая дельта
// дальше сравниваем дельты // дальше сравниваем дельты
// по идее если они равны то с большим приоритетом робот поедет в левую часть, // по идее если они равны то с большим приоритетом робот поедет в левую часть,
// а левую дельту вообще уменьшу на 1, чтобы цель слева казалась ближе // а левую дельту вообще уменьшу на 1, чтобы цель слева казалась ближе
if (rd > ld - 1) { if (rd > ld - 1) {
return left; return left;
} else { } else {
return right; return right;
}
} }
} }
@ -128,24 +114,24 @@ void scheduler_main()
robot1_lock_zone = -1; robot1_lock_zone = -1;
robot2_lock_zone = -1; robot2_lock_zone = -1;
// ставим всем барабанам которые в промывках флаг ночного барабана (кроме тех, что заняты роботами) // // ставим всем барабанам которые в промывках флаг ночного барабана (кроме тех, что заняты роботами)
for (short i = 0; i < BARRELS_COUNT; i++) { // for (short i = 0; i < BARRELS_COUNT; i++) {
if (barrels[i].flags.is_exist && barrels[i].flags.robot == 0) { // if (barrels[i].flags.is_exist && barrels[i].flags.robot == 0) {
const short zones[] = { // const short zones[] = {
ZONE_LOAD_1, // ZONE_LOAD_1,
ZONE_WASHING_1A, ZONE_WASHING_1B, // ZONE_WASHING_1A, ZONE_WASHING_1B,
ZONE_WASHING_2A, ZONE_WASHING_2B, // ZONE_WASHING_2A, ZONE_WASHING_2B,
ZONE_WASHING_3A, ZONE_WASHING_3B, // ZONE_WASHING_3A, ZONE_WASHING_3B,
ZONE_WASHING_4A, ZONE_WASHING_4B // ZONE_WASHING_4A, ZONE_WASHING_4B
}; // };
for (short t = 0; t < 9; t++) { // for (short t = 0; t < 9; t++) {
if (barrels[i].zone == zones[t]) { // if (barrels[i].zone == zones[t]) {
barrels[i].flags.is_night = -1; // barrels[i].flags.is_night = -1;
break; // break;
} // }
} // }
} // }
} // }
} }
if (scheduler_en) { if (scheduler_en) {

368
utils.c
View File

@ -6,13 +6,22 @@
#include <stdio.h> #include <stdio.h>
#include "emulator.h" #include "emulator.h"
#else #else
#include "main.h" #include "utils.h"
#endif #endif
#define LOCK_ZONE_BORDER 1 #define LOCK_ZONE_BORDER 1
const short NIGHT_ZONES[9] = {
ZONE_LOAD_1,
ZONE_WASHING_1A, ZONE_WASHING_1B,
ZONE_WASHING_2A, ZONE_WASHING_2B,
ZONE_WASHING_3A, ZONE_WASHING_3B,
ZONE_WASHING_4A, ZONE_WASHING_4B
};
char zone_is_busy(short zone) { char zone_is_busy(short zone) {
for (short i = 0; i < BARRELS_COUNT; i++) { for (short i = 0; i < BARRELS_COUNT; i++) {
if (barrels[i].flags.is_exist && barrels[i].zone == zone) { if (barrels[i].flags.is_exist && barrels[i].zone == zone) {
@ -23,6 +32,18 @@ char zone_is_busy(short zone) {
} }
short get_first_night_zone() {
// всего зон, куда можно сныкать барабаны (всего 9 мест: 8 промывок и выгрузка)
for (short i = 0; i < 9; i++) {
if (!zone_is_busy(NIGHT_ZONES[i])) {
return NIGHT_ZONES[i];
}
}
return -1;
}
// TODO обновить метод для работы с двумя роботами // TODO обновить метод для работы с двумя роботами
// вернет можно ли ехать и главное куда ехать, если можно (нельзя если вернулось значение < 0) // вернет можно ли ехать и главное куда ехать, если можно (нельзя если вернулось значение < 0)
// -1 вернет что перемещать нельзя // -1 вернет что перемещать нельзя
@ -44,199 +65,186 @@ short can_move(struct barrel *bar, char robot_id) {
return -2; return -2;
} }
// проверка ночного режима
if (hla_night_mode) { if (hla_night_mode) {
if (bar->flags.is_night) { if (bar->flags.is_night && !bar->flags.is_empty) {
return -1; return -1;
} }
// задача - найти первую свободную промывку
const short zones[] = {
ZONE_LOAD_1,
ZONE_WASHING_1A, ZONE_WASHING_1B,
ZONE_WASHING_2A, ZONE_WASHING_2B,
ZONE_WASHING_3A, ZONE_WASHING_3B,
ZONE_WASHING_4A, ZONE_WASHING_4B
};
// всего зон, куда можно сныкать барабаны (всего 9 мест: 8 промывок и выгрузка)
for (short i = 0; i < 9; i++) {
if (!zone_is_busy(zones[i])) {
return zones[i];
}
}
return -1;
} else { } else {
// дальше нужно проверить, что можно передвигать бочку
short dest_zone = -1;
// если барабан ночной, то надо проверить выгрузку (туда выгружаются ночные барабаны) }
if (bar->flags.is_night) {
if (!zone_is_busy(ZONE_LOAD_1)) { // дальше нужно проверить, что можно передвигать бочку
dest_zone = ZONE_LOAD_1; short dest_zone = -1;
// если барабан ночной, то надо проверить выгрузку (туда выгружаются ночные барабаны)
if (bar->flags.is_night) {
if (!zone_is_busy(ZONE_LOAD_1)) {
dest_zone = ZONE_LOAD_1;
}
} else {
switch (bar->zone) {
case ZONE_LOAD_2:
// загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание
if (!zone_is_busy(ZONE_DEGREASING)) {
dest_zone = ZONE_DEGREASING;
}
break;
case ZONE_DEGREASING:
// обезжиривание, нужна промывка 1А
if (!zone_is_busy(ZONE_WASHING_1A)) {
dest_zone = ZONE_WASHING_1A;
}
break;
case ZONE_WASHING_1A:
// промывка 1А, нужна промывка 1Б
if (!zone_is_busy(ZONE_WASHING_1B)) {
dest_zone = ZONE_WASHING_1B;
}
break;
case ZONE_WASHING_1B:
// промывка 1Б, нужно травление (зоны 5-6)
if (etching_zone < 0) {
break;
}
if (!zone_is_busy((short)(ZONE_ETCHING_1 + etching_zone))) {
dest_zone = (short)(ZONE_ETCHING_1 + etching_zone);
}
break;
case ZONE_ETCHING_1:
case ZONE_ETCHING_2:
// травление, нужна промывка 2А
if (!zone_is_busy(ZONE_WASHING_2A)) {
dest_zone = ZONE_WASHING_2A;
}
break;
case ZONE_WASHING_2A:
// промывка 2А, нужна промывка 2Б
if (!zone_is_busy(ZONE_WASHING_2B)) {
dest_zone = ZONE_WASHING_2B;
}
break;
case ZONE_WASHING_2B:
// промывка 2Б, нужно цинкование (зоны 9-16)
if (galvanizing_zone < 0) {
break;
}
if (!zone_is_busy((short)(ZONE_GALVANIZING_1 + galvanizing_zone))) {
dest_zone = (short)(ZONE_GALVANIZING_1 + galvanizing_zone);
}
break;
case ZONE_GALVANIZING_1:
case ZONE_GALVANIZING_2:
case ZONE_GALVANIZING_3:
case ZONE_GALVANIZING_4:
case ZONE_GALVANIZING_5:
case ZONE_GALVANIZING_6:
case ZONE_GALVANIZING_7:
case ZONE_GALVANIZING_8:
// цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум)
if (!zone_is_busy(ZONE_WASHING_3A)) {
short count = 0;
// если зона 17 свободна, то диапазон начнется с
for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) {
if (zone_is_busy(i)) {
count++;
}
}
if (count < 3) {
dest_zone = ZONE_WASHING_3A;
}
}
break;
case ZONE_WASHING_3A:
// промывка 3А, перекладываем в промывку 3Б
if (!zone_is_busy(ZONE_WASHING_3B)) {
dest_zone = ZONE_WASHING_3B;
}
break;
case ZONE_WASHING_3B:
// это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию
if (!zone_is_busy(ZONE_PASSIVATION) && !zone_is_busy(ZONE_WASHING_4A)) {
dest_zone = ZONE_PASSIVATION;
}
// это атомарная операция, по идее вносить барабан в пассивацию нельзя
break;
case ZONE_PASSIVATION:
// процесс пассивации, нужна промывка 4A
// чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет
if (!zone_is_busy(ZONE_WASHING_4A)) {
dest_zone = ZONE_WASHING_4A;
}
break;
case ZONE_WASHING_4A:
// промывка 4А, перекладываем в промывку 4Б
if (!zone_is_busy(ZONE_WASHING_4B)) {
dest_zone = ZONE_WASHING_4B;
}
break;
case ZONE_WASHING_4B:
// процесс пассивации, нужна промывка 4B (зона 21) (потому что сейчас я в 4A)
if (!zone_is_busy(ZONE_UNLOAD)) {
dest_zone = ZONE_UNLOAD;
}
break;
case ZONE_UNLOAD:
// последняя промывка, нужно разрешение на выгрузку
if (one_robot_mode && button_unload) {
// нужно промывку загрузку 0
if (!zone_is_busy(ZONE_LOAD_1)) {
dest_zone = ZONE_LOAD_1;
}
}
break;
}
}
if (!one_robot_mode) {
if (robot_id == 1) {
// если робот 1, то это старый, который ближе к концу линнии.
// Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон
short border = robot2.dx.current_zone;
if (robot2_lock_zone > border) {
border = robot2_lock_zone;
}
border += LOCK_ZONE_BORDER;
if (bar->zone <= border || dest_zone <= border) {
dest_zone = -1;
} }
} else { } else {
switch (bar->zone) { // если робот 2, то это новый, который ближе к началу линнии.
case ZONE_LOAD_2: // Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон
// загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание short border = robot1.dx.current_zone;
if (!zone_is_busy(ZONE_DEGREASING)) { if (robot1_lock_zone < border) {
dest_zone = ZONE_DEGREASING; border = robot1_lock_zone;
} }
break; border -= LOCK_ZONE_BORDER;
case ZONE_DEGREASING: if (bar->zone >= border || dest_zone >= border) {
// обезжиривание, нужна промывка 1А dest_zone = -1;
if (!zone_is_busy(ZONE_WASHING_1A)) {
dest_zone = ZONE_WASHING_1A;
}
break;
case ZONE_WASHING_1A:
// промывка 1А, нужна промывка 1Б
if (!zone_is_busy(ZONE_WASHING_1B)) {
dest_zone = ZONE_WASHING_1B;
}
break;
case ZONE_WASHING_1B:
// промывка 1Б, нужно травление (зоны 5-6)
if (etching_zone < 0) {
break;
}
if (!zone_is_busy((short)(ZONE_ETCHING_1 + etching_zone))) {
dest_zone = (short)(ZONE_ETCHING_1 + etching_zone);
}
break;
case ZONE_ETCHING_1:
case ZONE_ETCHING_2:
// травление, нужна промывка 2А
if (!zone_is_busy(ZONE_WASHING_2A)) {
dest_zone = ZONE_WASHING_2A;
}
break;
case ZONE_WASHING_2A:
// промывка 2А, нужна промывка 2Б
if (!zone_is_busy(ZONE_WASHING_2B)) {
dest_zone = ZONE_WASHING_2B;
}
break;
case ZONE_WASHING_2B:
// промывка 2Б, нужно цинкование (зоны 9-16)
if (galvanizing_zone < 0) {
break;
}
if (!zone_is_busy((short)(ZONE_GALVANIZING_1 + galvanizing_zone))) {
dest_zone = (short)(ZONE_GALVANIZING_1 + galvanizing_zone);
}
break;
case ZONE_GALVANIZING_1:
case ZONE_GALVANIZING_2:
case ZONE_GALVANIZING_3:
case ZONE_GALVANIZING_4:
case ZONE_GALVANIZING_5:
case ZONE_GALVANIZING_6:
case ZONE_GALVANIZING_7:
case ZONE_GALVANIZING_8:
// цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум)
if (!zone_is_busy(ZONE_WASHING_3A)) {
short count = 0;
// если зона 17 свободна, то диапазон начнется с
for (short i = ZONE_WASHING_3B; i <= (short)ZONE_UNLOAD; i++) {
if (zone_is_busy(i)) {
count++;
}
}
if (count < 3) {
dest_zone = ZONE_WASHING_3A;
}
}
break;
case ZONE_WASHING_3A:
// промывка 3А, перекладываем в промывку 3Б
if (!zone_is_busy(ZONE_WASHING_3B)) {
dest_zone = ZONE_WASHING_3B;
}
break;
case ZONE_WASHING_3B:
// это перед пассивацией, требует свободную промывку 4А и на всякий случай свободную пассивацию
if (!zone_is_busy(ZONE_PASSIVATION) && !zone_is_busy(ZONE_WASHING_4A)) {
dest_zone = ZONE_PASSIVATION;
}
// это атомарная операция, по идее вносить барабан в пассивацию нельзя
break;
case ZONE_PASSIVATION:
// процесс пассивации, нужна промывка 4A
// чисто теоретически сюда никогда не попадем, но если вдруг выстрелит пусть будет
if (!zone_is_busy(ZONE_WASHING_4A)) {
dest_zone = ZONE_WASHING_4A;
}
break;
case ZONE_WASHING_4A:
// промывка 4А, перекладываем в промывку 4Б
if (!zone_is_busy(ZONE_WASHING_4B)) {
dest_zone = ZONE_WASHING_4B;
}
break;
case ZONE_WASHING_4B:
// процесс пассивации, нужна промывка 4B (зона 21) (потому что сейчас я в 4A)
if (!zone_is_busy(ZONE_UNLOAD)) {
dest_zone = ZONE_UNLOAD;
}
break;
case ZONE_UNLOAD:
// последняя промывка, нужно разрешение на выгрузку
if (one_robot_mode && button_unload) {
// нужно промывку загрузку 0
if (!zone_is_busy(ZONE_LOAD_1)) {
dest_zone = ZONE_LOAD_1;
}
}
break;
} }
} }
if (!one_robot_mode) {
if (robot_id == 1) {
// если робот 1, то это старый, который ближе к концу линнии.
// Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон
short border = robot2.dx.current_zone;
if (robot2_lock_zone > border) {
border = robot2_lock_zone;
}
border += LOCK_ZONE_BORDER;
if (bar->zone <= border || dest_zone <= border) {
dest_zone = -1;
}
} else {
// если робот 2, то это новый, который ближе к началу линнии.
// Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон
short border = robot1.dx.current_zone;
if (robot1_lock_zone < border) {
border = robot1_lock_zone;
}
border -= LOCK_ZONE_BORDER;
if (bar->zone >= border || dest_zone >= border) {
dest_zone = -1;
}
}
}
return dest_zone;
} }
return dest_zone;
} }
// выставляет приоритет операции (зависит только от зоны, в которой робот находится) // выставляет приоритет операции
short get_operation_priority(short barrel_id) { short get_operation_priority(short barrel_id) {
// сделать приоритет на барабан, который больше всего ждет // сделать приоритет на барабан, который больше всего ждет
if (barrels[barrel_id].zone >= ZONE_GALVANIZING_1 && barrels[barrel_id].zone <= ZONE_GALVANIZING_8) { if (barrels[barrel_id].zone >= ZONE_GALVANIZING_1 && barrels[barrel_id].zone <= ZONE_GALVANIZING_8) {

View File

@ -224,8 +224,12 @@ extern char scheduler_start_signal;
#define hla_robot2_en _c_hla_robot2_en #define hla_robot2_en _c_hla_robot2_en
#define auto_mode_pause _c_auto_mode_pause #define auto_mode_pause _c_auto_mode_pause
#define hla_night_mode _c_hla_night_mode
#endif #endif
extern const short NIGHT_ZONES[9];
#define ROBOT_CMD_MASK (short)0xF000 #define ROBOT_CMD_MASK (short)0xF000
#define ROBOT_CMD_END_code (short)0x0000 #define ROBOT_CMD_END_code (short)0x0000