Использование акселерометра с Arduino в качестве датчика удара
Мне очень нужна помощь. У меня нет абсолютно никакого опыта работы с акселерометрами, и у меня есть проект, который отлично работал бы, если бы я мог интегрировать его в него. Я не намекаю на то, чтобы кто-то написал мне код, просто направьте меня в нужное русло.
Мой код (ниже) был написан для работы с двумя кнопками и светодиодом. По сути, это не что иное, как таймер реакции, использующий жидкокристаллический дисплей RGB.
Последовательность событий...
- включить
- отображает "нажмите кнопку для запуска"
- при нажатии кнопки на панели цикл начинается со случайного выбора Время «ПОЖАР» при нажатии кнопки «ОГОНЬ» повторяет время взял
- моя инструкция FOR позволяет ей выполнить три цикла, прежде чем вернуться к начало.
Это было все, что я намеревался сделать с самого начала. Моя сестра использовала его в доме престарелых, чтобы поиграть с некоторыми пациентами. Недавно она спросила, можно ли вместо кнопки «огонь» запрограммировать ее на простое нажатие всего устройства, нажатие на устройство или даже использование какого-либо троса. Я понял, что акселерометр был билетом.
Я купил ADXL345 и попытался поиграть с несколькими скетчами из GitHub. Я обнаружил, что акселерометр ВСЕГДА выдает информацию. Я думал, что он на самом деле будет «отдыхать», когда его физически не двигают.
Как я могу использовать ADXL345, чтобы он находился в полной остановке, пока его не «переместят», чтобы он активировал оператор WHILE???
#include <Wire.h>
#include <LiquidCrystal.h>
#include <SparkFun_ADXL345.h>
ADXL345 adxl = ADXL345();
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);
int lcdRedPWMPin = 17;
int lcdGreenPWMPin = 16;
int lcdBluePWMPin = 15;
void setDisplayRGB(int r, int g, int b)
{
analogWrite(lcdRedPWMPin, r);
analogWrite(lcdGreenPWMPin, g);
analogWrite(lcdBluePWMPin, b);
}
void setup()
{
lcd.begin(16, 2);
lcd.clear();
pinMode(13, OUTPUT);
Serial.begin(115200);
adxl.powerOn();
adxl.setRangeSetting(2); // Допустимые значения: 2 г, 4 г, 8 г или 16 г
//adxl.setSpiBit(0);
adxl.setActivityXYZ(1, 1, 1);
adxl.setActivityThreshold(70);
adxl.ActivityINT(1);
pinMode(13, INPUT);
digitalWrite(13, LOW);
pinMode(9, INPUT); //кнопка панели
digitalWrite(9, HIGH);
pinMode(8, INPUT); //Кнопка ПОЖАР
digitalWrite(8, HIGH);
pinMode(10, OUTPUT); // ПОЖАР светодиод
digitalWrite(10, LOW);
// int fireButton = digitalRead(8);
int panelButton = digitalRead(9);
lcd.clear();
setDisplayRGB(100, 100, 75);
lcd.setCursor(1, 0);
lcd.print("Let's see what");
lcd.setCursor(1, 1);
lcd.print("what you got!");
delay(2000);
}
double timeToFire = 0; //время, которое потребовалось для (триггер пожара)
double fireTimerStarts = millis(); //огонь (запускается таймер)
double triggerTimerStops ; //триггер (таймер останавливается)
int ran; //случайный
void loop()
{
int x, y, z;
adxl.readAccel(&x, &y, &z);
// байтовые прерывания = adxl.getInterruptSource();
int average = (x + y + z);
while (digitalRead(9) == HIGH)
{
lcd.clear();
setDisplayRGB(40, 200, 75); //фиолетовый 40,200,75
lcd.setCursor(0, 0);
lcd.print("Press Button");
lcd.setCursor(0, 1);
lcd.print("to Start ...");
delay(50);
}
for (int panelButton = 0; panelButton < 3; panelButton++)
{
lcd.clear();
lcd.setCursor(0, 0);
setDisplayRGB(255, 255, 0); //синий
lcd.print(" ---READY---");
delay((int)random(1000, 5000));
{
ran = random(1, 3);
Serial.println(ran);
if ( ran == 1)
lcd.clear();
lcd.setCursor(0, 0);
setDisplayRGB( 0, 155, 155 ); //красный
lcd.print(" <FIRE> ");
lcd.setCursor(0, 1);
lcd.print(average);
fireTimerStarts = millis();
digitalWrite(10, HIGH);
// if(adxl.triggered>порог активности)
while (adxl.triggered(13, HIGH))
//пока (digitalRead(8) == HIGH)
{
triggerTimerStops = millis();
}
digitalWrite (13, LOW);
digitalWrite(10, LOW);
setDisplayRGB(100, 100, 225); //зеленый
}
timeToFire = (triggerTimerStops - fireTimerStarts) / 1000;
delay(500);
{
lcd.clear();
setDisplayRGB(0, 255, 0);
lcd.setCursor(0, 1);
lcd.print(timeToFire);
lcd.setCursor(11, 1);
lcd.print("Sec's");
lcd.setCursor(0, 0);
lcd.print("Your time was ...");
delay(1500);
}
}
}
@Bender, 👍2
3 ответа
Я купил ADXL345 и попытался поиграть с несколькими скетчами из GitHub. Я обнаружил, что акселерометр ВСЕГДА выдает информацию. Я думал, что он на самом деле будет «отдыхать», когда его физически не двигают.
Акселерометр постоянно сообщает о текущем ускорении по каждой оси, независимо от того, изменяется это ускорение или нет. В состоянии покоя и в вертикальном положении он покажет около 1,0 g по оси Z; при вращении в другом направлении и удерживании в неподвижном состоянии векторная величина ускорений по трем осям будет близка к 1,0. Величина вектора вычисляется как квадратный корень из суммы квадратов элементов, поэтому вместо усреднения вам нужно сделать следующее:
int x, y, z;
adxl.readAccel(&x, &y, &z);
float mag = sqrt( x*x + y*y + z*z );
Это значение mag
должно незначительно измениться, если вы осторожно повернете акселерометр. Это базовое значение представляет собой 1,0 g ускорения от силы тяжести Земли.
Быстрое движение акселерометра на короткое время приведет к увеличению или уменьшению значения. Выясните, какое пороговое значение имеет смысл для вашего приложения, и выполните что-то вроде:
if (mag > (BASELINE_GRAVITY * 1.2f))
{
lcd.setCursor(0, 0);
lcd.print("You moved!");
}
Альтернативой использованию акселерометра является простой датчик вибрации. Adafruit имеет переключатель датчика быстрой вибрации: https://www.adafruit.com/product/1766, переключатель датчика средней вибрации : https://www.adafruit.com/product/2384 и датчик медленной вибрации: https://www.adafruit.com/product/1767, каждый стоит 1 доллар.
Обновление 1:
Если вы ищете "ADXL345_ACTIVITY" в скетче SparkFun_ADXL345_Example.ino, там есть комментарий, который гласит: "добавьте сюда код, который будет выполняться при обнаружении активности".
Я предлагаю сначала заставить ADXL345 работать с этим скетчем, а затем начать удалять из него лишний код, который вам не нужен. Когда у вас будет минимальный код, необходимый для достижения вашей цели, попробуйте интегрировать его в текущий скетч.
Существует несколько «настроек чувствительности», которые можно выполнить в разделе кода «Настройка параметров ADXL345».
Честно говоря, VE7JRO, пока вы не опубликовали этот ответ, я даже не знал, что такие вещи вообще существуют. Конечно, зайдя на сайт Adafruit, я не знал, что существует много таких вещей. Ваша идея отлично сработает, но я сейчас воюю с этим акселерометром и пока не сдаюсь., @Bender
Согласно техническому описанию adxl345, этот чип (то есть модуль) имеет функцию однократного и двойного касания. Как описано в техническом описании, вы можете настроить чип так, как хотите, чтобы он работал. Чип имеет 2 вывода прерывания. Когда он сконфигурирован для работы в одном из режимов касания и обнаруживает касание, он подает сигнал прерывания. Вы можете проверить этот сигнал и обработать информацию.
- Как объявить массив переменного размера (глобально)
- Программирование Arduino с использованием Python, а не C/C ++
- Загрузка Arduino Nano дает ошибку: avrdude: stk500_recv(): programmer is not responding
- Как справиться с rollover millis()?
- Является ли использование malloc() и free() действительно плохой идеей для Arduino?
- Можно ли сделать несколько функций loop() с помощью Arduino Uno?
- Какие накладные расходы и другие соображения существуют при использовании структуры по сравнению с классом?
- устаревшее преобразование из строковой константы в 'char*'
Спасибо за ваш ответ, Рассел. Как будет определяться "BASELINE_GRAVITY"?, @Bender
Я не смог определить это, взглянув на документацию - мне неясно, какие единицы измерения возвращаются библиотекой adxl. Это то, что усредняет
mag
, когда акселерометр неподвижен., @Russell Borogove