Проблемы с шаговиками и ультразвуковым датчиком в связке
- Войдите на сайт для отправки комментариев
Всем привет. Возможно я пложу темы, извините, но похожих тем много , а схожей проблемы я не нашёл. Суть проблемы такова - вот видео http://www.youtube.com/watch?v=r4kN3lEvER4&list=PLj_E1AdSVXNJnP2S9gUzfplKMUphPgh7j . Цель - заставить ехать робота вперёд, пока расстояние до препятствия будет более 50 см, если меньше, то включаем один двигатель из двух до тех пор , пока расстояние не увеличется, после чего включаем 2 двигаеля. Проблема в том , что почемуто если просто использовать скетч без условий (включить двигатели оба), то оба двигателя одновременно довольно шустро крутятся , если же вставить код определения расстояния и условия то получается картина что когда нужно чтобы крутилось 2 привода - они еле крутятся рывками как видно на видео (иногда вообще не предсказуемо - то быстро то медленно), а вот когда расстояние меньше 50 и нужно включить 1 двигатель для поворота, то он вполне нормально работает. Вот скетч
#include <AccelStepper.h>
#include <AFMotor.h>
#include "Ultrasonic.h"
AF_Stepper motor1(48, 1);
AF_Stepper motor2(48, 2);
Ultrasonic sonic(22, 24);
const int Trig = 22; //Ultrasonic
const int Echo = 24;
int time_us;
int distance_sm;
int dist;
// you can change these to DOUBLE or INTERLEAVE or MICROSTEP!
void forwardstep1() {
motor1.onestep(FORWARD, DOUBLE);
}
void backwardstep1() {
motor1.onestep(BACKWARD, DOUBLE);
}
void forwardstep2() {
motor2.onestep(FORWARD, DOUBLE);
}
void backwardstep2() {
motor2.onestep(BACKWARD, DOUBLE);
}
AccelStepper stepper1(backwardstep1, forwardstep1 ); // use functions to step
AccelStepper stepper2(forwardstep2, backwardstep2); // use functions to step
void setup()
{
Serial.begin(9600); // set up Serial library at 9600 bps
Serial.println("Stepper test!");
stepper1.setMaxSpeed(100);
stepper1.setSpeed(100);
stepper2.setMaxSpeed(100);
stepper2.setSpeed(100);
}
void loop()
{
dist=sonic.Ranging(CM);
Serial.println(dist);
if (dist>0 & dist<50) {
// stepper1.runSpeed();
stepper2.runSpeed();
}
else
{
stepper2.runSpeed();
stepper1.runSpeed();
}
}
Подскажите пож в чём тут проблема, не могу понять.
Странное ж дело...
void loop() { static uint32_t miilis_prev; if(millis()-miilis_prev >= 200) { miilis_prev = millis(); dist=sonic.Ranging(CM); Serial.println(dist); } if(dist <= 0 || dist >= 50) stepper2.runSpeed(); stepper1.runSpeed(); }Извините, не совсем понимаю этот код , что это за процедура
millis()и смысл этой строчкиstaticuint32_t miilis_prev;Программирование
Сори за ликбез )) , но поменяв код процедуры loop на Ваш, ситуация не изменилась, при расстоянии больше 50 оба дигателя медленно дёргаясь крутятся вперёд, при расстоянии меньше 50 первый двигатель стоит и нормально начинает крутиться второй двигатель
Serial тормозит шаговики. Попробуйте закомментировать строку 45.
Что-то я вообще запутался, в коде нигде не указано, что при расстоянии менее 50 см крутится только один двигатель, но происходит именно так .
void loop() { static uint32_t miilis_prev; if(millis()-miilis_prev >= 200) { miilis_prev = millis(); dist=sonic.Ranging(CM); Serial.println(dist); } if(dist <= 0 || dist >= 50) stepper2.runSpeed(); stepper1.runSpeed(); }Потому что это вам только кажется что не указано.
vvadim - закоментировал, но не помогло. Ситуация таже. Не могу понять в чём проблема. Причём иногда всётаки оба моторв на пару секунд начинают работать нормально. Может проблема в схеме подключения?
НУ если без условий крутятся, значит подключены нормально. Я сталкивался с тем, что даже антидребезг и вывод на дисплей тормозит шаговик. Вполне может датчик тормозить. Попробуйте его вывести в отдельную функцию
Кажись я заметил какую-то закономерность (если расстояние меньше 50 один мотор крутится норм, если расстояние больше 50 но меньше гдето 70 оба крутятся нормально, но когда на датчике проскакивает 1000-5000 то моторы сразу начинают еле крутиться дёргаясь ). Общим ещё поексперементирую с условиями, но гдето здесь зарыта собака. Паралельно попробую вынести измерение расстояния в функцию.
Проблема оказывается не в этом, maksim был прав, частично, его код действительно заработал, только 200 нужно было поменять минимум на 1000 , и тогда в теч 1 с. моторы работали нормально, поставим 2000 то 2с. мотры работают нормально, но если в теч этих 2-х с. изменяется расстояние например до 20см реакции никакой, тоесть моторы так и крутятся, так что эксперементируем дальше.
Проблема в том что функция sonic.Ranging(CM); блокирующая, а значит пока датчик измеряет расстояние моторы останавливаются и чем больше расстояние тем дольше происходит измерение - тем тодьше стоят моторы.
Я об этом догадывался, а как эту проблему решить ?Попробовал загнать измерение расстояния в процедуру, не помогло.
int usonic() { int dist; dist=sonic.Ranging(CM); delay(200); return dist; }Конечно не помогло. Нужно писать неблокирующую функцию работы с датчиком.
что то в этом роде ?
const int Trig = 3; const int Echo = 2; int sonar() { digitalWrite(Trig, HIGH); delayMicroseconds(10); digitalWrite(Trig, LOW); time_us=pulseIn(Echo, HIGH); distance_sm=time_us/58; return distance_sm; }это тоже не помогло(((. Кто знает как решить проблему, подскажите пож.
Это и не поможет, неблокирующие функции не имеют задержек, в то время как у вас есть delayMicroseconds();, и pulseIn(); - которая тоже блокирующая.
Измерить расстояние без задержки нельзя.
Ну если вам нельзя - значит нельзя. Мне, например, да и многим другим можно.
All, можно ли на одном МК держать датчик а на другом двигатели? Будет ли блокировка на время обмена инфой, если связать их по i2c?
А зачем, если на одном мк можно
Конечно. Все просто.
Примером мигаем без делэй дергаем Trig и ловим в прерывании фронты Echo подключив заведомо на ногу с прерыванием.
Спасибо максим за направление в котром нужно копать, смысл функции attachinterrupt вроде бы понятен, но видимо у меня не получается правильно её применить. вот мой вариант кода (он ситуацию не изменил)))
AF_Stepper motor1(48, 1); AF_Stepper motor2(48, 2); Ultrasonic sonic(21, 24); void forwardstep1() { motor1.onestep(FORWARD, DOUBLE); } void backwardstep1() { motor1.onestep(BACKWARD, DOUBLE); } void forwardstep2() { motor2.onestep(FORWARD, DOUBLE); } void backwardstep2() { motor2.onestep(BACKWARD, DOUBLE); } AccelStepper stepper1(backwardstep1, forwardstep1 ); // use functions to step AccelStepper stepper2(forwardstep2, backwardstep2); // use functions to step void setup() { Serial.begin(9600); // set up Serial library at 9600 bps stepper1.setMaxSpeed(100); stepper1.setSpeed(100); stepper2.setMaxSpeed(100); stepper2.setSpeed(100); attachInterrupt(2,startt,CHANGE); } void loop() { dist=sonic.Ranging(CM); Serial.println(dist); if (dist>0 & dist<50) { // stepper1.runSpeed(); stepper2.runSpeed(); } else { start(); } } void startt() { stepper2.runSpeed(); stepper1.runSpeed(); }Как я понимаю , садим выход Trig датчика на 21 пин ардуины, для функции attachinterrupt это параметр 2, задаем функцию , которая должна вызываться по внешнему прерыванию - у меня это startt() и CHANGE прерывание вызывается при смене значения на порту, с LOW на HIGH и наоборот. Но я явно чтото не то делаю либо недопонимаю. Укажите пож на ошибку и если можно правильный код. Спасибо конечно maksim за направление, я уже понял что он знает намного больше меня, но хотелось бы более проще и нагляднее нежели коментарии типа многие знают а ты сюда зря зашёл и в качестве снисхождения обратим на это внимание.
Trig может быть на любом выводе, на прерывание нужно подключить Echo. И библиотеку Ultrasonic тут никак нельзя использовать - она блокирующая. И вы не поняли о чем идет речь.
Я понял что я напутал ))) сейчас пытаюсь вырулить, пока не уснул мож чего стоящее и придумаю.)
Вот новый код, направление правильное ? Код правда не компилится на 35 строке выдаёт expected `)' before ';' token. Но чтото не соображу где там не хватает ). Но больше меня интересует ход мыслей , правильно или нет.
#include <AccelStepper.h> #include <AFMotor.h> #define Trig 22; #define INTERVAL 10UL; AF_Stepper motor1(48, 1); AF_Stepper motor2(48, 2); // const int Trig = 22; //Ultrasonic int Echo = 21; // int Trig = 22; volatile int dist = 0; volatile int time = 0; // you can change these to DOUBLE or INTERLEAVE or MICROSTEP! void forwardstep1() { motor1.onestep(FORWARD, DOUBLE); } void backwardstep1() { motor1.onestep(BACKWARD, DOUBLE); } void forwardstep2() { motor2.onestep(FORWARD, DOUBLE); } void backwardstep2() { motor2.onestep(BACKWARD, DOUBLE); } AccelStepper stepper1(backwardstep1, forwardstep1 ); // use functions to step AccelStepper stepper2(forwardstep2, backwardstep2); // use functions to step void setup() { Serial.begin(9600); // set up Serial library at 9600 bps Serial.println("Stepper test!"); pinMode(Trig, OUTPUT); stepper1.setMaxSpeed(100); stepper1.setSpeed(100); stepper2.setMaxSpeed(100); stepper2.setSpeed(100); attachInterrupt(2,sonar,RISING); } void loop() { static unsigned long PreviousMillis = 0; if( millis() - PreviousMillis > INTERVAL) { PreviousMillis = millis(); digitalWrite(Trig,!digitalRead(Trig)); } // Serial.println(dist); if (dist>0 && dist<50) { stepper2.runSpeed(); } else { stepper2.runSpeed(); stepper1.runSpeed(); } } void sonar() { time=digitalWrite(Echo,time); dist=time/58; }Правильное.
Проблемы с компиляцией в процедуре
volatile int Echo = 21; volatile int dist = 0; volatile int time = 0; void sonar() { time=digitalWrite(Echo,time); dist=time/58; }выдает следующую ошибку по строке
sketch_4.ino: In function 'void sonar()':
sketch_4:59: error: void value not ignored as it ought to be
А что вы пытаетесь сделать этой строкой?
считать в переменнную time параметр ножки Echo , после чего рассчитать расстояние в переменную dist. Чтобы потом эту dist использовать в условиях для алгоритма поведения моторов.
мдааа, в элементарных вещах запутался. Но у меня вопроос функция pulseIn в моей процедупе sonar использовать можно? А то она у меня кроме 0 ничего не выдаёт.
#17
да блокирующая, но мож во внешнем прерывании она бы и сработала, вот и спрашиваю. Но раз тут тупик, тогда как правильно функцию sonar описать ?