На этой странице ты найдёшь все нужные материалы для проектов набора Робот Ампи: Шасси из серии IO.KIT:
Обрати внимание
Для сборки и функционирования шасси робота Ампи тебе понадобится IO.KIT Базовый!
Прежде чем приступать к экспериментам, нужно подготовить свой компьютер:
Драйвер чипа CH340
Установи драйвер CH340 для Windows или Linux, чтобы твой компьютер мог корректно распознать и прошить плату Iskra Nano.
Переверни шасси робота Ампи на спину колёсами вверх и протестируй сервоприводы.
// Подключаем библиотеку для работы с сервомоторами #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); }
Запусти движение шасси вперёд и назад с остановками на отдых.
// Подключаем библиотеку для работы с сервомоторами #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); }
Научи шасси робота Ампи держать ровный курс.
// Подключаем библиотеку для работы с сервомоторами #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); }
Запусти движение шасси змейкой с возможностью настройки траектории.
// Подключаем библиотеку для работы с сервомоторами #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); }
Активируй дальномер и считай расстояние до препятствия в консоль.
// Подключаем библиотеку для работы с дальномером #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); }
Пусть шасси робота Ампи несёт дозор и активирует сирену при виде постороннего объекта.
// Подключаем библиотеку для работы с дальномером #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); }
Научи шасси робота Ампи останавливаться перед препятствиями.
// Подключаем библиотеку для работы с дальномером #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)); } }
Научи шасси робота Ампи по-умному огибать препятствия.
// Подключаем библиотеку для работы с дальномером #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)); } }
Пусть шасси робота Ампи убегает прочь от приближающихся объектов.
// Подключаем библиотеку для работы с дальномером #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)); } }
Сделай из робота Ампи настоящего сыщика: пусть он пресле- дует замеченные дальномером объекты.
// Подключаем библиотеку для работы с дальномером #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); }