Искусственный интеллект для детей или Знакомим детей с ИИ, не перегружая их взрослыми понятиями

от автора

В этой статье расскажу, как мы с ребятами из Летней компьютерной школы собирали робота с искусственным интеллектом и что из этого получилось.


Введение

Занятия нашей ЛКШ (Летняя компьютерная школа) проходили в августе 2024 года, на живописном берегу реки Луга в Новгородской области, во время третьей смены лагеря «Зарница». Больше 40 школьников в течение трех недель изучали программирование, робототехнику и участвовали в лагерных мероприятиях.

Мы уже много лет делаем летние лагеря, и всегда хочется сделать их интереснее, чем в прошлом году, а программу максимально полезной и приближенной к технологиям и тенденциям сегодняшнего дня. В этом году, очевидно, в тренде всё, что связано с искусственным интеллектом. А так как школа у нас робототехническая, то хотелось наделить интеллектом роботов.

В итоге одним из главных мероприятий стал конкурс по разработке робота, который распознаёт голосовые команды и управляется ими. Он должен был пройти лабиринт, используя только голосовое управление — команды от «водителя».

Выбираем аппаратуру

Понятно, что сделать с нуля распознавание речи на Ардуино – задача неподъёмная для школьников, это сложно и столько времени в лагере не будет, поэтому искали готовые решения.
Нашли два варианта, один китайский, второй – российский. Китайский вариант отпал, так как не поддерживал распознавание русского языка, сложен для интеграции и отсутствует какая-либо поддержка. Второй вариант нашли на Озоне, российская плата, которая распознаёт команды на русском языке, продавец сразу же ответил и пообещал помощь, поэтому платы закупили сразу для всех команд.

В начале смены ребятам были выданы:

  • Готовый набор комплектующих для сборки простой двухмоторной тележки

  • Драйвер двигателей и плата Arduino UNO с россыпью проводов, батарейками и прочей мелочёвкой.

  • Миниатюрный модуль искусственного интеллекта для Ардуино-роботов, который мы купили на Озоне.

Модуль распознаёт простые голосовые команды, такие как «Вперёд», «Назад», «Влево», «Вправо», «Стоп» и так далее, повторяет их (можно подключить динамик прямо к плате), а затем отправляет их на Ардуинку по UART, SPI и I2C для преобразования в команды для двигателей.

Также, на всякий случай, мы заранее сами собрали одну тележку и протестировали модуль, поэтому дополнительно у ребят был «образец» робота и шаблон скетча, от которых можно было отталкиваться в своей разработке.

Но для школьников задача всё равно оставалась трудной, так как нами «собранный на коленке» робот, хоть и реагировал на команды, работал неидеально, и проехать на нём лабиринт, как того требовали условия конкурса, с помощью голосовых команд было невозможно. Сейчас расскажу, почему, и какие проблемы решали наши воспитанники.

Трудности с реальным применением модуля

Первая проблема была в самом модуле: микрофон для приёма команд маленький и находится на самой плате модуля. Поэтому, когда в помещении становится шумно, и много людей сразу говорят, подсказывают, кричат, модуль перестаёт понимать команды, или, что хуже, понимает их неверно, заставляя робота врезаться в стенки лабиринта.

Решать это приходилось организационно. Члены команды и жюри обеспечивали относительную тишину в помещении, не давая болельщикам и соперникам мешать водителям роботов.

Дополнительно распознаванию мешал шум двигателей, поэтому сразу же было принято решение пошагового управления: команда – действие – остановка. Это позволяло роботу двигаться медленнее, но по верной траектории.

Как мы узнали позже, ещё была возможность модуль разместить не на роботе, а отдельно, в виде пульта: держать в руке и говорить в него. А команды роботу передавались бы по Bluetooth, который встроен в модуль. Но всё равно Bluetooth-модулей для Ардуино у нас в наличии не было, поэтому этот вариант мы не рассматривали.

В итоге модуль установили на саму тележку, из доступных протоколов (I2C, UART, SPI) выбрали I2C.

Трудности в управлении двигателями и пути их преодоления

Двигатели и драйвер управления были совсем простенькими. Поэтому, например, скорость вращения двигателей могла меняться от раза к разу и отличаться на двигателях, а также сильно зависела от уровня заряда батарей.

Команда, добравшаяся до финала, в итоге пришла к решению отдельно питать Ардуино с помощью «Кроны» и отдельно запитать драйвер двигателей от пяти АА батареек для повышения напряжения.

Также ребята программно реализовали плавный разгон двигателей, что добавило стабильности поведению робота:

Код текстом

#define ESP_SLAVE_ADDR    0x36 #include <Wire.h>  //const byte Motor1; //const byte Motor2; bool IsCommandAvilable = true;  class Driver{   byte IN1;   byte IN2;   double Deltime = 0, StartTime = 0;   int SpeedFrom = 0, SpeedTo = 0l    void BasicMove(int Speed, int Pin1, int Pin2){     Speed = constrain(Speed, 0, 255);     Serial.println(map(mills() - StartTime, 0, DeltaTime, SpeedFron, SpeedTo));     analogWrite(Pin1, Speed);     analogWrite(Pin2, LOW);   }    

А ещё ребята отказались от Ардуиновского Delay, поскольку команда останавливает работу микроконтроллера, и использовали свой класс, что позволило двигателям робота двигаться прогнозируемое время.

Код текстом

class Delay{   void (*Task)();   double Delay = 0, StartTime = 0;     public:   void SetTask(double Delay, void (*Task)()){     this->Task = Task;     this->Delay = Delay;     StartTime = millis();   }    void Tick(){       if(Task != nullptr && millis() - StartTime > Delay){         Task();         Task = nullptr;        }    } };

Сам AI-модуль распознавания голосовых команд запитали от Ардуинки.


На картинке: зеленый провод «земля», желтый – 5V с платы Ардуино, оранжевый и красный – SCL и SDA I2C-подключения.

Немного про основной алгоритм

Команды от модуля присылаются в виде строковой переменной, например, «вперёд». После поступления команды в первую очередь отключается приём других команд. Ребята добавили это для защиты от «наложения» команд друг на друга. Затем происходит разгон и торможение мотора. И приём команд разрешается снова.

При этом заметили, что даже если модуль распознал команду корректно, что подтверждается тем, что он правильно повторил её, изредка могут возникать помехи при передаче команды на Ардуино. Предположительно, помехи вносятся двигателями, но глубоко вопрос не изучали, так как не было необходимости.

Код тестом

if (command.indexOf("вперед") != -1) {   IsCommandAvailable = false;   Motor2.Interpolate(200, -100, -255);   Motor1.Interpolate(200, -100, -255);   Del.SetTask(350, [](){ Motor1.Interpolate(250, -255, 0); Motor2.Interpolate(250, -255, 0); IsCommandAvailable = true;}); } if (command.indexOf("назад") != -1) {   IsCommandAvailable = false;   Motor2.Interpolate(200, 100, 255);   Motor1.Interpolate(200, 100, 255);   Del.SetTask(350, [](){ Motor1.Interpolate(250, 255, 0); Motor2.Interpolate(250, 255, 0); IsCommandAvailable = true;}); } if (command.indexOf("влево") != -1) {   IsCommandAvailable = false;   Motor2.Interpolate(50, 40, 100);   Motor1.Interpolate(50, -40, -100);   Del.SetTask(350, [](){ Motor1.Interpolate(50, -100, 0); Motor2.Interpolate(50, 100, 0); IsCommandAvailable = true;}); }  

Чтобы понять, как же всё получилось, можно посмотреть видео про то, как робот проходит лабиринт.

(по картинке переход на ЯДиск)

Вместо заключения

Как видите, ребята проделали большую работу: собрали самих роботов, написали Ардуино-скетчи, провели тестирование и отладку, которая занимала часы (!) свободного времени, несмотря на использование готовых модулей, таких как платы распознавания голосовых команд и готовые наборы тележки с двигателями.

Нам важно было создать у ребят максимальный интерес к достаточно сложной и амбициозной задаче (роботов на голосовом управлении у нас ещё не было), но при этом не убить этот интерес сложностью и неподъёмностью реализации, сосредоточиться именно на тех вещах, которые ребятам по плечу.

Вообще такие летние лагеря — прекрасное место для прокачки опыта. Дома постоянно что-то отвлекает: большую часть года — школа, занятия и уроки, летом — множество других интересных вещей. Преимущество летнего лагеря в том, что команда постоянно находится вместе, и, несмотря на лагерную жизнь, не слишком распыляется. Поэтому дети получают опыт командной работы, которая нацелена на результат, и который потом пригодится для работы в реальных командах программистов, формируют правильные навыки, которые пригодятся в реальной работе.


ссылка на оригинал статьи https://habr.com/ru/articles/848284/