Электронное приложение к набору «IO.KIT Робот Ампи: Шасси»
На этой странице ты найдёшь все нужные материалы для проектов набора Робот Ампи: Шасси из серии IO.KIT:
- Схему подключения модулей.
- Исходный код программ (копируй его в редактор Arduino IDE).
- Дополнительные материалы: программные библиотеки, даташиты и т. п.
Обрати внимание
Для сборки и функционирования шасси робота Ампи тебе понадобится IO.KIT Базовый!
Схема
Проекты
Прежде чем приступать к экспериментам, нужно подготовить свой компьютер:
- Установи среду программирования Arduino IDE и копируй туда готовый код проектов.
- Установи дополнительные библиотеки для Arduino IDE, пользуясь нашим руководством.
Драйвер чипа CH340
Установи драйвер CH340 для Windows или Linux, чтобы твой компьютер мог корректно распознать и прошить плату Iskra Nano.
№1. Техосмотр
Переверни шасси робота Ампи на спину колёсами вверх и протестируй сервоприводы.
- Testing.ino
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 100;
- // Создаём объекты для работы с левым и правым сервомотором
- Servo servoL;
- Servo servoR;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Задаём плавно максимальную скорость вперёд
- motorsDrive(100, 100);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(DELAY_STOP);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- } else if (speedL < 0) {
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- } else if (speedR < 0) {
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
№2. Движение волной
Запусти движение шасси вперёд и назад с остановками на отдых.
- Drive.ino
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Создаём объекты для работы с левым и правым сервомотором
- Servo servoL;
- Servo servoR;
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 100;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Задаём плавно максимальную скорость вперёд
- motorsDrive(100, 100);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(DELAY_STOP);
- // Задаём плавно максимальную скорость назад
- motorsDrive(-100, -100);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(DELAY_STOP);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- } else if (speedL < 0) {
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- } else if (speedR < 0) {
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
№3. Калибровка моторов
Научи шасси робота Ампи держать ровный курс.
- DriveCalibration.ino
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Создаём объекты для работы с левым и правым сервомотором
- Servo servoL;
- Servo servoR;
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- // Определите в какую сторону клонит робота
- // Отклонение вправо: левый мотор быстрее правого.
- // Увеличивайте константу SPEED_FACTOR_L до тех пор, пока движение не выровняется
- // Отклонение влево: правый мотор быстрее левого.
- // Увеличивайте константу SPEED_FACTOR_R до тех пор, пока движение не выровняется
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Задаём плавно максимальную скорость вперёд
- motorsDrive(100, 100);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(DELAY_STOP);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
№4. Змейка
Запусти движение шасси змейкой с возможностью настройки траектории.
- Snake.ino
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Создаём объекты для работы с левым и правым сервомотором
- Servo servoL;
- Servo servoR;
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 500;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Задаём на скорости поворот влево
- motorsDrive(20, 100);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- // Задаём на скорости поворот вправо
- motorsDrive(100, 20);
- // Ждём интервал задержки езды
- delay(DELAY_DRIVE);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
№5. Консольный дальномер
Активируй дальномер и считай расстояние до препятствия в консоль.
- LidarConsole.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- void setup() {
- // Открываем монитор Serial-порта
- Serial.begin(9600);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Выводим результат в консоль
- Serial.print(distance);
- Serial.println(" cm");
- // Ждём 100 мс
- delay(100);
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
№6. Часовой
Пусть шасси робота Ампи несёт дозор и активирует сирену при виде постороннего объекта.
- Security.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Создаём константы для хранения минимальной и максимальной частоты в Гц
- constexpr int MIN_FREQUENCY = 634;
- constexpr int MAX_FREQUENCY = 912;
- // Создаём константы для задержки ноты и паузы в мс
- constexpr int DELAY_NOTE = 7;
- constexpr int DELAY_PAUSE = 500;
- // Создаём константу для хранения тригера сигнализации в см
- constexpr int DISTANCE_ALARM = 10;
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний
- delay(10);
- // Если текущее расстояние до препятствия меньше тригера
- if (distance < DISTANCE_ALARM) {
- // Включаем звуковую сигнализацию
- melodyAlarm();
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
- // Функция звуковой сигнализации
- void melodyAlarm() {
- // Создаём константу для хранения текущей частоты
- int frequency;
- // Медленно восходящий тон
- for (frequency = MIN_FREQUENCY; frequency <= MAX_FREQUENCY; frequency++) {
- tone(BUZZER_PIN, frequency);
- delay(DELAY_NOTE);
- }
- // Медленно нисходящий тон
- for (frequency = MAX_FREQUENCY; frequency >= MIN_FREQUENCY; frequency--) {
- tone(BUZZER_PIN, frequency);
- delay(DELAY_NOTE);
- }
- // Пауза
- noTone(BUZZER_PIN);
- delay(DELAY_PAUSE);
- // Серия быстро восходящих и нисходящих тонов
- for (int count = 0; count < 10; count++) {
- for (frequency = MIN_FREQUENCY; frequency <= MAX_FREQUENCY; frequency++) {
- tone(BUZZER_PIN, frequency);
- delayMicroseconds(50);
- }
- for (frequency = MAX_FREQUENCY; frequency >= MIN_FREQUENCY; frequency--) {
- tone(BUZZER_PIN, frequency);
- delayMicroseconds(50);
- }
- }
- // Пауза
- noTone(BUZZER_PIN);
- delay(DELAY_PAUSE);
- // Серия повторяющего тона
- for (int count = 0; count < 3; count++) {
- tone(BUZZER_PIN, (MIN_FREQUENCY + MAX_FREQUENCY) / 6, 300);
- delay(DELAY_NOTE * 75);
- }
- // Пауза
- noTone(BUZZER_PIN);
- delay(DELAY_PAUSE);
- }
№7. Препятствие, стоп!
Научи шасси робота Ампи останавливаться перед препятствиями.
- Obstacle.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Создаём константу для хранения базовой частоты
- constexpr int FREQUENCY = 2000;
- // Создаём константы для хранения минимальной и максимальной частоты
- constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY);
- constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY);
- // Создаём константу для хранения тригера сигнализации в см
- constexpr int DISTANCE_DETOUR = 20;
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- // Создаём объект для работы с сервомоторами
- Servo servoL;
- Servo servoR;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Передаём случайное число с пина A1
- // для последующей генерации случайных чисел
- randomSeed(analogRead(A1));
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Задаём максимальную скорость вперёд
- motorsDrive(100, 100, false);
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний с дальномера
- delay(10);
- // Если текущее расстояние до препятствия меньше тригера
- if (distance < DISTANCE_DETOUR) {
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Запускаем мелодию R2-D2
- melodyR2D2();
- // Замораживаем программу
- while (1)
- ;
- }
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
- // Функция мелодии R2-D2
- void melodyR2D2() {
- // Вызываем функцию генератора последовательных длинных семплов
- toneLongSamples();
- // Вызываем функцию генератора непоследовательных коротких семплов
- toneShortSamples();
- }
- // Функция генерации последовательных длинных семплов
- void toneLongSamples() {
- // Генерируем случайное количество семплов от 1 до 6
- int countSamples = random(1, 7);
- // Перебираем нумерацию семплов в цикле
- for (int i = 0; i < countSamples; i++) {
- // Генерируем случайное число: true или false
- bool typeSamples = random(0, 2);
- // Если тип семпла true
- if (typeSamples) {
- // Вызываем функцию генерации тона toneSlowDownFastUp:
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- toneSlowDownFastUp();
- } else {
- // Если тип семпла false
- // Вызываем функцию генерации тона toneSlowUpFastDown:
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- toneSlowUpFastDown();
- }
- }
- }
- // Функция генерации непоследовательных коротких семплов
- void toneShortSamples() {
- // Генерируем случайное количество семплов от 3 до 9
- int countSamples = random(3, 10);
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- for (int i = 0; i <= countSamples; i++) {
- // Генерируем случайный интервал на базе FREQUENCY
- int range = random(-FREQUENCY, FREQUENCY);
- tone(BUZZER_PIN, frequency + range);
- // Выполняем случайную задержку от 70 до 170 мс
- delay(random(70, 170));
- // Выключаем звук
- noTone(BUZZER_PIN);
- // Выполняем случайную задержку от 0 до 30 мс
- delay(random(0, 30));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- void toneSlowDownFastUp() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый повышающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, frequency + (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- void toneSlowUpFastDown() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный возрастающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
№8. Препятствие, поворот, поехали!
Научи шасси робота Ампи по-умному огибать препятствия.
- ObstacleAvoidance.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Создаём константу для хранения базовой частоты
- constexpr int FREQUENCY = 2000;
- // Создаём константы для хранения минимальной и максимальной частоты
- constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY);
- constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY);
- // Создаём константу для хранения тригера сигнализации в см
- constexpr int DISTANCE_DETOUR = 20;
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- // Создаём объект для работы с сервомоторами
- Servo servoL;
- Servo servoR;
- // Создаём перечисление состояний робота с соответствующей переменной
- enum {
- ROBOT_DRIVE, // Робот едет вперёд
- ROBOT_DETECT_DETOUR, // Робот зафиксировал препятствие
- } robotState;
- // Создаём перечисление направления движения робота с соответствующей переменной
- enum DirectionDetours {
- LEFT,
- RIGHT,
- } direction;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Передаём случайное число с пина A1
- // для последующей генерации случайных чисел
- randomSeed(analogRead(A1));
- // Включаем стартовую мелодию
- melodyStart();
- // Устанавливаем режим «Робот едет вперёд»
- robotState = ROBOT_DRIVE;
- }
- void loop() {
- // Если установлен режим «Робот едет вперёд»
- if (robotState == ROBOT_DRIVE) {
- // Переходим в функцию обработки режима «Робот едет вперёд»
- handleRobotDrive();
- }
- // Если установлен режим «Робот зафиксировал препятствие»
- if (robotState == ROBOT_DETECT_DETOUR) {
- // Переходим в функцию обработки режима «Робот зафиксировал препятствие»
- handleRobotDetectDetour();
- }
- }
- // Функция обработки режима «Робот едет вперёд»
- void handleRobotDrive() {
- // Задаём максимальную скорость вперёд
- motorsDrive(100, 100, false);
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний с дальномера
- delay(10);
- // Если текущее расстояние до препятствия меньше тригера
- if (distance < DISTANCE_DETOUR) {
- // Устанавливаем режим «Робот зафиксировал препятствие»
- robotState = ROBOT_DETECT_DETOUR;
- }
- }
- // Функция обработки режима «Робот зафиксировал препятствие»
- void handleRobotDetectDetour() {
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Запускаем мелодию R2-D2
- melodyR2D2();
- // Ждём 1 сек
- delay(1000);
- // Объезжаем препятствие слева 500 мс
- motorsDetourBarrier(LEFT, 500);
- // Устанавливаем режим «Робот едет вперёд»
- robotState = ROBOT_DRIVE;
- }
- // Функция объезда препятствие
- void motorsDetourBarrier(DirectionDetours direction, int delayDrive) {
- // Выбираем направления заднего хода для разворота
- if (direction == LEFT) {
- motorsDrive(-50, 0, false);
- } else if (direction == RIGHT) {
- motorsDrive(0, -50, false);
- }
- // Ждём интервал задержки езды
- delay(delayDrive);
- // Останавливаем сервомоторы с плавным торможением
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(1000);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
- // Функция мелодии R2-D2
- void melodyR2D2() {
- // Вызываем функцию генератора последовательных длинных семплов
- toneLongSamples();
- // Вызываем функцию генератора непоследовательных коротких семплов
- toneShortSamples();
- }
- // Функция генерации последовательных длинных семплов
- void toneLongSamples() {
- // Генерируем случайное количество семплов от 1 до 6
- int countSamples = random(1, 7);
- // Перебираем нумерацию семплов в цикле
- for (int i = 0; i < countSamples; i++) {
- // Генерируем случайное число: true или false
- bool typeSamples = random(0, 2);
- // Если тип семпла true
- if (typeSamples) {
- // Вызываем функцию генерации тона toneSlowDownFastUp:
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- toneSlowDownFastUp();
- } else {
- // Если тип семпла false
- // Вызываем функцию генерации тона toneSlowUpFastDown:
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- toneSlowUpFastDown();
- }
- }
- }
- // Функция генерации непоследовательных коротких семплов
- void toneShortSamples() {
- // Генерируем случайное количество семплов от 3 до 9
- int countSamples = random(3, 10);
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- for (int i = 0; i <= countSamples; i++) {
- // Генерируем случайный интервал на базе FREQUENCY
- int range = random(-FREQUENCY, FREQUENCY);
- tone(BUZZER_PIN, frequency + range);
- // Выполняем случайную задержку от 70 до 170 мс
- delay(random(70, 170));
- // Выключаем звук
- noTone(BUZZER_PIN);
- // Выполняем случайную задержку от 0 до 30 мс
- delay(random(0, 30));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- void toneSlowDownFastUp() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый повышающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, frequency + (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- void toneSlowUpFastDown() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный возрастающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
№9. Трусливый бот
Пусть шасси робота Ампи убегает прочь от приближающихся объектов.
- DriveAway.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Создаём константу для хранения базовой частоты
- constexpr int FREQUENCY = 2000;
- // Создаём константы для хранения минимальной и максимальной частоты
- constexpr int MIN_FREQUENCY = FREQUENCY - (0.25 * FREQUENCY);
- constexpr int MAX_FREQUENCY = FREQUENCY + (0.25 * FREQUENCY);
- // Создаём константу для хранения тригера сигнализации в см
- constexpr int DISTANCE_DETOUR = 20;
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- // Создаём объект для работы с сервомоторами
- Servo servoL;
- Servo servoR;
- // Создаём перечисление состояний робота с соответствующей переменной
- enum {
- ROBOT_STANDING, // Робот стоит на месте
- ROBOT_STANDING_DETECT_DETOUR, // Робот стоял на месте и зафиксировал препятствие
- ROBOT_DRIVE, // Робот едет вперёд
- ROBOT_DRIVE_DETECT_DETOUR, // Робот ехал вперёд и зафиксировал препятствие
- } robotState;
- // Создаём перечисление направления движения робота с соответствующей переменной
- enum DirectionDetours {
- LEFT,
- RIGHT,
- } direction;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Передаём случайное число с пина A1
- // для последующей генерации случайных чисел
- randomSeed(analogRead(A1));
- // Включаем стартовую мелодию
- melodyStart();
- // Устанавливаем режим «Робот стоит на месте»
- robotState = ROBOT_STANDING;
- }
- void loop() {
- // Если установлен режим «Робот стоит на месте»
- if (robotState == ROBOT_STANDING) {
- // Переходим в функцию обработки режима «Робот стоит на месте»
- handleRobotStanding();
- }
- // Если установлен режим «Робот стоял на месте и зафиксировал препятствие»
- if (robotState == ROBOT_STANDING_DETECT_DETOUR) {
- // Переходим в функцию обработки режима «Робот стоял на месте и зафиксировал препятствие»
- handleRobotStandingDetectDetour();
- }
- // Если установлен режим «Робот едет вперёд»
- if (robotState == ROBOT_DRIVE) {
- // Переходим в функцию обработки режима «Робот едет вперёд»
- handleRobotDrive();
- }
- // Если установлен режим «Робот ехал вперёд и зафиксировал препятствие»
- if (robotState == ROBOT_DRIVE_DETECT_DETOUR) {
- // Переходим в функцию обработки режима «Робот ехал вперёд и зафиксировал препятствие»
- handleRobotDriveDetectDetour();
- }
- }
- // Функция обработки режима «Робот стоит на месте»
- void handleRobotStanding() {
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний с дальномера
- delay(10);
- // Если текущее расстояние до препятствия меньше тригера
- if (distance < DISTANCE_DETOUR) {
- // Устанавливаем режим «Робот стоял на месте и зафиксировал препятствие»
- robotState = ROBOT_STANDING_DETECT_DETOUR;
- }
- }
- // Функция обработки режима «Робот стоял на месте и зафиксировал препятствие»
- void handleRobotStandingDetectDetour() {
- // Запускаем мелодию R2-D2
- melodyR2D2();
- // Ждём 1 сек
- delay(1000);
- // Объезжаем препятствие слева 1000 мс
- motorsDetourBarrier(LEFT, 1000);
- // Устанавливаем режим «Робот едет вперёд»
- robotState = ROBOT_DRIVE;
- }
- // Функция обработки режима «Робот едет вперёд»
- void handleRobotDrive() {
- // Задаём максимальную скорость вперёд
- motorsDrive(100, 100, false);
- // Считываем расстояние до объекта в см
- float dist = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний с дальномера
- delay(10);
- // Если текущее расстояние до препятствия меньше тригера
- if (dist < DISTANCE_DETOUR) {
- // Устанавливаем режим «Робот зафиксировал препятствие»
- robotState = ROBOT_DRIVE_DETECT_DETOUR;
- }
- }
- // Функция обработки режима «Робот зафиксировал препятствие»
- void handleRobotDriveDetectDetour() {
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Запускаем мелодию R2-D2
- melodyR2D2();
- // Ждём 1 сек
- delay(1000);
- // Объезжаем препятствие слева 500 мс
- motorsDetourBarrier(LEFT, 500);
- // Устанавливаем режим «Робот едет вперёд»
- robotState = ROBOT_DRIVE;
- }
- // Функция объезда препятствие
- void motorsDetourBarrier(DirectionDetours direction, int delayDrive) {
- // Выбираем направления заднего хода для разворота
- if (direction == LEFT) {
- motorsDrive(-50, 0, false);
- } else if (direction == RIGHT) {
- motorsDrive(0, -50, false);
- }
- // Ждём интервал задержки езды
- delay(delayDrive);
- // Останавливаем плавно сервомоторы
- motorsDrive(0, 0);
- // Ждём интервал задержки остановки
- delay(1000);
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
- // Функция мелодии R2-D2
- void melodyR2D2() {
- // Вызываем функцию генератора последовательных длинных семплов
- toneLongSamples();
- // Вызываем функцию генератора непоследовательных коротких семплов
- toneShortSamples();
- }
- // Функция генерации последовательных длинных семплов
- void toneLongSamples() {
- // Генерируем случайное количество семплов от 1 до 6
- int countSamples = random(1, 7);
- // Перебираем нумерацию семплов в цикле
- for (int i = 0; i < countSamples; i++) {
- // Генерируем случайное число: true или false
- bool typeSamples = random(0, 2);
- // Если тип семпла true
- if (typeSamples) {
- // Вызываем функцию генерации тона toneSlowDownFastUp:
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- toneSlowDownFastUp();
- } else {
- // Если тип семпла false
- // Вызываем функцию генерации тона toneSlowUpFastDown:
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- toneSlowUpFastDown();
- }
- }
- }
- // Функция генерации непоследовательных коротких семплов
- void toneShortSamples() {
- // Генерируем случайное количество семплов от 3 до 9
- int countSamples = random(3, 10);
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- for (int i = 0; i <= countSamples; i++) {
- // Генерируем случайный интервал на базе FREQUENCY
- int range = random(-FREQUENCY, FREQUENCY);
- tone(BUZZER_PIN, frequency + range);
- // Выполняем случайную задержку от 70 до 170 мс
- delay(random(70, 170));
- // Выключаем звук
- noTone(BUZZER_PIN);
- // Выполняем случайную задержку от 0 до 30 мс
- delay(random(0, 30));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный убывающий тон со случайными задержками
- // Затем быстрый возрастающий тон со случайными задержками
- void toneSlowDownFastUp() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый повышающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, frequency + (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
- // Функция генерации звуковой последовательности
- // Сначала медленный возрастающий тон со случайными задержками
- // Затем быстрый убывающий тон со случайными задержками
- void toneSlowUpFastDown() {
- // Генерируем случайную частоту на базе FREQUENCY
- int frequency = random(MIN_FREQUENCY, MAX_FREQUENCY);
- // Генерируем медленный возрастающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 2));
- delayMicroseconds(random(0, 1000));
- }
- // Генерируем быстрый понижающий тон со случайными задержками
- for (int range = 0; range <= random(100, 1000); range++) {
- tone(BUZZER_PIN, (range * 10));
- delayMicroseconds(random(0, 1000));
- }
- }
№10. Следопыт
Сделай из робота Ампи настоящего сыщика: пусть он пресле- дует замеченные дальномером объекты.
- Detective.ino
- // Подключаем библиотеку для работы с дальномером
- #include <EasyUltrasonic.h>
- // Подключаем библиотеку для работы с сервомоторами
- #include <Servo.h>
- // Даём понятное имя пину 3 с пищалкой
- constexpr uint8_t BUZZER_PIN = 3;
- // Даём понятные имена пинам 12 и 11 с дальномером
- constexpr uint8_t TRIG_PIN = 12;
- constexpr uint8_t ECHO_PIN = 11;
- // Даём понятное имя пину 7 с левым сервомотором
- constexpr uint8_t SERVO_WHEEL_L_PIN = 7;
- // Даём понятное имя пину 10 с правым сервомотором
- constexpr uint8_t SERVO_WHEEL_R_PIN = 10;
- // Задаём максимально доступную скорость сервомоторов
- // в сырых значениях по часовой и против часовой стрелки
- constexpr int SPEED_RAW_MAX_CW = 30;
- constexpr int SPEED_RAW_MAX_CCW = 150;
- // Вычисляем показатель остановки сервомоторов в сырых значениях
- constexpr int SPEED_RAW_STOP = (SPEED_RAW_MAX_CW + SPEED_RAW_MAX_CCW) / 2;
- // Создаём константы для калибровки скорости левого и правого мотора
- constexpr int SPEED_FACTOR_L = 0;
- constexpr int SPEED_FACTOR_R = 30;
- // Создаём константу задержки езды
- constexpr int DELAY_DRIVE = 3000;
- // Создаём константу задержки остановки
- constexpr int DELAY_STOP = 1000;
- // Создаём константу задержки плавной остановки
- constexpr int DELAY_SMOOTH = 30;
- // Создаём константу для желаемого расстояние зоны поиска объекта в см
- constexpr int DISTANCE_RANGE = 100;
- // Создаём константу для желаемого расстояние до объекта в см
- constexpr int DISTANCE_TARGET = 30;
- // Создаём константы для хранения желаемой зоны до объекта
- constexpr int MIN_DISTANCE_TARGET = DISTANCE_TARGET - (0.25 * DISTANCE_TARGET);
- constexpr int MAX_DISTANCE_TARGET = DISTANCE_TARGET + (0.25 * DISTANCE_TARGET);
- // Создаём объект для работы с дальномером
- EasyUltrasonic distSensor;
- // Создаём объект для работы с сервомоторами
- Servo servoL;
- Servo servoR;
- // Прототип функции управления моторами
- void motorsDrive(int speedL, int speedR, bool smooth = true);
- void setup() {
- // Настраиваем пин с пищалкой в режим выхода
- pinMode(BUZZER_PIN, OUTPUT);
- // Подключаем дальномер
- distSensor.attach(TRIG_PIN, ECHO_PIN);
- // Подключаем сервомоторы
- servoL.attach(SERVO_WHEEL_L_PIN);
- servoR.attach(SERVO_WHEEL_R_PIN);
- // Останавливаем сервомоторы
- motorsDrive(0, 0, false);
- // Включаем стартовую мелодию
- melodyStart();
- }
- void loop() {
- // Считываем расстояние до объекта в см
- float distance = distSensor.getDistanceCM();
- // Задержка для стабилизации показаний с дальномера
- delay(10);
- // Проверяем расстояние до объекта
- if (distance > DISTANCE_RANGE) {
- // Если в зоне поиска робота нет объектов, стоим
- motorsDrive(0, 0);
- } else if (distance < MIN_DISTANCE_TARGET) {
- // Если робот слишком близко к цели, едем назад
- motorsDrive(-50, -50);
- } else if (distance > MIN_DISTANCE_TARGET && distance < MAX_DISTANCE_TARGET) {
- // Если робот в зоне слежения цели, стоим
- motorsDrive(0, 0);
- } else if (distance > MAX_DISTANCE_TARGET) {
- // Если робот далеко от цели, едем вперёд
- motorsDrive(50, 50);
- }
- }
- // Функция управления сервомоторами
- void motorsDrive(int speedL, int speedR, bool smooth) {
- // Создаём переменные для хранения текущей скорости
- // левого и правого мотора в сырых значениях
- int speedRawL = 0;
- int speedRawR = 0;
- // Создаём переменные для хранения обновлённой скорости
- // левого и правого мотора в сырых значениях
- int newSpeedRawL = 0;
- int newSpeedRawR = 0;
- // Создаём переменные для хранения калибровочных коэффициентов скорости
- // левого и правого мотора
- int speedFactorL = 0;
- int speedFactorR = 0;
- // Вычисляем калибровочные коэффициенты для моторов
- speedFactorL = (SPEED_FACTOR_L * speedL) / 100;
- speedFactorR = (SPEED_FACTOR_R * speedR) / 100;
- // Получаем текущие показания моторов в сырых значениях
- speedRawL = servoL.read();
- speedRawR = servoR.read();
- // Преобразуем показания скорости левого мотора
- if (speedL == 0) {
- newSpeedRawL = SPEED_RAW_STOP;
- } else if (speedL > 0) {
- speedL -= speedFactorL;
- } else if (speedL < 0) {
- speedL += speedFactorL;
- }
- // Преобразуем показания скорости правого мотора
- if (speedR == 0) {
- newSpeedRawR = SPEED_RAW_STOP;
- } else if (speedR > 0) {
- speedR -= speedFactorR;
- } else if (speedR < 0) {
- speedR += speedFactorR;
- }
- // Проверяем состояние флага: плавное или мгновенное изменение скорости
- if (smooth) {
- // Плавное изменение скорости
- int steps = 10;
- for (int i = 0; i <= steps; i++) {
- int newSpeedRawSmoothL = map(i, 0, steps, speedRawL, newSpeedRawL);
- int newSpeedRawSmoothR = map(i, 0, steps, speedRawR, newSpeedRawR);
- servoL.write(newSpeedRawSmoothL);
- servoR.write(newSpeedRawSmoothR);
- delay(DELAY_SMOOTH);
- }
- } else {
- // Мгновенное изменение скорости
- servoL.write(newSpeedRawL);
- servoR.write(newSpeedRawR);
- }
- }
- // Функция стартовой мелодии
- void melodyStart() {
- tone(BUZZER_PIN, 300, 500);
- delay(1000);
- tone(BUZZER_PIN, 400, 500);
- delay(1000);
- tone(BUZZER_PIN, 500, 500);
- delay(1000);
- tone(BUZZER_PIN, 700, 300);
- delay(1000);
- }
Ресурсы
- Наборы IO.KIT в магазине