Здраствуйте. Не могу найти примера для того, чтобы на его базе написать скетч. Может, кто-то поможет советом. Я хочу сделать следующее: подключаем к ардуино датчик движения, мотор-шилд и мотор-редуктор к мотор-шилду. Когда датчик улавливает движение, он отдает команду шилду, что мотор должен вращаться (допустим 2000сек по ч.с.). Как управлять моторами с помощью шилда я использую такой код: #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration) { analogWrite(SPEED_LEFT, speedLeft); analogWrite(SPEED_RIGHT, speedRight); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); delay(duration); } void setup() { for(int i = 5; i <= 8; i++) pinMode(i, OUTPUT); } void loop() { go(255, 0, true, false, 2000); } а вот как написать скетч для PIR сенсора, чтобы он включал мотор... Можно ли управляющий скетч вписать в голове моего скетча управления моторами? Pir-сенсор подключается при этом к ардуино или к шилду? И еще вопрос: можно ли вместо времени вращения для мотора указать градусы поворота? Как это сделать...
PIR сенсор подключается к ардуине. Полазив по форумам найдёте кучу примеров работы с ним. Когда всё слепите и будут непонятки - тогда вопросы в студию. Для поворота моторов на градусы нужен или шаговый двигатель или dc мотор с энкодером высокого разрешения плюс программа для считывания данных с энкодера и перевод в градусы. С шаговиком проще - там легче оперировать с шагами и к ним привязать градусы.
Градусы поворота можно задать для шагового двигателя (через количество шагов) или сервы (которая обычная, 0-180 градусов). Для обычного коллекторного двигателя даже с энкодером не хватит реакции системы, чтобы точно его остановить. Pir сенсор подключается к пину ардуины. Если подключен шилд, то транзитом через шилд. Главное, не использовать пины, задействованные шилдом (в случае мотора 4, 5, 6, 7), чтобы не мешать шилду. Pir лучше проверять через прерывание (т.е. подклбючать к пину 2 или 3). В теории прерывание Соответственно, в прерывании устанавливать значение переменной, а в loop реагировать на это значение, делать дело, сбрасывать значение. Что-то вроде такого: Код (Text): volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало unsigned long int motionsensorontime=0; #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 // задержка на 2000 с= 2000000 мс #define MOTO_DURATION 2000000 void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight) { analogWrite(SPEED_LEFT, speedLeft); analogWrite(SPEED_RIGHT, speedRight); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); } void stop() { go(0, 0, true, false); } void setup() { Serial.begin(9600)l; pinMode(3, INPUT); // сенсор к третьему пину, прерывание1 attachInterrupt(1, MotionSensorInterrupt, RISING); } void loop() { if (motionsensoron==2) { motionsensoron=0; Serial.println("Motion Sensor ON!"); go(255, 0, true, false); Serial.println("Motion sensor sleep"); motionsensorontime=millis(); } if (motionsensoron==0) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=1; stop(); Serial.println("Motion sensor ready"); } } } void MotionSensorInterrupt() { if (motionsensoron==1) motionsensoron=2; }
Спасибо за ответы. Скажите , пожалуйста, в даном коде если я подключу действие второго мотора таким образом: volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало unsigned long int motionsensorontime=0; #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 // задержка на 2000 с= 2000000 мс #define MOTO_DURATION 2000000 void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration) { analogWrite(SPEED_LEFT, speedLeft); analogWrite(SPEED_RIGHT, speedRight); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); } void stop() { go(0, 0, true, false); } void setup() { Serial.begin(9600)l; pinMode(3, INPUT); // сенсор к третьему пину, прерывание1 attachInterrupt(1, MotionSensorInterrupt, RISING); } void loop() { if (motionsensoron==2) { motionsensoron=0; Serial.println("Motion Sensor ON!"); go(255, 0, true, false, 10000); go(0, 255, true, true, 10000); go(0, 255, true, true, 10000); go(255, 0, false, true, 10000); Serial.println("Motion sensor sleep"); motionsensorontime=millis(); } if (motionsensoron==0) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=1; stop(); Serial.println("Motion sensor ready"); } } } void MotionSensorInterrupt() { if (motionsensoron==1) motionsensoron=2; } Таким образом, по моей задумке, последовательность действий такая: срабатывает датчик движения, он дает команду первому мотору вращаться 10сек, после этого первый мотор отключается, вращается второй мотор 10сек., потом второй мотор вращается 10сек. в обратном направлении, останавливается, вращается первый мотор 10сек в обратном направлении. Правильно? Работать будет, как вы думаете?
тут я ошыбочку допустил будет так: go(255, 0, true, false, 10000); go(0, 255, true, true, 10000); go(0, 255, true, false, 10000); go(255, 0, false, true, 10000);
В данном варианте кода передавать длительность в go бессмысленно. Нужно или обрабатывать длительности и переходы между состояниями в блоке if (motionsensoron==0) или вернуть delay(duration); в go и выкинуть все, что связано с обработкой состояний. Если самый простой вариант, то получится примерно так: Код (Text): volatile int motionsensoron=1; // 1-ожидание, 0-пауза, 2-сработало #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 // задержка на 2000 с= 2000000 мс #define MOTO_DURATION 2000000 void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight, int duration) { analogWrite(SPEED_LEFT, speedLeft); analogWrite(SPEED_RIGHT, speedRight); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); delay(duration); analogWrite(SPEED_LEFT, 0); analogWrite(SPEED_RIGHT,0); } void stop() { go(0, 0, true, false); } void setup() { Serial.begin(9600); pinMode(3, INPUT); // сенсор к третьему пину, прерывание attachInterrupt(1, MotionSensorInterrupt, RISING); } void loop() { if (motionsensoron==2) { motionsensoron=0; Serial.println("Motion Sensor ON!"); Serial.println("Motion sensor sleep"); go(255, 0, true, false, 10000); go(0, 255, true, true, 10000); go(0, 255, true, false, 10000); go(255, 0, false, true, 10000); motionsensoron=1; } } void MotionSensorInterrupt() { if (motionsensoron==1) motionsensoron=2; }
В этом месте проверка кода требует добавить значение duration void stop() { go(0, 0, true, false); } Нужно ли здесь указать время остановки? Например, 2сек. void stop() { go(0, 0, true, false, 2000); } И, насколько правильно я понял код, теперь у нас должна быть последовательность: сенсор сработал, переключился в режим паузы, закрутился первый мотор в одну сторону 10сек., остановился, закрутился второй мотор в одну сторону 10сек., закрутился второй мотор 10сек. в обратную сторону, остановился, закрутился первый мотор в обратную сторону, остановился, сенсор перешел в режим ожидания движения.
Во втором варианте кода stop можно совсем выкинуть, поскольку он вообще не используется (я просто забыл выкинуть). В первом варианте stop был нужен для того, чтобы остановить двигатели потом, за пределами функции go. В принципе так же можно было бы реализовать и управление двумя двигателями, добавив количество промежуточных состояний между 0 и 1, соответствующих точкам между остановками и запусками двигателей по заданному алгоритму (). Данный вариант позволяет "нагрузить" программу "параллельными задачами", которые будут выполняться мелкими порциями независимо от того, сработал ли Pir, работают ли двигатели, или нет. Примерно так получаем третий вариант (возможны ошибки, набрасывал без проверки): Код (Text): volatile int motionsensoron=1; // 1-ожидание, 2-сработало 0- первый 3-второй 4-второй назад 5-первый назад // 3,4,5 между 0 и 1 unsigned long int motionsensorontime=0; #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 // задержка на 2000 с= 2000000 мс #define MOTO_DURATION 10000 void go(int speedLeft, int speedRight, bool reverseLeft, bool reverseRight) { analogWrite(SPEED_LEFT, speedLeft); analogWrite(SPEED_RIGHT, speedRight); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); } void stop() { go(0, 0, true, false); } void setup() { Serial.begin(9600)l; pinMode(3, INPUT); // сенсор к третьему пину, прерывание1 attachInterrupt(1, MotionSensorInterrupt, RISING); } void loop() { if (motionsensoron==2) { motionsensoron=0; Serial.println("Motion Sensor ON!"); go(255, 0, true, false); Serial.println("Motion sensor sleep"); motionsensorontime=millis(); } if (motionsensoron==0) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=3; go(0, 255, true, true); motionsensorontime=millis(); } } if (motionsensoron==3) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=4; go(0, 255, true, false); motionsensorontime=millis(); } } if (motionsensoron==4) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=5; go(255, 0, false, false); motionsensorontime=millis(); } } if (motionsensoron==5) { if ((millis()-motionsensorontime)>=MOTO_DURATION) { motionsensoron=1; stop(); Serial.println("Motion sensor ready"); } } } void MotionSensorInterrupt() { if (motionsensoron==1) motionsensoron=2; } Во втором варианте в реакции на присваивание двойки переменной состояния реализован полный цикл отработки двигателей по алгоритму с задержками. При этом выполнение программы тормозится, и выполнение любых "параллельных задач" во время отработки двигателей становится невозможным. Достоинством второго варианта является то, что он проще.
Привет я написал такой скетч для мотор шилд и датчик движения. все работает. если захочешь что то поменять например разворот или движения прямо то в моем скетче все есть. #define LED 13 #define PIR 2 #define SPEED_LEFT 6 #define SPEED_RIGHT 5 #define DIR_LEFT 7 #define DIR_RIGHT 4 void go(int speed, bool reverseLeft, bool reverseRight, int duration) { // Для регулировки скорости `speed` может принимать значения от 0 до 255, // чем болше, тем быстрее. analogWrite(SPEED_LEFT, speed); analogWrite(SPEED_RIGHT, speed); digitalWrite(DIR_LEFT, reverseLeft ? LOW : HIGH); digitalWrite(DIR_RIGHT, reverseRight ? LOW : HIGH); delay(duration); } void setup() { pinMode(PIR, INPUT); pinMode(LED,OUTPUT); for(int i = 5; i <= 8; i++) pinMode(i, OUTPUT); } void loop() { delay(1000); int pirVal = digitalRead(PIR); if (digitalRead(pirVal) == HIGH) if (pirVal == HIGH) { digitalWrite(LED, HIGH); // Задержка 1 секунда после включения питания delay(1000); // Две секуды вперёд go(80, false, false, 1000); // Разворот на 180 градусов go(125, true, false, 1350); // Две секуды вперёд go(80, false, false, 1000); // Разворот на 180 градусов в другую сторону go(125, false, true, 1300); // Две секуды вперёд go(80, false, false, 1000); // Поворот на 90 градусов go(125, true, false, 680); // Медленно назад полторы секунды go(80, true, true, 1000); // Две секуды вперёд go(80, false, false, 1000); // Поворот на 90 градусов go(125, true, false, 680); // Две секуды вперёд go(80, false, false, 1000); // Медленно назад полторы секунды go(80, true, true, 1000); // Остановка до ресета или выключения питания go(0, false, false, 0); digitalWrite (LED, LOW); delay(1000); } }