ПМК 3 курс Практические задания 06 Практическая работа 6 - BysonHunter/Tavrich_college GitHub Wiki

🏠 Главная · Программирование микроконтроллеров · 3 курс · Практические работы по программированию микроконтроллеров — 3 курс


Практическая работа №6

Тема: «Разработка многофункциональных устройств на базе Arduino с индикацией»

Текст описания, целей и постановки заданий сохранён по исходному PDF. Технические замечания ниже исправляют или уточняют только обнаруженные неоднозначности и ошибки.

Технические корректировки и уточнения

  • В исходных схемах заданий есть конфликты пинов: базовая распиновка 4-разрядного индикатора занимает D2–D13, а последующие задания повторно назначают эти же выводы кнопкам, HC-SR04, DHT22 и Servo. При сборке необходимо перераспределить выводы или использовать дополнительный драйвер/регистр.
  • Для каждого сегмента нужен токоограничивающий резистор. Общие выводы разрядов желательно коммутировать транзисторными ключами, чтобы не превышать допустимый ток вывода Arduino.
  • В секундомере при паузе необходимо отдельно хранить уже накопленное время; простое переопределение startTime = millis() при каждом запуске приведёт к потере времени до паузы.
  • Код сегментов зависит от типа общего анода/катода и фактической распиновки A–G/DP; двоичный шаблон нельзя считать универсальным.
  • Для DHT22, динамической индикации, Servo и датчиков следует использовать независимые неблокирующие таймеры, а не длительные delay().

Описание работы и задания

1. Цель работы: Закрепление практических навыков программирования

микроконтроллеров Arduino и интеграции различных периферийных устройств, с фокусом на освоение методов вывода информации на семисегментный индикатор (статическая и динамическая индикация) и символьный LCD-дисплей, а также на организацию взаимодействия этих устройств с датчиками и исполнительными механизмами.

2. Задачи работы

  1. Изучить устройство, распиновку и принципы работы семисегментных
    

индикаторов (одноразрядного и четырехразрядного).

  1. Освоить метод динамической индикации для экономии выводов
    

микроконтроллера.

  1. Научиться выводить текстовую и числовую информацию на LCD1602 через
    

I²C.

  1. Исследовать принципы работы датчиков (потенциометр, DHT22, HC-SR04) и
    

исполнительных устройств (сервопривод).

  1. Разработать пять цифровых устройств возрастающей сложности, в каждом из
    

которых обязательно задействованы 7-сегментный индикатор и LCD.

  1. Научиться отлаживать программы, использующие неблокирующие задержки
    

(таймеры millis()) для одновременной работы нескольких компонентов.

Студент должен знать:

  • Основы цифрового ввода/вывода на Arduino.

  • Принципы работы шины I²C.

  • Понятие ШИМ (PWM) и его применение.

  • Принципы работы ультразвуковых дальномеров, цифровых датчиков температуры/влажности, потенциометров и сервоприводов.

  • Методы динамической индикации и работу с матрицами сегментов. Студент должен уметь:

  • Читать электрические схемы.

  • Подключать внешние устройства к Arduino.

  • Использовать среду разработки Arduino IDE.

  • Подключать и использовать библиотеки (LiquidCrystal_I²C.h, Servo.h, DHT.h, NewPing.h).

  • Разрабатывать алгоритмы и писать код на C++ для Arduino.

  • Использовать функцию millis() для создания неблокирующих таймеров. Практические навыки, приобретаемые студентом:

  • Сборка сложных макетных схем.

  • Программирование динамической индикации для 4-разрядного индикатора.

  • Вывод информации одновременно на два типа дисплеев (сегментный и символьный).

  • Программирование обмена данными по протоколам I²C.

  • Обработка аналоговых сигналов (потенциометр) и данных с цифровых датчиков.

  • Реализация многозадачности на микроконтроллере с помощью конечных автоматов и millis().

Основные теоретические сведения

  1. 7-сегментный индикатор:
  • Представляет собой набор из 7 (или 8 с точкой) светодиодов, соединенных катодами (общий катод) или анодами (общий анод).

  • Для зажигания цифры необходимо подать HIGH (для ОК) или LOW (для ОА) на соответствующие сегменты A-G.

  • Для многоразрядных индикаторов используется динамическая индикация: разряды зажигаются по очереди с высокой частотой (>50 Гц на каждый разряд). Человеческий глаз не замечает мерцания, создается иллюзия одновременного свечения.

  1. LCD1602 (I²C): Символьный дисплей 16x2, управляемый по двум проводам (SDA, SCL). Адрес на шине I²C чаще всего 0x27 или 0x3F. Библиотека LiquidCrystal_I²C.h.

  2. Потенциометр: Аналоговый датчик. Используется как делитель напряжения. Значение на среднем выводе считывается функцией analogRead() (0-1023).

  3. Сервопривод: Управляется ШИМ-сигналом с периодом 20 мс и длительностью импульса от 0.5-1 мс (0°) до 2-2.5 мс (180°). Библиотека Servo.h.

  4. Ультразвуковой датчик HC-SR04: Измеряет расстояние методом эхолокации. Время между отправкой и приемом сигнала преобразуется в расстояние: Расстояние (см) = (длительность импульса (мкс) * скорость звука) / 2. В воздухе скорость звука ~340 м/с или 0.034 см/мкс. Часто используют формулу см = мкс / 58.2.

  5. Датчик DHT22: Цифровой датчик температуры и влажности. Имеет свой протокол связи. Требует библиотеки DHT.h.

Задания Для Практической Работы

Задание 1.

Разработать цифровое устройство: Счетчик от 0 до 9999 с шагом 1, управляемый одной кнопкой. Текущее значение счетчика отображается на 4-разрядном семисегментном индикаторе. На LCD-дисплей выводится сообщение: "Counter: XXXX".

Схема подключения:

  • 4x7-сегментный индикатор (общий катод): Сегменты A-G через резисторы (220 Ом) к пинам 6-12. Разряды (D1, D2, D3, D4) к пинам 2,3,4,5.

− Lcd1602 (I²C): Vcc -> 5V, Gnd -> Gnd, Sda -> A4, Scl -> A5.

  • Кнопка: Один контакт к пину 13, другой к GND (используем

Input_Pullup).

Описание алгоритма:

  1. В setup() настроить пины, инициализировать LCD, создать буфер для хранения кодов цифр для каждого разряда.

  2. В loop():

  • Постоянно вызывать функцию dispTick() (динамическая индикация).

  • Проверять, нажата ли кнопка (с антидребезгом). Если нажата, увеличить переменную counter на 1. Если counter > 9999, сбросить в 0.

  • Разбить число counter на отдельные цифры (тысячи, сотни, десятки, единицы).

  • Поместить в буфер индикатора коды цифр для отображения.

  • Каждые 300 мс (или при изменении значения) обновлять информацию на LCD, выводя "Counter: N".

Код для Arduino:

  • Библиотека LiquidCrystal_I²C.h.
  • Реализация динамической индикации (как в лекции 9).
  • Функция для разбиения числа на цифры.

Задание 2. Аналоговый вольтметр

Разработать цифровое устройство измерения напряжения на потенциометре (0-5 В)

с отображением:

  • На 7-сегментном индикаторе - текущее значение напряжения с точностью до десятых долей (например, 2.5 В).

  • На LCD - сырое значение АЦП (0-1023) и уровень сигнала в процентах. Схема подключения:

  • 4x7-сегментный индикатор (подключение как в Задании 1).

  • LCD1602 (I²C) (подключение как в Задании 1).

  • Потенциометр: средний вывод -> A0. Описание алгоритма:

  1. Реализовать динамическую индикацию для 4 разрядов. Для отображения числа 2.5 нужно вывести 2.5 (зажечь десятичную точку на втором разряде). Это требует модификации функции вывода: добавить отдельный массив для точек или специальный код для цифры с точкой.

  2. В loop():

  • Считать значение с A0 (adcValue).

  • Преобразовать его в напряжение: voltage = (adcValue / 1023.0) * 5.0.

  • Подготовить данные для 7-сегментного индикатора: извлечь целую часть и первый знак после запятой. Установить флаг десятичной точки для нужного разряда.

  • Вывести на LCD: "ADC: 1023" на первой строке и "Level: 100%" на второй.

  • Вызвать функцию dispTick().

  • Небольшая задержка (50-100 мс) для стабильности. Код для Arduino:

  • Модифицированная функция dispTick(), умеющая зажигать DP (десятичную точку).

  • Логика преобразования float в цифры для индикатора.

Задание 3. Секундомер

Разработать цифровое устройство: Секундомер с точностью до десятых долей секунды, отображающий время на 7-сегментном индикаторе в формате СС.Д (секунды и десятые). Управление: кнопка "Старт/Стоп", кнопка "Сброс". На LCD выводится общее время в секундах и состояние секундомера ("RUN", "STOP").

Схема подключения:

  • 4x7-сегментный индикатор (подключение как в Задании 1).
  • LCD1602 (I²C) (подключение как в Задании 1).
  • Кнопка 1 (Старт/Стоп) -> Пин 13.
  • Кнопка 2 (Сброс) -> Пин 12. Описание алгоритма:
  1. Использовать таймер на millis() для неблокирующего отсчета времени.

  2. Переменная state (true/false) для хранения состояния "RUN/STOP".

  3. При нажатии "Старт/Стоп" инвертировать state. При переходе из STOP в RUN запомнить текущее millis() в переменной startTime.

  4. Если state == RUN, то текущее время currentTime = millis() - startTime. Иначе время не меняется.

  5. При нажатии "Сброс" обнулить startTime и currentTime, перевести state в

Stop.

  1. Преобразовать currentTime (мс) в секунды и десятые доли. Например, 1234 мс
  • 1.2 с (отобразить как 01.2).

  1. Вывести на 7-сегментный индикатор, зажигая точку на втором разряде.
  2. Вывести на LCD состояние и общее время.
  3. Постоянно вызывать dispTick(). Код для Arduino:
  • Неблокирующий код на millis().
  • Обработка дребезга кнопок.
  • Преобразование миллисекунд в формат для индикатора.

Задание 4. Парктроник

Разработать цифровое устройство измерения расстояния с помощью HC-SR04.

  • На 7-сегментном индикаторе отображается расстояние в сантиметрах (например, 186).

  • На LCD выводится: "Dist: XXX cm" и индикаторная шкала (например, [#####---]) для визуализации близости препятствия (0-200 см).

Схема подключения:

  • 4x7-сегментный индикатор (подключение как в Задании 1).
  • LCD1602 (I²C) (подключение как в Задании 1).
  • HC-SR04: Trig -> Пин 3, Echo -> Пин 2, VCC -> 5V, GND -> GND. Описание алгоритма:
  1. Функция getDistance() отправляет импульс на Trig и с помощью pulseIn() получает время на Echo. Возвращает расстояние в см (duration / 58.2).

  2. В loop():

  • Вызывать dispTick() постоянно.

  • Каждые 200 мс (неблокирующая проверка) вызывать getDistance(). Полученное значение ограничить, например, до 200 см.

  • Поместить расстояние в буфер 7-сегментного индикатора (только целая часть).

  • На LCD: на первой строке вывести "Dist: XXX cm".

  • На второй строке нарисовать шкалу. Например, количество закрашенных сегментов = map(distance, 0, 200, 10, 0). Использовать 10 символов, например, # для заполнения и - для пустого места.

Код для Arduino:

  • Библиотека NewPing.h или собственная реализация.
  • Неблокирующий таймер для опроса датчика.
  • Генерация псевдографической шкалы для LCD.

Задание 5. Климат-контроль с регистратором пиковых значений

Разработать цифровое устройство мониторинга температуры и влажности (датчик DHT22) с возможностью управления сервоприводом (например, для открытия/закрытия форточки) и регистрации минимальной и максимальной температуры за время работы.

На 7-сегментном индикаторе циклически (по нажатию кнопки) отображается:

текущая температура (t. 23), текущая влажность (h. 55), минимальная температура (L. 21), максимальная температура (H. 25). Формат: одна буква-идентификатор и три цифры. На LCD отображается подробная информация: "Temp:23C Hum:55%" на первой строке и "Min:21C Max:25C" на второй. Серводвигатель управляется вторым потенциометром: крайнее левое положение потенциометра соответствует 0° (форточка закрыта), крайнее правое — 90° (форточка открыта). Положение серво также отображается на LCD.

Схема подключения:

  • 4x7-сегментный индикатор, LCD1602 (I²C), DHT22 (Pin 7), сервопривод (Pin 9), потенциометр для серво (A1), кнопка переключения режима индикатора (Pin 8). Описание алгоритма
  1. Многозадачность: Все работает на millis():
  • dispTick() (каждые 5 мс).

  • Опрос DHT22 (каждые 2000 мс).

  • Опрос потенциометра серво и управление серво (каждые 50 мс).

  • Антидребезг кнопки и переключение режима отображения на 7-сегм. индикаторе (mode 0-3).

  • Обновление LCD (при изменении данных или режима).

  1. Логика:
  • При каждом успешном чтении с DHT22 сравнивать значение с переменными minTemp, maxTemp и обновлять их.

  • Считывать значение с потенциометра (A1), маппить на угол 0-90, подавать на серво.

  • По нажатию кнопки циклически переключать mode.

  • В dispTick() в зависимости от mode в буфер индикатора помещаются данные: для mode0 — буква t и текущая температура, mode1 — h и влажность, mode2 — L и мин. температура, mode3 — H и макс. температура.

Код для Arduino:

  • Библиотеки: LiquidCrystal_I²C.h, DHT.h, Servo.h.

  • Полностью событийно-ориентированный код на таймерах.

  • Работа с массивами символов для подготовки вывода на 7-сегментный индикатор (включая буквы).

  • Обновление LCD только при изменении данных для уменьшения мерцания.

Содержание Отчета

Отчёт о выполнении лабораторной работы должен содержать:

– титульный лист с номером и названием работы;

– цель работы;

– краткие теоретические сведения о подключаемых устройствах и особенностях их

работы; – схемы соединения элементов, выполненные в программе Fritzing или Tinkercad; – описание алгоритма работы собранного устройства; – текст программ, содержащий необходимые комментарии и пояснения; – описание особенностей подключения библиотек и функции, которые были использованы из импортированных библиотек; – общие выводы по работе.

Контрольные Вопросы Для Защиты Работы:

  1. В чем разница между индикатором с общим анодом и общим катодом? Как это влияет на код программы?

  2. Объясните суть динамической индикации. Почему без нее невозможно использовать многоразрядный индикатор, подключенный напрямую к микроконтроллеру?

  3. Какие резисторы и для чего используются в цепи семисегментного индикатора? Что произойдет, если их не поставить?

  4. Как с помощью одного 4-разрядного индикатора отобразить число с плавающей точкой (например, 3.14)?

  5. Каковы преимущества и недостатки использования библиотеки LiquidCrystal_I²C перед прямым подключением LCD1602?

  6. Как организовать на Arduino выполнение нескольких задач одновременно (например, опрос кнопки, динамическая индикация и измерение расстояния)? Приведите пример с функцией millis().

  7. Почему при работе с ультразвуковым датчиком HC-SR04 не рекомендуется использовать длительную задержку delay() в основном цикле?

  8. Каким образом функция pulseIn() измеряет длительность импульса и в чем ее ограничение?

  9. Для чего нужна функция map() и как она применяется при работе с потенциометром и сервоприводом?

  10. Опишите алгоритм преобразования двоичного кода цифры (например, 0b01111101 для цифры 6) в сигналы на пинах для зажигания соответствующих сегментов.


← Практическая работа №5

Оригинал материала на GitHub