Модератор
Регистрация: 19.01.2010
Возраст: 59
Город: Санкт-Петербург
Регион: 78, 98
Сообщений: 2,655
|
Цитата:
Сообщение от Serdj
неплохо было бы добавить библиотеку irremote...
|
Я совсем не программист. "Нажал-поехало-открыл" еще смогу написать. Все, что связано с Eeprom, прерываниями и прочим для меня сложно. Но по существу вопроса- есть вот такой скетч в свободном доступе. В шапке ссылка на первоисточник. Возможно это то, что нужно?
Скопировано без изменений.
PHP код:
/* v.01 Arduino servo IR EEPROM speed ИК пультом **************************** урок от Дмитрия Осипова. http://www.youtube.com/user/d36073?feature=watch v.01 Arduino servo IR EEPROM speed ИК пультом Version 0.1-2013/08/19 ----------------------------- изменения; в Version 0.1-2013/ 1. 2. ------------------------------ идеология; управление двумя servo любым (ИК) инфракрасным пультом,для управления задействуем 5 кнопок ИК пульта, 4 кнопки для плавного поворота вправо или влево, а одну кнопку для регулировки скорости поворота. Также задействуем ОЗУ EEPROM (энергонезависимая память): (данные сохраняются при отключении питания). То бишь после включения питания, градус поворота servo, и установленная скорость поворота, будут теми же какие были на момент отключения. внимание, при первой заливки sketch, Arduino будет читать значение скорости из ячейки №3 ОЗУ. ОЗУ скорей всего у вас девственный, поэтому нужно сначала нажать на кнопку ИК пульта управления скоростью, чтоб в ячейке №3 появились данные. В следующих заливках sketch это делать не нужно. Рекомендую использовать конденсаторы для сглаживания электрических колебаний которые создают servo во время работы. Также рекомендую отключать servo от Arduino в момент заливки sketch, USB компьютера может не потянуть нагрузку, servo потребляют много тока. ------------------------------------------ скетч sketch: v.01 Arduino servo IR EEPROM speed ИК пультом ================================ что нам понадобиться. Аппаратное: 1.servo 2. любая Arduino 3. ИК инфракрасный приёмник 4. Светодиоды нужны только для визуального контроля за процессом. 5. конденсаторы -------------------------------- программное: Библиотеки. 1.IRremote, библиотека для работы с ИК сигналом. Скачать библиотеку IRremote для ИК пульта https://disk.yandex.ru/public/?hash=yNz1au3lm3/yyMHOYtnZ2UGSf19wTvYBZnkxmhW4Xt0%3D IRremote эта библиотека кажется по новее будет http://yadi.sk/d/0jIS1tfw6tbb7 https://github.com/shirriff/Arduino-IRremote ======================================================= подробную видео инструкцию выложу здесь ++++++++++++++++++++++++++++++ Вспомогательные видео обзоры, скетчи..... скетч arduino чтобы узнать код кнопки ИК пульта sketch arduino buttons on the remote to learn the code https://disk.yandex.ru/public/?hash=KzLtuC1ljISPaCoXw03D6mbiKea8spktcWL5QKJHGRQ%3D 4/6 как ? узнать код - кнопки своего ИК пульта http://www.youtube.com/watch?v=InZuGntH_wk v.01 Arduino IR Управление с ИК пульта в режиме удержания кнопки https://www.youtube.com/watch?v=AjIASUNiWkY Самый дешевый Arduino Uno 5$ Minimal Atmega328 without Arduino Board http://www.youtube.com/watch?v=joSc-AT8o5k v.01 Arduino управление servo любым ИК пультом Control IR + speed http://www.youtube.com/watch?v=KYNoWX4yG8s&feature=c4-overview&list=UU7aH7HVqDvwB1xNHfSl-fDw */
#include <EEPROM.h> // подключаем библиотеку EEPROM #include <Servo.h> // подключаем библиотеку для Servo #include <IRremote.h> // подключаем СКАЧЕННУЮ библиотеку IRremote для ИК пульта
int RECV_PIN = 2; //вход ИК инфракрасного приемника IRrecv irrecv(RECV_PIN); decode_results results;
Servo dimkaservo_1; //даём имена servo Servo dimkaservo_2;
//Pin для светодиодов,светодиоды для визуального контроля за процессом int ledPin_1 = 15; //PIN 15, на Arduino Uno, Atmega328 (A1) int ledPin_2 = 16; int ledPin_3 = 17; int ledPin_4 = 18;
// 1. для сглаживания пульсирующего ИК сигнала. // 2. для отключения светодиодов ledPin после пропадания ИК сигнала, без использования delay. int timer_ledPIN = 14; //индикация таймера //PIN 14, на Arduino Uno, Atmega328 (A0)
// (спидометр)для визуального контроля яркостью светодиода, за изменением (увеличения или уменьшения) скорости работы servo. int speed_PWM_ledPin = 5;
// переменные для плавного вращения servo,чтоб не использовать delay. // промежуточная переменная для хранения (увеличенного диапазона от 0 до 30000)значений (увеличения или уменьшения)PWM, // с последующей конвертации в переменную(val) диапазон градусов поворота доступных для servo. int a_1; int a_2;
// переменные для экономии ресурсов ОЗУ EEPROM int e_1; int e_2;
//переменные для конвертации (увеличенного диапазона значений от 0 до 30000) (a_1;),(a_2;),в значения требуемые для поворота servo. int val_1; int val_2;
//переменная для (увеличения или уменьшения)скорости поворота servo. int speed_PWM;
//переменная eventTime, для паузы, вместо delay,будем использовать функцию millis. unsigned long eventTime=0;
void setup() { // Serial.begin(9600); irrecv.enableIRIn(); // включить ИК приёмник
dimkaservo_1.attach(9); // серво подключён на цифровой вход (pin 9) dimkaservo_2.attach(10); // серво подключён на цифровой вход (pin 10)
pinMode(ledPin_1, OUTPUT); pinMode(ledPin_2, OUTPUT); pinMode(ledPin_3, OUTPUT); pinMode(ledPin_4, OUTPUT);
pinMode(timer_ledPIN, OUTPUT);
pinMode(speed_PWM_ledPin, OUTPUT);
// после подключения питания или перезагрузки, читаем значение из ячейки №1 ОЗУ // умножаем это значение на *118 и записываем его в переменную a_1 // делаем это в void setup то бишь только один раз в момент подключения питания a_1=EEPROM.read(1)*118; a_2=EEPROM.read(2)*118;
// также записываем значение из ячейки №3 ОЗУ, в переменную speed_PWM отвечающую за скорость поворота servo speed_PWM=EEPROM.read(3); }
void loop() { // По приёму и обработки сигнала от ИК инфракрасного пульта. //Мой опыт работы с ИК пультами выявил разные принципы отправки ИК сигналов кодов у разных производителей техники (пультов) //мне нужно, чтоб система могла работать и в режиме удержания кнопки, для этого нужно постоянно слать ИК код с пульта // пока кнопка на пульте нажата. //Увы, есть пульты которые шлют код только один раз, в момент нажатия кнопки. // послав 1 код, пульт далее продолжает, слать (в момент удержания кнопки), (назовем его (пустой инфракрасный сигнал). // после отпускания кнопки (пустой инфракрасный сигнал) исчезает. // Задача такая, после приёма определённого кода кнопки,сразу перехватывать идущий за ним (кодом), (пустой инфракрасный сигнал) // и считать его, (пустой инфракрасный сигнал), за код кнопки. //после пропадания (пустого инфракрасного сигнала), будем считать, что код перестал слаться
// Эта конструкция нужна чтобы. //1.после приёма определённого кода кнопки,перехватывать (пустой инфракрасный сигнал) //2.конвертировать пульсирующий (-) с (ИК) преемника сигнал в постоянный. //После появления и пропадания сигнала, состояние сразу не меняется! а ждет 100 миллисекунд. //Если 100 миллисекунд не прошло, и поступил еще один ИК сигнал с пульта, тогда таймер заново запускается на 100 миллисекунд.
//Проще говоря, пока кнопка на ИК пульте нажата timer_ledPIN остается HIGH //если кнопка на пульте отпущена, LOW.
// Читаем состояние ноги у (ИК) преемника. В момент приема данных, у (ИК) //приемника на выходе появляется пульсирующий (-)отрицательный сигнал
if (digitalRead(RECV_PIN) == LOW) eventTime=millis(),digitalWrite(timer_ledPIN, HIGH); if(millis()-eventTime>100) digitalWrite(timer_ledPIN, LOW),digitalWrite(ledPin_1, LOW),digitalWrite(ledPin_2, LOW), digitalWrite(ledPin_3, LOW),digitalWrite(ledPin_4, LOW);
//если ledPin_1) ==, выставляем ограничение для переменной(a_1) до (&& a_1<30000).и Начинаем увеличивать // значения переменной(a_1) прибавляем на значение переменной speed_PWM, //и также выставляем ограничение при убывании (&& a_1>0) if(digitalRead(ledPin_1) == HIGH && a_1<30000 ) a_1=a_1+speed_PWM; if(digitalRead(ledPin_2) == HIGH && a_1>0 ) a_1=a_1-speed_PWM;
//читаем значение (a_1) и конвертируем его в значение val_1, то бишь в значение поворота в градусов доступных для servo. // правильно было бы конвертировать в, (от 0, до 180) градусов, но мои дешёвые servo доходя до краёв, //начинают дребезжать,поэтому я кастрировал их (края) по 10 градусов (10, 170);) val_1 = a_1; val_1 = map(val_1, 0, 30000, 10, 170); // scale it to use it with the servo (val_1ue between 10 and 170) dimkaservo_1.write(val_1); // sets the servo position according
//делаем тоже самое и для dimkaservo_2 if(digitalRead(ledPin_3) == HIGH && a_2<30000 ) a_2=a_2+speed_PWM; if(digitalRead(ledPin_4) == HIGH && a_2>0 ) a_2=a_2-speed_PWM;
val_2 = a_2; val_2 = map(val_2, 0, 30000, 10, 170); dimkaservo_2.write(val_2); //записываем значения val_2 в dimkaservo_2
// эта конструкция отвечает за запись положения градусов servo в ОЗУ EEPROM. // Можно было бы сделать так if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH)EEPROM.write(1, a_1/118);. // В документации на ATMEGA328P-PU указано, количество записи и чтения в ячейку ОЗУ гарантировано не более 100.000 раз, // поэтому будем экономить ОЗУ, то бишь записывать не постоянно в (момент движения) изменения градусов servo, //а только тогда, когда servo остановилась. //когда кнопка №1 или №2 на ИК пульте нажата if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH) // фиксируем это событие в переменную e_1 и записываем в неё =1; (e_1=1;) // когда кнопку №1 И №2 отпустили, то бишь servo остановилась //(ledPin_1) == LOW && digitalRead(ledPin_2)== LOW// // и && e_1==1 то бишь перед тем как servo остановилась она была включена, //записываем в ячейку №1 EEPROM значение переменной a_1. // Так как ячейка EEPROM может хранить значения от (0 до 255), а диапазон значений переменной a_1 //от (1 до 30.000), то перед записью в ячейку №1, делим значение переменной a_1 на 118 //(1, a_1/118)// // и меняем значение переменной e_1 на 0 // ,e_1=0;//
if(digitalRead(ledPin_1) == HIGH || digitalRead(ledPin_2)== HIGH)e_1=1; if(digitalRead(ledPin_1) == LOW && digitalRead(ledPin_2)== LOW && e_1==1)EEPROM.write(1, a_1/118),e_1=0;
if(digitalRead(ledPin_3) == HIGH || digitalRead(ledPin_4)== HIGH)e_2=1; if(digitalRead(ledPin_3) == LOW && digitalRead(ledPin_4)== LOW && e_2==1)EEPROM.write(2, a_2/118),e_2=0;
//Serial.println(EEPROM.read(1));
// Эта часть отвечает за приём и обработку ИК кодов // здесь считываем коды от ИК пульта
// У моего пульта при нажатии на одну и ту же кнопку, могут отсылаться два разных (КОДА) сигнала, чтобы обойти эту проблему //я использовал Логический оператор "или" (||) if (results.value == 0x1000809 || results.value == 0xF7283C77 // Теперь неважно какой код отправлен с кнопки пульта, первый или второй // Если ваша кнопка пульта не страдает раздвоением личности, можете написать так if (results.value == 0x1000809 //также мною замечено при использовании разных ИК приемников, частотой 36,или 38, кГц, библиотека IRremote // выдает Разные коды. //можно сделать 4 "или" (||), чтобы можно было управлять с двух разных ИК пультов
//ВАЖНО !!! (1000809) это код кнопки №1 - моего (ИК)! (инфракрасного пульта)!, - //-у вашего пульта будет другой код, замените на свой!
if (irrecv.decode(&results)) { if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1000809 || results.value == 0xF7283C77))digitalWrite(ledPin_1, HIGH); if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1008889 || results.value == 0x757FB4DF))digitalWrite(ledPin_2, HIGH);
if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1004849 || results.value == 0xB33B4597))digitalWrite(ledPin_3, HIGH); if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x100C8C9 || results.value == 0x3C03E507))digitalWrite(ledPin_4, HIGH);
//эта кнопка пульта для (увеличения или уменьшения)скорости поворота servo. // начинаем увеличивать скорость на одну позицию speed_PWM++; // и ставим ограничение на количество скоростей if (speed_PWM > 51) // дойдя до 51 скорости,сбрасываемся на первую скорость > 51)speed_PWM=1; // записываем в ячейку №3 EEPROM значение speed_PWM
if(digitalRead(timer_ledPIN) == HIGH && (results.value == 0x1002829 || results.value == 0xE705551F)) speed_PWM=speed_PWM+1,EEPROM.write(3,speed_PWM); if (speed_PWM > 51)speed_PWM=1; //Serial.println(EEPROM.read(3));
//для визуального контроля за состоянием скоростной коробки передач (спидометр),используем светодиод speed_PWM_ledPin //(увеличивая или уменьшая)PWM сигнал (analogWrite) "записываем в светодиод" значения от переменной speed_PWM, // для контрастности изменений в яркости, умножаем speed_PWM на 5 (speed_PWM*5)
analogWrite(speed_PWM_ledPin,speed_PWM*5); //Serial.println(speed_PWM);
irrecv.resume(); } }
// уникальность этого sketch в том, что не используется ни одного delay();. // Благодаря этому, значение (плавность поворота servo) высокое. // Есть возможность параллельно выполнять в постоянном режиме другие процессы.
|