Занятие № 2. Аналоговые сигналы. Фоторезистор. Пьезодинамик. Потенциометр. Сервомотор.
По окончании занятия учащиеся смогут…
- объяснить назначение пьезодинамика, фоторезистора, потенциометра и сервомотора;
- объяснить, для чего используется делитель напряжения;
- составлять программы, которые получают и выводят информация с датчиков с помощью последовательного порта (Serial);
- собирать схемы с аналоговыми датчиками, и считывать их показания;
- использовать ШИМ-сигнал для управления яркостью светодиода и частотой звука пьезодинамика;
- использовать готовую библиотеку для управления сервомотором (Servo).
Задание № 1. Измерение освещённости. Фоторезистор
Соберите схему с фоторезистором для измерения уровня освещённости. Полученные значения выводите на экран.
Схема для сборки
и резистор на 10 кОм образуют делитель напряжения. Напряжение считывается из точки между двумя сопротивлениями и подаётся на аналоговый пин A0. Аналогово-цифровой преобразователь поможет привести показания с датчика к целым значениям в диапазоне от 0 до 1023.
Выходное напряжение можно измерить по следующей формуле:
\[ U_{out}= U_{in}\cdot \frac{R_2}{R_1 + R_2} \]
Если сопротивление первого резистора зафиксировать, то выходное напряжение будет зависеть только от сопротивления второго резистора.
Значение измеренного напряжения - величина непрерывная. Микроконтроллер может обрабатывать лишь дискретные значения. Для преобразования аналогового сигнала в цифровой используется аналогово-цифровой преобразователь (АЦП).
Опорное напряжение \(U_{ref}\) влияет на максимально возможное напряжение на входе АЦП, которое будет корректно преобразовано в цифровое значение.
Цифровое значение на выходе АЦП определяется по следующей формуле: \[ A=\frac{U_{in}}{U_{ref}}\cdot (2^n-1) \]
Программа
Переменная val
хранит сырые показания датчика, полученные напрямую с пина A0. В переменной normalVal
сохраним значение с датчика приведённое к диапазону 0..100.
// Чтение аналоговых датчиков
// информационный пин фоторезистора назовём LDR_PIN
// и будем ссылаться на аналоговый пин A0
#define LDR_PIN A0
int val; // хранение сырых показаний с датчика 0..1023
int normalVal; // хранение показаний приведённых к 0..100
void setup()
{
// Начинаем связь через последовательный порт
Serial.begin(9600);
}
void loop()
{
// сохраняем показания с аналогового пина A0
val = analogRead(LDR_PIN);
/*
С помощью функции map приводим показания с фоторезистора
val из диапазона 0..1023 к диапазону 0..100 и сохраняем
результат в переменную normalVal
*/
normalVal = map(val, 0, 1023, 0, 100);
/*
Выводим информацию в монитор последовательного порта
print - выводит в текущую строку
println - вывод и перенос на новую строку
Ответ выводим в формате:
val, normalVal
*/
Serial.print(val);
Serial.print(", ");
Serial.println(normalVal);
}
Для обмена информацией между Arduino-скетчем и компьютером используем библиотеку Serial
. Чтобы посмотреть сообщения в Arduino IDE, выберите пункт меню Инструменты - Монитор порта ⌃Ctrl + ⇧Shift + M Плата должна быть подключена к компьютеру. При моделировании в TinkerCad, откройте вкладку Код и нажмите по кнопке Монитор последовательного интерфейса внизу окна.
Чтобы преобразовать один диапазон значений в другой, используем функцию map(значение, текущий_минимум, текущий_максимум, новый_минимум, новый_максимум)
.
Задание № 2. Терменвокс. Пьезодинамик
Соберите схему с фоторезистотором и пьезодинамиком. Используйте показания фоторезистора для того, чтобы воспроизводить звуки различной частоты, собрав и запрограммировав устройство, похожее на терменвокс.
Схема для сборки
Сборка схемы
Схема этого задания основана на предыдущем. Можете добавить пьезодинамик к уже собранной схеме.
Программа
// Терменвокс
// Пин управления пьезодинамиком
#define BUZZER_PIN 3
// Пин фоторезистора
#define LDR_PIN A0
void setup()
{
// Пин пьезодинамика настраиваем на выход
// При этом пин должен поддерживать ШИМ
pinMode(BUZZER_PIN, OUTPUT);
}
void loop()
{
// val - хранение показаний с фоторезистора
// freq - вычисленная частота звука
int val, freq;
// считываем уровень освещённости - 0..1023
val = analogRead(LDR_PIN);
// Расчитываем частоту звука. Преобразуем диапазон
// 0..1023 в диапазон частот от 250 до 500 Гц.
freq = map(val, 0, 1023, 250, 500);
// Воспроизводим звук с частотой freq в течении 20 миллисекунд
tone(BUZZER_PIN, freq, 20);
}
Создайте переменные val
- значение с аналогового входа, note
- номер воспроизводимой ноты, minL
и maxL
для хранения минимального и максимального значения освещённости соответственно.
Чтобы привести значение с пина A0 к номеру ноты от 0 до 83, используем следующую формулу: \[ freq=[\frac{(val - minL)\cdot 83}{(maxL - minL)}] \]
Задание № 3. Управление яркостью светодиода
Составьте программу, которая при нажатии на кнопку, будет увеличивать яркость светодиода.
Схема для сборки
Резистор на 10 кОм в схеме называется стягивающим. Он тянет значение на 8 пине к земле, пока кнопка не нажата.
Подтягивающий резистор
Если нужно, чтобы в не нажатом состоянии на пине с кнопкой была логическая единица (5 В), то кнопку подключают к питанию через подтягивающий резистор, который подтягивает значение на пине к напряжению 5 В.
Программа
Для регулирования яркости светодиода через цифровой выход, используем Широтно-импульсную модуляцию. Путём быстрого включения и выключения напряжения на цифровом выходе можно симулировать подачу аналогового усреднённого значения на вход светодиода.
Чем больше частота, тем менее заметным станет мигание светодиода во время его периодического включения и выключения.
// Яркость светодиода
/* объявляем переменную и сразу инициализируем
начальным значением, равным 0
в переменной храним текущее значение яркости */
int brightness = 0;
void setup()
{
// пин светодиода 9 настраиваем на выход
pinMode(9, OUTPUT);
// режим INPUT для пина кнопки не указываем
// по умолчанию пины настроены на этот режим
}
void loop()
{
// если кнопка нажата ...
if (digitalRead(8) == HIGH) {
// увеличиваем текущую яркость на 15
brightness = brightness + 15;
// небольшая задержка, чтобы убрать
// ложное повторное срабатывание
delay(100);
}
// подаём ШИМ-сигнал на пин светодиода
analogWrite(9, brightness);
}
Чтобы подать ШИМ-сигнал на выбранный пин используется функция analogWrite(пин, заполнение)
. Коэффициент заполнения может находится в диапазоне от 0 (всегда выключен) до 255 (всегда включён).
Дополнительное задание
Добавьте к схеме ещё одну кнопку, подключённую к пину 7. При нажатии на кнопку значение яркости должно уменьшаться на 15.
Задание № 4. Управление сервомотором
Составьте программу, которая будет управлять вращение сервомотора. Последовательно поверните на 45, 90 и 180 градусов. Затем верните в начальное положение - 0 градусов.
Схема для сборки
Программа
// Управление серводвигателем
// подключение библиотеки Servo
#include <Servo.h>
// управляющий пин серводвигателя
#define SERVO_PIN 9
/*
создаём объект класса Servo
с помощью этого объекта сможем
управлять двигателем
*/
Servo motor;
void setup()
{
// с помощью метода attach() указываем
// номер управляющиего пина серводвигателя
motor.attach(SERVO_PIN);
}
void loop(){
motor.write(45); // поворачиваем в положение 45 градусов
delay(1000);
motor.write(90); // поворачиваем в положение 90 градусов
delay(1000);
motor.write(180); // поворачиваем в положение 180 градусов
delay(1000);
motor.write(0); // поворачиваем в положение 0 градусов
delay(2000);
}
Чтобы управлять сервоприводом используем готовую библиотеку Servo. Чтобы импортировать библиотеки используется директива #include
.
Задание № 5. Пантограф
Соберите схему с сервомотором и потенциометр. Вращение ручки потенциометра должно управлять положением сервомотора. Получится своеобразный пантограф.
Схема для сборки
Сборка схемы
Схема этого задания основана на предыдущем. Можете добавить потенциометр к уже собранной схеме.
Напряжение на среднем контакте потенциометра зависит от положения ручки управления. По этому средний контакт подключен к аналоговому входу платы.
Программа
// Пантограф
// импортируем библиотеку Servo
#include <Servo.h>
#define SERVO_PIN 9 // управляющий пин сервомотора
#define POT_PIN A0 // аналоговый пин для потенциометра
int angle; // положение сервомотора (угол) 0..180
int pot; // значение с потенциометра 0..1023
Servo motor;
void setup()
{
// Аналоговые пины по умолчанию настроены на
// вход. Поэтому не нужно писать команду
// pinMode(POT_PIN, INPUT);
motor.attach(SERVO_PIN);
}
void loop()
{
// Получаем значение с потенциомера 0..1023
pot = analogRead(POT_PIN);
// Преобразуем значение с потенциометра
// в угол для сервомотора
angle = map(pot, 0, 1023, 0, 180);
// поворачиваем сервомотор на вычисленный угол
motor.write(angle);
}
Задание № 6 Умный светильник
Разработайте систему правления умным светильником. Светодиод должен включаться, если освещённость в комнате падает ниже определённого порога. Порог срабатывания задаётся потенциометром.
Соберите схему, состоящую из трёх контуров:
- с фоторезистором;
- с потенциометром;
- со светодиодом.
После сборки схемы составьте программу по следующему алгоритму: