====== Электронное приложение к набору «Arduino. Восьмибитная академия» ======
Привет, дружище!
Добро пожаловать в уютную Восьмибитную академию.
На этой странице мы собрали всё, чтобы тебе было удобнее проходить набор:
* Схемы проектов в электронном виде.
* Исходный код учебных программ (копируй его в редактор Arduino IDE).
* Дополнительные материалы: программные библиотеки, даташиты и т. п.
**Обрати внимание**
Именно здесь находятся //самые актуальные// версии кода с исправлениями. Написанному верить!
**Обрати внимание**
Для успешной загрузки скетчей понадобиться драйвер CH340. Прочитайте наши статьи по установке драйвера [[articles:driver-ch340|для Windows]] или [[projects:installing-the-ch340-on-linux|для Linux]]
===== Эксперименты =====
В начале книги идёт вступительная часть с экспериментами №1–№6, где тебе не потребуется никакое программирование.
Поэтому в электронной версии мы приводим материалы, начиная с эксперимента №7.
==== №7. Цифролампа ====
{{ :arduino:070-schematic.png?nolink&600 |}}
{{ :arduino:070-wiring-cmyk.png?nolink |}}
void setup() {
// Настраиваем пин 2 в режим выхода
pinMode(2, OUTPUT);
// Подаем на пин 2 высокий уровень
digitalWrite(2, HIGH);
}
void loop() {
}
==== №8. Маячок ====
{{ :arduino:080-schematic.png?nolink&300 |}}
{{ :arduino:080-wiring-cmyk.png?nolink |}}
void setup() {
// Настраиваем пин 2 в режим выхода
pinMode(2, OUTPUT);
}
void loop() {
// Подаем на пин 2 высокий уровень
digitalWrite(2, HIGH);
// Ждём 200 мс
delay(200);
// Подаем на пин 2 низкий уровень
digitalWrite(2, LOW);
// Ждём 800 мс
delay(800);
}
==== №9. Светофор ====
{{ :arduino:090-schematic.png?nolink&300 |}}
{{ :arduino:090-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_RED_PIN = 2;
constexpr int LED_YELLOW_PIN = 3;
constexpr int LED_GREEN_PIN = 4;
// Константа для хранения паузы в миллисекундах
constexpr int PAUSE = 2000;
void setup() {
// Настраиваем пины светодиодов в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_YELLOW_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
}
void loop() {
// Зажигаем красный светодиод
digitalWrite(LED_RED_PIN, HIGH);
// Ждём 2 секунды
delay(PAUSE);
// Гасим красный светодиод
digitalWrite(LED_RED_PIN, LOW);
// Зажигаем жёлтый светодиод
digitalWrite(LED_YELLOW_PIN, HIGH);
// Ждём 2 секунды
delay(PAUSE);
// Гасим жёлтый светодиод
digitalWrite(LED_YELLOW_PIN, LOW);
// Зажигаем зелёный
digitalWrite(LED_GREEN_PIN, HIGH);
// Ждём 2 секунды
delay(PAUSE);
// Гасим зелёный светодиод
digitalWrite(LED_GREEN_PIN, LOW);
}
==== №10. SOS ====
{{ :arduino:100-schematic.png?nolink&300 |}}
{{ :arduino:100-wiring-cmyk.png?nolink |}}
// Даём пину со светодиодом понятное имя
constexpr int LED_RED_PIN = 2;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
}
void loop() {
// Переменная для хранения паузы в миллисекундах
int pause = 200;
// Мигаем красным светодиодом с интервалом из переменной pause
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
// Меняем значение паузы
pause = 500;
// Мигаем красным светодиодом с интервалом из переменной pause
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
// Меняем значение паузы
pause = 200;
// Мигаем красным светодиодом с интервалом из переменной pause
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
delay(pause);
digitalWrite(LED_RED_PIN, HIGH);
delay(pause);
digitalWrite(LED_RED_PIN, LOW);
// Меняем значение паузы
pause = 2000;
// Ставим задержку перед следующим циклом мигания
delay(pause);
}
==== №11. Охотники за приведениями ====
=== Схема №1 ===
{{ :arduino:110-schematic.1.png?nolink&500 |}}
{{ :arduino:110-wiring-cmyk.1.png?nolink |}}
=== Схема №2 ===
{{ :arduino:110-schematic.2.png?nolink&500 |}}
{{ :arduino:110-wiring-cmyk.2.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int WIRE_PIN = 4;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с подключённым проводом в режим входа
pinMode(WIRE_PIN, INPUT);
}
void loop() {
// Создаём переменную для хранения сигнала с провода
bool wireState;
// Считываем значение уровня сигнала сигнала с провода
// Если провод соединён с линией питания, получим логическую единицу
// Если провод соединён с линией GND, получим логический ноль
wireState = digitalRead(WIRE_PIN);
// Применим полученное значение для светодиода
// Логическая единица — светодиод горит
// Логический ноль — светодиод не горит
digitalWrite(LED_PIN, wireState);
}
==== №12. Фонарик ====
{{ :arduino:120-schematic.png?nolink&500 |}}
{{ :arduino:120-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа
pinMode(BUTTON_PIN, INPUT);
}
void loop() {
// Создадим переменную для хранения состояния с кнопки
// И сразу же запишем значение уровня сигнала
// Если кнопка нажата — логический ноль
// Если кнопка не нажата — логическая единица
bool buttonState = digitalRead(BUTTON_PIN);
// Применим полученное значение для управления светодиодом
digitalWrite(LED_PIN, buttonState);
}
=== Программный код №2 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа
pinMode(BUTTON_PIN, INPUT);
}
void loop() {
// Создадим переменную для хранения состояния с кнопки
// Считываем инвертированное состояние с кнопки
// Если кнопка нажата — логическая единица
// Если кнопка не нажата — логический ноль
bool buttonState = !digitalRead(BUTTON_PIN);
// Применим полученное значение для управления светодиодом
digitalWrite(LED_PIN, buttonState);
}
==== №13. Фонарик без посторонних ====
{{ :arduino:130-schematic.png?nolink&500 |}}
{{ :arduino:130-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Создадим переменную для хранения состояния кнопки
// Считываем инвертированное состояние с кнопки
// Если кнопка нажата — логическая единица
// Если кнопка не нажата — логический ноль
bool buttonState = !digitalRead(BUTTON_PIN);
// Применим полученное значение для управления светодиодом
digitalWrite(LED_PIN, buttonState);
}
==== №14. Выключатель ====
{{ :arduino:140-schematic.png?nolink&500 |}}
{{ :arduino:140-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
// Создаём переменную для хранения состояние светодиода
// В начале программы светодиод должен быть потушен,
// поэтому присваиваем переменной значение LOW
bool ledState = LOW;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Создаём переменную для хранения состояние кнопки
// Считываем инвертированное состояние с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
// Проверяем нажата ли кнопка сейчас
if (buttonState == HIGH) {
// Если да, значит это клик
// Меняем состояние переменной для светодиода
ledState = !ledState;
// Применяем новое значение переменной для управления светодиодом
digitalWrite(LED_PIN, ledState);
}
}
=== Программный код №2 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
// Создаём переменную для хранения состояние светодиода
// В начале программы светодиод должен быть потушен,
// поэтому присваиваем переменной значение LOW
bool ledState = LOW;
// Создаём переменную для хранения последнего состояние кнопки
// В начале программы кнопка должна быть отпущена,
// поэтому присваиваем переменной значение LOW
bool lastButtonState = LOW;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Создаём переменную для хранения состояние кнопки
// Считываем инвертированное состояние с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
// Проверяем два условия
// Условие 1: нажата ли кнопка сейчас
// Условие 2: была ли кнопка отжата до фиксирования нового нажатия
if (buttonState == HIGH && lastButtonState == LOW) {
// Если оба условия прошли, значит это клик
// Меняем состояние переменной для светодиода
ledState = !ledState;
// Применяем новое значение переменной для управления светодиодом
digitalWrite(LED_PIN, ledState);
}
// Запишем в переменную новое значение состояния кнопки
lastButtonState = buttonState;
}
==== №15. Выключатель без глюков ====
{{ :arduino:150-schematic.png?nolink&500 |}}
{{ :arduino:150-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_PIN = 2;
constexpr int BUTTON_PIN = 4;
// Создаём переменную для хранения состояние светодиода
// В начале программы светодиод должен быть потушен,
// поэтому присваиваем переменной значение LOW
bool ledState = LOW;
// Создаём переменную для хранения последнего состояние кнопки
// В начале программы кнопка должна быть отпущена,
// поэтому присваиваем переменной значение LOW
bool lastButtonState = LOW;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пины с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Создаём переменную для хранения состояние кнопки
// Считываем инвертированное состояние с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
// Проверяем два условия
// Условие 1: нажата ли кнопка сейчас
// Условие 2: была ли она отжата кнопка до фиксирования нового нажатия
if (buttonState && !lastButtonState) {
// Подождём пока дребезг кнопки затихнет
delay(10);
// Снова считываем инвертированное состояние с кнопки
buttonState = !digitalRead(BUTTON_PIN);
// Проверяем нажата ли ещё кнопка сейчас
if (buttonState) {
// Если кнопка всё ещё нажата
// Меняем состояние переменной для светодиода
ledState = !ledState;
// Применяем новое значение переменной для управления светодиодом
digitalWrite(LED_PIN, ledState);
}
}
// Запишем в переменную новое значение состояния кнопки
lastButtonState = buttonState;
}
==== №16. Рулим яркостью ====
{{ :arduino:160-schematic.png?nolink&300 |}}
{{ :arduino:160-wiring-cmyk.png?nolink |}}
// Даём пину со светодиодом понятное имя
constexpr int LED_PIN = 3;
// Константа для хранения паузы в миллисекундах
constexpr int PAUSE = 500;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Выдаём на светодиод ШИМ-сигнал
// Для начала зажжём светодиод на 25% яркости
// 25% от числа 255 будет примерно 64
// 25% от напряжения 5В будет примерно 1,25 В
analogWrite(LED_PIN, 64);
// Ждём 250 мс
delay(PAUSE);
// Зажжём светодиод на 50% яркости
// 50% от числа 255 будет примерно 128
// 50% от напряжения 5В будет примерно 2,5 В
analogWrite(LED_PIN, 128);
// Ждём 250 мс
delay(PAUSE);
// Зажжём светодиод на 75% яркости
// 75% от числа 255 будет примерно 192
// 75% от напряжения 5В будет примерно 3,75 В
analogWrite(LED_PIN, 192);
// Ждём 250 мс
delay(PAUSE);
// Зажжём светодиод на 100% яркости
// 100% от числа 255 будет 255
// 100% от напряжения 5В будет 5 В
analogWrite(LED_PIN, 255);
// Ждём 250 мс
delay(PAUSE);
// В завершении потушим светодиод, т.е. дадим 0% яркости
// 0% от числа 255 будет 0
// 0% от напряжения 5В будет 0 В
analogWrite(LED_PIN, 0);
// Ждём 250 мс
delay(PAUSE);
}
==== №17. Дыхание света ====
{{ :arduino:170-schematic.png?nolink&300 |}}
{{ :arduino:170-wiring-cmyk.png?nolink |}}
// Даём пину со светодиодом понятное имя
constexpr int LED_PIN = 3;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
}
void loop() {
// Создаём цикл для перебора всех значений от 0 до 255
// Выдаём на светодиод ШИМ-сигнал
for (int brightness = 0; brightness <= 255; brightness++) {
analogWrite(LED_PIN, brightness);
// Ждём 10 мс
delay(10);
}
// Создаём цикл для перебора всех значений от 255 до 0
// Выдаём на светодиод ШИМ-сигнал
for (int brightness = 255; brightness >= 0; brightness--) {
analogWrite(LED_PIN, brightness);
// Ждём 10 мс
delay(10);
}
}
==== №18. Охотники за приведениями 2.0 ====
{{ :arduino:180-schematic.png?nolink&500 |}}
{{ :arduino:180-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_PIN = 3;
constexpr int WIRE_PIN = A0;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с подключённым проводом в режим входа
pinMode(WIRE_PIN, INPUT);
}
void loop() {
// Создаём переменную для хранения сигнала с провода
// Считываем значение уровня сигнала сигнала с провода
// Функция analogRead считывает напряжение на пине от 0 до 5 В
// и преобразует его к числу от 0 до 1023
int wireState = analogRead(WIRE_PIN);
// Создаём переменную для хранения состояние светодиода
// Разрядность АЦП В Iskra Nano — 10 бит
// т.е. «analogRead» возвращает числовой диапазон от 0 до 1023
// Разрядность ШИМ В Iskra Nano — 8 бит
// т.е. «analogWrite» ожидает диапазон от 0 до 255
// Преобразуем значения из одного диапазона [0; 1023] в другой [0; 255],
// самый простой способ разделить на четыре
int brightness = wireState / 4;
// Выдаём результат на светодиод
analogWrite(LED_PIN, brightness);
}
==== №19. Диммер ====
{{ :arduino:190-schematic.png?nolink&500 |}}
{{ :arduino:190-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 3;
constexpr int POT_PIN = A0;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int rotation = analogRead(POT_PIN);
// Преобразуем значение из шкалы 10 бит в 8 бит,
// самый простой способ разделить на четыре
int brightness = rotation / 4;
// Выдаём результат на светодиод
analogWrite(LED_PIN, brightness);
}
=== Программный код №2 ===
// Даём пинам понятные имена
constexpr int LED_PIN = 3;
constexpr int POT_PIN = A0;
void setup() {
// Настраиваем пин со светодиодом в режим выхода
pinMode(LED_PIN, OUTPUT);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int rotation = analogRead(POT_PIN);
// Преобразуем значение из шкалы 10 бит в 8 бит,
// используем функцию map
int brightness = map(rotation, 0, 1023, 0, 255);
// Выдаём результат на светодиод
analogWrite(LED_PIN, brightness);
}
==== №20. Цветовая рулетка ====
{{ :arduino:200-schematic.png?nolink&500 |}}
{{ :arduino:200-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Даём понятные имена пинам к которым подключены выводы RGB-светодиода
constexpr int LED_RED_PIN = 9;
constexpr int LED_GREEN_PIN = 10;
constexpr int LED_BLUE_PIN = 11;
// Даём понятное имя пину с кнопкой
constexpr int BUTTON_PIN = A0;
// Создаём три переменные для хранения яркости каждого цвета RGB-светодиода
int red, green, blue;
void setup() {
// Настраиваем пины RGB-светодиода в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Считываем нажатие с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
if (buttonState) {
// Генерируем случайное число от 1 до 7
int number = random(1, 8);
// В зависимости от сгенерированного числа,
// подаём разные сигнала на ножки RGB-светодиода
if (number == 1) {
red = HIGH; green = LOW; blue = LOW;
} else if (number == 2) {
red = LOW; green = HIGH; blue = LOW;
} else if (number == 3) {
red = LOW; green = LOW; blue = HIGH;
} else if (number == 4) {
red = HIGH; green = HIGH; blue = LOW;
} else if (number == 5) {
red = LOW; green = HIGH; blue = HIGH;
} else if (number == 6) {
red = HIGH; green = LOW; blue = HIGH;
}
// Выводим полученные значения на ножки RGB-светодиода
digitalWrite(LED_RED_PIN, red);
digitalWrite(LED_GREEN_PIN, green);
digitalWrite(LED_BLUE_PIN, blue);
// Ждём одну секунду
delay(1000);
// Подаём на все ножки RGB-светодиода логический ноль
digitalWrite(LED_RED_PIN, LOW);
digitalWrite(LED_GREEN_PIN, LOW);
digitalWrite(LED_BLUE_PIN, LOW);
}
}
=== Программный код №2 ===
// Даём понятные имена пинам к которым подключены выводы RGB-светодиода
constexpr int LED_RED_PIN = 9;
constexpr int LED_GREEN_PIN = 10;
constexpr int LED_BLUE_PIN = 11;
// Даём понятное имя пину с кнопкой
constexpr int BUTTON_PIN = A0;
// Создаём три переменные для хранения яркости каждого цвета RGB-светодиода
int red, green, blue;
void setup() {
// Настраиваем пины RGB-светодиода в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
// Передаём случайное число с пина A5
// для последующей генерации случайных чисел
randomSeed(analogRead(A5));
}
void loop() {
// Считываем нажатие с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
if (buttonState) {
// Генерируем случайное число от 1 до 7
int number = random(1, 8);
// В зависимости от сгенерированного числа,
// подаём разные сигнала на ножки RGB-светодиода
if (number == 1) {
red = HIGH; green = LOW; blue = LOW;
} else if (number == 2) {
red = LOW; green = HIGH; blue = LOW;
} else if (number == 3) {
red = LOW; green = LOW; blue = HIGH;
} else if (number == 4) {
red = HIGH; green = HIGH; blue = LOW;
} else if (number == 5) {
red = LOW; green = HIGH; blue = HIGH;
} else if (number == 6) {
red = HIGH; green = LOW; blue = HIGH;
}
// Выводим полученные значения на ножки RGB-светодиода
digitalWrite(LED_RED_PIN, red);
digitalWrite(LED_GREEN_PIN, green);
digitalWrite(LED_BLUE_PIN, blue);
// Ждём одну секунду
delay(1000);
// Подаём на все ножки RGB-светодиода логический ноль
digitalWrite(LED_RED_PIN, LOW);
digitalWrite(LED_GREEN_PIN, LOW);
digitalWrite(LED_BLUE_PIN, LOW);
}
}
==== №21. Лампа настроения ====
{{ :arduino:210-schematic.png?nolink&500 |}}
{{ :arduino:210-wiring-cmyk.png?nolink |}}
// Даём понятные имена пинам к которым подключены выводы RGB-светодиода
constexpr int LED_RED_PIN = 9;
constexpr int LED_GREEN_PIN = 10;
constexpr int LED_BLUE_PIN = 11;
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A0;
// Создаём три переменные для хранения яркости каждого цвета RGB-светодиода
int red, green, blue;
void setup() {
// Настраиваем пины RGB-светодиода в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
pinMode(LED_BLUE_PIN, OUTPUT);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int rotation = analogRead(A0);
// В зависимости от поворота ручки потенциометра,
// генерируем разными методами цвета Red, Green и Blue
if (rotation <= 170) {
red = 255;
green = map(rotation, 0, 170, 0, 255);
blue = 0;
}
else if (rotation <= 340) {
red = map(rotation, 170, 340, 255, 0);
green = 255;
blue = 0;
}
else if (rotation <= 512) {
red = 0;
green = 255;
blue = map(rotation, 340, 512, 0, 255);
}
else if (rotation <= 682) {
red = 0;
green = map(rotation, 512, 682, 255, 0);
blue = 255;
}
else if (rotation <= 852) {
red = map(rotation, 682, 852, 0, 255);
green = 0;
blue = 255;
}
else {
red = 255;
green = 0;
blue = map(rotation, 852, 1023, 255, 0);
}
// Выводим полученные значения на ножки RGB-светодиода
analogWrite(LED_RED_PIN, red);
analogWrite(LED_GREEN_PIN, green);
analogWrite(LED_BLUE_PIN, blue);
}
==== №22. О частота, ты звук! ====
{{ :arduino:220-schematic.png?nolink&500 |}}
{{ :arduino:220-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int BUZZER_PIN = 3;
constexpr int BUTTON_PIN = 4;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Считываем нажатие с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
// Применяем полученное значение к пищалке
digitalWrite(BUZZER_PIN, buttonState);
}
==== №23. На старт, внимание, бзз! ====
{{ :arduino:230-schematic.png?nolink&250 |}}
{{ :arduino:230-wiring-cmyk.png?nolink |}}
// Даём пину с пищалкой понятное имя
constexpr int BUZZER_PIN = 3;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Выдаём на пищалку ШИМ-сигнал с коэффициентом заполнения 50%
analogWrite(BUZZER_PIN, 127);
}
void loop() {
}
==== №24. Синтезатор ====
{{ :arduino:240-schematic.png?nolink&500 |}}
{{ :arduino:240-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 3;
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A0;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int rotation = analogRead(POT_PIN);
// Преобразуем значение с потенциометра в частотный диапазон для пищалки
int frequency = map(rotation, 0, 1023, 20, 20000);
// Заставляем пин с пищалкой звучать на высчитанной частоте
tone(BUZZER_PIN, frequency);
}
==== №25. Я вам спою ====
{{ :arduino:250-schematic.png?nolink&500 |}}
{{ :arduino:250-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 7;
// Даём понятное имя пину с кнопкой
constexpr int BUTTON_PIN = 4;
// Создаём звуковой шрифт из нот со своими частотами
constexpr int NOTE_B3 = 247;
constexpr int NOTE_C4 = 262;
constexpr int NOTE_D4 = 294;
constexpr int NOTE_E4 = 330;
constexpr int NOTE_F4 = 349;
constexpr int NOTE_G4 = 392;
constexpr int NOTE_A4 = 440;
constexpr int NOTE_B4 = 494;
constexpr int NOTE_C5 = 523;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Настраиваем пин с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_PIN, INPUT_PULLUP);
}
void loop() {
// Считываем нажатие с кнопки
bool buttonState = !digitalRead(BUTTON_PIN);
// По нажатию кнопки проигрываем мелодию из последовательности нот
if (buttonState) {
tone(BUZZER_PIN, NOTE_E4, 100);
delay(150);
tone(BUZZER_PIN, NOTE_E4, 100);
delay(300);
tone(BUZZER_PIN, NOTE_E4, 100);
delay(300);
tone(BUZZER_PIN, NOTE_C4, 100);
delay(100);
tone(BUZZER_PIN, NOTE_E4, 100);
delay(300);
tone(BUZZER_PIN, NOTE_G4, 100);
delay(550);
tone(BUZZER_PIN, NOTE_C5, 100);
delay(575);
}
}
==== №26. Кнопочные ковбои ====
{{ :arduino:260-schematic.png?nolink |}}
{{ :arduino:260-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int BUZZER_PIN = 4;
constexpr int LED_ONE_PIN = 3;
constexpr int LED_TWO_PIN = 5;
constexpr int BUTTON_ONE_PIN = 2;
constexpr int BUTTON_TWO_PIN = 6;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Настраиваем пины со светодиодами в режим выхода
pinMode(LED_ONE_PIN, OUTPUT);
pinMode(LED_TWO_PIN, OUTPUT);
// Настраиваем пины с кнопкой в режим входа с подтяжкой к питанию
pinMode(BUTTON_ONE_PIN, INPUT_PULLUP);
pinMode(BUTTON_TWO_PIN, INPUT_PULLUP);
// Передаём случайное число с пина A0
// для последующей генерации случайных чисел
randomSeed(analogRead(A0));
}
void loop() {
// Выжидаем случайное время от 2 до 10 секунд
delay(random(2000, 10000));
// Даём сигнал «пли!»
// Пищим 250 миллисекунд с частотой 3 килогерца
tone(BUZZER_PIN, 3000, 250);
// Запускаем бесконечный цикл while
while (true) {
// Считываем состояния кнопок двух игроков
bool buttonPlayerOne = !digitalRead(BUTTON_ONE_PIN);
bool buttonPlayerTwo = !digitalRead(BUTTON_TWO_PIN);
// Проверяем, нажата ли одна из кнопок.
if (buttonPlayerOne || buttonPlayerTwo) {
if (buttonPlayerOne) {
// Если на кнопку нажал первый игрок
// Зажигаем первый светодиод на 1000 мс
// Выводим звуковой сигнал 4000 Гц / 1000 мс
digitalWrite(LED_ONE_PIN, HIGH);
tone(BUZZER_PIN, 4000, 1000);
delay(1000);
digitalWrite(LED_ONE_PIN, LOW);
// Если на кнопку нажал второй игрок
// Зажигаем первый светодиод на 1000 мс
// Выводим звуковой сигнал 4000 Гц / 1000 мс
} else if (buttonPlayerTwo) {
digitalWrite(LED_TWO_PIN, HIGH);
tone(BUZZER_PIN, 4000, 1000);
delay(1000);
digitalWrite(LED_TWO_PIN, LOW);
}
// Выходим из бесконечного цикла
break;
}
}
}
==== №27. Терминал ====
void setup() {
// Открываем соединения с последовательным портом (терминалом)
Serial.begin(9600);
// Выводим приветственную строку в терминал
Serial.println("Hello, world");
}
void loop() {
// Выводим каждую секунду новую строку
Serial.println("This is a new line");
delay(1000);
}
==== №28. Время жизни ====
void setup() {
// Открываем соединения с последовательным портом (терминалом)
Serial.begin(9600);
// Выводим приветственную строку в терминал
Serial.println("Hello, world");
}
void loop() {
// Создаём переменную time
// и присваиваем ей количество секунд с начала работы программы
int time = millis() / 1000;
// Выводим полученные данные
Serial.print("Time life: ");
Serial.print(time);
Serial.println(" seconds");
delay(1000);
}
==== №29. Бегущий огонь ====
{{ :arduino:290-schematic.png?nolink&600 |}}
{{ :arduino:290-wiring-cmyk.png?nolink |}}
// Создаём массив с контактами светодиодов
constexpr int PIN_LEDS[] = {2, 3, 4, 5, 6, 7, 8, 9};
// Количество светодиодов в массиве
constexpr int COUNT_LEDS = 8;
void setup() {
// Настраиваем пины со светодиодами в режим выхода
for (int i = 0; i < COUNT_LEDS ; i++) {
pinMode(PIN_LEDS[i], OUTPUT);
}
}
void loop() {
// Мигаем каждым светодиодом в цикле по очереди
for (int i = 0; i < COUNT_LEDS; i++) {
digitalWrite(PIN_LEDS[i], HIGH);
delay(100);
digitalWrite(PIN_LEDS[i], LOW);
delay(100);
}
}
==== №30. Многопоточность ====
{{ :arduino:300-schematic.png?nolink&600 |}}
{{ :arduino:300-wiring-cmyk.png?nolink |}}
// Даём пинам понятные имена
constexpr int LED_RED_PIN = 2;
constexpr int LED_GREEN_PIN = 3;
// Переменные для счётчиков красного и зелёного светодиода
long millisLastRed = 0;
long millisLastGreen = 0;
// Переменные для хранения состояний светодиодов
bool ledRedState = false;
bool ledGreenState = false;
void setup() {
// Настраиваем пины со светодиодами в режим выхода
pinMode(LED_RED_PIN, OUTPUT);
pinMode(LED_GREEN_PIN, OUTPUT);
}
void loop() {
// Засекаем текущее время
long millisNow = millis();
if (millisNow - millisLastRed > 100) {
// Если интервал красного LED превысил 100 мс
// Инвертируем его состояние
millisLastRed = millisNow;
ledRedState = !ledRedState;
digitalWrite(LED_RED_PIN, ledRedState);
}
if (millisNow - millisLastGreen > 1000) {
// Если интервал зелёного LED превысил 1000 мс
// Инвертируем его состояние
millisLastGreen = millisNow;
ledGreenState = !ledGreenState;
digitalWrite(LED_GREEN_PIN, ledGreenState);
}
}
==== №31. Выкручивание напряжения ====
{{ :arduino:310-schematic.png?nolink&150 |}}
{{ :arduino:310-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A0;
void setup() {
// Открываем соединения с последовательным портом
Serial.begin(9600);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int sensorADC = analogRead(POT_PIN);
// Преобразуем отсчёты АЦП в напряжение
float sensorVoltage = (sensorADC * 5) / 1024;
// Выводим в терминал показания с потенциометра
// в отсчётах АЦП и в напряжении
Serial.print(sensorADC);
Serial.print(" ADC");
Serial.print("\t\t");
Serial.print(sensorVoltage);
Serial.println(" Volts");
delay(1000);
}
=== Программный код №2 ===
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A0;
void setup() {
// Открываем соединения с последовательным портом
Serial.begin(9600);
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int sensorADC = analogRead(POT_PIN);
// Преобразуем отсчёты АЦП в напряжение
float sensorVoltage = (sensorADC * 5.0) / 1024.0;
// Выводим в терминал показания с потенциометра
// в отсчётах АЦП и в напряжении
Serial.print(sensorADC);
Serial.print(" ADC");
Serial.print("\t\t");
Serial.print(sensorVoltage);
Serial.println(" Volts");
delay(1000);
}
==== №32. Термометр ====
{{ :arduino:320-schematic.png?nolink&250 |}}
{{ :arduino:320-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с датчиком температуры TMP36
constexpr int TMP36_PIN = A0;
void setup() {
// Открываем соединения с последовательным портом
Serial.begin(9600);
}
void loop() {
// Считываем аналоговый сигнал с TMP36
int tmp36ADC = analogRead(TMP36_PIN);
// Преобразуем отсчёты АЦП в напряжение
float tmp36Voltage = (tmp36ADC * 5.0) / 1024.0;
// Преобразуем напряжение с датчика в значение температуры
float tmp36Temperature = (tmp36Voltage - 0.5) * 100;
// Выводим результаты измерений в терминал
Serial.print(tmp36ADC);
Serial.print(" ADC");
Serial.print("\t\t");
Serial.print(tmp36Voltage);
Serial.print(" Volts");
Serial.print("\t");
Serial.print(tmp36Temperature);
Serial.println(" Degrees C");
delay(1000);
}
==== №33. Функциональный термометр ====
{{ :arduino:330-schematic.png?nolink&250 |}}
{{ :arduino:330-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с датчиком температуры TMP36
constexpr int TMP36_PIN = A0;
float readTemperature() {
// Считываем аналоговый сигнал с TMP36
int tmp36ADC = analogRead(TMP36_PIN);
// Преобразуем отсчёты АЦП в напряжение
float tmp36Voltage = (tmp36ADC * 5.0) / 1024.0;
// Преобразуем напряжение с датчика в значение температуры
float tmp36Temperature = (tmp36Voltage - 0.5) * 100.0;
// Возвращаем результат
return tmp36Temperature;
}
void setup() {
// Открываем соединения с последовательным портом
Serial.begin(9600);
}
void loop() {
// Запрашиваем температуру у датчика TMP36
float tmp36Temp = readTemperature();
// Выводим результат измерений в терминал
Serial.print(tmp36Temp);
Serial.println(" Degrees C");
delay(1000);
}
==== №34. Библиотечный термометр ====
{{ :arduino:340-schematic.png?nolink&250 |}}
{{ :arduino:340-wiring-cmyk.png?nolink |}}
// Библиотека для работы с датчиком температуры TMP36
#include
// Даём понятное имя пину с датчиком температуры TMP36
constexpr int TMP36_PIN = A0;
// Создаём объект для работы с датчиком температуры TMP36
// В параметре передаём пин, к которому подключен сенсор
TroykaThermometer tmp36(TMP36_PIN);
void setup() {
// Открываем соединения с последовательным портом
Serial.begin(9600);
}
void loop() {
// Считываем данные с датчика TMP36
tmp36.read();
// Запрашиваем температуру у датчика TMP36
float tmp36Temp = tmp36.getTemperatureC();
// Выводим результат измерений в терминал
Serial.print(tmp36Temp);
Serial.println(" Degrees C");
delay(1000);
}
[[https://github.com/amperka/TroykaThermometer | Библиотека TroykaThermometer]]
==== №35. Заводим дисплей ====
{{ :arduino:350-schematic.png?nolink&250 |}}
{{ :arduino:350-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем
#include
// Назначаем контакты для подключения дисплея
// Используется 4-битный параллельный интерфейс
constexpr int RS_PIN = 2;
constexpr int EN_PIN = 3;
constexpr int DB4_PIN = 4;
constexpr int DB5_PIN = 5;
constexpr int DB6_PIN = 6;
constexpr int DB7_PIN = 7;
// Создаём объект для работы с дисплеем
// В параметрах передаём используемые пины
LiquidCrystal lcd(RS_PIN, EN_PIN, DB4_PIN, DB5_PIN, DB6_PIN, DB7_PIN);
void setup() {
// Инициализируем дисплей на 2 строки по 16 символов
lcd.begin(16, 2);
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Печатем первую строку
lcd.print("Hello, world!");
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Печатем вторую строку
lcd.print("www.amperka.ru");
}
void loop() {
}
[[https://www.arduino.cc/reference/en/libraries/liquidcrystal/ | Библиотека LiquidCrystal]]
==== №36. Бегущая строка ====
{{ :arduino:360-schematic.png?nolink&250 |}}
{{ :arduino:360-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем
#include
// Назначаем контакты для подключения дисплея
// Используется 4-битный параллельный интерфейс
constexpr int RS_PIN = 2;
constexpr int EN_PIN = 3;
constexpr int DB4_PIN = 4;
constexpr int DB5_PIN = 5;
constexpr int DB6_PIN = 6;
constexpr int DB7_PIN = 7;
// Создаём объект для работы с дисплеем
// В параметрах передаём используемые пины
LiquidCrystal lcd(RS_PIN, EN_PIN, DB4_PIN, DB5_PIN, DB6_PIN, DB7_PIN);
void setup() {
// Инициализируем дисплей на 2 строки по 16 символов
lcd.begin(16, 2);
// Открываем соединения с последовательным портом
Serial.begin(9600);
}
void loop() {
// Создаём объект динамической строки
String data;
if (Serial.available()) {
// Если пришли данные с последовательного порта
// Считываем их в строку
data = Serial.readString();
// Выводим данные из строки на дисплей в виде бегущей строки
lcdPrintScroll(data);
}
}
// Функция для вывода эффекта бегущей строки
void lcdPrintScroll(String str) {
// Очищаем дисплей
lcd.clear();
// Устанавливаем курсор на шестнадцатом знакоместе во второй строке
lcd.setCursor(16, 1);
// Печатаем строку на дисплей
lcd.print(str);
// Сдвигаем видимую область дисплея влево на шестнадцать символов
for(int i = 0; i < str.length() + 16; i++) {
lcd.scrollDisplayLeft();
delay(200);
}
}
[[https://www.arduino.cc/reference/en/libraries/liquidcrystal/ | Библиотека LiquidCrystal]]
==== №37. Бегущая строка без правил ====
{{ :arduino:370-schematic.png?nolink&250 |}}
{{ :arduino:370-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем
#include
// Назначаем контакты для подключения дисплея
// Используется 4-битный параллельный интерфейс
constexpr int RS_PIN = 2;
constexpr int EN_PIN = 3;
constexpr int DB4_PIN = 4;
constexpr int DB5_PIN = 5;
constexpr int DB6_PIN = 6;
constexpr int DB7_PIN = 7;
// Создаём объект для работы с дисплеем
// В параметрах передаём используемые пины
LiquidCrystal lcd(RS_PIN, EN_PIN, DB4_PIN, DB5_PIN, DB6_PIN, DB7_PIN);
void setup() {
// Инициализируем дисплей на 2 строки по 16 символов
lcd.begin(16, 2);
// Открываем соединение с последовательным портом
Serial.begin(9600);
}
void loop() {
// Создаём объект динамической строки
String data;
if (Serial.available()) {
// Если пришли данные с последовательного порта
// Считываем их в строку
data = Serial.readString();
// Выводим данные из строки на дисплей в виде бегущей строки
lcdPrintScroll(data);
}
}
// Функция для вывода эффекта бегущей строки
void lcdPrintScroll(String str) {
// Создаём строку и заполняем её 16-ю пробелами
String strSpace;
for (int i = 0; i <= 15; i++) {
strSpace.concat(" ");
}
// Создаём строку и заполняем её:
String str16;
str = strSpace + str + strSpace;
for (int i = 0; i < str.length(); i++) {
str16 = str.substring(i, i + 16);
lcd.setCursor(0, 1);
lcd.print(str16);
delay(200);
}
}
[[https://www.arduino.cc/reference/en/libraries/liquidcrystal/ | Библиотека LiquidCrystal]]
==== №38. I²C-сканер ====
{{ :arduino:380-schematic.png?nolink&250 |}}
{{ :arduino:380-wiring-cmyk.png?nolink |}}
// Библиотека для работы с I²C-устройствами
#include
void setup() {
// Инициализируем шину I²C
Wire.begin();
// Открываем соединение с последовательным портом
Serial.begin(9600);
}
void loop() {
// Выводим сообщение о начале работы сканера
Serial.println("I2C Scanner begin...");
int address;
int countDevices = 0;
// Сканируем адреса шины I²C от 0 до 127
for (address = 1; address < 127; address++ ) {
Wire.beginTransmission(address);
if (Wire.endTransmission() == 0) {
// Если найдено устройство I²C, выводим его адрес в терминал
Serial.println("I2C device found at address:");
Serial.print("DEC:");
Serial.println(address);
Serial.print("HEX:0x");
Serial.println(address, HEX);
countDevices++;
}
}
// Если устройства I²C не обнаружены, выводим сообщение в терминал
if (countDevices == 0) {
Serial.println("No I2C devices found!");
}
// Выводим сообщение о завершении работы сканера
Serial.println("I2C Scanner end!\n");
delay(5000);
}
[[https://reference.arduino.cc/reference/en/language/functions/communication/wire/ | Библиотека Wire]]
==== №39. Заводим дисплей по I²C ====
{{ :arduino:390-schematic.png?nolink&250 |}}
{{ :arduino:390-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Печатаем первую строку
lcd.print("Hello, world");
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Печатаем вторую строку
lcd.print("www.amperka.ru");
}
void loop() {
}
[[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №40. Системы счисления ====
{{ :arduino:400-schematic.png?nolink&600 |}}
{{ :arduino:400-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A0;
// Переменная для хранения переводимого числа
int value = 0;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Печатаем данные на дисплей
printDataLCD(value);
}
void loop() {
// Считываем сигнал с потенциометра
int valueNow = readPot(POT_PIN);
// Если текущее показание потенциометра отличается от предыдущего
if (value != valueNow) {
// Обновляем показатель
value = valueNow;
// Печатаем данные на дисплей
printDataLCD(value);
}
}
// Функция для считывания аналогового сигнала с потенциометра
// с преобразованием в диапазон значений от 0 до 16
int readPot(int pin) {
int sensorADC = 0;
int sensorValue = 0;
// Фильтруем данные
а затем делим результат
for (int i = 0; i < 32; i++) {
sensorADC += analogRead(pin);
delay(10);
}
sensorADC = sensorADC / 32;
// Преобразуем выходной сигнал с потенциометра в диапазон значений от 0 до 16
sensorValue = map(sensorADC, 0, 1023, 0, 15);
// Возвращаем результат
return sensorValue;
}
// Функция для вывода числа на дисплей в различных системах счисления
void printDataLCD(int numberNow) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("DEC:");
lcd.print(numberNow, DEC);
lcd.setCursor(8, 0);
lcd.print("BIN:");
lcd.print(numberNow, BIN);
lcd.setCursor(0, 1);
lcd.print("OCT:");
lcd.print(numberNow, OCT);
lcd.setCursor(8, 1);
lcd.print("HEX:");
lcd.print(numberNow, HEX);
}
[[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №41. Термометр на ЖК ====
{{ :arduino:410-schematic.png?nolink&600 |}}
{{ :arduino:410-wiring-cmyk.png?nolink |}}
// Библиотека для работы с датчиком температуры TMP36
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Даём понятное имя пину с датчиком температуры TMP36
constexpr int TMP36_PIN = A0;
// Создаём объект для работы с датчиком температуры TMP36
// В параметре передаём пин, к которому подключен сенсор
TroykaThermometer tmp36(TMP36_PIN);
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("");
}
void loop() {
// Считываем данные с датчика TMP36
tmp36.read();
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Выводим данные температуры на дисплей
lcd.print("T = ");
lcd.print(tmp36.getTemperatureC());
lcd.print(" C");
delay(1000);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaThermometer | Библиотека TroykaThermometer]]
==== №42. Настольные часы ====
{{ :arduino:420-schematic.png?nolink&600 |}}
{{ :arduino:420-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с кнопкой
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём объекты кнопок для управления
TroykaButton buttonMinute(2);
TroykaButton buttonHour(3);
int hours, minutes, seconds;
long millisLastTime = 0;
void setup() {
// Инициализируем кнопки
buttonMinute.begin();
buttonHour.begin();
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("");
setTime(12, 45, 30);
}
void loop() {
// Обновляем время посекундно
updateTime();
// Обновляем время через кнопки
updateTimeButtons();
// Преобразуем время
wrapTime();
// Выводим на дисплее время в формате «чч:мм:сс»
printTimeLCD();
}
// Функция для установки времени
void setTime(int h, int m, int s) {
hours = h;
minutes = m;
seconds = s;
}
// Функция для отсчёта времени посекундно
void updateTime() {
long millisNowTime = millis();
if (millisNowTime - millisLastTime > 1000) {
millisLastTime = millisNowTime;
seconds++;
}
}
// Функция для обновления времени через кнопки
void updateTimeButtons() {
buttonHour.read();
buttonMinute.read();
if (buttonHour.isClick()) {
hours++;
}
if (buttonMinute.isClick()) {
minutes++;
}
}
// Функция для форматирования времени
// При достижении лимита в 60 секунд, 60 минут и 24 часа отсчёт начинается заново
void wrapTime() {
if (seconds >= 60) {
minutes++;
seconds -= 60;
}
if (minutes >= 60) {
hours++;
minutes -= 60;
}
if (hours >= 24) {
hours = 0;
}
}
// Функция для вывода на дисплее времени в формате «чч:мм:сс»
void printTimeLCD() {
lcd.setCursor(0, 1);
lcd.print("TIME: ");
printTwoDigits(hours);
lcd.print(":");
printTwoDigits(minutes);
lcd.print(":");
printTwoDigits(seconds);
}
// Функция для вывода на дисплей двух цифр:
// на первом знакоместе 0, если цифра меньше 10
void printTwoDigits(int digit) {
if (digit < 10) {
lcd.print("0");
}
lcd.print(digit);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaButton | Библиотека TroykaButton]]
==== №43. Часы с термометром ====
{{ :arduino:430-schematic.png?nolink&600 |}}
{{ :arduino:430-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с кнопкой
#include
// Библиотека для работы с датчиком температуры TMP36
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём объекты кнопок для управления
TroykaButton buttonMinute(2);
TroykaButton buttonHour(3);
// Создаём объект для работы с датчиком температуры TMP36
// В параметре передаём пин, к которому подключен сенсор
TroykaThermometer tmp36(A0);
// Переменные для хранения часов, минут и секунд
int hours, minutes, seconds;
// Переменные для хранения температуры
float temparature;
long millisLastTime = 0;
long millisLastTemp = 0;
void setup() {
// Инициализируем кнопки
buttonMinute.begin();
buttonHour.begin();
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Устанавливаем тестовое время 12:45:30
setTime(12, 45, 30);
}
void loop() {
// Обновляем время посекундно
updateTime();
// Обновляем время через кнопки
updateTimeButtons();
// Обновляем температуру
updateTemperature();
// Преобразуем время
wrapTime();
// Выводим на дисплее время в формате «чч:мм:сс»
printTimeLCD();
}
// Функция для установки времени
void setTime(int h, int m, int s) {
hours = h;
minutes = m;
seconds = s;
}
// Функция для отсчёта времени
void updateTime() {
long millisNowTime = millis();
if (millisNowTime - millisLastTime > 1000) {
millisLastTime = millisNowTime;
seconds++;
}
}
// Функция для обновления температуры
void updateTemperature() {
long millisNowTemp = millis();
if (millisNowTemp - millisLastTemp > 500) {
millisLastTemp = millisNowTemp;
tmp36.read();
temparature = tmp36.getTemperatureC();
}
}
// Функция для обновления времени через кнопки
void updateTimeButtons() {
buttonHour.read();
buttonMinute.read();
if (buttonHour.isClick()) {
hours++;
}
if (buttonMinute.isClick()) {
minutes++;
}
}
// Функция для форматирования времени
// При достижении лимита в 60 секунд, 60 минут и 24 часа отсчёт начинается заново
void wrapTime() {
if (seconds >= 60) {
minutes++;
seconds -= 60;
}
if (minutes >= 60) {
hours++;
minutes -= 60;
}
if (hours >= 24) {
hours = 0;
}
}
// Функция для вывода на дисплее времени в формате «чч:мм:сс» и температуры
void printDataLCD() {
lcd.setCursor(0, 0);
lcd.print("TIME: ");
printTwoDigits(hours);
lcd.print(":");
printTwoDigits(minutes);
lcd.print(":");
printTwoDigits(seconds);
lcd.setCursor(0, 1);
lcd.print("TEMP: ");
lcd.print(temparature);
lcd.print(" C");
}
// Функция для вывода на дисплей двух цифр:
// на первом знакоместе 0, если цифра меньше 10
void printTwoDigits(int digit) {
if (digit < 10) {
lcd.print("0");
}
lcd.print(digit);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaThermometer | Библиотека TroykaThermometer]]
* [[https://github.com/amperka/TroykaButton | Библиотека TroykaButton]]
==== №44. Карманный девайс ====
{{ :arduino:440-schematic.png?nolink&600 |}}
{{ :arduino:440-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с кнопкой
#include
// Библиотека для работы с датчиком температуры TMP36
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём объекты кнопок для управления
TroykaButton buttonMinute(2);
TroykaButton buttonHour(3);
// Создаём объект для работы с датчиком температуры TMP36
// В параметре передаём пин, к которому подключен сенсор
TroykaThermometer tmp36(A0);
// Переменные для хранения часов, минут и секунд
int hours, minutes, seconds;
// Переменные для хранения температуры
float temparature;
long millisLastTime = 0;
long millisLastTemp = 0;
void setup() {
// Инициализируем кнопки
buttonMinute.begin();
buttonHour.begin();
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Устанавливаем тестовое время 12:45:30
setTime(12, 45, 30);
}
void loop() {
// Обновляем время посекундно
updateTime();
// Обновляем время через кнопки
updateTimeButtons();
// Обновляем температуру
updateTemperature();
// Преобразуем время
wrapTime();
// Выводим на дисплее время в формате «чч:мм:сс»
printTimeLCD();
}
// Функция для установки времени
void setTime(int h, int m, int s) {
hours = h;
minutes = m;
seconds = s;
}
// Функция для отсчёта времени
void updateTime() {
long millisNowTime = millis();
if (millisNowTime - millisLastTime > 1000) {
millisLastTime = millisNowTime;
seconds++;
}
}
// Функция для обновления температуры
void updateTemperature() {
long millisNowTemp = millis();
if (millisNowTemp - millisLastTemp > 500) {
millisLastTemp = millisNowTemp;
tmp36.read();
temparature = tmp36.getTemperatureC();
}
}
// Функция для обновления времени через кнопки
void updateTimeButtons() {
buttonHour.read();
buttonMinute.read();
if (buttonHour.isClick()) {
hours++;
}
if (buttonMinute.isClick()) {
minutes++;
}
}
// Функция для форматирования времени
// При достижении лимита в 60 секунд, 60 минут и 24 часа отсчёт начинается заново
void wrapTime() {
if (seconds >= 60) {
minutes++;
seconds -= 60;
}
if (minutes >= 60) {
hours++;
minutes -= 60;
}
if (hours >= 24) {
hours = 0;
}
}
// Функция для вывода на дисплее времени в формате «чч:мм:сс» и температуры
void printDataLCD() {
lcd.setCursor(0, 0);
lcd.print("TIME: ");
printTwoDigits(hours);
lcd.print(":");
printTwoDigits(minutes);
lcd.print(":");
printTwoDigits(seconds);
lcd.setCursor(0, 1);
lcd.print("TEMP: ");
lcd.print(temparature);
lcd.print(" C");
}
// Функция для вывода на дисплей двух цифр:
// на первом знакоместе 0, если цифра меньше 10
void printTwoDigits(int digit) {
if (digit < 10) {
lcd.print("0");
}
lcd.print(digit);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaThermometer | Библиотека TroykaThermometer]]
* [[https://github.com/amperka/TroykaButton | Библиотека TroykaButton]]
==== №45. Биты и байты ====
{{ :arduino:450-schematic.png?nolink&600 |}}
{{ :arduino:450-wiring-cmyk.png?nolink |}}
// Библиотека для работы с кнопкой
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём переменную для хранения тестового числа
byte value = 127;
// Максимальныое знакоместо на дисплее
constexpr int COL_MAX = 11;
// Индекс положения курсора
int digitIndex = 0;
// Создаём объекты кнопок для управления
TroykaButton buttonLeft(3);
TroykaButton buttonRight(2);
TroykaButton buttonSet(A3);
void setup() {
// Инициализируем кнопки
buttonLeft.begin();
buttonRight.begin();
buttonSet.begin();
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Отображаем курсор
lcd.cursor();
// Включаем мигание курсора
lcd.blink();
// Печатаем данные на дисплей
printDataLCD();
lcd.setCursor(COL_MAX - digitIndex, 0);
}
void loop() {
// Считываем состояние кнопок
buttonLeft.read();
buttonRight.read();
buttonSet.read();
// Если нажата кнопка «вправо», смещаем курсор на одно знакоместо «вправо»
if (buttonRight.isClick() && digitIndex > 0) {
digitIndex--;
lcd.setCursor(COL_MAX - digitIndex, 0);
}
// Если нажата кнопка «влево», смещаем курсор на одно знакоместо «влево»
if (buttonLeft.isClick() && digitIndex < 7) {
digitIndex++;
lcd.setCursor(COL_MAX - digitIndex, 0);
}
// Если нажата кнопка «Установка»
// «переворачиваем» значение выбранного курсором бита
if (buttonSet.isClick()) {
bitInvert(digitIndex);
printDataLCD();
lcd.setCursor(COL_MAX - digitIndex, 0);
}
}
// Функция для вывода числа на дисплей в системах счисления BIN и DEC
void printDataLCD() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("BIN:");
printByteLCD();
lcd.setCursor(0, 1);
lcd.print("DEC:");
lcd.print(value);
}
// Функция для вывода числа по байтам
void printByteLCD() {
for (int i = 7; i >= 0; i--) {
lcd.print(bitRead(value, i));
}
}
// Функция для инвертирования значение бита
void bitInvert(int bitNumber) {
bool bitValue = bitRead(value, bitNumber);
bitValue = !bitValue;
bitWrite(value, bitNumber, bitValue);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaButton | Библиотека TroykaButton]]
==== №46. Тайны знакогенератора ====
{{ :arduino:460-schematic.png?nolink&300 |}}
{{ :arduino:460-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
}
void loop() {
// Устанавливаем курсор на третьем знакоместе в первой строке
lcd.setCursor(2, 0);
lcd.print("ASCII Table");
// Выводим в цикле все символы знакогенератора с кодом от 0 до 255
for (int i = 0 ; i <= 255 ; i++) {
lcd.setCursor(0, 1);
if (i < 16) {
lcd.print("0");
}
lcd.print(i, HEX);
lcd.print(" = ");
lcd.write(i);
delay(500);
}
lcd.clear();
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №47. Я календарь переключу… ====
{{ :arduino:470-schematic.png?nolink&300 |}}
{{ :arduino:470-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Константа с адресом нулевой страницы знакогенератора
constexpr int LCD_PAGE_0 = 0b101000;
// Константа с адресом первой страницы знакогенератора
constexpr int LCD_PAGE_1 = 0b101010;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на четвёртом знакоместе в первой строке
lcd.setCursor(3, 0);
// Выводим строку на дисплей
lcd.print("Switch Page");
// Устанавливаем курсор на шестом знакоместе во второй строке
lcd.setCursor(5, 1);
// Выводим пять символов из таблицы знакогенератора
lcd.print("\x9f\x9e\x9d\x9c\x9b");
}
void loop() {
// Переключаем две страницы знакогенератора с интервалом каждую секунду
lcd.command(LCD_PAGE_0);
delay(1000);
lcd.command(LCD_PAGE_1);
delay(1000);
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №48. Индикатор заряда ====
{{ :arduino:480-schematic.png?nolink&600 |}}
{{ :arduino:480-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Даём понятное имя пину, который подключен
// к батарейному отсеку через резистивный делитель
constexpr int VOLTAGE_PIN = A3;
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём константы резисторного делителя:
// номиналы резисторов и коэффициент делителя
constexpr float R1 = 10;
constexpr float R2 = 1;
constexpr float k = R2/(R2+R1);
// Создаём константы с адресами иконок заряда батареи из таблицы знакогенератора
constexpr int LCD_ICON_BATTERY_1 = 0x9B;
constexpr int LCD_ICON_BATTERY_2 = 0x9C;
constexpr int LCD_ICON_BATTERY_3 = 0x9D;
constexpr int LCD_ICON_BATTERY_4 = 0x9E;
constexpr int LCD_ICON_BATTERY_5 = 0x9F;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("Charge indicator");
}
void loop() {
// Измеряем напряжение на батарейном отсеке
float batVoltage = readVoltage();
// Устанавливаем курсор на первом знакоместе в второй строке
lcd.setCursor(0, 1);
// Выводим напряжение на батарейном отсеке
lcd.print(batVoltage);
lcd.print(" V / ");
// Выводим иконку, которая соответствует остаточному уровню заряда батареи
if (batVoltage >= 9) {
lcd.write(LCD_ICON_BATTERY_1);
} else if (batVoltage >= 8) {
lcd.write(LCD_ICON_BATTERY_2);
} else if (batVoltage >= 7) {
lcd.write(LCD_ICON_BATTERY_3);
} else if (batVoltage >= 6) {
lcd.write(LCD_ICON_BATTERY_4);
} else {
lcd.write(LCD_ICON_BATTERY_5);
}
delay(1000);
}
// Функция для считывания напряжения c батарейного отсека
float readVoltage() {
// Считываем аналоговый сигнал с резисторного делителя
int batADC = analogRead(VOLTAGE_PIN);
// Преобразуем отсчёты АЦП в напряжение с учётом коэффициента делителя
float batVoltage = ((batADC * 5.0) / 1024.0) / k;
return batVoltage;
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №49. Люксметр ====
{{ :arduino:490-schematic.png?nolink&500 |}}
{{ :arduino:490-wiring-cmyk.png?nolink |}}
=== Программный код №1 ===
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с фоторезистором
#include
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём объект для работы с фоторезистором
TroykaLight ldr(LDR_PIN);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("");
}
void loop() {
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
long ldrLight = ldr.getLightLux();
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Выводим показания освещенности на дисплей
lcd.print("L = ");
lcd.print(ldrLight);
lcd.print(" Lx");
delay(1000);
}
=== Программный код №2 ===
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с фоторезистором
#include
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём объект для работы с фоторезистором
TroykaLight ldr(LDR_PIN);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("");
}
void loop() {
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
long ldrLight = ldr.getLightLux();
// Создаём динамическую строку класса String, которая содержит шесть символов:
// показание освещённости с ведущими нулями
String ldrLightStr = longToStr(ldrLight, 6);
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Выводим показания освещенности на дисплей
lcd.print("L = ");
lcd.print(ldrLightStr);
lcd.print(" Lx");
delay(1000);
}
// Функция для преобразования переменной типа long в переменную String,
// оставляя при этом заданное количество знаков.
String longToStr(long value, int countDigits) {
String strValue;
int lenValue = String(value).length();
for (int i = countDigits; i > lenValue; i--) {
strValue += "0";
}
strValue += String(value);
return strValue;
}
* [[https://github.com/amperka/TroykaLight | Библиотека TroykaLight]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №50. Терменвокс ====
{{ :arduino:500-schematic.png?nolink&500 |}}
{{ :arduino:500-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 7;
void setup() {
// Настраиваем пин с фоторезистором в режим входа
pinMode(LDR_PIN, INPUT);
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
}
void loop() {
// Считываем аналоговый сигнал с фоторезистора
int ldrLight = analogRead(LDR_PIN);
// Преобразуем значение с фоторезистора в частотный диапазон для пищалки
int frequency = map(ldrLight, 0, 1023, 500, 5000);
// Заставляем пин с пищалкой звучать на высчитанной частоте
tone(BUZZER_PIN, frequency);
}
==== №51. Умная подсветка ====
{{ :arduino:510-schematic.png?nolink&600 |}}
{{ :arduino:510-wiring-cmyk.png?nolink |}}
// Библиотека для работы с фоторезистором
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A2;
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Создаём объект для работы с фоторезистором
TroykaLight ldr(LDR_PIN);
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int potADC = analogRead(POT_PIN);
// Преобразуем значение с потенциометра в диапазон освещённости
// для порог срабатывания подсветки
long limitLight = map(potADC, 0, 1023, 0, 100000);
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
long ldrLight = ldr.getLightLux();
// Выводим на дисплей
// порог освещенности срабатывания подсветки и текущую освещенность
printDataLCD(limitLight, ldrLight);
if (ldrLight < limitLight) {
// Если текущее показание фоторезистора ниже порога, включаем подсветку
lcd.backlight();
} else if (ldrLight > limitLight) {
// Если текущее показание фоторезистора выше порога, выключаем подсветку
lcd.noBacklight();
}
delay(1000);
}
// Функция для вывода на дисплей
// порога освещенности срабатывания подсветки и текущую освещенность
void printDataLCD(long limitLight, long ldrLight) {
String limitLightStr = longToStr(limitLight, 6);
String ldrLightStr = longToStr(ldrLight, 6);
lcd.setCursor(0, 0);
lcd.print("P = ");
lcd.print(limitLightStr);
lcd.print(" Lx");
lcd.setCursor(0, 1);
lcd.print("L = ");
lcd.print(ldrLightStr);
lcd.print(" Lx");
}
// Функция для преобразования переменной типа long в переменную String,
// оставляя при этом заданное количество знаков.
String longToStr(long value, int countDigits) {
String strValue;
int lenValue = String(value).length();
for (int i = countDigits; i > lenValue; i--) {
strValue += "0";
}
strValue += String(value);
return strValue;
}
* [[https://github.com/amperka/TroykaLight | Библиотека TroykaLight]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №52. Умная подсветка без глюков ====
{{ :arduino:520-schematic.png?nolink&600 |}}
{{ :arduino:520-wiring-cmyk.png?nolink |}}
// Библиотека для работы с фоторезистором
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A2;
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Создаём объект для работы с фоторезистором
TroykaLight ldr(LDR_PIN);
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int potADC = analogRead(POT_PIN);
// Преобразуем значение с потенциометра в диапазон освещённости
// для порог срабатывания подсветки
long limitLight = map(potADC, 0, 1023, 0, 100000);
// Создаём переменную для хранения гистерезиса
int hyster = limitLight * 0.1 + 50;
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
long ldrLight = ldr.getLightLux();
// Выводим на дисплей
// порог освещенности срабатывания подсветки и текущую освещенность
printDataLCD(limitLight, ldrLight);
if (ldrLight < limitLight - hyster) {
// Если текущее показание фоторезистора ниже нижней границы гистерезиса,
// включаем подсветку
lcd.backlight();
} else if (ldrLight > limitLight + hyster) {
// Если текущее показание фоторезистора выше верхней границы гистерезиса,
// выключаем подсветку
lcd.noBacklight();
}
delay(1000);
}
// Функция для вывода на дисплей
// порога освещенности срабатывания подсветки и текущую освещенность
void printDataLCD(long limitLight, long ldrLight) {
String limitLightStr = longToStr(limitLight, 6);
String ldrLightStr = longToStr(ldrLight, 6);
lcd.setCursor(0, 0);
lcd.print("P = ");
lcd.print(limitLightStr);
lcd.print(" Lx");
lcd.setCursor(0, 1);
lcd.print("L = ");
lcd.print(ldrLightStr);
lcd.print(" Lx");
}
// Функция для преобразования переменной типа long в переменную String,
// оставляя при этом заданное количество знаков.
String longToStr(long value, int countDigits) {
String strValue;
int lenValue = String(value).length();
for (int i = countDigits; i > lenValue; i--) {
strValue += "0";
}
strValue += String(value);
return strValue;
}
* [[https://github.com/amperka/TroykaLight | Библиотека TroykaLight]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №53. Оптопрерыватель ====
{{ :arduino:530-schematic.png?nolink&600 |}}
{{ :arduino:530-wiring-cmyk.png?nolink |}}
// Библиотека для работы с фоторезистором
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Даём понятное имя пину с потенциометром
constexpr int POT_PIN = A2;
// Даём понятное имя пину с фоторезистором
constexpr int LDR_PIN = A3;
// Создаём объект для работы с фоторезистором
TroykaLight ldr(LDR_PIN);
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
long ldrLight;
long lightNormal;
int hyster;
// Переменная для хранения кол-ва проходящих нарушителей
int passCount = 0;
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Устанавливаем курсор на первом знакоместе в первой строке
lcd.setCursor(0, 0);
// Выводим строку на дисплей
lcd.print("Security system");
// Устанавливаем курсор на первом знакоместе во второй строке
lcd.setCursor(0, 1);
// Выводим строку на дисплей
lcd.print("Pass count: ");
// Печатаем кол-во проходящих нарушителей
lcd.print(passCount);
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
ldrLight = ldr.getLightLux();
// Корректируем значение штатного освещения и гистерезиса
updateLightNormal(ldrLight);
}
void loop() {
// Считываем данные с фоторезистора
ldr.read();
// Запрашиваем освещенность у фоторезистора
ldrLight = ldr.getLightLux();
if (ldrLight < lightNormal - hyster) {
// Если уровень освещённости падает ниже нормального с учётом гистерезиса
lcd.setCursor(12, 1);
// Обновляем кол-во нарушителей
lcd.print(++passCount);
// Пищим зуммеров
playMelodyAlarm();
} else {
// Корректируем значение штатного освещения и гистерезиса
updateLightNormal(ldrLight);
}
delay(100);
}
// Функция для корректировки значений штатного освещения и гистерезиса
void updateLightNormal(long ldrLight) {
lightNormal = ldrLight;
hyster = lightNormal * 0.1 + 50;
}
// Функция для воспроизведения сигнала тревоги
void playMelodyAlarm() {
for (int i = 0; i <= 2; i++) {
tone(BUZZER_PIN, 200, 300);
delay(200);
tone(BUZZER_PIN, 120, 300);
delay(200);
}
}
* [[https://github.com/amperka/TroykaLight | Библиотека TroykaLight]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №54. Заметки мейкера ====
{{ :arduino:540-schematic.png?nolink&300 |}}
{{ :arduino:540-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Константа для хранения паузы в миллисекундах
constexpr int PAUSE = 5000;
// Создаём три строки в виде массива символов
char str1[] = "1. Read the manual carefully.";
char str2[] = "2. Wire all breadboard contents.";
char str3[] = "3. Flash the Iskra Nano board.";
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
}
void loop() {
// Поочерёдно выводим строки на дисплей
// с автопереносом символов на следующую строку
printLCDAutoLine(str1);
delay(PAUSE);
printLCDAutoLine(str2);
delay(PAUSE);
printLCDAutoLine(str3);
delay(PAUSE);
}
// Функция для вывода строки на дисплей
// с автопереносом символов на следующую строку
void printLCDAutoLine(char *str) {
lcd.clear();
lcd.setCursor(0, 0);
for (int i = 0; i < 16 && str[i] != '\0'; i++) {
lcd.print(str[i]);
}
lcd.setCursor(0, 1);
for (int i = 16; i < 32 && str[i] != '\0'; i++) {
lcd.print(str[i]);
}
}
[[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №55. Кастомные символы ====
{{ :arduino:550-schematic.png?nolink&300 |}}
{{ :arduino:550-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём символ динозаврика в двоичной системе BIN
byte dino[8] = {
0b00000, 0b00111, 0b00111, 0b10110,
0b11111, 0b01010, 0b01010, 0b00000
};
// Создаём символ кактуса в двоичной системе BIN
byte cactus[8] = {
0b00100, 0b00101, 0b10101, 0b10101,
0b10111, 0b11100, 0b00100, 0b00000
};
// Создаём символ сердца в двоичной системе BIN
byte heart[8] = {
0b00000, 0b01010, 0b11111, 0b11111,
0b11111, 0b01110, 0b00100, 0b00000
};
// Константы для хранения адресов символов из таблицы знакогенератора
constexpr byte LCD_ICON_DINO = 0x00;
constexpr byte LCD_ICON_CACTUS = 0x01;
constexpr byte LCD_ICON_HEART = 0x02;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Добавляем собственный символы в ячейки знакогенератора
lcd.createChar(LCD_ICON_DINO, dino);
lcd.createChar(LCD_ICON_CACTUS, cactus);
lcd.createChar(LCD_ICON_HEART, heart);
// Выводим на дисплей строки и созданные символы
lcd.setCursor(0, 0);
lcd.print("I ");
lcd.write(LCD_ICON_HEART);
lcd.print(" Arduino! ");
lcd.setCursor(0, 1);
lcd.write(LCD_ICON_DINO);
lcd.setCursor(5, 1);
lcd.write(LCD_ICON_CACTUS);
lcd.setCursor(8, 1);
lcd.write(LCD_ICON_CACTUS);
lcd.setCursor(13, 1);
lcd.print("\x02");
}
void loop() {
}
[[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №56. Бегущий динозаврик ====
{{ :arduino:560-schematic.png?nolink&500 |}}
{{ :arduino:560-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Библиотека для работы с кнопкой
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 7;
// Создаём звуковой шрифт из нот со своими частотами
constexpr int NOTE_B3 = 247;
constexpr int NOTE_C4 = 262;
constexpr int NOTE_D4 = 294;
constexpr int NOTE_E4 = 330;
constexpr int NOTE_F4 = 349;
constexpr int NOTE_G4 = 392;
constexpr int NOTE_A4 = 440;
constexpr int NOTE_B4 = 494;
constexpr int NOTE_C5 = 523;
// Создаём символ динозаврика в двоичной системе BIN
byte dino[8] = {
0b00000, 0b00111, 0b00111, 0b10110,
0b11111, 0b01010, 0b01010, 0b00000
};
// Создаём символ кактуса в двоичной системе BIN
byte cactus[8] = {
0b00100, 0b00101, 0b10101, 0b10101,
0b10111, 0b11100, 0b00100, 0b00000
};
// Назначаем константы с адресами кастомных символов в таблице знакогенератора
constexpr byte LCD_ICON_DINO = 0x00;
constexpr byte LCD_ICON_CACTUS = 0x01;
// Назначаем константы с адресами штатных символов в таблице знакогенератора
constexpr byte LCD_ICON_BLOCK = 0xFF;
constexpr byte LCD_ICON_EMPTY = 0x20;
// Переменные для подсчёта набранных очков и хранения рекордов
int score = 0;
int bestScore = 0;
// Переменная для блокировки очков
bool stateFreezeScore = false;
// Массив игровой области
// Нижняя строка дисплея
char gameArea[16];
// Ячейка дисплея
// динозаврик в прыжке или нет
char gameDinoJump;
long millisLastTime = 0;
long millisLastJump = 0;
// Время зависания динозавра в воздухе
int jumpInterval = 50;
// Скорость прокрутки дисплея
int speedScroller = 300;
// Создаём перечисления состояний игры
enum {
GAME_BEGIN,
GAME_PLAY,
GAME_OVER
} stateGame;
// Создаём объект для работы с кнопкой
TroykaButton button(5);
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Добавляем собственные символы в ячейки знакогенератора
lcd.createChar(LCD_ICON_DINO, dino);
lcd.createChar(LCD_ICON_CACTUS, cactus);
// Инициализируем кнопку
button.begin();
// Задаём зерно генерации случайных чисел
randomSeed(analogRead(A0));
// Устанавливаем режим «Начало игры»
stateGame = GAME_BEGIN;
}
void loop() {
// Если установлен режим «Начало игры»
if (stateGame == GAME_BEGIN) {
// Обнуляем текущий результат
score = 0;
// Очищаем массив игровой зоны
for (int i = 0; i <= 15; i++) {
gameArea[i] = LCD_ICON_EMPTY;
}
// Выводим начальную заставку на дисплей
printGameBegin();
// Выводим приветственную музыку
melodyGameBegin();
// Ожидаем нажатие кнопки для старта
while (!button.isClick()) {
button.read();
}
// Устанавливаем режим «Процесс игры»
stateGame = GAME_PLAY;
// Очищаем дисплей
lcd.clear();
delay(1000);
}
// Если установлен режим «Процесс игры»
if (stateGame == GAME_PLAY) {
// и функция playGame выдаёт ложное значение,
// переходим в режим «Конец игры».
if (playGame() == false) {
stateGame = GAME_OVER;
}
}
// Если установлен режим «Конец игры»
if (stateGame == GAME_OVER) {
// Выводим конечную заставку на дисплей
printGameOver();
// Выводим завершающую музыку
melodyGameOver();
// Ждём нажатия кнопки для повторной игры
while (!button.isClick()) {
button.read();
}
// Заново переходим в режим «Начало игры»
stateGame = GAME_BEGIN;
delay(1000);
}
}
// Функция вывода начальной заставки на экран
void printGameBegin() {
// Очищаем дисплей
lcd.clear();
lcd.setCursor(4, 0);
lcd.print("Dino Game");
lcd.setCursor(3, 1);
lcd.print("Press Start");
// Выводим два барьера по бокам
lcd.setCursor(0, 1);
lcd.write(LCD_ICON_BLOCK);
lcd.setCursor(15, 1);
lcd.write(LCD_ICON_BLOCK);
// Выводим динозаврика
lcd.setCursor(1, 1);
lcd.write(LCD_ICON_DINO);
}
// Функция вывода конечной заставки на экран
void printGameOver() {
// Выводим сообщение «Игра окончена»
lcd.setCursor(4, 1);
lcd.print("Game Over");
delay(1000);
lcd.clear();
// Выводим набранный счёт
lcd.setCursor(4, 0);
lcd.print("Score: ");
lcd.print(score);
// Если счёт превзошёл предыдущий рекорд, обновляем значение рекорда
if (score > bestScore) {
bestScore = score;
}
// Выводим лучший результат игры за все попытки
lcd.setCursor(5, 1);
lcd.print("Best: ");
lcd.print(bestScore);
}
// Функция обработки игрового процесса
bool playGame() {
button.read();
// Запоминаем текущее время
unsigned long millisNowTime = millis();
// Если прошёл заданный интервал
if (millisNowTime - millisLastTime >= speedScroller) {
millisLastTime = millisNowTime;
// Генерируем случайно число от 0 до 10
int randomNumber = random(0, 10);
// Если выпало число 0
if (randomNumber == 0) {
// Выводим препятствие
gameArea[15] = LCD_ICON_CACTUS;
} else {
// В остальных случаях выводим пустоту
gameArea[15] = LCD_ICON_EMPTY;
}
// Сдвигаем игровую область дисплея на шаг влево
for (int i = 0; i <= 15; i++) {
gameArea[i] = gameArea[i + 1];
}
// Если блокировка очков выключена, увеличиваем очки
if (!stateFreezeScore) {
score++;
}
}
// Выводим барьеры
gameArea[0] = LCD_ICON_BLOCK;
gameArea[15] = LCD_ICON_BLOCK;
// Если нажата кнопка
if (button.isPressed()) {
tone(BUZZER_PIN, 1000, 100);
// Включаем динозаврика в прыжке
gameDinoJump = LCD_ICON_DINO;
// Включаем заморозку очков
stateFreezeScore = true;
// Запоминаем текущее время прыжка
millisLastJump = millis();
}
// Если время прыжка истекло и внизу нет препятствия
if (millis() - millisLastJump >= jumpInterval) {
if (gameArea[1] == LCD_ICON_EMPTY ||
gameArea[1] == LCD_ICON_DINO) {
// Возвращаем динозаврика на землю
gameArea[1] = LCD_ICON_DINO;
gameDinoJump = LCD_ICON_EMPTY;
// Выключаем заморозку очков
stateFreezeScore = false;
} else {
return false;
}
}
// Обновляем содержимое на дисплее
updateDataLCD();
return true;
}
// Функция вывода данных на дисплей
void updateDataLCD() {
// Печатаем игровое поле
for (int i = 0; i <= 15; i++) {
lcd.setCursor(i, 1);
lcd.write(gameArea[i]);
}
// Выводим ячейку для прыжка и текущее количество очков
lcd.setCursor(1, 0);
lcd.write(gameDinoJump);
lcd.setCursor(4, 0);
lcd.print("Score: ");
lcd.print(score);
}
// Функция вступительной мелодии
void melodyGameBegin() {
tone(BUZZER_PIN, NOTE_E4, 100);
delay(150);
tone(BUZZER_PIN, NOTE_E4,100);
delay(300);
tone(BUZZER_PIN, NOTE_E4,100);
delay(300);
tone(BUZZER_PIN, NOTE_C4,100);
delay(100);
tone(BUZZER_PIN, NOTE_E4,100);
delay(300);
tone(BUZZER_PIN, NOTE_G4, 100);
delay(550);
tone(BUZZER_PIN, NOTE_C5, 100);
delay(575);
}
// Функция завершающей мелодии
void melodyGameOver() {
for (int i = 0; i <= 2; i++) {
tone(BUZZER_PIN, NOTE_G4, 300);
delay(200);
tone(BUZZER_PIN, NOTE_C4, 300);
delay(200);
}
}
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
* [[https://github.com/amperka/TroykaButton | Библиотека TroykaButton]]
==== №57. Светодиодная лента своими руками ====
{{ :arduino:570-schematic.png?nolink&300 |}}
{{ :arduino:570-wiring-cmyk.png?nolink |}}
==== №58. Сдаём вождение по току ====
{{ :arduino:580-schematic.png?nolink&600 |}}
{{ :arduino:580-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с транзистором,
// который управляет светодиодной лентой
constexpr int PIN_TRANSISTOR_BJT = 2;
void setup() {
// Настраиваем пин с транзистором в режим выхода
pinMode(PIN_TRANSISTOR_BJT, OUTPUT);
}
void loop() {
// Зажигаем ленту
digitalWrite(PIN_TRANSISTOR_BJT, HIGH);
// Ждём 200 мс
delay(200);
// Гасим ленту
digitalWrite(PIN_TRANSISTOR_BJT, LOW);
// Ждём 800 мс
delay(800);
}
==== №59. Волшебное прикосновение ====
{{ :arduino:590-schematic.png?nolink&600 |}}
{{ :arduino:590-wiring-cmyk.png?nolink |}}
==== №60. Сдаём вождение по напряжению ====
{{ :arduino:600-schematic.png?nolink&600 |}}
{{ :arduino:600-wiring-cmyk.png?nolink |}}
// Даём понятное имя пину с транзистором,
// который управляет светодиодной лентой
constexpr int PIN_MOSFET = 2;
void setup() {
// Настраиваем пин с транзистором в режим выхода
pinMode(PIN_MOSFET, OUTPUT);
}
void loop() {
// Зажигаем ленту
digitalWrite(PIN_MOSFET, HIGH);
// Ждём 200 мс
delay(200);
// Гасим ленту
digitalWrite(PIN_MOSFET, LOW);
// Ждём 800 мс
delay(800);
}
==== №61. Саймон говорит ====
{{ :arduino:610-schematic.png?nolink&600 |}}
{{ :arduino:610-wiring-cmyk.png?nolink |}}
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Создаём звуковой шрифт из нот со своими частотами
constexpr int NOTE_C3 = 131;
constexpr int NOTE_D3 = 147;
constexpr int NOTE_E3 = 165;
constexpr int NOTE_F3 = 175;
constexpr int NOTE_G3 = 196;
constexpr int NOTE_A3 = 220;
constexpr int NOTE_B3 = 247;
constexpr int NOTE_C4 = 262;
constexpr int NOTE_D4 = 294;
constexpr int NOTE_E4 = 330;
constexpr int NOTE_F4 = 349;
constexpr int NOTE_G4 = 392;
constexpr int NOTE_A4 = 440;
constexpr int NOTE_B4 = 494;
constexpr int NOTE_C5 = 523;
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 2;
// Даём понятные имена пинам со светодиодами
constexpr int LED_1_PIN = 3;
constexpr int LED_2_PIN = 4;
constexpr int LED_3_PIN = 5;
constexpr int LED_4_PIN = 6;
// Даём понятные имена пинам с кнопками
constexpr int BUTTON_1_PIN = A3;
constexpr int BUTTON_2_PIN = A2;
constexpr int BUTTON_3_PIN = A1;
constexpr int BUTTON_4_PIN = A0;
// Массив нот для мелодии «Начало игры»
constexpr int NOTE_GAME_BEGIN[] = {
NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4,
NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4,
NOTE_E4, NOTE_F4, NOTE_G4
};
// Массив длительности нот для мелодии «Начало игры
constexpr int NOTE_DURATION_GAME_BEGIN[] = {
8, 4, 8, 4, 8, 4, 8, 8, 8, 8, 4, 8, 2
};
// Количество нот в мелодии «Начало игры
constexpr int NOTE_COUNT_GAME_BEGIN = 13;
// Массив нот для мелодии «Выигрыш»
constexpr int NOTE_GAME_WIN[] = {
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5
};
// Массив длительности нот для мелодии «Выигрыш»
constexpr int NOTE_DURATION_GAME_WIN[] = {
8, 8, 8, 4, 8, 4
};
// Количество нот в мелодии «Выигрыш»
constexpr int NOTE_COUNT_GAME_WIN = 6;
// Массив пинов со светодиодами
constexpr int LED_NUMBER[] = {
LED_1_PIN, LED_2_PIN, LED_3_PIN, LED_4_PIN
};
// Массив нот для светодиодов
constexpr int LED_NOTE[] = { NOTE_F3, NOTE_G3, NOTE_A3, NOTE_B3 };
// Массив пинов с кнопками
constexpr int BUTTON_NUMBER[] = {
BUTTON_1_PIN, BUTTON_2_PIN, BUTTON_3_PIN, BUTTON_4_PIN
};
// Количество светодиодов и кнопок в массиве
constexpr int LED_BUTTON_COUNTS = 4;
// Переменные для текущего и лучшего счёта
int score = 0;
int scoreBest = 0;
// Константа максимального счёта
constexpr int SCORE_MAX = 128;
// Массив последовательности случайно сгенерированных комбинаций
int randomArray[SCORE_MAX];
// Массив последовательности нажатия кнопок
int inputArray[SCORE_MAX];
// Создаём перечисления состояний игры
enum {
GAME_BEGIN,
GAME_PLAY,
GAME_OVER
} stateGame;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Назначаем пины светодиодов в режим выхода
// А пины кнопок в режим входа с подтяжкой к питанию
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
pinMode(LED_NUMBER[i], OUTPUT);
pinMode(BUTTON_NUMBER[i], INPUT_PULLUP);
}
// Задаём зерно генерации случайных чисел
randomSeed(analogRead(A6));
// Устанавливаем режим «Начало игры»
stateGame = GAME_BEGIN;
}
void loop() {
// Если установлен режим «Начало игры»
if (stateGame == GAME_BEGIN) {
// Обнуляем текущий результат
score = 0;
// Выводим приветственную заставку на дисплей
printLCDGameBegin();
// Выводим приветственную музыку
playMelodyGameBegin();
// Даём пользователю время на просмотр заставки
delay(1000);
// Очищаем дисплей
lcd.clear();
// Устанавливаем режим «Процесс игры»
stateGame = GAME_PLAY;
}
// Если установлен режим «Процесс игры»
if (stateGame == GAME_PLAY) {
// и функция playGame выдаёт ложное значение,
// переходим в режим «Конец игры».
if (playGame() == false) {
stateGame = GAME_OVER;
}
}
// Если установлен режим «Конец игры»
if (stateGame == GAME_OVER) {
// Выводим конечную заставку на дисплей
printLCDGameOver();
// Выводим завершающую музыку
playMelodyGameOver();
stateGame = GAME_BEGIN;
delay(1000);
}
}
// Функция обработки игрового процесса
bool playGame() {
lcd.setCursor(2, 0);
lcd.print("");
lcd.setCursor(0, 1);
lcd.print("Score:");
while (true) {
// Отображаем на дисплее текущее количество очков
lcd.setCursor(6, 1);
lcd.print(score);
// Зажигаем все светодиоды
ledsSetAll(HIGH);
// Включаем победную мелодию
playMelodyGameWin();
// Гасим все светодиоды
ledsSetAll(LOW);
// Ждём
delay(1000);
// Демонстрируем случайную последовательность светодиодов
generateRandomArray();
// Игра продолжается и счёт увеличивается,
// пока функция readInputArray истинна.
if (readInputArray()) {
score++;
} else {
return false;
}
}
}
// Функция вывода начальной заставки на экран
void printLCDGameBegin() {
// Очищаем дисплей
lcd.clear();
// Выводим текст начальной заставки
lcd.setCursor(2, 0);
lcd.print("");
lcd.setCursor(4, 1);
lcd.print("DIY Game");
}
// Функция вывода конечной заставки на экран
void printLCDGameOver() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Score:");
lcd.print(score);
// Если счёт превзошёл предыдущий рекорд, обновляем значение рекорда
if (score > scoreBest) {
scoreBest = score;
}
// Выводим лучший результат игры за все попытки
lcd.setCursor(0, 0);
lcd.print("Best: ");
lcd.print(scoreBest);
}
// Функция вывода мелодии «Начало игры
void playMelodyGameBegin() {
// Выполняем перебор нот
for (int i = 0; i < NOTE_COUNT_GAME_BEGIN; i++) {
int led = random(0, LED_BUTTON_COUNTS);
// Зажигаем случайно выбранный светодиод
digitalWrite(LED_NUMBER[led], HIGH);
// Играем ноту с определённой длительностью
tone(BUZZER_PIN, NOTE_GAME_BEGIN[i], 1000 / NOTE_DURATION_GAME_BEGIN[i]);
// Делаем задержку для выделения нот в мелодии:
// Длительность текущей ноты плюс 30%
delay((1000 / NOTE_DURATION_GAME_BEGIN[i]) * 1.3);
// Гасим случайно выбранный светодиод
digitalWrite(LED_NUMBER[led], LOW);
}
}
// Функция вывода мелодии «Выигрыш»
void playMelodyGameWin() {
// Выполняем перебор нот
for (int i = 0; i < NOTE_COUNT_GAME_WIN; i++) {
// Играем ноту с определённой длительностью
tone(BUZZER_PIN, NOTE_GAME_WIN[i], 1000 / NOTE_DURATION_GAME_WIN[i]);
// Делаем задержку для выделения нот в мелодии:
// Длительность текущей ноты плюс 30%
delay((1000 / NOTE_DURATION_GAME_WIN[i]) * 1.3);
}
}
// Функция вывода мелодии «Проигрыш»
void playMelodyGameOver() {
for (int i = 0; i <= 2; i++) {
// Зажигаем все светодиоды
ledsSetAll(HIGH);
// Издаём звуковой сигнал
tone(BUZZER_PIN, NOTE_G3, 300);
delay(200);
// Гасим все светодиоды
ledsSetAll(LOW);
// Издаём звуковой сигнал
tone(BUZZER_PIN, NOTE_C3, 300);
delay(200);
}
}
// Функция вывода произвольной комбинации светодиодов
void generateRandomArray() {
// Генерируем случайное число в диапазоне от 0 до 3
randomArray[score] = random(0, LED_BUTTON_COUNTS);
// Зажигаем по очереди всю последовательность светодиодов
for (int scoreNow = 0; scoreNow <= score; scoreNow++) {
ledBeep(randomArray[scoreNow]);
}
}
// Функция считывания угадываемой комбинации кнопок
bool readInputArray() {
int scoreNow = 0;
// Пока количество нажатий на кнопки не превысило количество очков
while (scoreNow <= score) {
// Проверяем каждую кнопку
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
if (!digitalRead(BUTTON_NUMBER[i])) {
// Подаём светодиодный звуковой сигнал нажатой кнопки
ledBeep(i);
// Присваиваем массиву кода кнопок, текущий номер кнопки
inputArray[scoreNow] = i;
delay(250);
// Если текущая нажатая клавиша не совпадает со случайно сгенерированной
if (inputArray[scoreNow] != randomArray[scoreNow]) {
// Функция ложна
return false;
}
scoreNow++;
}
}
}
return true;
}
// Функция включение или отключение всех светодиодов
void ledsSetAll(bool state) {
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
digitalWrite(LED_NUMBER[i], state);
}
}
// Функция светодиодного звукового сигнала
void ledBeep(int led) {
// Зажигаем выбранный светодиод
digitalWrite(LED_NUMBER[led], HIGH);
// Подаём звуковой сигнал зажжённого светодиода
tone(BUZZER_PIN, LED_NOTE[led], 100);
delay(400);
// Гасим выбранный светодиод
digitalWrite(LED_NUMBER[led], LOW);
delay(100);
}
[[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №62. Саймон говорит с сохранением ====
{{ :arduino:620-schematic.png?nolink&600 |}}
{{ :arduino:620-wiring-cmyk.png?nolink |}}
// Библиотека для доступа к энергонезависимой памяти EEPROM
#include
// Библиотека для работы с текстовым дисплеем по шине I²C
#include
// Создаём объект для работы с дисплеем
// В параметрах передаём I²C-адрес дисплея, кол-во строк и символов
LiquidCrystal_I2C lcd(0x38, 16, 2);
// Константа для хранения адреса ячейки в памяти EEPROM
// для сохранения и считывания данных игры
constexpr int EEPROM_ADDRESS = 200;
// Создаём звуковой шрифт из нот со своими частотами
constexpr int NOTE_C3 = 131;
constexpr int NOTE_D3 = 147;
constexpr int NOTE_E3 = 165;
constexpr int NOTE_F3 = 175;
constexpr int NOTE_G3 = 196;
constexpr int NOTE_A3 = 220;
constexpr int NOTE_B3 = 247;
constexpr int NOTE_C4 = 262;
constexpr int NOTE_D4 = 294;
constexpr int NOTE_E4 = 330;
constexpr int NOTE_F4 = 349;
constexpr int NOTE_G4 = 392;
constexpr int NOTE_A4 = 440;
constexpr int NOTE_B4 = 494;
constexpr int NOTE_C5 = 523;
// Даём понятное имя пину с пищалкой
constexpr int BUZZER_PIN = 2;
// Даём понятные имена пинам со светодиодами
constexpr int LED_1_PIN = 3;
constexpr int LED_2_PIN = 4;
constexpr int LED_3_PIN = 5;
constexpr int LED_4_PIN = 6;
// Даём понятные имена пинам с кнопками
constexpr int BUTTON_1_PIN = A3;
constexpr int BUTTON_2_PIN = A2;
constexpr int BUTTON_3_PIN = A1;
constexpr int BUTTON_4_PIN = A0;
// Массив нот для мелодии «Начало игры»
constexpr int NOTE_GAME_BEGIN[] = {
NOTE_C4, NOTE_F4, NOTE_C4, NOTE_F4, NOTE_C4,
NOTE_F4, NOTE_C4, NOTE_F4, NOTE_G4, NOTE_F4,
NOTE_E4, NOTE_F4, NOTE_G4
};
// Массив длительности нот для мелодии «Начало игры
constexpr int NOTE_DURATION_GAME_BEGIN[] = {
8, 4, 8, 4, 8, 4, 8, 8, 8, 8, 4, 8, 2
};
// Количество нот в мелодии «Начало игры
constexpr int NOTE_COUNT_GAME_BEGIN = 13;
// Массив нот для мелодии «Выигрыш»
constexpr int NOTE_GAME_WIN[] = {
NOTE_C4, NOTE_C4, NOTE_G4, NOTE_C5, NOTE_G4, NOTE_C5
};
// Массив длительности нот для мелодии «Выигрыш»
constexpr int NOTE_DURATION_GAME_WIN[] = {
8, 8, 8, 4, 8, 4
};
// Количество нот в мелодии «Выигрыш»
constexpr int NOTE_COUNT_GAME_WIN = 6;
// Массив пинов со светодиодами
constexpr int LED_NUMBER[] = {
LED_1_PIN, LED_2_PIN, LED_3_PIN, LED_4_PIN
};
// Массив нот для светодиодов
constexpr int LED_NOTE[] = { NOTE_F3, NOTE_G3, NOTE_A3, NOTE_B3 };
// Массив пинов с кнопками
constexpr int BUTTON_NUMBER[] = {
BUTTON_1_PIN, BUTTON_2_PIN, BUTTON_3_PIN, BUTTON_4_PIN
};
// Количество светодиодов и кнопок в массиве
constexpr int LED_BUTTON_COUNTS = 4;
// Переменные для текущего и лучшего счёта
int score = 0;
int scoreBest = 0;
// Константа максимального счёта
constexpr int SCORE_MAX = 128;
// Массив последовательности случайно сгенерированных комбинаций
int randomArray[SCORE_MAX];
// Массив последовательности нажатия кнопок
int inputArray[SCORE_MAX];
// Создаём перечисления состояний игры
enum {
GAME_BEGIN,
GAME_PLAY,
GAME_OVER
} stateGame;
void setup() {
// Инициализируем дисплей
lcd.init();
// Включаем подсветку
lcd.backlight();
// Назначаем пины светодиодов в режим выхода
// А пины кнопок в режим входа с подтяжкой к питанию
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
pinMode(LED_NUMBER[i], OUTPUT);
pinMode(BUTTON_NUMBER[i], INPUT_PULLUP);
}
// Задаём зерно генерации случайных чисел
randomSeed(analogRead(A6));
// Считываем лучший результат игры из EEPROM
EEPROM.get(EEPROM_ADDRESS, scoreBest);
// Устанавливаем режим «Начало игры»
stateGame = GAME_BEGIN;
}
void loop() {
// Если установлен режим «Начало игры»
if (stateGame == GAME_BEGIN) {
// Обнуляем текущий результат
score = 0;
// Выводим приветственную заставку на дисплей
printLCDGameBegin();
// Выводим приветственную музыку
playMelodyGameBegin();
// Даём пользователю время на просмотр заставки
delay(1000);
// Очищаем дисплей
lcd.clear();
// Устанавливаем режим «Процесс игры»
stateGame = GAME_PLAY;
}
// Если установлен режим «Процесс игры»
if (stateGame == GAME_PLAY) {
// и функция playGame выдаёт ложное значение,
// переходим в режим «Конец игры».
if (playGame() == false) {
stateGame = GAME_OVER;
}
}
// Если установлен режим «Конец игры»
if (stateGame == GAME_OVER) {
// Выводим конечную заставку на дисплей
printLCDGameOver();
// Выводим завершающую музыку
playMelodyGameOver();
stateGame = GAME_BEGIN;
delay(1000);
}
}
// Функция обработки игрового процесса
bool playGame() {
lcd.setCursor(2, 0);
lcd.print("");
lcd.setCursor(0, 1);
lcd.print("Score:");
while (true) {
// Отображаем на дисплее текущее количество очков
lcd.setCursor(6, 1);
lcd.print(score);
// Зажигаем все светодиоды
ledsSetAll(HIGH);
// Включаем победную мелодию
playMelodyGameWin();
// Гасим все светодиоды
ledsSetAll(LOW);
// Ждём
delay(1000);
// Демонстрируем случайную последовательность светодиодов
generateRandomArray();
// Игра продолжается и счёт увеличивается,
// пока функция readInputArray истинна.
if (readInputArray()) {
score++;
} else {
return false;
}
}
}
// Функция вывода начальной заставки на экран
void printLCDGameBegin() {
// Очищаем дисплей
lcd.clear();
// Выводим текст начальной заставки
lcd.setCursor(2, 0);
lcd.print("");
lcd.setCursor(4, 1);
lcd.print("DIY Game");
}
// Функция вывода конечной заставки на экран
void printLCDGameOver() {
lcd.clear();
lcd.setCursor(0, 1);
lcd.print("Score:");
lcd.print(score);
// Если счёт превзошёл предыдущий рекорд, обновляем значение рекорда
if (score > scoreBest) {
scoreBest = score;
// Сохраняем лучший результат игры в EEPROM
EEPROM.put(EEPROM_ADDRESS, scoreBest);
}
// Выводим лучший результат игры за все попытки
lcd.setCursor(0, 0);
lcd.print("Best: ");
lcd.print(scoreBest);
}
// Функция вывода мелодии «Начало игры
void playMelodyGameBegin() {
// Выполняем перебор нот
for (int i = 0; i < NOTE_COUNT_GAME_BEGIN; i++) {
int led = random(0, LED_BUTTON_COUNTS);
// Зажигаем случайно выбранный светодиод
digitalWrite(LED_NUMBER[led], HIGH);
// Играем ноту с определённой длительностью
tone(BUZZER_PIN, NOTE_GAME_BEGIN[i], 1000 / NOTE_DURATION_GAME_BEGIN[i]);
// Делаем задержку для выделения нот в мелодии:
// Длительность текущей ноты плюс 30%
delay((1000 / NOTE_DURATION_GAME_BEGIN[i]) * 1.3);
// Гасим случайно выбранный светодиод
digitalWrite(LED_NUMBER[led], LOW);
}
}
// Функция вывода мелодии «Выигрыш»
void playMelodyGameWin() {
// Выполняем перебор нот
for (int i = 0; i < NOTE_COUNT_GAME_WIN; i++) {
// Играем ноту с определённой длительностью
tone(BUZZER_PIN, NOTE_GAME_WIN[i], 1000 / NOTE_DURATION_GAME_WIN[i]);
// Делаем задержку для выделения нот в мелодии:
// Длительность текущей ноты плюс 30%
delay((1000 / NOTE_DURATION_GAME_WIN[i]) * 1.3);
}
}
// Функция вывода мелодии «Проигрыш»
void playMelodyGameOver() {
for (int i = 0; i <= 2; i++) {
// Зажигаем все светодиоды
ledsSetAll(HIGH);
// Издаём звуковой сигнал
tone(BUZZER_PIN, NOTE_G3, 300);
delay(200);
// Гасим все светодиоды
ledsSetAll(LOW);
// Издаём звуковой сигнал
tone(BUZZER_PIN, NOTE_C3, 300);
delay(200);
}
}
// Функция вывода произвольной комбинации светодиодов
void generateRandomArray() {
// Генерируем случайное число в диапазоне от 0 до 3
randomArray[score] = random(0, LED_BUTTON_COUNTS);
// Зажигаем по очереди всю последовательность светодиодов
for (int scoreNow = 0; scoreNow <= score; scoreNow++) {
ledBeep(randomArray[scoreNow]);
}
}
// Функция считывания угадываемой комбинации кнопок
bool readInputArray() {
int scoreNow = 0;
// Пока количество нажатий на кнопки не превысило количество очков
while (scoreNow <= score) {
// Проверяем каждую кнопку
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
if (!digitalRead(BUTTON_NUMBER[i])) {
// Подаём светодиодный звуковой сигнал нажатой кнопки
ledBeep(i);
// Присваиваем массиву кода кнопок, текущий номер кнопки
inputArray[scoreNow] = i;
delay(250);
// Если текущая нажатая клавиша не совпадает со случайно сгенерированной
if (inputArray[scoreNow] != randomArray[scoreNow]) {
// Функция ложна
return false;
}
scoreNow++;
}
}
}
return true;
}
// Функция включение или отключение всех светодиодов
void ledsSetAll(bool state) {
for (int i = 0; i < LED_BUTTON_COUNTS; i++) {
digitalWrite(LED_NUMBER[i], state);
}
}
// Функция светодиодного звукового сигнала
void ledBeep(int led) {
// Зажигаем выбранный светодиод
digitalWrite(LED_NUMBER[led], HIGH);
// Подаём звуковой сигнал зажжённого светодиода
tone(BUZZER_PIN, LED_NOTE[led], 100);
delay(400);
// Гасим выбранный светодиод
digitalWrite(LED_NUMBER[led], LOW);
delay(100);
}
* [[https://docs.arduino.cc/learn/built-in-libraries/eeprom | Библиотека EEPROM]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C | Библиотека LiquidCrystal_I2C]]
==== №63. Бегущая тень ====
{{ :arduino:630-schematic.png?nolink&600 |}}
{{ :arduino:630-wiring-cmyk.png?nolink |}}
// Назначаем контакты для связи с выходным сдвиговым регистром
constexpr int LATCH_PIN = 10;
constexpr int DATA_PIN = 11;
constexpr int CLOCK_PIN = 13;
// Переменная для хранения значений восьми светодиодов в битовом виде
byte leds = 0b00000000;
void setup() {
// Настраиваем пины для связи с выходным сдвиговым регистром в режим выхода
pinMode(LATCH_PIN, OUTPUT);
pinMode(DATA_PIN, OUTPUT);
pinMode(CLOCK_PIN, OUTPUT);
}
void loop() {
// Последовательно зажигаем светодиоды через сдвиговый регистр
for (int i = 0; i < 8; i++) {
bitWrite(leds, i, HIGH);
sendData();
delay(100);
}
// Последовательно гасим светодиоды через сдвиговый регистр
for (int i = 0; i < 8; i++) {
bitWrite(leds, i, LOW);
sendData();
delay(100);
}
}
// Функция для переди байта в сдвиговый регистр
// через программный SPI начиная с младшего бита
void sendData() {
digitalWrite(LATCH_PIN, LOW);
shiftOut(DATA_PIN, CLOCK_PIN, LSBFIRST, leds);
digitalWrite(LATCH_PIN, HIGH);
}
==== №64. Бегущая тень по SPI ====
{{ :arduino:640-schematic.png?nolink&600 |}}
{{ :arduino:640-wiring-cmyk.png?nolink |}}
// Библиотека для работы с SPI-устройствами
#include
// Назначаем контакт для защёлки сдвигового регистра
constexpr int LATCH_PIN = 10;
// Переменная для хранения значений восьми светодиодов в битовом виде
byte leds = 0b00000000;
void setup() {
// Инициализируем шину SPI
SPI.begin();
// Инициируем передачу данных по SPI младшим битом вперёд
SPI.setBitOrder(LSBFIRST);
// Назначаем контакт защёлки сдвигового регистра в режим выхода
pinMode(LATCH_PIN, OUTPUT);
}
void loop() {
// Последовательно зажигаем светодиоды через сдвиговый регистр
for (int i = 0; i < 8; i++) {
bitWrite(leds, i, HIGH);
sendData();
delay(100);
}
// Последовательно гасим светодиоды через сдвиговый регистр
for (int i = 0; i < 8; i++) {
bitWrite(leds, i, LOW);
sendData();
delay(100);
}
}
// Функция для переди байта в сдвиговый регистр
// через аппаратный SPI начиная с младшего бита
void sendData() {
digitalWrite(LATCH_PIN, LOW);
SPI.transfer(leds);
digitalWrite(LATCH_PIN, HIGH);
}
[[https://reference.arduino.cc/reference/en/language/functions/communication/spi/ | Библиотека SPI]]
===== Полезные скетчи =====
==== Очистка EEPROM ====
// Библиотека для работы с EEPROM-памятью
#include
// Даём понятное имя встроенном светодиоду
constexpr int LED_PIN = 13;
void setup() {
// Выставляем светодиод в редим выхода
pinMode(LED_PIN, OUTPUT);
// Шасим светодиод
digitalWrite(LED_PIN, LOW);
// прогогняем по очереди все ячейки EEPROM-памяти
for (int i = 0; i < EEPROM.length(); i++) {
// Заполняем каждую ячейку значением 0xFF
EEPROM.write(i, 0xFF);
}
// После очистки памяти, зажигаем светодиод
digitalWrite(LED_PIN, HIGH);
}
void loop() {
}
==== Чтение EEPROM ====
// Библиотека для работы с EEPROM-памятью
#include
void setup() {
// Открываем Serial-порт
Serial.begin(9600);
// Прогогняем по очереди все ячейки EEPROM-памяти
for (int i = 0; i < EEPROM.length(); i++) {
// Считываем каждую ячейку памяти
Serial.print(i);
Serial.print("\t");
Serial.println(EEPROM.read(i));
}
}
void loop() {
}
===== Ресурсы =====
* Набор «[[amp>product/arduino-8-bit-academy-kit?utm_source=man&utm_campaign=arduino-8-bit-academy-kit&utm_medium=wiki|Arduino. Восьмибитная академия]]» в магазине.
==== Софт ====
* [[amp>page/arduino-ide?utm_source=announce&utm_campaign=arduino&utm_medium=wiki |Страница загрузки Arduino IDE]]
* [[https://maxpromer.github.io/LCD-Character-Creator/|Онлайн-редактор символов для текстовых дисплеев]]
==== Библиотеки ====
* [[https://github.com/amperka/TroykaThermometer|TroykaThermometer]]
* [[https://github.com/amperka/TroykaButton|TroykaButton]]
* [[https://github.com/amperka/TroykaLight|TroykaLight]]
* [[https://www.arduino.cc/reference/en/libraries/liquidcrystal/|LiquidCrystal]]
* [[https://github.com/johnrickman/LiquidCrystal_I2C|LiquidCrystal_I2C]]
* [[https://docs.arduino.cc/learn/built-in-libraries/eeprom|EEPROM]]
* [[https://reference.arduino.cc/reference/en/language/functions/communication/serial/|Serial]]
* [[https://reference.arduino.cc/reference/en/language/functions/communication/wire/|Wire]]
* [[https://reference.arduino.cc/reference/en/language/functions/communication/spi/|SPI]]
==== Datasheet ====
* {{ :arduino:atmega328p-datasheet.pdf |Datasheet на микроконтроллер ATmega328P}}
* {{ :arduino:mt-16s2h-i-datasheet.pdf |Datasheet на текстовый дисплей 16×2 (I²C)}}
* {{ :arduino:tmp36-datasheet.pdf |Datasheet на датчик температуры TMP36}}
* {{ :arduino:gl5528-datasheet.pdf |Datasheet на фоторезистор GL5528}}
* {{ :arduino:bc337-datasheet.pdf |Datasheet на биполярный транзистор BJT BC337}}
* {{ :arduino:irf530n-datasheet.pdf |Datasheet на полевой транзистор MOSFET IRF530N}}
* {{ :arduino:sn74hc595-datasheet.pdf |Datasheet на выходной сдвиговый регистр 74HC595}}