Серва и гироскоп.Где лажаю?

volondvvo
Offline
Зарегистрирован: 13.08.2013

Добрый! Вопрос такой: где ошибка? Смысл заставить серву вращаться по оси Х. Плата UNO, гироскоп - 10DOF L3G4200D ADXL345 HMC5883L BMP085 .

#include <Wire.h>
#include <L3G.h>
#include <Servo.h> //Подключаем библиотеку Servo
Servo servo ;
L3G gyro;

void setup() {
  Serial.begin(9600);
  Wire.begin();
  servo.attach(10);

  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
}

void loop() {
  gyro.read();

  Serial.print("G ");
  Serial.print("X: ");
  Serial.println((int)gyro.g.x);
 

  delay(100);
}
 void servo1()
	{
	  // Печатаем на монитор
	  Serial.println(analogRead((int)gyro.g.x));
	  int val = analogRead((int)gyro.g.x);// Создаем переменную val для чтения      analogRead
	  val= constrain(val,! 2000 ,2000);// Ограничиваем диапазон работы датчика посмотрев его на мониторе
	  
int servoAngl = map(val,! 2000, 2000, 0, 180);//Преобразуем диапазон выдаваемый датчиком в диапазон углов сервы
	   servo.write(servoAngl);// Устанавливаем серву на угол который получаем через преобразование
	 }

 

sva1509
Offline
Зарегистрирован: 07.12.2012

А где в цикле loop Вы вызываете функцию servo1() ?

 

leshak
Offline
Зарегистрирован: 29.09.2011
! 2000

Это что?

leshak
Offline
Зарегистрирован: 29.09.2011

И почитайте analogRead, особенно про то в каком диапазоне он возвращает значения.

А вообще разбирательство - лучше начинать с просмотра базовых примеров. Они идут со всеми библиотеками стандартными. File/Servo/Examples/Knob

Ну или на сайте его же посмотреть. Там с картинками

Arduino - Knob

int val = analogRead((int)gyro.g.x);

А что вы тут вообще хотели сделать? Вопрос на засыпку: и какой же пин вы тут прочитали с помощью analogRead?

sva1509
Offline
Зарегистрирован: 07.12.2012

логическое отрицание !x = 0, ели x > 0; !x = 1, если x = 0;

 

volondvvo
Offline
Зарегистрирован: 13.08.2013

спасибо ребята! Буду разбираться! Я так понял мне нужно сохранить получаемые данные с гироскопа, а только потом производить перевод в градусы для сервы?

volondvvo
Offline
Зарегистрирован: 13.08.2013

leshak 1int val = analogRead((int)gyro.g.x); пытался прочитать значения Х.

Подскажите как правильно!

leshak
Offline
Зарегистрирован: 29.09.2011

volondvvo пишет:

спасибо ребята! Буду разбираться! Я так понял мне нужно сохранить получаемые данные с гироскопа, а только потом производить перевод в градусы для сервы?

Ну вообщем да. Хотя точно тут не скажешь. Не только ардуина, но и я лично не могу однозначно понять "что вы хотите сделать". Вообщем попробуйте сначала, все-таки, с базовых примеров. Покрутить серву от переменного резистора, отдельно получить данные с гироскопа и вывести в Serial (уверен что у библиотеки гироскопа - тоже есть примеры. их разобрать - построчно). А потому уже браться за "Объединение".

leshak
Offline
Зарегистрирован: 29.09.2011

volondvvo пишет:

leshak 1int val = analogRead((int)gyro.g.x); пытался прочитать значения Х.

Подскажите как правильно!

Правильно - прочитать analogRead, посмотреть что он принимает в качестве свого параметра. Посмотреть что у вас хранится в gyro.g.x и каким боком оно отностися к тому что ждет analogRead()? И зачем вообще тут analogRead()?

Вообщем разберите построчно "что и зачем вы тут делаете". Програмирование это не "заучить правильные заклинания", а "составление пошаговой инструкции для дебила". Дебил, в данном случае, - микроконтроллер. выполняет вашу инструкцию "тупо-буквально", поэтому и инструкция должна быть "четкой и однозначной". Причем словарный запас у дебила - ограничен. Поэтому нужно пользоватся тем что описано в Программирование, что-бы объяснить ему "что ты хочешь".

volondvvo
Offline
Зарегистрирован: 13.08.2013

Немного почитал,покрутил и дибил вроде пощёл на контакт.Может немного коряво, но работает. Жду критику!

#include <Wire.h>
#include <L3G.h>
#include <Servo.h>
int val;  
Servo myservo; 

L3G gyro;

void setup() {
 
  Wire.begin();
  myservo.attach(9);

  if (!gyro.init())
  {
    Serial.println("Failed to autodetect gyro type!");
    while (1);
  }

  gyro.enableDefault();
}

void loop() {
  gyro.read();
  Serial.println((int)gyro.g.z);
  int (gyro.g.z);
  delay(100);
  val = (int(gyro.g.z));            
  val = map(val, -2000,2000, 0, 150);     and 180) 
  myservo.write(val);
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Да, в принципе все нормаьлно. Ну разве что 

"and 180)" какое-то не понятно, но , я так понимаю это уже "просто так вставилось".

 int (gyro.g.z);

Непонятно что вы тут делаете.  В строке 26. Не мешает но и полезности нет. Вообщем прямо как у  классика "Толку было с него, правда, как с козла молока,Но вреда, однако, тоже - никакого." :)

Что-бы улучшить потребительские качества, можно к примеру, в случае проблем с giro не тупо зацикливать скетч, а начинать, скажем мигать светодиодом часто. Встроенным. 13-тым. Вместо

while(1);

написать

pinMode(13,OUTPUT);
while(true){ digitalWrite(13,!digitalRead(13));delay(200);}

Использовать встроенный диод в качестве "диагностики ошибки". Что-бы не нужно было смотреть в Serial что-бы понять "почему не работает". Замигал бысторо - значит проблемы с гироскомоп.

Еще. Serial.println - вы используете. А где Serial.begin? Нужно же выставить скорость порта.

Дальше - ну вообщем-то уже тоже не обязательно. Но если планируете еще что-то делать в этом скетче, развивать его дальше - с большой долей вероятности нужно будет отказывать от delay(). Переходить на millis(). Читать пример Мигаем светодиодом без delay() и думать "как нечто подобное" у себя сделать. 

Ну и   Serial.println((int)gyro.g.z); можно тоже не так часто делать. Сам гироском опрашивать и серву крутить - можно и раз в 100 миллисекунд, как сейчас, а вот "выводить лог" - можно и реже. Что-бы и "канал не забивать", да и... все равно с такой скоростью вы не успеете глазами цифры читать :)

Итого: все вместе это скорее не "замечания", а "идеи дальнейшего развития" (ну кроме отсуствия Serial.begin - это замечание)

volondvvo
Offline
Зарегистрирован: 13.08.2013

Серва стоит в положении 90(середина). При повороте гироскопа вправо серва поворачиваеться или в сторону 0 и потом возвращается в положение 90. Вопрос на будующее : что нужно для того что бы серва не возвращалась в положение 90?

leshak
Offline
Зарегистрирован: 29.09.2011
volondvvo
Offline
Зарегистрирован: 13.08.2013

нашёл скетч на перевод значений с ADXL345 в градусы,но ось Z некоректно отображается.Она зависима от оси у. Может для  оси Z используют компас?И ешё вопрос- шаговик крутит на заданный угол который выдаёт аксель , наклонил аксель на 45 и мотор крутит 45 на градусов и крутит и крутит с задержкой 100. Я измучился весь что бы заставить  шаговик крутануть например на 45 и остановиться.


#include <Wire.h>
#include <ADXL345.h>
ADXL345 adxl;
#define DIR_PIN 2
#define STEP_PIN 3

/
int minVal = 270;
int maxVal = -270;



void setup() {
  Serial.begin(9600); 
  adxl.powerOn();
  pinMode(DIR_PIN, OUTPUT);
  pinMode(STEP_PIN, OUTPUT);

}

void loop ()
{
  int x,y,z;  
   adxl.readXYZ(&x,&y,&z); 
  
  int xRead = ((int)x);
  int yRead = ((int)y);
  int zRead = ((int)z);

  
  int xAng = map(xRead, minVal, maxVal, -180, 180);
  int yAng = map(yRead, minVal, maxVal, -180, 180);
  int zAng = map(zRead, minVal, maxVal, -180, 180);

  
  x = RAD_TO_DEG * (atan2(-yAng, -zAng) + PI);
  y = RAD_TO_DEG * (atan2(-xAng, -zAng) + PI);
  z = RAD_TO_DEG * (atan2(-yAng, -xAng) + PI);

  
  Serial.print("x: ");
  Serial.print(x);
  Serial.print(" | y: ");
  Serial.print(y);
  Serial.print(" | z: ");
  Serial.println(z);
  delay (100);
  
  rotateDeg(x, 1);
 
}
  
  

  
  



void rotateDeg(float deg, float speed)
{
  
  int dir = (deg > 0)? HIGH:LOW;
  digitalWrite(DIR_PIN,dir);



  int steps = abs(deg)*(1/0.225);
  float usDelay = (1/speed) * 70;

  for(int i=0; i < steps; i++){
    digitalWrite(STEP_PIN, HIGH);

    delayMicroseconds(usDelay);

    digitalWrite(STEP_PIN, LOW);

    delayMicroseconds(usDelay);
  }
}

 

leshak
Offline
Зарегистрирован: 29.09.2011

Школа Физика/Геометрия

Акселерометр возвращает вам ускорение самого устройства + проекцию силы тяжести на оси координат. Если у вас ось Z расположена точно вертикально, то по Z-ту вам будет возращатся ускорение 9.8  . И как бы вы не крутили устройсво вокруг оси Z акселерометр в принципе не может заметить это вращение. Проекция силы тяжести - остается точно такой же. А вот если вы его "наклонили", а потом начали вокруг Z вращать, тогда он имеет шанс заметить это вращение.

Что-бы не зависить от силы тяжести - придумали гироскопы. У него принцип определения "куда нас крутят" основан на том, что он старается сохранить свое текущее положение и замеряет силу которая "заставляет его изменить свое положение".

Гироскоп - у вас тоже есть. Но вы его - не используете. Хотя, для этого - достаточно было загуглить ваш шилд, одной из первых ссылок, к примеру статья Подключение IMU 10DOF L3G4200D+ADXL345+HMC5883L+BMP085 - Популярная робототехника

Где видно как общатся со всеми вашими устройствами. Правда на обычном C, но "принцип тот же самый" (но, практически уверен что если погуглить дольше 5-ти секунд, то найдутся и Arduino варианты). К примеру Using the GY80 10DOF module with Arduino | Fork Robotics

 

Кстати, возможно, гироскоп может через некоторое время давать "уход", "сбиватся". Поэтому время от времени его нужно калибровать. Основываясь на показаниях других дачиков (магнитометр, акселерометр).

Вообщем погуглите свое железо. Оно не редкое. Все эти задачи в среде квадрокоптеростроителей постоянно обсуждаются/решаются. У них это "чуть ли не основное" занятие :). От ее решения зависит разобъется ли в щепки девайс за пару килобаксов или нет :)

Начните хотябы с принципа действия гироскопа и акселерометра. Что-бы понимать область их применимости, их возможностей и ограничений.