Проблемы с шаговиками и ультразвуковым датчиком в связке

alexpzas
Offline
Зарегистрирован: 09.06.2013

Всем привет. Возможно я пложу темы, извините, но похожих тем много , а схожей проблемы я не нашёл. Суть проблемы такова - вот видео 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();
  }
}
 

Подскажите пож в чём тут проблема, не могу понять.

maksim
Offline
Зарегистрирован: 12.02.2012

Странное ж дело...

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();
}

 

alexpzas
Offline
Зарегистрирован: 09.06.2013

Извините, не совсем понимаю  этот код , что это за процедура millis()  и смысл этой строчки  static uint32_t miilis_prev;

maksim
Offline
Зарегистрирован: 12.02.2012
alexpzas
Offline
Зарегистрирован: 09.06.2013

Сори за ликбез )) , но поменяв код процедуры loop на Ваш, ситуация не  изменилась, при расстоянии больше 50 оба дигателя медленно дёргаясь крутятся вперёд, при расстоянии меньше 50 первый двигатель стоит и нормально начинает крутиться второй двигатель

vvadim
Offline
Зарегистрирован: 23.05.2012

Serial тормозит шаговики. Попробуйте закомментировать строку 45. 

alexpzas
Offline
Зарегистрирован: 09.06.2013

Что-то я вообще запутался, в коде нигде не указано, что при расстоянии менее 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();
}
 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Потому что это вам только кажется что не указано.

alexpzas
Offline
Зарегистрирован: 09.06.2013

vvadim - закоментировал, но не помогло. Ситуация таже.  Не могу понять в чём проблема. Причём иногда всётаки оба моторв на пару секунд начинают работать нормально. Может проблема в схеме подключения?

vvadim
Offline
Зарегистрирован: 23.05.2012

НУ если без условий крутятся, значит подключены нормально. Я сталкивался с тем, что даже антидребезг и вывод на дисплей тормозит шаговик. Вполне может датчик тормозить. Попробуйте его вывести в отдельную функцию

alexpzas
Offline
Зарегистрирован: 09.06.2013

Кажись я заметил какую-то закономерность (если расстояние меньше 50 один мотор крутится норм, если расстояние больше 50 но меньше гдето 70 оба крутятся нормально, но когда на датчике проскакивает 1000-5000 то моторы сразу начинают еле  крутиться дёргаясь ). Общим ещё поексперементирую с условиями, но гдето здесь зарыта собака. Паралельно попробую вынести измерение расстояния в функцию.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Проблема оказывается не в этом, maksim был прав, частично, его код действительно заработал, только 200 нужно было поменять минимум на 1000 , и тогда в теч 1 с. моторы работали нормально, поставим  2000 то  2с. мотры работают нормально, но если в теч этих 2-х с. изменяется расстояние например до 20см реакции никакой, тоесть моторы так и крутятся, так что эксперементируем дальше.

maksim
Offline
Зарегистрирован: 12.02.2012

Проблема в том что функция sonic.Ranging(CM); блокирующая, а значит пока датчик измеряет расстояние моторы останавливаются и чем больше расстояние тем дольше происходит измерение - тем тодьше стоят моторы.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Я об этом догадывался, а как эту проблему решить ?Попробовал загнать измерение расстояния в процедуру, не помогло.


int usonic()
{
int dist;
dist=sonic.Ranging(CM);
delay(200);
return dist;
}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Конечно не помогло. Нужно писать неблокирующую функцию работы с датчиком.

alexpzas
Offline
Зарегистрирован: 09.06.2013

что то в этом роде ?

 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;
  }  

 

alexpzas
Offline
Зарегистрирован: 09.06.2013

это тоже не помогло(((. Кто знает как решить проблему, подскажите пож.

maksim
Offline
Зарегистрирован: 12.02.2012

Это и не поможет, неблокирующие функции не имеют задержек, в то время как у вас есть delayMicroseconds();, и pulseIn(); - которая тоже блокирующая.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Измерить расстояние без задержки нельзя.

maksim
Offline
Зарегистрирован: 12.02.2012

Ну если вам нельзя - значит нельзя. Мне, например, да и многим другим можно.

std
Offline
Зарегистрирован: 05.01.2012

All, можно ли на одном МК держать датчик а на другом двигатели? Будет ли блокировка на время обмена инфой, если связать их по i2c?

vvadim
Offline
Зарегистрирован: 23.05.2012

А зачем, если на одном мк можно

 

maksim
Offline
Зарегистрирован: 12.02.2012

Конечно. Все просто.
Примером мигаем без делэй дергаем Trig и ловим в прерывании фронты Echo подключив заведомо на ногу с прерыванием.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Спасибо максим за направление в котром нужно копать, смысл функции 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 за направление, я уже понял что он знает намного больше меня, но хотелось бы более проще и нагляднее нежели коментарии типа  многие знают а ты сюда зря зашёл и в качестве снисхождения обратим на это внимание.

maksim
Offline
Зарегистрирован: 12.02.2012

Trig может быть на любом выводе, на прерывание нужно подключить Echo. И библиотеку Ultrasonic тут никак нельзя использовать - она блокирующая. И вы не поняли о чем идет речь.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Я понял что я напутал ))) сейчас пытаюсь вырулить, пока не уснул мож чего стоящее и придумаю.)

alexpzas
Offline
Зарегистрирован: 09.06.2013

Вот новый код, направление правильное ? Код правда не компилится на 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;
    
  }  
 

 

maksim
Offline
Зарегистрирован: 12.02.2012

Правильное.

alexpzas
Offline
Зарегистрирован: 09.06.2013

Проблемы с компиляцией в процедуре

volatile int Echo = 21;
volatile int dist = 0;
volatile int time = 0;
void sonar()
  {
    time=digitalWrite(Echo,time);
    dist=time/58;
  }  

выдает следующую ошибку по строке

 time=digitalWrite(Echo,time);

sketch_4.ino: In function 'void sonar()':
sketch_4:59: error: void value not ignored as it ought to be

maksim
Offline
Зарегистрирован: 12.02.2012

А что вы пытаетесь сделать этой строкой?

alexpzas
Offline
Зарегистрирован: 09.06.2013

считать в переменнную time параметр  ножки Echo , после чего рассчитать расстояние в переменную dist. Чтобы потом эту dist использовать в условиях для алгоритма поведения моторов.

maksim
Offline
Зарегистрирован: 12.02.2012
alexpzas
Offline
Зарегистрирован: 09.06.2013

мдааа, в элементарных вещах запутался. Но у меня вопроос функция pulseIn в моей процедупе sonar использовать можно? А то она у меня кроме 0 ничего не выдаёт.

maksim
Offline
Зарегистрирован: 12.02.2012

#17

alexpzas
Offline
Зарегистрирован: 09.06.2013

да блокирующая, но мож во внешнем прерывании  она бы и сработала, вот и спрашиваю. Но раз тут тупик, тогда как правильно функцию sonar описать ?