Как добавить еще одно условие в цикл?
Я использую mpu6050 для подсчета подергиваний. Алгоритм подсчитывает пик/подергивание всякий раз, когда оно превышает пороговое значение. Теперь я хочу добавить, что алгоритм подсчитывает подергивание только тогда, когда оно превышает пороговое значение, и все подергивания в течение 90 секунд считаются как одно движение подергивания. Пожалуйста, помогите мне с этим. Также попробуйте интегрировать это в мой код.
Вот код:
#include "I2Cdev.h"
#include "MPU6050.h"
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
#include "Wire.h"
#endif
MPU6050 accelgyro;
int16_t ax, ay, az;
float threshhold=5000.0;
float conmove=4;
const int sampletime=90000;
float xval[100]={0};
float yval[100]={0};
float zval[100]={0};
float xavg;
float yavg;
float zavg;
int twitch,flag=0;
MPU6050 mpu6050;
int16_t tr; // значение регистра необработанных данных температуры
char buffer[7]; // временный строковый буфер; используется с функцией dtostrf()
#define OUTPUT_READABLE_ACCELGYRO
#define LED_PIN 13
bool blinkState = false;
void setup() {
// подключаемся к шине I2C (библиотека I2Cdev не делает этого автоматически)
#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
Wire.begin();
#elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
Fastwire::setup(400, true);
#endif
Serial.begin(115200);
// инициализируем устройство
Serial.println("Initializing I2C devices...");
accelgyro.initialize();
mpu6050.initialize(); // инициализируем сенсорный модуль MPU6050
// проверяем соединение
Serial.println("Testing device connections...");
Serial.println(accelgyro.testConnection() ? "MPU6050 connection successful" : "MPU6050 connection failed");
pinMode(LED_PIN, OUTPUT);
calibrate();
delay(5000);
}
void loop() {
accelgyro.getAcceleration(&ax, &ay, &az);
tr = mpu6050.getTemperature();
#ifdef OUTPUT_READABLE_ACCELGYRO
+
// отображение значений ускорения/гироскопа x/y/z, разделенных табуляцией
Serial.print("a/g:\t");
Serial.print(ax); Serial.print("\t");
Serial.print(ay); Serial.print("\t");
Serial.print(az);
#endif
#ifdef OUTPUT_BINARY_ACCELGYRO
Serial.write((uint8_t)(ax >> 8)); Serial.write((uint8_t)(ax & 0xFF));
Serial.write((uint8_t)(ay >> 8)); Serial.write((uint8_t)(ay & 0xFF));
Serial.write((uint8_t)(az >> 8)); Serial.write((uint8_t)(az & 0xFF));
#endif
// мигать светодиодом для индикации активности
blinkState = !blinkState;
digitalWrite(LED_PIN, blinkState);
int acc=0;
float totvect[100]={0};
float totave[100]={0};
float xaccl[100]={0};
float yaccl[100]={0};
float zaccl[100]={0};
for (int i=0;i<100;i++)
{
xaccl[i]=float(ax);
delay(1);
yaccl[i]=float(ay);
delay(1);
zaccl[i]=float(az);
delay(1);
totvect[i] = sqrt(((xaccl[i]-xavg)* (xaccl[i]-xavg))+ ((yaccl[i] - yavg)*(yaccl[i] - yavg)) + ((zval[i] - zavg)*(zval[i] - zavg)));
totave[i] = (totvect[i] + totvect[i-1]) / 2 ;
//acc=acc+totave[i];
Serial.println(totave[i]);
Serial.print("T = "); Serial.print(dtostrf(tr/340.0+36.53, 5, 1, buffer)); Serial.println(" °C");
// delay(200);
// кал дергаться
if (totave[i]>threshhold && flag==0)
{
twitch=twitch+1;
flag=1;
}
else if (totave[i] > threshhold && flag==1 )
{
//ничего не делать
}
if (totave[i] <threshhold && flag==1 )
{flag=0;}
Serial.println('\n');
Serial.print("twitch=");
Serial.println(twitch);
}
//время с плавающей запятой=acc/100;
//Serial.println(тим);
delay(1000);
// пошаговое вычисление(всего);
}
void calibrate()
{
digitalWrite(13,HIGH);
accelgyro.getAcceleration(&ax, &ay, &az);
float sum=0;
float sum1=0;
float sum2=0;
for (int i=0;i<100;i++)
{
xval[i]=float(ax);
sum=xval[i]+sum;
}
delay(100);
xavg=sum/100.0;
Serial.println(xavg);
for (int j=0;j<100;j++)
{
yval[j]=float(ay);
sum1=yval[j]+sum1;
}
yavg=sum1/100.0;
Serial.println(yavg);
delay(100);
for (int i=0;i<100;i++)
{
zval[i]=float(az);
sum2=zval[i]+sum2;
}
zavg=sum2/100.0;
delay(100);
Serial.println(zavg);
digitalWrite(13,LOW);
}
@zuni, 👍1
1 ответ
Лучший ответ:
Это можно сделать с помощью функции millis()
. Он возвращает количество миллисекунд с момента запуска и может использоваться как простые часы. Возьмите оператор if, в котором вы увеличиваете twitch
:
if (totave[i]>threshhold && flag==0)
{
if(millis()-last_twitch_timestamp > 90000){
twitch=twitch+1;
flag=1;
last_twitch_timestamp = millis();
}
}
Это проверит, прошло ли не менее 90 секунд (90000 мс) с момента последнего зарегистрированного подергивания (разница во времени между текущим временем и отметкой времени последнего подергивания). Если да, он зарегистрирует еще одно подергивание и сбросит отметку времени на текущее время (возвращаемое значение millis()
). Это деактивирует регистрацию подергиваний на 90 секунд после каждого подергивания.
Чтобы это работало, вам нужно определить переменную last_twitch_timestamp
в глобальном масштабе:
unsigned long last_twitch_timestamp = 90000;
Я инициализирую временную метку на 90000, чтобы можно было зарегистрировать самое первое подергивание. Если вы инициализируете его нулем, вам нужно будет подождать 90 секунд, пока не будет зарегистрировано первое подергивание.
Кстати: следующие задержки не имеют никакого смысла. Вы можете удалить их:
xaccl[i]=float(ax);
delay(1);
yaccl[i]=float(ay);
delay(1);
zaccl[i]=float(az);
delay(1);
И вы действительно должны соблюдать правильный отступ для всех строк. В Arduino IDE есть функция автоформатирования, которая упрощает работу с вами.
- Как очистить буфер FIFO на MPU6050?
- Как сгенерировать аппаратное прерывание в mpu6050 для пробуждения Arduino из режима SLEEP_MODE_PWR_DOWN?
- Понимание того, почему следует избегать «String» и альтернативных решений
- Объяснение кода MPU6050
- Изменение адреса I2C MPU-6050
- Снять гравитацию с акселерометра MPU-6050
- Скорость передачи данных акселерометра mpu6050 в Arduino Uno и частота дискретизации mpu6050
- Как соединить L293D и MPU6050 для совместной работы?
Благодарю за ваш ответ. Да, он считает все те подергивания, которые происходят в течение 90 с, как одно, но после 90 с он распознает следующее подергивание примерно через 5 с задержки. таким образом, эта 5-секундная задержка в подсчете повлияет на наши данные. Пожалуйста, помогите мне с этим., @zuni
Кроме того, как мы можем добавить, что подергивание засчитывается как одно в течение 90 с, но в течение этих 90 с должно быть минимум 4 движения., @zuni
@zuni Что вы подразумеваете под 5-секундной задержкой? Вы имеете в виду, что следующее подергивание распознается только через 95 с, а не через 90 с?, @chrisl
да можно сказать не сразу после 90х., @zuni
В вашем коде общая задержка составляет около 1,5 с. Это сокращает время вашей реакции. Если вам нужно более быстрое время реакции, вы должны полностью отказаться от вызовов задержки, перейдя к неблокирующему коду, как в примере
BlinkWithoutDelay
, @chrislхорошо, что помогло. пожалуйста, помогите мне с этим **Более того, как мы можем добавить, что подергивание считается как одно в течение 90 секунд, но в течение этих 90 секунд должно быть минимум 4 движения.**, @zuni
подсчитайте другую переменную прямо перед оператором millis if. Затем вы можете проверить это внутри оператора if и сбросить его там до нуля., @chrisl
вы бы написали синтаксис для этого ??, @zuni