====== Электронное приложение к набору «IO.KIT Сонар» ======
На этой странице ты найдёшь все нужные материалы для сборки мини-проектов набора [[amp>product/io-kit-sonar?utm_source=man&utm_campaign=io-kit-clock&utm_medium=wiki|Сонар]] из серии [[amp>collection/io-kits?utm_source=man&utm_campaign=io-kit-clock&utm_medium=wiki|IO.KIT]]:
* Схемы проектов в электронном виде.
* Исходный код программ (копируй его в редактор Arduino IDE).
* Дополнительные материалы: программные библиотеки, даташиты и т. п.
**Обрати внимание**
Для сборки и функционирования сонара тебе понадобится [[amp>product/io-kit-basic?utm_source=man&utm_campaign=io-kit-sonar&utm_medium=wiki|IO.KIT Базовый]]!
===== Проекты =====
Прежде чем приступать к экспериментам, нужно подготовить свой компьютер:
* Установи среду программирования [[https://amperka.ru/page/arduino-ide?utm_source=announce&utm_campaign=io-kit-sonar&utm_medium=wiki|Arduino IDE]] и копируй туда готовый код проектов.
* Установи [[#библиотеки|дополнительные библиотеки]] для Arduino IDE, пользуясь [[программирование:библиотеки|нашим руководством]].
**Драйвер чипа CH340**
Установи [[articles:driver-ch340|драйвер CH340 для Windows]] или [[projects:installing-the-ch340-on-linux|Linux]], чтобы твой компьютер мог корректно распознать и прошить плату Iskra Nano.
==== №1. Счётчик чисел ====
{{ :kits:io-kit:sonar:010-drawing-wiring-cmyk.png?nolink&500 |}}
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект матрицы
TroykaLedMatrix matrix;
void setup() {
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем шрифт
matrix.selectFont(FONT_8X8_BASIC);
}
void loop() {
// Перечисляем символы от 0 до 9
for (char i = '0'; i <= '9'; i++) {
// Выводим текущий символ на матрицу
matrix.drawSymbol(i);
// Ждём 500 мс
delay(500);
}
}
==== №2. Бегущая строка ====
{{ :kits:io-kit:sonar:020-drawing-wiring-cmyk.png?nolink&500 |}}
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект матрицы
TroykaLedMatrix matrix;
// Создаём массив с текстом для бегущей строки
char str[] = " Amperka";
// Вычисляем длину массива
constexpr int LEN_STR = sizeof(str);
// Создаём переменную для хранения смещение бегущей строги
uint8_t shift = 0;
void setup() {
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем шрифт
matrix.selectFont(FONT_8X8_BASIC);
}
void loop() {
// Печатаем текст бегущей строкой
matrix.marqueeText(str, LEN_STR, shift++);
// Если смещение строки достигло конца
if (shift == LEN_STR * 8) {
// Обнуляем смещение строки
shift = 0;
}
// Ждём 75 мс
delay(75);
}
==== №3. Дыхание Амперки ====
{{ :kits:io-kit:sonar:030-drawing-wiring-cmyk.png?nolink&500 |}}
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект матрицы
TroykaLedMatrix matrix;
// Даём понятное имя пину A2 с потенциометром
constexpr int POT_PIN = A2;
// Создаём иконку лого Амперки в двоичной системе BIN
const uint8_t amperka[] {
0b00011000,
0b00100100,
0b10011001,
0b01000010,
0b10011001,
0b10011001,
0b01000010,
0b00111100
};
// Создаём иконку сердца в двоичной системе BIN
const uint8_t heart[] {
0b00000000,
0b01100110,
0b11111111,
0b11111111,
0b11111111,
0b01111110,
0b00111100,
0b00011000
};
// Создаём иконку смайлика в двоичной системе BIN
const uint8_t smile[] {
0b00111100,
0b01000010,
0b10100101,
0b10000001,
0b10100101,
0b10011001,
0b01000010,
0b00111100
};
void setup() {
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем ориентацию матрицы на 0 градусов (по умолчанию)
matrix.setRotation(ROTATION_0);
// Отображаем на матрице лого Амперки
matrix.drawBitmap(amperka);
}
void loop() {
// Считываем значение с потенциометра
int brightness = readPot(POT_PIN);
// Отражаем показания с потенциометра на яркости матрице
updateBrightnessMatrix(brightness);
}
// Функция считывания показаний с потенциометра
int readPot(int pin) {
// Создаём переменную для хранения
// аналогового сигнала с потенциометра в отчётах АЦП
int sensorADC = 0;
// Создаём переменную для хранения
// преобразованных показаний с потенциометра
int sensorValue = 0;
// Считываем аналоговый сигнал с потенциометра
sensorADC = analogRead(pin);
// Преобразуем диапазон значений с потенциометра [0;1023]
// в диапазон значений для выбора яркости матрицы [0;9]
sensorValue = map(sensorADC, 0, 1023, 0, 9);
// Возвращаем полученное значение
return sensorValue;
}
// Функция обновления яркости матрицы
void updateBrightnessMatrix(int value) {
switch (value) {
case 0: matrix.setCurrentLimit(ROW_CURRENT_05MA); break;
case 1: matrix.setCurrentLimit(ROW_CURRENT_10MA); break;
case 2: matrix.setCurrentLimit(ROW_CURRENT_15MA); break;
case 3: matrix.setCurrentLimit(ROW_CURRENT_20MA); break;
case 4: matrix.setCurrentLimit(ROW_CURRENT_25MA); break;
case 5: matrix.setCurrentLimit(ROW_CURRENT_30MA); break;
case 6: matrix.setCurrentLimit(ROW_CURRENT_35MA); break;
case 7: matrix.setCurrentLimit(ROW_CURRENT_40MA); break;
case 8: matrix.setCurrentLimit(ROW_CURRENT_45MA); break;
case 9: matrix.setCurrentLimit(ROW_CURRENT_50MA); break;
}
}
==== №4. Управление углом ====
{{ :kits:io-kit:sonar:040-drawing-wiring-cmyk.png?nolink&550 |}}
// Подключаем библиотеку для работы с сервоприводом
#include
// Создаём объект сервопривода
Servo servo;
// Даём понятное имя пину 5 с сервоприводом
constexpr uint8_t SERVO_PIN = 5;
// Задаём минимальный и максимальный угол поворота сервопривода
constexpr uint8_t MIN_ANGLE = 0;
constexpr uint8_t MAX_ANGLE = 180;
// Вычисляем средний угол сервопривода
constexpr uint8_t MID_ANGLE = (MIN_ANGLE + MAX_ANGLE) / 2;
void setup() {
// Подключаем сервомотор
servo.attach(SERVO_PIN);
}
void loop() {
// Устанавливаем вал сервопривода в минимальный угол
servo.write(MIN_ANGLE);
// Ждём 1 секунду
delay(1000);
// Устанавливаем вал сервопривода в среднее положение
servo.write(MID_ANGLE);
// Ждём 1 секунду
delay(1000);
// Устанавливаем вал сервопривода в максимальный угол
servo.write(MAX_ANGLE);
// Ждём 1 секунду
delay(1000);
// Устанавливаем вал сервопривода в среднее положение
servo.write(MID_ANGLE);
// Ждём 1 секунду
delay(1000);
}
==== №5. Штурвал ====
{{ :kits:io-kit:sonar:050-drawing-wiring-cmyk.png?nolink&700 |}}
// Подключаем библиотеку для работы с сервоприводом
#include
// Создаём объект сервопривода
Servo servo;
// Даём понятное имя пину 5 с сервоприводом
constexpr uint8_t SERVO_PIN = 5;
// Даём понятное имя пину A2 с потенциометром
constexpr uint8_t POT_PIN = A2;
void setup() {
// Настраиваем пин с потенциометром в режим входа
pinMode(POT_PIN, INPUT);
// Подключаем сервомотор
servo.attach(SERVO_PIN);
}
void loop() {
// Считываем аналоговый сигнал с потенциометра
int rotation = analogRead(POT_PIN);
// Преобразуем диапазон значений с потенциометра [0;1023]
// в диапазон значений для угла вала сервопривода [0;180]
int position = map(rotation, 0, 1023, 0, 180);
// Выдаём результат на сервопривод
servo.write(position);
}
==== №6. Замок ====
{{ :kits:io-kit:sonar:060-drawing-wiring-cmyk.png?nolink&700 |}}
// Подключаем библиотеку для работы с сервоприводом
#include
// Подключаем библиотеку для работы с кнопкой
#include
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект сервопривода
Servo servo;
// Создаём объект кнопки на пине A2
TroykaButton button(A2);
// Создаём объект матрицы
TroykaLedMatrix matrix;
// Даём понятное имя пину 5 с сервоприводом
constexpr uint8_t SERVO_PIN = 5;
// Задаём минимальный и максимальный угол поворота сервопривода
constexpr uint8_t MIN_ANGLE = 0;
constexpr uint8_t MAX_ANGLE = 180;
// Создаём переменную для хранения состояние замка
bool lockState;
// Создаём иконку закрытого замка в двоичной системе BIN
const uint8_t lockClosed[] {
0b00110000,
0b01001000,
0b01001000,
0b11111100,
0b10000100,
0b10000100,
0b10000100,
0b11111100
};
// Создаём иконку открытого замка в двоичной системе BIN
const uint8_t lockOpen[] {
0b00000110,
0b00001001,
0b00001001,
0b11111100,
0b10000100,
0b10000100,
0b10000100,
0b11111100
};
void setup() {
// Подключаем сервомотор
servo.attach(SERVO_PIN);
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем состояние открытого замка
lockState = true;
// Отображаем на матрице иконку открытого замка
matrix.drawBitmap(lockOpen);
// Устанавливаем вал сервопривода в минимальный угол
servo.write(MIN_ANGLE);
}
void loop() {
// Считываем состояние с кнопки
button.read();
// Определяем нажатие кнопки
if (button.justPressed()) {
// Если замок открыт
if (lockState) {
// Устанавливаем вал сервопривода в максимальный угол
servo.write(MAX_ANGLE);
// Отображаем на матрице иконку закрытого замка
matrix.drawBitmap(lockClosed);
} else {
// Устанавливаем вал сервопривода в минимальный угол
servo.write(MIN_ANGLE);
// Отображаем на матрице иконку открытого замка
matrix.drawBitmap(lockOpen);
}
// Инвертируем переменную состояние замка
lockState = !lockState;
}
}
==== №7. Консольный дальномер ====
{{ :kits:io-kit:sonar:070-drawing-wiring-cmyk.png?nolink&550 |}}
// Подключаем библиотеку для работы с дальномером
#include
// Создаём объект дальномера
EasyUltrasonic distSensor;
// Даём понятные имена пинам дальномера TRIG и ECHO
constexpr uint8_t TRIG_PIN = 11;
constexpr uint8_t ECHO_PIN = 10;
void setup() {
// Открываем монитор Serial-порта
Serial.begin(9600);
// Инициализируем дальномер
distSensor.attach(TRIG_PIN, ECHO_PIN);
}
void loop() {
// Считываем расстояние до объекта в см
float distance = distSensor.getDistanceCM();
// Выводим результат в консоль
Serial.print(distance);
Serial.println(" cm");
// Ждём 100 мс
delay(100);
}
==== №8. Графический дальномер ====
{{ :kits:io-kit:sonar:080-drawing-wiring-cmyk.png?nolink&700 |}}
// Подключаем библиотеку для работы с дальномером
#include
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект дальномера
EasyUltrasonic distSensor;
// Создаём объект матрицы
TroykaLedMatrix matrix;
// Даём понятное имя пину A2 с пищалкой
constexpr uint8_t BUZZER_PIN = A2;
// Даём понятные имена пинам дальномера TRIG и ECHO
constexpr uint8_t TRIG_PIN = 11;
constexpr uint8_t ECHO_PIN = 10;
// Задаём минимальное и максимальное детектируемое расстояние дальномера в см
constexpr uint8_t MIN_DIST = 5;
constexpr uint8_t MAX_DIST = 30;
// Создаём константу для хранения паузы между кадрами анимации
constexpr int DELAY_FRAME = 500;
// Создаём константу для хранения тригера сигнализации в см
constexpr int ALARM_DIST = 30;
// Создаём массив для хранения расстояния до объекта в матричном представлении
byte distMatrix[8];
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Инициализируем дальномер
distSensor.attach(TRIG_PIN, ECHO_PIN, MIN_DIST, MAX_DIST);
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем ориентацию матрицы на 90 градусов
matrix.setRotation(ROTATION_90);
}
void loop() {
// Считываем расстояние до объекта в см
int dist = distSensor.getDistanceCM();
// Преобразуем диапазон значений с дальномера [MIN_DIST;MAX_DIST]
// в графический диапазон значений для столбца матрицы от 0 до 8 точек
distMatrix[0] = matrix.map(dist, MIN_DIST, MAX_DIST);
// Отображаем все столбцы на матрице
matrix.drawBitmap(distMatrix);
// Обновляем звуковую сигнализацию
updateAlarm(dist);
// Сдвигаем кадр на один столбец
shiftMatrixImage();
// Ждём 500 мс
delay(DELAY_FRAME);
}
// Функция сдвига кадра по столбцам
void shiftMatrixImage() {
for (int i = 7; i > 0; i--) {
distMatrix[i] = distMatrix[i - 1];
}
}
// Функция обновления звуковой сигнализации
void updateAlarm(int dist) {
// Если текущее расстояние до препятствия меньше тригера
if (dist < ALARM_DIST) {
// Включаем звуковую сигнализацию
tone(BUZZER_PIN, 1000, 100);
} else {
// Выключаем звуковую сигнализацию
noTone(BUZZER_PIN);
}
}
==== №9 Сонар ====
{{ :kits:io-kit:sonar:090-drawing-wiring-cmyk.png?nolink&700 |}}
// Подключаем библиотеку для работы с дальномером
#include
// Подключаем библиотеку для работы с сервоприводом
#include
// Подключаем библиотеку для работы со светодиодной матрицей
#include
// Создаём объект дальномера
EasyUltrasonic distSensor;
// Создаём объект сервопривода
Servo servo;
// Создаём объект матрицы
TroykaLedMatrix matrix;
// Даём понятное имя пину A2 с пищалкой
constexpr uint8_t BUZZER_PIN = A2;
// Даём понятные имена пинам дальномера TRIG и ECHO
constexpr uint8_t TRIG_PIN = 11;
constexpr uint8_t ECHO_PIN = 10;
// Даём понятное имя пину 5 с сервоприводом
constexpr uint8_t SERVO_PIN = 5;
// Задаём минимальный и максимальный угол поворота сервопривода
constexpr uint8_t MIN_ANGLE = 0;
constexpr uint8_t MAX_ANGLE = 180;
// Вычисляем количество градусов в каждом секторе,
// делим диапазон угла сервопривода на 8 равных секторов
constexpr uint8_t STEP_ANGLE = (MAX_ANGLE - MIN_ANGLE) / 7;
// Задаём минимальное и максимальное детектируемое расстояние дальномера в см
constexpr uint8_t MIN_DIST = 5;
constexpr uint8_t MAX_DIST = 30;
// Создаём константу для хранения тригера сигнализации в см
constexpr int ALARM_DIST = 30;
// Создаём константу для хранения паузы между поворотом вала сервопривода
constexpr int DELAY_SWEEP = 50;
// Создаём массив для хранения расстояния до объекта в матричном представлении
byte distMatrix[8];
void setup() {
// Настраиваем пин с пищалкой в режим выхода
pinMode(BUZZER_PIN, OUTPUT);
// Инициализируем дальномер
distSensor.attach(TRIG_PIN, ECHO_PIN, MIN_DIST, MAX_DIST);
// Подключаем сервомотор
servo.attach(SERVO_PIN);
// Инициализируем матрицу
matrix.begin();
// Очищаем матрицу
matrix.clear();
// Устанавливаем ориентацию матрицы на 90 градусов
matrix.setRotation(ROTATION_90);
}
void loop() {
// Перебираем значения угла сервопривода от min до max
for (int angle = MIN_ANGLE; angle <= MAX_ANGLE; angle++) {
// Вызываем функцию обновления состояние сонара
updateSonar(angle);
}
// Перебираем значения угла сервопривода от max до min
for (int angle = MAX_ANGLE; angle >= MIN_ANGLE; angle--) {
// Вызываем функцию обновления состояние сонара
updateSonar(angle);
}
}
// Функция обновления состояния сонара
void updateSonar(int angle) {
// Отправляем текущий угол на сервопривод
servo.write(angle);
// Выжидаем паузу
delay(DELAY_SWEEP);
// Если вал мотора достиг нового сектора
if (angle % STEP_ANGLE == 0) {
// Вычисляем номер сектора от 0 до 7
int colMatrix = angle / STEP_ANGLE;
// Считываем расстояние до объекта в см
int dist = distSensor.getDistanceCM();
// Преобразуем диапазон значений с дальномера [MIN_DIST;MAX_DIST]
// в графический диапазон значений для столбца матрицы от 0 до 8 точек
distMatrix[colMatrix] = matrix.map(dist, MIN_DIST, MAX_DIST);
// Отображаем все столбцы на матрице
matrix.drawBitmap(distMatrix);
// Обновляем звуковую сигнализацию
updateAlarm(dist);
}
}
// Функция обновления звуковой сигнализации
void updateAlarm(int dist) {
// Если текущее расстояние до препятствия меньше тригера
if (dist < ALARM_DIST) {
// Включаем звуковую сигнализацию
tone(BUZZER_PIN, 1000, 100);
} else {
// Выключаем звуковую сигнализацию
noTone(BUZZER_PIN);
}
}
===== Ресурсы =====
* [[amp>collection/io-kits?utm_source=man&utm_campaign=io-kit-sonar&utm_medium=wiki|Наборы IO.KIT]] в магазине
* [[kits:io-kit|Электронные материалы IO.KIT]]
==== Софт ====
* [[amp>page/arduino-ide?utm_source=announce&utm_campaign=io-kit-sonar&utm_medium=wiki|Страница загрузки Arduino IDE]]
==== Библиотеки ====
* [[https://github.com/SpulberGeorge/EasyUltrasonic|EasyUltrasonic]]
* [[https://www.arduino.cc/reference/en/libraries/servo/|Servo]]
* [[https://github.com/amperka/TroykaLedMatrix/|TroykaLedMatrix]]
* [[https://xantorohara.github.io/led-matrix-editor/|Редактор изображений для LED-матрицы]]