Первая тестируемая на ПЛК версия

This commit is contained in:
VladislavOstapov 2023-01-28 12:12:01 +03:00
parent 14b5cdf06d
commit d8fee17444
4 changed files with 198 additions and 111 deletions

View File

@ -344,9 +344,9 @@ int main() {
} }
robot_main(); robot_main();
// scheduler_main(); scheduler_main();
increment_zone(ROBOT_ZONE_GAL); // increment_zone(ROBOT_ZONE_GAL);
increment_zone(ROBOT_ZONE_ETCH); // increment_zone(ROBOT_ZONE_ETCH);
send_str("\033c"); send_str("\033c");
showAll(); showAll();

View File

@ -101,8 +101,8 @@ static void emulate_robot(robot_code &code, robot_regs& r, char robot_id) {
case ROBOT_CMD_UP_code: case ROBOT_CMD_UP_code:
if (code.barrel_id >= 0 && cmd_arg) { if (code.barrel_id >= 0 && cmd_arg) {
// не давать ехать перед тем как истечет таймер // не давать ехать перед тем как истечет таймер (только для не пустых барабанов)
if (barrels[code.barrel_id].software_timer > 0) { if (!barrels[code.barrel_id].flags.is_empty && barrels[code.barrel_id].software_timer > 0) {
break; break;
} }
barrels[code.barrel_id].flags.is_up = true; barrels[code.barrel_id].flags.is_up = true;

View File

@ -122,6 +122,14 @@ void scheduler_main()
} }
} }
// автоматический инкремент зон травления и цинкования
if (etching_zone < 0) {
increment_zone(ROBOT_ZONE_ETCH);
}
if (galvanizing_zone < 0) {
increment_zone(ROBOT_ZONE_GAL);
}
// кнопки на линии // кнопки на линии
// кнопка загрузки барабана // кнопка загрузки барабана
@ -222,21 +230,28 @@ void scheduler_main()
// для каждого робота нужно получить свой список задач // для каждого робота нужно получить свой список задач
// и надо еще сделать так, чтобы роботы не столкнулись // и надо еще сделать так, чтобы роботы не столкнулись
// суть этого предела в том, чтобы робот всегда был свободен ЗА зоной gal8,
// но при этом если зоной обмена выбрана промывка 3а, то за ней тоже, получается max(ZONE_G8, exchange_zone)
const short robot1_border = ZONE_GALVANIZING_8 > hla_exchange_zone ? ZONE_GALVANIZING_8 : hla_exchange_zone;
// суть этого предела в том, чтобы робот всегда держал свободной зону gal1,
// но при этом если зоной обмена выбрана промывка 2б, то за ней тоже, получается min(ZONE_G1, exchange_zone)
const short robot2_border = ZONE_GALVANIZING_1 < hla_exchange_zone ? ZONE_GALVANIZING_1 : hla_exchange_zone;
// логика для того, чтобы роботы не столкнулись в начале // логика для того, чтобы роботы не столкнулись в начале
if (robot1.dx.current_zone < ZONE_GALVANIZING_1) { if (robot1.dx.current_zone < robot1_border) {
// начальная позиция робота 1 - промывка 3Б
robot2_lock_zone = -1; robot2_lock_zone = -1;
robot1_lock_zone = ZONE_WASHING_3B; robot1_lock_zone = robot1_border;
if (robot1_code.PC < 0) { if (robot1_code.PC < 0) {
robot1_code.barrel_id = -1; robot1_code.barrel_id = -1;
robot1_code.code[0] = ROBOT_CMD_DOWN(); robot1_code.code[0] = ROBOT_CMD_DOWN();
robot1_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_3B); robot1_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(robot1_border + 2);
robot1_code.code[2] = ROBOT_CMD_END(); robot1_code.code[2] = ROBOT_CMD_END();
robot1_code.PC = 0; robot1_code.PC = 0;
} }
} else if (robot2.dx.current_zone < ZONE_DEGREASING) { } else if (robot2.dx.current_zone < ZONE_DEGREASING) {
// начальная позиция робота 1 - обезжир // начальная позиция робота 1 - обезжир
robot2_lock_zone = ZONE_WASHING_2A; robot2_lock_zone = ZONE_DEGREASING;
if (robot2_code.PC < 0) { if (robot2_code.PC < 0) {
robot2_code.barrel_id = -1; robot2_code.barrel_id = -1;
robot2_code.code[0] = ROBOT_CMD_DOWN(); robot2_code.code[0] = ROBOT_CMD_DOWN();
@ -244,6 +259,16 @@ void scheduler_main()
robot2_code.code[2] = ROBOT_CMD_END(); robot2_code.code[2] = ROBOT_CMD_END();
robot2_code.PC = 0; robot2_code.PC = 0;
} }
} else if (robot2.dx.current_zone > robot2_border) {
// это уже граница робота 2
robot2_lock_zone = robot2_border - 2;
if (robot2_code.PC < 0) {
robot2_code.barrel_id = -1;
robot2_code.code[0] = ROBOT_CMD_DOWN();
robot2_code.code[1] = ROBOT_CMD_MOVE_TO_ZONE(robot2_border - 2);
robot2_code.code[2] = ROBOT_CMD_END();
robot2_code.PC = 0;
}
} else { } else {
// отдельно просчитаем все для первого робота // отдельно просчитаем все для первого робота
if (robot1_code.PC < 0) { if (robot1_code.PC < 0) {

104
utils.c
View File

@ -33,10 +33,18 @@ char zone_is_busy(short zone) {
short get_first_night_zone() { short get_first_night_zone() {
// TODO сделать корректное вычисление ночной зоны
// всего зон, куда можно сныкать барабаны (всего 9 мест: 8 промывок и выгрузка) // всего зон, куда можно сныкать барабаны (всего 9 мест: 8 промывок и выгрузка)
for (short i = 0; i < 9; i++) { for (short nz = 0; nz < 9; nz++) {
if (!zone_is_busy(NIGHT_ZONES[i])) { char found = 0;
return NIGHT_ZONES[i]; for (short i = 0; i < BARRELS_COUNT; i++) {
if (barrels[i].flags.is_exist && barrels[i].zone == NIGHT_ZONES[nz] && !barrels[i].flags.is_night) {
found = 1;
}
}
if (found == 0) {
return NIGHT_ZONES[nz];
} }
} }
@ -47,7 +55,13 @@ short get_first_night_zone() {
short _get_dest_zone(struct barrel *bar) { short _get_dest_zone(struct barrel *bar) {
if (bar->flags.is_night) { if (bar->flags.is_night) {
return ZONE_LOAD_1; return ZONE_LOAD_1;
} else { }
// если это зона обмена и барабан пустой
if (bar->zone == hla_exchange_zone && bar->flags.is_empty) {
return ZONE_LOAD_1;
}
switch (bar->zone) { switch (bar->zone) {
case ZONE_LOAD_2: case ZONE_LOAD_2:
// загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание // загрузка 2, только в нее можно грузить новые барабаны, нужно обезжиривание
@ -92,7 +106,6 @@ short _get_dest_zone(struct barrel *bar) {
case ZONE_GALVANIZING_6: case ZONE_GALVANIZING_6:
case ZONE_GALVANIZING_7: case ZONE_GALVANIZING_7:
case ZONE_GALVANIZING_8: case ZONE_GALVANIZING_8:
// TODO перенести эту логику в функцию can_move
// цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум) // цинкование, требуется чтобы в зонах 17-22 было максимум 2 барабана (3 барабана для этой части линии - максимум)
if (!zone_is_busy(ZONE_WASHING_3A)) { if (!zone_is_busy(ZONE_WASHING_3A)) {
short count = 0; short count = 0;
@ -141,15 +154,23 @@ short _get_dest_zone(struct barrel *bar) {
case ZONE_UNLOAD: case ZONE_UNLOAD:
// последняя промывка, нужно разрешение на выгрузку // последняя промывка, нужно разрешение на выгрузку
if (button_unload) { if (button_unload) {
if (hla_night_mode) {
if (one_robot_mode) { if (one_robot_mode) {
return ZONE_LOAD_1; return ZONE_LOAD_1;
} else { } else {
return hla_exchange_zone; return hla_exchange_zone;
} }
} else {
short nz = get_first_night_zone();
if (nz < hla_exchange_zone) {
return hla_exchange_zone;
} else {
return nz;
}
}
} }
break; break;
} }
}
return -1; return -1;
} }
@ -160,38 +181,64 @@ short can_move(struct barrel *bar, char robot_id) {
if (robot_id != 1 && robot_id != 2) { if (robot_id != 1 && robot_id != 2) {
return -3; return -3;
} }
// сразу отсекаем варианты, при которых невозможно переместить барабан // сразу отсекаем варианты, при которых невозможно переместить барабан
if (!bar->flags.is_exist) { if (!bar->flags.is_exist) {
return -3; return -3;
} }
if (bar->software_timer > 0) {
return -2;
}
if (bar->flags.robot != 0) { if (bar->flags.robot != 0) {
return -3; return -3;
} }
// проверка ночного режима // проверка ночного режима
if (hla_night_mode) { if (hla_night_mode) {
if (bar->flags.is_night && !bar->flags.is_empty) { if (bar->flags.is_night) {
return -1; return -1;
} }
} }
// тут просчет примерного времени, в течении которого можно доехать до барабана
if (!bar->flags.is_empty) {
short approximate_time;
if (robot_id == 1) {
approximate_time = bar->zone - robot1.dx.current_zone;
} else {
approximate_time = bar->zone - robot1.dx.current_zone;
}
// abs(approximate_time)
if (approximate_time < 0) {
approximate_time = -approximate_time;
}
#ifndef EMULATOR
approximate_time *= 4;
#endif
if (bar->software_timer > -approximate_time) {
return -2;
}
}
// дальше нужно проверить, что можно передвигать бочку // дальше нужно проверить, что можно передвигать бочку
short dest_zone = _get_dest_zone(bar); short dest_zone = _get_dest_zone(bar);
if (zone_is_busy(dest_zone)) {
return -1;
}
if (!one_robot_mode && dest_zone >= 0) { if (!one_robot_mode && dest_zone >= 0) {
if (robot_id == 1) { if (robot_id == 1) {
// если робот 1, то это старый, который ближе к концу линнии. // если робот 1, то это старый, который ближе к концу линнии.
// Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон // Ему нельзя ехать если хоть одна из зон <= max(r2_pos, r2_lock) + кол-во пограничных зон
short border = robot2.dx.current_zone; short border = robot2.dx.current_zone;
if (robot2_lock_zone > border) { if (border < robot2_lock_zone) {
border = robot2_lock_zone; border = robot2_lock_zone;
} }
if (border < ZONE_WASHING_2A) {
border = ZONE_WASHING_2A;
}
border += LOCK_ZONE_BORDER; border += LOCK_ZONE_BORDER;
if (bar->zone <= border || dest_zone <= border) { if (bar->zone <= border || dest_zone <= border) {
@ -201,9 +248,13 @@ short can_move(struct barrel *bar, char robot_id) {
// если робот 2, то это новый, который ближе к началу линнии. // если робот 2, то это новый, который ближе к началу линнии.
// Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон // Ему нельзя ехать если хоть одна из зон >= max(r2_pos, r2_lock) - кол-во пограничных зон
short border = robot1.dx.current_zone; short border = robot1.dx.current_zone;
if (robot1_lock_zone < border) { if (border > robot1_lock_zone) {
border = robot1_lock_zone; border = robot1_lock_zone;
} }
if (border > ZONE_WASHING_3B) {
border = ZONE_WASHING_3B;
}
border -= LOCK_ZONE_BORDER; border -= LOCK_ZONE_BORDER;
if (bar->zone >= border || dest_zone >= border) { if (bar->zone >= border || dest_zone >= border) {
@ -435,6 +486,9 @@ void create_operation(struct robot_code *code, short barrel_id, const short star
if (barrel_id >= 0) { if (barrel_id >= 0) {
barrels[barrel_id].flags.robot = robot_id; barrels[barrel_id].flags.robot = robot_id;
if (hla_night_mode && barrels[barrel_id].flags.is_empty && dest_zone == get_first_night_zone()) {
barrels[barrel_id].flags.is_night = -1;
}
} }
short cmd_index = 0; short cmd_index = 0;
@ -653,19 +707,27 @@ void create_operation(struct robot_code *code, short barrel_id, const short star
if (!one_robot_mode && !hla_night_mode) { if (!one_robot_mode && !hla_night_mode) {
if (robot_id == 2) { if (robot_id == 2) {
if (dest_zone >= ZONE_GALVANIZING_1) { // суть этого предела в том, чтобы робот всегда держал свободной зону gal1,
// но при этом если зоной обмена выбрана промывка 2б, то за ней тоже, получается min(ZONE_G1, exchange_zone)
const short robot2_border = (ZONE_GALVANIZING_1 < hla_exchange_zone ? ZONE_GALVANIZING_1 : hla_exchange_zone) - 1;
if (dest_zone >= robot2_border) {
// из промывки 2б он перекладывал, пусть едет в промывку 2а // из промывки 2б он перекладывал, пусть едет в промывку 2а
code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_WASHING_2A); code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(robot2_border - 1);
code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_2A); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(robot2_border - 1);
} else if (dest_zone < ZONE_DEGREASING) { } else if (dest_zone < ZONE_DEGREASING) {
code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_DEGREASING); // code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_DEGREASING);
code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_DEGREASING); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_DEGREASING);
} }
} else if (robot_id == 1) { } else if (robot_id == 1) {
if (dest_zone <= ZONE_WASHING_3A) { // суть этого предела в том, чтобы робот всегда был свободен ЗА зоной gal8,
// но при этом если зоной обмена выбрана промывка 3а, то за ней тоже, получается max(ZONE_G8, exchange_zone)
const short robot1_border = (ZONE_GALVANIZING_8 > hla_exchange_zone ? ZONE_GALVANIZING_8 : hla_exchange_zone) + 1;
if (dest_zone <= robot1_border) {
// чтобы из этой зоны можно было переложить барабан первому роботу // чтобы из этой зоны можно было переложить барабан первому роботу
code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(ZONE_WASHING_4A); // code->code[cmd_index++] = ROBOT_CMD_SET_LOCK_ZONE(robot1_border + 1);
code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(ZONE_WASHING_4A); code->code[cmd_index++] = ROBOT_CMD_MOVE_TO_ZONE(robot1_border + 1);
} }
} }
} }