Акселерометр MPU6050

Mig_1337
Offline
Зарегистрирован: 02.01.2019

Всем здрасти) Помогите пожалуйста.

Имеется аклерерометр MPU 6050, Arduino UNO. Собрал скетч из кучи разных. В работе все устраивает, кроме одного. Как сделать так, чтобы при нажитии на кнопку в монитор порта записывалось одно конкретное значение угла.

Есть идея типа: 

if нажата копка->включается в работу скетч-> выводит значение угла (одно)

else retern 0

сильно не бейте))

#include "I2Cdev.h"
#include "MPU6050.h"


#define TO_DEG 57.29577951308232087679815481410517033
#define T_OUT 20


MPU6050 accel;

float angle_ax;
long int t_next;

int val[3];
int val_filter;
byte index;

// медианный фильтр из 3ёх значений
float middle_of_3(float a, float b, float c) {
int middle;
if ((a <= b) && (a <= c)) {
middle = (b <= c) ? b : c;
}
else {
if ((b <= a) && (b <= c)) {
middle = (a <= c) ? a : c;
}
else {
middle = (a <= b) ? a : b;
}
}
return middle;
}


float clamp(float v, float minv, float maxv){
    if( v>maxv )
        return maxv;
    else if( v<minv )
        return minv;
    return v;
}

void setup() {
    Serial.begin(9600);
    accel.initialize(); // первичная настройка датчика
    Serial.println(accel.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}

void loop() {
    long int t = millis();
    if( t_next < t ){
        int16_t ax_raw, ay_raw, az_raw, gx_raw, gy_raw, gz_raw;
        float ay,gx;

        t_next = t + T_OUT;
        accel.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_raw, &gy_raw, &gz_raw);
 
        // сырые данные акселерометра нужно преобразовать в единицы гравитации
        // при базовых настройках 1G = 4096
        ay = ay_raw / 16444.0;
        // на случай, если на акселерометр действуют посторонние силы, которые могут
        // увеличить ускорение датчика свыше 1G, установим границы от -1G до +1G  
        ay = clamp(ay, -4.0, 4.0);

        // функция acos возвращает угол в радианах, так что преобразуем
        // его в градусы при помощи коэффициента TO_DEG
        if( ay >= 0){
            angle_ax = 90 - TO_DEG*acos(ay);
        } else {
            angle_ax = TO_DEG*acos(-ay) - 90;
        }
  
       //Serial.println(angle_ax); // вывод в порт угла поворота вокруг оси X
}


 {
if (++index > 2) index = 0; // переключаем индекс с 0 до 2 (0, 1, 2, 0, 1, 2…)
val[index] = angle_ax; // записываем значение с датчика в массив
// фильтровать медианным фильтром из 3ёх ПОСЛЕДНИХ измерений
val_filter = middle_of_3(val[0], val[1], val[2]);
Serial.println(val_filter); // для примера выводим в порт
}

}

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Так, а где попытка это сделать?

Скетч не самописный, самостоятельно решить проблему Вы даже не попытались ... см. п. 5 здесь.

 

Mig_1337
Offline
Зарегистрирован: 02.01.2019

Да, скетч не лично мной с 0 разрабатывался, но корректировал я его под свои надобности 3 дня, много чего добавлено. Вопрос лишь в том, как остановить этот поток чисел в мониторе порта? Предполагаю что это делается какой то командой типа pause или stop. Я даже не знаю как загуглить, чтобы почитать что либо на эту тему или премьер скетча в котором это реализовано. Я не прошу что то за меня писать. Просьба направить куда копать.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Mig_1337 пишет:

 

Есть идея типа: 

if нажата копка->включается в работу скетч-> выводит значение угла (одно)

else retern 0

 

Идея хорошая. Попробуйте воплотить ее в жизнь. 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Mig_1337 пишет:
Просьба направить куда копать.
Для начала - https://drive.google.com/open?id=0B9r7cRXQ4DU4dTBtRFpub0tfV00

Изучите, разберите примеры и делайте. Пока Вы не делаете сами, никто за Васделать не будет.

Mig_1337
Offline
Зарегистрирован: 02.01.2019

В чем ошибка? Почему цикл не останавливается при (val_filter != val_filter) (в самом конце)

Плоттер выдает следующее: 

0

-5

-5

-5

#include "I2Cdev.h"
#include "MPU6050.h"


#define TO_DEG 57.29577951308232087679815481410517033
#define T_OUT 20


MPU6050 accel;

float angle_ax;
long int t_next;

int val[3];
int val_filter;
byte index;

// медианный фильтр из 3ёх значений
float middle_of_3(float a, float b, float c) {
int middle;
  if ((a <= b) && (a <= c)) {
   middle = (b <= c) ? b : c;
}
  else {
  if ((b <= a) && (b <= c)) {
  middle = (a <= c) ? a : c;
}
  else {
  middle = (a <= b) ? a : b;
  }
  }
  return middle;
}


float clamp(float v, float minv, float maxv){
    if( v>maxv )
        return maxv;
    else if( v<minv )
        return minv;
    return v;
}

void setup() {
    Serial.begin(9600);
    accel.initialize(); // первичная настройка датчика
    Serial.println(accel.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}

void loop() {
    long int t = millis();
    if( t_next < t ){
        int16_t ax_raw, ay_raw, az_raw, gx_raw, gy_raw, gz_raw;
        float ay,gx;

        t_next = t + T_OUT;
        accel.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_raw, &gy_raw, &gz_raw);
 
        // сырые данные акселерометра нужно преобразовать в единицы гравитации
        // при базовых настройках 1G = 4096
        ay = ay_raw / 16444.0;
        // на случай, если на акселерометр действуют посторонние силы, которые могут
        // увеличить ускорение датчика свыше 1G, установим границы от -1G до +1G  
        ay = clamp(ay, -4.0, 4.0);

        // функция acos возвращает угол в радианах, так что преобразуем
        // его в градусы при помощи коэффициента TO_DEG
        if( ay >= 0){
            angle_ax = 90 - TO_DEG*acos(ay);
        } else {
            angle_ax = TO_DEG*acos(-ay) - 90;
        }
        }
   do {
      if (++index > 2) index = 0; // переключаем индекс с 0 до 2 (0, 1, 2, 0, 1, 2…)
      val[index] = angle_ax; // записываем значение с датчика в массив
      // фильтровать медианным фильтром из 3ёх ПОСЛЕДНИХ измерений
       val_filter = middle_of_3(val[0], val[1], val[2]);
    delay(250);
   }
   while (val_filter != val_filter);
Serial.println(val_filter);
}

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Mig_1337 пишет:

В чем ошибка? 

В том, что Вы проигнорировали совет изучить книгу и продолжаете пытаться что-то сделать даже не с нулевыми, а с отрицательными знаниями (отрицательными потому, что Вы что-то слышали, напревильно поняли, и считаете это неправильно понятное"знаниями").

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

зачем Вы спрашиваете советов, если их не слушаете?

Mig_1337
Offline
Зарегистрирован: 02.01.2019

Пример из книжки)

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Mig_1337 пишет:

Пример из книжки)

Что "пример из книжки"?

Mig_1337
Offline
Зарегистрирован: 02.01.2019

Do...while 

не понимаю почему при выполнении условия val_filter != val_filter программа не останавливается.

Do-выполнять какое то действие while(пока), условно говоря, 15 не равно 15, как только они сравнялись цикл по идее должен остановиться. Что не так в моих мыслях?))

   do {

      if (++index > 2) index = 0; // переключаем индекс с 0 до 2 (0, 1, 2, 0, 1, 2…)

      val[index] = angle_ax; // записываем значение с датчика в массив

      // фильтровать медианным фильтром из 3ёх ПОСЛЕДНИХ измерений

       val_filter = middle_of_3(val[0], val[1], val[2]);

    delay(250);

   }

   while (val_filter != val_filter);

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Проблема в том, что 15 всегда остается равным 15и.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Mig_1337 пишет:

Do...while 

не понимаю почему при выполнении условия val_filter != val_filter программа не останавливается.

Do-выполнять какое то действие while(пока), условно говоря, 15 не равно 15, как только они сравнялись цикл по идее должен остановиться. Что не так в моих мыслях?))

   do {

      if (++index > 2) index = 0; // переключаем индекс с 0 до 2 (0, 1, 2, 0, 1, 2…)

      val[index] = angle_ax; // записываем значение с датчика в массив

      // фильтровать медианным фильтром из 3ёх ПОСЛЕДНИХ измерений

       val_filter = middle_of_3(val[0], val[1], val[2]);

    delay(250);

   }

   while (val_filter != val_filter);

 

Почитайте про
while()
{
  
}
 
А также
 
do
{
  
}
while();
 
и посмотрите разницу!!!
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Mig_1337 пишет:

не понимаю почему при выполнении условия val_filter != val_filter программа не останавливается.

Do-выполнять какое то действие while(пока), условно говоря, 15 не равно 15, как только они сравнялись цикл по идее должен остановиться.

Это можно занести в анналы. 

-NMi-
Offline
Зарегистрирован: 20.08.2018

Или "слить" в канналы )))

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Mig_1337 пишет:

цикл по идее должен остановиться. Что не так в моих мыслях?))

Что не так в Ваших мыслях, я Вам уже говорил в посте #6. Не так то, что вместо изучения материала, Вы пытаетесь решить проблему методом наскока, выхватив какую-то случайную фразу изи какого-то руководства, без понимания её смысла. Изучите предмет систематически, вопросы снимутся.

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

Mig_1337
Offline
Зарегистрирован: 02.01.2019

Скоро мозг взлетит. Перепробовал все варианты и while, и do..while, и for. Никак не могу остановить этот гребанный цикл. На данный момент программа каждые 5 сек выдает значение угла. Т.е. имеется условие: for (int i=0; i<5; i++), программа его выполняет и возвращается в начало. Использовал break. Соответственно значение угла отображалось каждую секунду (понятно почему). Не понятно почему программа не выдает 5 значений угла и на этом не останавливается?

#include "I2Cdev.h"
#include "MPU6050.h"

#define TO_DEG 57.29577951308232087679815481410517033

MPU6050 accel;

float angle_ax;

float clamp(float v, float minv, float maxv){
    if( v>maxv )
        return maxv;
    else if( v<minv )
        return minv;
    return v;
}

void setup() {
    Serial.begin(9600);
    accel.initialize();
    Serial.println(accel.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
}

void loop() {
   
        for (int i=0; i<5; i++){
          
        int16_t ax_raw, ay_raw, az_raw, gx_raw, gy_raw, gz_raw;
        float ay,gx;
        accel.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_raw, &gy_raw, &gz_raw);
        ay = ay_raw / 16444.0;
        ay = clamp(ay, -4.0, 4.0);
        
         if( ay >= 0){
            angle_ax = 90 - TO_DEG*acos(ay);
        } else {
            angle_ax = TO_DEG*acos(-ay) - 90;
        }
        delay (1000);
        }
   
Serial.println(angle_ax);
}

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Прочитайте https://drive.google.com/file/d/0B9r7cRXQ4DU4dTBtRFpub0tfV00/view как вам, тут, уже советовали. 

 

Mig_1337
Offline
Зарегистрирован: 02.01.2019

да я читал и на ютубе смотрел, делаю по аналогии,а получаю все не то

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Mig_1337 пишет:

да я читал и на ютубе смотрел, делаю по аналогии,а получаю все не то

 

Из книги

loop()
После вызова функции setup() – управление переходит к функции loop() , которая
делает в точности то, что означает её имя — непрерывно выполняется, позволяя...
 
Ну и почему ваша программа должна остановиться?
Mig_1337
Offline
Зарегистрирован: 02.01.2019

Cпасибо за подсказку)) то, что loop () выполняется непрерывно я отчетливо помнил и после своего предыдущего примера окончательно это освоил. Просто не мог подумать, что в setup() может находиться весь код) Возможно скетч выглядит не красиво, но его работа на данный момент меня полностью устраивает) перехожу на следующий этап)) 

PS: не ругугайтесь на меня) я ж учусь пока.. не думаю, что дядя ЕвгенийП пытался программировать в 15 лет)

#include "I2Cdev.h"
#include "MPU6050.h"

#define TO_DEG 57.29577951308232087679815481410517033

MPU6050 accel;

float angle_ax;

float clamp(float v, float minv, float maxv){
    if( v>maxv )
        return maxv;
    else if( v<minv )
        return minv;
    return v;
}

void setup(){
  
    Serial.begin(9600);
    accel.initialize();
    Serial.println(accel.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
  
   
        int16_t ax_raw, ay_raw, az_raw, gx_raw, gy_raw, gz_raw;
        float ay,gx;
        accel.getMotion6(&ax_raw, &ay_raw, &az_raw, &gx_raw, &gy_raw, &gz_raw);
        ay = ay_raw / 16444.0;
        ay = clamp(ay, -4.0, 4.0);
        
         if( ay >= 0){
            angle_ax = 90 - TO_DEG*acos(ay);
        } else {
            angle_ax = TO_DEG*acos(-ay) - 90;
        }
        Serial.println(angle_ax);
}
        
   void loop () {}

 

bwn
Offline
Зарегистрирован: 25.08.2014

Mig_1337 пишет:

Просто не мог подумать, что в setup() может находиться весь код) Возможно скетч выглядит не красиво, но его работа на данный момент меня полностью устраивает) перехожу на следующий этап)) 

Можно и так, но если понадобится в процессе считать снова, придется добавлять код. Лучше оформить это в виде функции и вызвать ее из сетап. Если в проекте понадобятся еще считывания, просто обращаемся к этой функции.
Сетап выполняется только после перезагрузки.