Использование акселерометра с Arduino в качестве датчика удара

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

Мой код (ниже) был написан для работы с двумя кнопками и светодиодом. По сути, это не что иное, как таймер реакции, использующий жидкокристаллический дисплей RGB.

Последовательность событий...

  1. включить
  2. отображает "нажмите кнопку для запуска"
  3. при нажатии кнопки на панели цикл начинается со случайного выбора Время «ПОЖАР» при нажатии кнопки «ОГОНЬ» повторяет время взял
  4. моя инструкция 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);
    }
  }

}

, 👍2


3 ответа


0

Я купил 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!");
}
,

Спасибо за ваш ответ, Рассел. Как будет определяться "BASELINE_GRAVITY"?, @Bender

Я не смог определить это, взглянув на документацию - мне неясно, какие единицы измерения возвращаются библиотекой adxl. Это то, что усредняет mag, когда акселерометр неподвижен., @Russell Borogove


1

Альтернативой использованию акселерометра является простой датчик вибрации. 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


0

Согласно техническому описанию adxl345, этот чип (то есть модуль) имеет функцию однократного и двойного касания. Как описано в техническом описании, вы можете настроить чип так, как хотите, чтобы он работал. Чип имеет 2 вывода прерывания. Когда он сконфигурирован для работы в одном из режимов касания и обнаруживает касание, он подает сигнал прерывания. Вы можете проверить этот сигнал и обработать информацию.

,