Лабораторна робота 3
Лабораторна робота №03. Промислові цифрові сигнали та діагностика відмов
Мета: навчитися пояснювати 24 V промислову логіку та 3,3 V GPIO без небезпечного прямого з'єднання; розрізняти PNP/NPN, sourcing/sinking, NO/NC, COM і активний рівень; реалізувати симуляційний класифікатор станів; перевірити реакції на обрив, замикання, розбіжність каналів і відмови сервісів за data/fault-scenarios.json.
Результати навчання та передумови
Після виконання студент уміє:
- описати струмовий шлях для sourcing- і sinking-виходу без перенесення типової схеми на невідомий модуль;
- перетворити сирий рівень з урахуванням
active_lowу логічний стан; - пояснити роль COM, підтягування, оптичної/гальванічної розв'язки та захисту;
- класифікувати
inactive,active,ERROR,STOP_AND_ERRORу симуляції; - довести, що
null, розбіжність каналів і невідомий формат дають відмову за замовчуванням; - пояснити, чому два звичайні GPIO не є safety-системою.
Передумови: ЛР-01–02 або знання безпечного стану й оцінювання ризику; базові закони електричного кола на концептуальному рівні; Python і JSON.
Середовище виконання
| Середовище | Статус | Примітка |
|---|---|---|
| Google Colab | дозволено | Треба завантажити незмінений fault-scenarios.json; фізичних інтерфейсів немає |
| Локальний ПК | основне | Python зі стандартною бібліотекою, запуск із кореня репозиторію |
| Raspberry Pi | дозволено | Тільки файл даних і mock; GPIO не відкривається |
| Фізичний комплекс MERC-I5 | не потрібен | Заборонено створювати обриви, замикання або змінювати проводку |
Необхідні знання та матеріали
Знання
- напруга вимірюється відносно опорного провідника/COM;
- вхід не повинен залишатися у невизначеному «плаваючому» стані;
- розмикальний контакт NC і
active_low— різні аспекти: механічна конфігурація й програмна інтерпретація; nullу тестових даних означає «немає достовірного рівня», а не 0.- Power Hub модуль живлення
Обладнання та ПЗ
- фізичні сенсори, джерела 24 V і Raspberry Pi для цієї ЛР не потрібні;
- локальний файл
data/fault-scenarios.json; - Python зі стандартною бібліотекою і текстовий редактор.
Вхідні джерела
- апаратна частина MERC-I5;
- базова лінія ПЗ та API;
- політика допуску;
- офіційна документація Raspberry Pi — GPIO має 3,3 V логічні рівні; 5 V на GPIO може пошкодити плату;
- довідник MG400 — дані саме базових DI/DO робота, не карта сигналів MERC-I5.
- Power Hub модуль живлення
Ризики та правила безпеки
Ключові ризики
| Небезпека | Причина | Безпечна дія |
|---|---|---|
| Пошкодження Raspberry Pi | 5 V/24 V або від'ємна напруга подана на GPIO | не підключати; застосовувати лише затверджений перетворювач і розв'язку після перевірки схеми |
| Коротке замикання/перегрів | невідомі COM, полярність, струм або навантаження | не вимірювати й не перепідключати студентом |
| Хибний активний стан | плаваючий вхід, неправильний active_low, NO/NC | невідомий стан переводити в ERROR |
| Хибна довіра до двох каналів | спільне живлення, ПЗ або загальна причина відмови | не називати діагностичне дублювання safety-функцією |
Заборонені дії
- подавати 5 V або 24 V на GPIO Raspberry Pi;
- створювати фізичні
short_to_0v,short_to_24vабоwire_break; - від'єднувати COM, сенсор, оптопару, реле або аварійний канал;
- визначати pinout за кольором проводу чи типовою схемою;
- керувати виходами MG400, конвеєра, подавача або грипера.
Умови негайної зупинки
Припинити роботу й повідомити оператора за нагріву, запаху, пошкодження ізоляції, невідомої напруги, руху механізму, суперечливих фактичних показів або будь-якого випадкового доступу програми до GPIO.
Безпечний стан
Безпечний стан: усі виконавчі виходи поза межами цієї програми; вхід None, розбіжність або невідомий формат → ERROR; для втрати зв'язку з роботом чи заклинювання → STOP_AND_ERROR; відновлення потребує підтвердження оператора.
Передпусковий чекліст
- Файл має
scope: simulation_only. - Програма не імпортує GPIO/Modbus/SDK і не відкриває мережу.
- Жоден провід або модуль не від'єднують.
- Дані
nullне перетворюють на0. - Невідомий сценарій спричиняє контрольовану помилку.
- Результати позначають як симуляційні.
Методичні вказівки й теоретичні відомості
1. Рівень напруги, струмовий шлях і COM
«24 V промислова логіка» описує клас промислових сигналів, але не доводить точну напругу або допустимий струм невідомого модуля. GPIO Raspberry Pi працює з 3,3 V логікою. Між ними потрібен перевірений інтерфейс: перетворення рівнів, обмеження струму, захист і, коли це вимагає архітектура, гальванічна розв'язка. Пряме з'єднання неприпустиме.
- Sourcing/PNP-вихід у типовій концепції подає струм до навантаження/входу з позитивної шини.
- Sinking/NPN-вихід у типовій концепції відводить струм до 0 V.
- COM задає опорний/спільний вузол групи входів або виходів; його призначення треба читати зі схеми конкретного пристрою.
- NO/NC описує стан контакту без активування, а active-high/active-low — програмне трактування рівня. Вони не є синонімами.
Текстовий опис рисунка: невідомий промисловий сенсор під'єднується лише через захист, перевірене узгодження рівнів та, якщо передбачено проєктом, ізоляційний бар'єр; після нормалізації логіки підтверджені 0/1 утворюють стан, а None чи розбіжність переходять у ERROR.
flowchart LR
S["Промисловий сенсор: модель невідома"] --> P["Захист і перевірене узгодження рівнів"]
P --> I["Ізоляційний бар'єр, якщо передбачено проєктом"]
I --> G["Вхід 3,3 V GPIO через затверджений інтерфейс"]
G --> L["Нормалізація active_low / діагностика"]
L -->|"0 або 1, підтверджено"| A["Логічний стан"]
L -->|"None / розбіжність"| E["ERROR і блокування виходів"]
Рис. 1. Ілюстративний, неелектричний ланцюжок узгодження й діагностики сигналу
Схема навмисно не містить номерів контактів, номіналів і конкретного типу оптопари: ці дані MERC-I5 не підтверджені.
2. Оптопара, підтягування та плаваючий вхід
Оптопара може розділяти електричні домени, але її наявність не гарантує потрібної категорії ізоляції або safety-рівня. Потрібні правильні струми світлодіода, допустимі напруги, відстані, захист і схема обох сторін. Підтягувальний резистор задає визначений рівень розімкненого входу; його номінал і напрямок залежать від конкретного інтерфейсу. Вхід без визначеного рівня слід вважати недостовірним.
3. Діагностичні патерни
| Спостереження у симуляції | Можливі причини | Результат цієї ЛР |
|---|---|---|
| обидва канали 0 | підтверджений неактивний стан у заданій моделі | inactive |
| обидва канали 1 | підтверджений активний стан у заданій моделі | active |
raw=0, active_low=true | інверсна програмна логіка | active |
один канал null | обрив, недоступність або невизначеність | ERROR |
| канали різні | замикання, затримка або розбіжність | ERROR без часової поблажки |
| виконавчий механізм командовано, підтвердження не змінилося | заклинювання/втрата деталі | STOP_AND_ERROR |
Ці відповідності задані навчальним JSON і не є результатом вимірювання MERC-I5.
Хід виконання роботи
- Побудувати таблицю термінів і струмових шляхів.
- Перевірити структуру набору сценаріїв.
- Реалізувати класифікатор.
- Запустити весь набір і негативні тести.
- Сформувати діагностичну таблицю без апаратних висновків.
Виконання лабораторної роботи
Крок 1. Розібрати концептуальні сигнали
Для PNP/sourcing, NPN/sinking, NO, NC, active-high, active-low і COM запишіть визначення, типову роль та факт, який треба підтвердити перед підключенням.
Код/команда: не потрібні.
Очікуваний результат: сім коректних рядків без номера GPIO, кольору проводу чи номіналу невідомого модуля.
Критерій правильності: PNP/NPN не ототожнено з NO/NC; явно заборонено пряме 24 V→GPIO.
Якщо результат не отримано: поверніться до офіційного datasheet лише після ідентифікації моделі; не використовуйте випадкову типову схему.
Крок 2. Перевірити набір даних
Відкрийте data/fault-scenarios.json як текст. Не редагуйте оригінал. Знайдіть scope, default_safe_reaction, 11 сценаріїв і channel_discrepancy_timeout_ms.
python -m json.tool data/fault-scenarios.json
Очікуваний результат: валідний JSON із scope: simulation_only; час розбіжності — null.
Критерій правильності: нараховано 11 унікальних id; кожен має expected; null не замінено числом.
Якщо результат не отримано: перевірте запуск із кореня репозиторію та шлях; не створюйте замість файла власні «фактичні» дані.
Крок 3. Реалізувати безпечний класифікатор
Збережіть код як lab03_faults.py у корені робочої копії. Без аргументів він сам знаходить локальний набір і завершується після перевірки.
# safe-smoke
from __future__ import annotations
import json
from pathlib import Path
from typing import Any
def locate_dataset() -> Path:
starts = [Path.cwd(), Path(__file__).resolve().parent]
for start in starts:
for base in (start, *start.parents):
candidate = base / "data" / "fault-scenarios.json"
if candidate.is_file():
return candidate
raise FileNotFoundError("data/fault-scenarios.json not found")
def evaluate(scenario: dict[str, Any]) -> str:
inputs = scenario.get("inputs", {})
if isinstance(inputs, dict) and "raw" in inputs:
raw = inputs["raw"]
if raw not in (0, 1):
return "ERROR"
active = bool(raw) ^ bool(inputs.get("active_low", False))
return "active" if active else "inactive"
if isinstance(inputs, dict) and {"channel_a", "channel_b"} <= inputs.keys():
a, b = inputs["channel_a"], inputs["channel_b"]
if a not in (0, 1) or b not in (0, 1) or a != b:
return "ERROR"
return "active" if a == 1 else "inactive"
if scenario.get("available") is False:
return "STOP_AND_ERROR" if scenario.get("service") == "robot" else "ERROR"
if scenario.get("commanded") is True:
confirmations = [
value for key, value in scenario.items()
if key.endswith("_sensor_changed")
]
if confirmations and not all(value is True for value in confirmations):
return "STOP_AND_ERROR"
raise ValueError(f"unsupported scenario format: {scenario.get('id', '<no id>')}")
def load_and_check(path: Path) -> dict[str, object]:
payload = json.loads(path.read_text(encoding="utf-8"))
if payload.get("scope") != "simulation_only":
raise ValueError("dataset must be simulation_only")
scenarios = payload.get("scenarios")
if not isinstance(scenarios, list) or not scenarios:
raise ValueError("non-empty scenarios list required")
ids = [item.get("id") for item in scenarios if isinstance(item, dict)]
if len(ids) != len(set(ids)):
raise ValueError("scenario ids must be unique")
mismatches = []
for item in scenarios:
actual = evaluate(item)
if actual != item.get("expected"):
mismatches.append({"id": item.get("id"), "actual": actual, "expected": item.get("expected")})
if mismatches:
raise AssertionError(mismatches)
return {
"scope": payload["scope"],
"checked": len(scenarios),
"mismatches": 0,
"discrepancy_timeout_ms": payload.get("channel_discrepancy_timeout_ms"),
"hardware_tested": False,
}
def smoke_test() -> None:
result = load_and_check(locate_dataset())
assert result["checked"] == 11
assert result["discrepancy_timeout_ms"] is None
assert evaluate({"id": "boundary", "inputs": {"channel_a": None, "channel_b": None}}) == "ERROR"
try:
evaluate({"id": "unknown"})
except ValueError:
pass
else:
raise AssertionError("unknown format must fail closed")
print(json.dumps(result, ensure_ascii=False))
if __name__ == "__main__":
smoke_test()
python lab03_faults.py
Очікуваний результат: JSON із checked: 11, mismatches: 0, discrepancy_timeout_ms: null, hardware_tested: false.
Критерій правильності: код завершення 0; усі очікувані реакції збігаються; невідомий формат відхиляється.
Якщо результат не отримано: не переходьте до GPIO; перевірте шлях, валідність JSON і виведіть id першої розбіжності.
Крок 4. Виконати негативні та граничні тести
У копії даних послідовно змоделюйте: channel_a=null; 0/1; 1/0; невідомий запис без полів; дублікат id; неправильний scope. Оригінал не змінюйте.
Код/команда: повторно запустіть python lab03_faults.py після додавання локальних assert у копії скрипту.
Очікуваний результат: сигнальні невизначеності дають ERROR; заклинювання/втрата робота — STOP_AND_ERROR; структурні помилки спричиняють контрольований виняток.
Критерій правильності: 6/6 тестів відмовляють за замовчуванням; жоден null не класифіковано активним або неактивним.
Якщо результат не отримано: мінімізуйте один сценарій, перевірте типи JSON і не додавайте мовчазне значення за замовчуванням.
Крок 5. Оформити діагностичну таблицю
Для кожного з 11 id наведіть спостереження, результат, реакцію, можливі гіпотези й потрібний доказ. Не стверджуйте, що симуляційна причина відтворена на стенді.
Код/команда: використайте JSON-вивід програми; апаратна команда не потрібна.
Очікуваний результат: 11 рядків, чітка різниця між ERROR і STOP_AND_ERROR, усюди hardware_tested=no.
Критерій правильності: результат відділено від діагностичної гіпотези; відновлення не пропонується до встановлення причини.
Якщо результат не отримано: позначте гіпотезу невідомо, збережіть вихідні дані й не виконуйте фізичний тест.
Сценарії перевірки
| Тип | Сценарій | Очікувано | Критерій |
|---|---|---|---|
| Позитивний | sensor_normal_low/high | inactive/active | 2/2 |
| Позитивний | inverse_logic_nc | active | інверсія коректна |
| Негативний | wire_break | ERROR | null не замінено 0 |
| Негативний | short_to_0v, short_to_24v | ERROR | 2/2 розбіжності |
| Негативний | втрата робота/заклинювання | STOP_AND_ERROR | 3/3 |
| Граничний | обидва канали null | ERROR | fail-closed |
| Граничний | channel_discrepancy_timeout_ms=null | число не використано | safety-таймер не заявлено |
| Граничний | невідомий формат | ValueError | немає мовчазного стану |
Таблиці вимірювань і метрики
Результати сценаріїв
| ID | Вхід | Очікувано | Фактично | Реакція | Апаратно перевірено | |
|---|---|---|---|---|---|---|
| ні |
Підсумок
| Метрика | Результат | Критерій |
|---|---|---|
| Перевірено сценаріїв | 11 | |
Збігів із expected | 11/11 | |
| Невідомих форматів прийнято | 0 | |
| Вигаданих електричних параметрів | 0 | |
| Фізичних відмов створено | 0 | рівно 0 |
Вимоги до звіту
Дотримуйтеся загальних вимог. Додатково подайте таблицю термінів, пояснення різниці 24 V/3,3 V, ілюстративну архітектуру інтерфейсу, контрольну суму або незмінений фрагмент метаданих JSON, код, вивід 11 сценаріїв, усі негативні/граничні тести, діагностичну таблицю та фразу «Електричні з'єднання й фізичні відмови не перевірялися».
Критерії оцінювання
| Складова | Частка | Ознака повного виконання |
|---|---|---|
| Підготовка | 10% | джерела, терміни й simulation_only перевірено |
| Реалізація | 40% | класифікатор підтримує всі 11 сценаріїв і fail-closed |
| Перевірка | 25% | позитивні, негативні й граничні тести відтворюються |
| Аналіз | 15% | струмовий шлях, інверсію, ізоляцію й межі safety правильно пояснено |
| Звіт | 10% | повні таблиці, код, вивід, прогалини й межі перевірки |
| Разом | 100% |
Критична помилка: пряме підключення 5/24 V до GPIO, фізичне створення відмови або вигаданий pinout.
Контрольні питання
- Чим PNP/NPN відрізняються від NO/NC?
- Яку роль виконує COM?
- Чому
nullне можна трактувати як логічний нуль? - Для чого потрібен підтягувальний резистор?
- Чому оптопара не гарантує safety-рівень автоматично?
- Що робить
active_low? - Які спільні причини відмов можливі для двох GPIO?
- Чому час розбіжності не можна вигадати?
- Чим
ERRORвідрізняється відSTOP_AND_ERRORу навчальній моделі? - Які докази потрібні перед створенням фактичної схеми MERC-I5?
Висновки
У висновку наведіть кількість перевірених сценаріїв, частку збігів, поведінку на null і невідомому форматі, а також поясніть необхідність перевіреного інтерфейсу між 24 V і 3,3 V. Окремо зазначте, що файл описує симуляційні відмови, а pinout, час розбіжності та фізична реакція MERC-I5 не підтверджені.