Сегодня мы соберем машинку, которая будет объезжать препятствия, а так же научим ее ездить в небольшом лабиринте.
Корпус машинки я заказал на в интернете:
После сборки у меня вышла машинка с которой и будем работать дальше:
В качестве старта, мы возьмем плату Arduino Nano и напишем простой код для движения машинки вперед/назад.
В качестве стабилизации питания мы используем временно линейный стабилизатор на 5вольт 78L05 который запитаем от аккумуляторов (4 штуки).
В качестве модуля управления двигателями возьмем драйвер TB6612NG. Схему подключения мы рассматривали в уроках по микроконтроллерам.
Для начала поставим пару датчиков обнаружения препятствия:
Данных датчиков у нас будет три штуки: два спереди по бокам и один сзади. Датчики подключены к следующим ножкам: боковые датчики к **и **ножкам, задний датчик ****
Ультра звуковой датчик подключим к ножкам 9 (echo) и 10 (trig).
Сигналы управления драйвером двигателя ТВ6612 следующие: INA1-8, INA2-7, STBY-6, INB1-5, INB2-4 ШИМ1-3, ШИМ2-11.
Теперь напишем напишем простой алгоритм по которому наша машинка будет ехать вперед до объекта, после чего повернет его и поедет дальше.
Таким образом, мы получим следующий программный код:
//мотор
#define INA1 8
#define INA2 7
#define STBY 6
#define INB1 5
#define INB2 4
//ЭХО датчик
#define echoPin 9
#define trigPin 10
long cm=0;
int temp[10]={0};// храним выборку измерений
int insert =0;
int j=0;
void setup() {
// put your setup code here, to run once:
pinMode(3, OUTPUT); //ШИМ
pinMode(11, OUTPUT); //ШИМ
//ЭХО датчик
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
//датчики боковые
#define right 13
#define left 12
#define back 2
pinMode(right, INPUT);
pinMode(left, INPUT);
pinMode(back, INPUT);
//мотор
pinMode(INA1, OUTPUT);
pinMode(INA2, OUTPUT);
pinMode(STBY, OUTPUT);
pinMode(INB1, OUTPUT);
pinMode(INB2, OUTPUT);
/*TCCR2A = 01010011;
TCCR2B = 00001011;
OCR2A = 180;
OCR2B = 50;*/
// Контакты D3 и D11
TCCR2A = 0b00000011 ; // быстрый ШИМ
TCCR2B = 0b00000001 ; // х1
//CS2 Divisor Frequency
//001 1 31372.55
//010 8 3921.16
//011 32 980.39
//100 64 490.20 <—DEFAULT
//101 128 245.10
//110 256 122.55
//111 1024 30.64
Serial.begin(9600);
}
void loop() {
//меряем растояние до объекта
for (int i=0;i<=9;i++){
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
temp[i]=pulseIn(echoPin, HIGH);
}
for(int i=0;i<=9;i++){//сортировка
insert = temp[i];
j=i-1;
while((j>=0)and(temp[j]>insert)){
temp[j+1]=temp[j];
j—;
}
temp[j+1]=insert;
}
long duration=0;
for(int i=2;i<=7;i++){
duration+=temp[i]/58,8; // преобразуем время в расстояние
}
cm = duration / 6;
Serial.print(«cm=»);
Serial.println(cm);
if (cm<=10){// преграда
motor(0,50,50,1);
// проверяем по бокам преграду
if ((digitalRead(right)==1)and (digitalRead(left)==0)){// преграда справа
if ((digitalRead(back)==0)){// проверяем, что зади пусто
motor(1,180,180,0); // едим назад
delay(1000);//немного отъезжаем
}
motor(1,0,180,1);// поворачиваем влево
delay(1000);//время поворота
}
if ((digitalRead(right)==0)and (digitalRead(left)==1)){// преграда слева
if ((digitalRead(left)==0)){// проверяем, что зади пусто
motor(1,180,180,0); // едим назад
delay(1000);//немного отъезжаем
}
motor(1,180,0,1);// поворачиваем влево
delay(1000);//время поворота
}
if ((digitalRead(right)==1)and (digitalRead(left)==1)){// преграда либо с двух сторон
if ((digitalRead(back)==0)){// проверяем, что зади пусто
while ((digitalRead(right)==1)and (digitalRead(left)==1)){//едим назад пока есть преграда
motor(1,180,180,0); // едим назад
}
}
//рандомно выбираем направление
if (random(0, 2)== 1){// едим на лево
motor(1,0,180,1);// поворачиваем влево
delay(1000);//время поворота
}
else {//едим на право
motor(1,180,0,1);// поворачиваем влево
delay(1000);//время поворота
}
}
if ((digitalRead(right)==0)and (digitalRead(left)==0)){// по бокам преграды нету
//рандомно выбираем направление
if (random(0, 2)== 1){// едим на лево
motor(1,0,180,1);// поворачиваем влево
delay(1000);//время поворота
}
else {//едим на право
motor(1,180,0,1);// поворачиваем влево
delay(1000);//время поворота
}
}
}
else if((cm >10)and(cm<=20))
motor(1,120,120,1);
else if((cm >20)and(cm<=30))
motor(1,180,180,1);
else
motor(1,250,250,1);
}
void motor(boolean start, int speed_L,int speed_R, boolean direction){
if (start) digitalWrite(STBY, HIGH);
else digitalWrite(STBY, LOW);
if(direction){// прямо
digitalWrite(INA1, HIGH);
digitalWrite(INA2, LOW);
digitalWrite(INB1, HIGH);
digitalWrite(INB2, LOW);
}
else {// назад
digitalWrite(INA1, LOW);
digitalWrite(INA2, HIGH);
digitalWrite(INB1, LOW);
digitalWrite(INB2, HIGH);
}
analogWrite(11, speed_L);
analogWrite(3, speed_R);
Serial.print(«start»);
Serial.println(start);
}
Теперь когда наша машинка может ездить и объезжать препятствия будем улучшать нашу машинку. Для начала решим две задачи:
Для решения первой задачи воспользуемся следующей схемой импульсного DC/DC преобразователя:
Рассмотрим саму микросхему МС34063:
6 ножка — питание микросхемы, от 3 до 40В
7 ножка — вход ограничения тока, резистор подбирается таким образом, что бы максимально допустимы ток через катушку был меньше 1,5 А.
Таким образом номинал резистора R1 должен быть, таким, что бы при максимально допустимым рабочем токе микросхема отключила нагрузку. Напряжение при котором отключается нагрузка 0,3В (но бывает исключения в зависимости от корпуса, лучше посмотреть документацию). В нашем случаи R1=0.5 Ом, тоесть при I= 0,3/0,5=0,6А сработает защита и наш микроконтроллер отключиться от питания.
5 ножка — опорное напряжение, вместе с резисторами R5 и R6 устанавливают выходное напряжение: Uvix = 1.25*(1+R5/R6). Выходя из этой формулы для Uvix = 5В, соотношение резисторов должно быть 3/1. Я выбрал следующие номиналы: R5=30кОм R6=10кОм.
3 ножка — для подключения времязадающего конденсатора. Рабочая частота импульсного регулятора 100кГц. Для данной частоты по документации необходимо подключить емкость 1500pF.
8 и 1 ножку мы соединяем вместе и получаем «транзисторный ключ» с открытым коллектором. В качестве коммутирующего элемента мы подключаем транзистор Q1.
Номинал транзистора должен соответствовать нашим требованиям: максимальному току коллектора и напряжению эмиттер — коллектор. Рассеиваемая мощность и остальные параметры для нашей схемы не очень актуальны, так как мы 7-8 вольт будем получать 5В, при токе потребления до 0,1А (это максимум на данном этапе, по факту ток будет меньше). Резисторы R3 =160 — 470 Ом и R2=160Ом — расчет был сделан эмпирически: с учетом того, что транзистор работает в ключевом режиме и нам его надо как можно быстрей закрыть и открыть (R3 — отвечает за закрытие транзистора, R2 — ограничивает ток через базу когда мы подаем импульс открытия). Можно было конечно обойтись и без транзистора Q1, но при настройке машинки всегда можно замкнуть питание и спалить микросхему(даже при наличии защиты), а так мы потеряем транзистор. В будущем когда у нас все будет настроено, мы уйдем от транзистора.
Катушка L1 выбирается из документации: 220mГн. Диод самый обычный с рабочей частотой выше чем рабочая частота нашего преобразователя, емкости С1 — 10мкF, С4 — 470мкF, С3 — 0,1мкF.
Теперь соберем схему драйвера нашими двигателями, при этом мы будем только подавать команды куда ехать и с какой скоростью, а наш драйвер будет сами плавно набирать скорость, резко останавливаться, следить за скоростью двигателей, проверять исправность двигателей и т.д. и при необходимости сигнализировать об ошибках.
Драйвер мы соберем на микроконтроллере Atmega8:
***схема****