Автор работы: Пользователь скрыл имя, 03 Декабря 2012 в 16:37, доклад
Принцип действия.
Для управления машинкой используется обычный пульт дистанционного управления. Он посылает сигнал в виде чередующихся импульсов инфракрасного излучения. Эти импульсы передаются ИК-приемнику, который в свою очередь преобразует их в электрические импульсы, а затем в код клавиши. Далее, в зависимости от кода клавиши, Arduino отдает управляющие команды электромоторам, приводящим машинку в движение.
Машинка на пульте ДУ на базе Arduino.
Принцип действия.
Для управления машинкой используется обычный пульт дистанционного управления. Он посылает сигнал в виде чередующихся импульсов инфракрасного излучения. Эти импульсы передаются ИК-приемнику, который в свою очередь преобразует их в электрические импульсы, а затем в код клавиши. Далее, в зависимости от кода клавиши, Arduino отдает управляющие команды электромоторам, приводящим машинку в движение.
Необходимые запчасти:
Аппаратная часть.
ИК-приемник имеет 3 вывода:
У дисплея типа WH1602B-YYK-CTK 16 выводов, 12 из которых нам понадобятся:
Если после загрузки скетча на плату на дисплее ничего не видно, нужно подкрутить настроечный потенциометр до появления текста на дисплее.
Программная часть.
В данном приложении код каждой из клавиш пульта вычисляется исходя из отличий последовательности импульсов этой кнопки от последовательности импульсов опорной кнопки. Код каждой клавиши начинается с длинного положительного импульса (порядка нескольких миллисекунд), за которым следует последовательность коротких положительных и отрицательных импульсов. На данном этапе ведется запись последовательности импульсов одной из кнопок пульта, которая будет использоваться как опорная.
Код скетча для Arduino:
#include <EEPROM.h> //для работы с энергонезависимой памятью
enum { Intervals = 25 }; //Здесь мы указываем, сколько битов бы будем считывать
//разные
пульты выдают разное
int startt, endt, time,n, code;
char data[Intervals]; // Массив времени импульсов
byte otl;
int pin=12; //выход. к которому подключен ИК-приемник
void setup() {
pinMode(pin, INPUT);
}
void loop()
{ if (digitalRead(pin)==0) //Если сигнал есть
{
startt=micros(); //время начала импульса
while (digitalRead(pin)==0); //ждем пока он не прекратися.
endt=micros(); //время окончания импульса
time=endt-startt; // длительность импульса
if (time>1000) //если это стартовый импульс, начинаем считывать остальные биты
{while (n<Intervals) //в цикле считываем бит за битом
{ if (digitalRead(pin)==0) //если импульс положительный
{ startt=micros(); //высчитываем время импульса, как и в прошлый раз
while (digitalRead(pin)==0);
endt=micros();
time=endt-startt;
data[n]=time/100; //записываем в массив текущий код
//делим на 100 чтобы сэкономить место под переменные
n++; //прибавляем колличество считанных битов
}
if (digitalRead(pin)==1) //если импульс отрицательный
{startt=micros(); //время начала импульса
while (digitalRead(pin)==1) //проверка на остановку передачи
{endt=micros();
time=endt-startt;
if (time>10000) //условие конца передачи
{while (n<Intervals) //заполняем остальные длительности нулями
{data[n]=0 ;
n++;
}
goto out; //выходим из цикла считывания битов
}
}
endt=micros(); //если передача продолжается
time=endt-startt;
data[n]=-time/100;//запишем длительность отр-ого импулшьа с минусом
n++;
}
}
out: //после того как все биты считаны
n=0;
for (byte x=0; x<Intervals; x++) //в этом цикле запишем получившийся код в EEPROM
{EEPROM.write(x,data[x]);
}
}
}
}
В результате в памяти Arduino будет код опорной клавиши, т.е. мы будем в состоянии определить код каждой клавиши пульта. Коды остальных клавиш можно выяснить с помощью их распечатывания на дисплее или отправки их значений в последовательный порт. Для вычисления кода клавиши удобнее использовать функцию getCode(), рассмотренную далее.
На этом этапе приложение научится распознавать команды с пульта и реагировать на них. В итоге мы получим машинку, управляемую с обычного пульта ДУ.
Замечание: пульт, который использовал я, посылает с одной и той же клавиши 2 разных кода поочередно, поэтому при выяснении, какая клавиша была нажата используются составные условия.
Код скетча:
#include <EEPROM.h> //для работы с энергонезависимой памятью
#include <LiquidCrystal.h> //для работы с дисплеем
LiquidCrystal lcd(13,11,5,4,3,2); //задаем как подключен дисплей
const int Intervals=25,tz=300; //онстанты количества битов и длительности одной команды
char data[Intervals],array[
long rast,vrem,vr1,rast1;
int i,dv=1,kol,kolvp;
const int rastpin=8, p1=6,p2=7,p3=9,p4=10,pin=12; //выходы, к которым подключены
//двигатели, датчик рассояния, ИК-приемник
void setup()
{lcd.begin(16,2); //дисплей размером 2 строки по 16 символов
pinMode(p1,OUTPUT);
pinMode(pin,INPUT);
pinMode(p2,OUTPUT);
pinMode(p3,OUTPUT);
pinMode(p4,OUTPUT);
for (byte x=0; x<Intervals; x++) //читаем из EEPROM опорный масив
{data[x]=EEPROM.read(x); }
}
void loop(){
if(digitalRead(pin)==0){//если пришел сигнал с пульта
i=getCode();//определяем. что за клавиша нажата
if(i==174 || i==295) napravo(); //коды клвиши направо
if(i==192 || i==261)nalevo(); //коды клавиши налево
if(i==43 || i==111) {vpered(); dv=1;} //коды клавиши вперед
if(i==206) {nazad(); dv=-1;} //код клавиши назад
}
}
void vpered() //функция движения вперед
{lcd.clear(); //очищаем дисплей
lcd.print("forward"); //пишем куда едет машинка
lcd.setCursor(0,1); //переходим на 2 строку
long r=rasstoyanie(); //определяем расстояние до препятствия
if(r<15)while(rasstoyanie()<
else{ //если нет. двигаемся вперед
lcd.print(r); //пишем на дисплее расстояние до препятствия
digitalWrite(p1,HIGH); //вращаем оба мотора вперед
digitalWrite(p2,LOW); //в течение времени команды
digitalWrite(p3,HIGH);
digitalWrite(p4,LOW);
delay(tz);
digitalWrite(p1,LOW);
digitalWrite(p3,LOW); }
}
void nazad(){ //функция движения назад
lcd.clear(); //очистка дисплея
lcd.print("backward"); //пишем. куда едет машинка
digitalWrite(p1,LOW); //вращаем оба мотора назад
digitalWrite(p2,HIGH); //в течение времени команды
digitalWrite(p3,LOW);
digitalWrite(p4,HIGH);
digitalWrite(13,LOW);
delay(tz);
digitalWrite(p2,LOW);
digitalWrite(p4,LOW);
}
void napravo(){ //функция движения направо
lcd.clear(); //очистка дисплея
lcd.print("right"); //пишем. куда едет машинка
if(dv>0) {digitalWrite(p1,HIGH); //если до этого она ехала вперед
digitalWrite(p2,LOW);// вращаем левый мотор вперед
digitalWrite(13,HIGH);
delay(tz);
digitalWrite(p1,LOW);
digitalWrite(13,LOW);}
else //если до этого машинка ехала назад
{digitalWrite(p2,HIGH); //вращаем левый мотор назад
digitalWrite(p1,LOW);
delay(tz);
digitalWrite(p2,LOW);}
}
void nalevo(){//функция движения влево
lcd.clear();//все аналогично движению направо
lcd.print("left");
if(dv>0){digitalWrite(p3,HIGH)
digitalWrite(p4,LOW);
delay(tz);
digitalWrite(p3,LOW);}
else
{digitalWrite(p4,HIGH);
digitalWrite(p3,LOW);
delay(tz);
digitalWrite(p4,LOW);}
}
long rasstoyanie(){ //определение рассояния до препятствия
pinMode(rastpin,OUTPUT); //посылаем импульс
digitalWrite(rastpin,LOW);
delayMicroseconds(2);
digitalWrite(rastpin,HIGH);
delayMicroseconds(5);
digitalWrite(rastpin,LOW);
pinMode(rastpin,INPUT);//
vrem=-1;
vrem=pulseIn(rastpin,HIGH); //считаем. сколько времени он шел
if(vrem>=0)rast=vrem/29/2;//
return rast;
}
int getCode(){//функция получения кода клавиши пульта
int startt, endt, time,n, code;
byte otl;
otl=0;
code=0;
if (digitalRead(pin)==0) //цикл считывания битов кода
{ //аналогичен предыдущему скетчу
startt=micros();
while (digitalRead(pin)==0);
endt=micros();
time=endt-startt;
if (time>1000)
{while (n<Intervals)
{ if (digitalRead(pin)==0)
{ startt=micros();
while (digitalRead(pin)==0);
endt=micros();
time=endt-startt;
array[n]=time/100;
n++;
}
if (digitalRead(pin)==1)
{startt=micros();
while (digitalRead(pin)==1)
{endt=micros();
time=endt-startt;
if (time>10000)
{while (n<Intervals)
{array[n]=0 ;
n++;
}
goto out;
}
}
endt=micros();
time=endt-startt;
array[n]=-time/100;
n++;
}
}
out:
n=0;
for (byte x=0; x<Intervals; x++) // сравнение полученного кода с опорным
{if (abs(array[x]-data[x])>5 && array[x]!=0 && data[x]!=0) // проверка на отличия
{otl++;
code=code+(x+1)*otl; //генерируем код клавиши
}
}
return code;
}
}
}