Акселерометр LIS3DH выводит нулевые значения при использовании Arduino

Я использую Arduino Uno с Adafruit Motor Shield (v2) для питания и управления двигателем и акселерометром LIS3DH. С более простым кодом, в котором двигатель просто движется вперед для определенного количества импульсов (вывод от датчика), идентичная функция для акселерометра выводит правильные значения. Код показан ниже.

#include <Wire.h>
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_MotorShield.h>
#include <Adafruit_Sensor.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"#define pi 3.14159
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
float distance = 30;

Adafruit_LIS3DH lis = Adafruit_LIS3DH();
//
const byte encoder0pinA = 2;//A pin -> the interrupt pin 0
unsigned int pulsesperturn = 56 * 64 / 2 ;
float circumference = 5.25 * 3.14159;
int pulses;
//int count = 0;

#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endif

void setup(void) {
#ifndef ESP8266
while (!Serial);     // will pause Zero, Leonardo, etc until serial console opens
#endif

Serial.begin(9600);
AFMS.begin();

Serial.println("LIS3DH test!");
if (! lis.begin(0x19)) {   // change this to 0x19 for alternative i2c address
Serial.println("Couldnt start");
while (1);
}
Serial.println("LIS3DH found!");
lis.setRange(LIS3DH_RANGE_4_G);   // 2, 4, 8 or 16 G!
//

}

void loop() {

//  //  }
//  myMotor->setSpeed(255); // this will end up changing but is constant for testing validation purposes
//  myMotor->run(FORWARD);
//  delay(2500);
//  myMotor->setSpeed(0);
//  //  right = 0;
//  delay(1000);
//  //  right = 1;
//  myMotor->run(BACKWARD);
//  myMotor->setSpeed(255);
//  delay(2500);
//  myMotor->setSpeed(0);
//  //  right = 0;
//  delay(1000);
//  //  right = 1;
myMotor->run(FORWARD);
myMotor->setSpeed(255); // this will end up changing but is constant for testing validation purposes

if (pulsesperturn  <= pulses ) {
myMotor->run(RELEASE);
myMotor->run(RELEASE);
myMotor->setSpeed(0);
stoppedAccel();
pulses = 0;
}

// Then print out the raw data
//  Serial.print("X:  "); Serial.print(lis.x);
//  Serial.print("  \tY:  "); Serial.print(lis.y);
//  Serial.print("  \tZ:  "); Serial.print(lis.z);

//  for (int a = 1; a < 20; a = a + 1) {

//  lis.read();      // get X Y and Z data at once
//  sensors_event_t event;
//  lis.getEvent(&event);
//
//  /* Display the results (acceleration is measured in m/s^2) */
//  //      Serial.print("  \tAngle:  "); Serial.print(angle);
//  //
//  //  Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
//  Serial.print(" \tY: "); Serial.print(event.acceleration.y);
//  Serial.print(" \tZ: "); Serial.print(event.acceleration.z);
//  //      Serial.println(" m/s^2 ");
//
//  Serial.println();
//  //
//  //  char buffer[5];
//  //  Serial.print("#S|WRITEDATA|[");
//  //  Serial.print(angle); // accels
//  //  Serial.println("]#");
//
//  //  WriteAccel();
//  delay(10);
//  }
//  myMotor->run(FORWARD);//
//  myMotor->run(RELEASE);
//  myMotor->setSpeed(255);
//  if (distance / circumference * pulsesperturn <= pulses) {
//    myMotor->setSpeed(0);
//    delay(2500);
//  }
//  myMotor->setSpeed(255);
//  myMotor->run(FORWARD);
//  pulses = 0;

Serial.print("pulses = ");
Serial.println(pulses);

attachInterrupt(digitalPinToInterrupt(encoder0pinA), counter, RISING);
/* Or....get a new sensor event, normalized */}

void counter()
{
pulses++;
}

void stoppedAccel()
{
for (int a = 1; a < 150; a = a + 1) {
lis.read();      // get X Y and Z data at once
sensors_event_t event;
lis.getEvent(&event);
float angle = asin(event.acceleration.z / 9.81) * 180  / pi  ;

Serial.print("  \tAngle:  "); Serial.print(angle);
//
//  Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
//    Serial.print(" \tY: "); Serial.print(event.acceleration.y);
//    Serial.print(" \tZ: "); Serial.print(event.acceleration.z);
//      Serial.println(" m/s^2 ");

Serial.println();

//
//  char buffer[5];
//  Serial.print("#S|WRITEDATA|[");
//  Serial.print(angle); // accels
//  Serial.println("]#");
delay(10);
}
}

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

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
Adafruit_LIS3DH lis = Adafruit_LIS3DH();
//The sample code for driving one way motor encoder
const byte encoder0pinA = 2;//A pin -> the interrupt pin 0
//byte encoder0PinALast;
int duration;//the number of the pulses
//unsigned long timeold;
unsigned int pulsesperturn = 56 * 64 / 2;
float widthDetector = 10; //distance needed, in cm
float circumference = 5.25 * 3.14159;
float pulses;
int count = 0;
#define pi 3.14159

//bool answered = 0;
//float distanceTotal = 100;
//float waitTime = 0.01;
//unsigned int pulsesper100forward = 56 * 64 ;
//unsigned int pulsesper100back = 56 * 64 ;
int b = 0;
float conversion = 171 / 169;#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endifvoid setup(void)
{
#ifndef ESP8266
while (!Serial);     // will pause Zero, Leonardo, etc until serial console opens
#endifSerial.begin(9600);
AFMS.begin();
Serial.println("LIS3DH test!");
if (! lis.begin(0x19)) {   // change this to 0x19 for alternative i2c address
Serial.println("Couldnt start");
while (1);
}
Serial.println("LIS3DH found!");
lis.setRange(LIS3DH_RANGE_4_G);   // 2, 4, 8 or 16 G!//  myMotor->run(FORWARD);
myMotor->setSpeed(255); // this will end up changing but is constant for testing validation purposes
}

void loop() {
motorDirection();
}

void counter()
{
pulses++;
}

void bcounter()
{
b++;
}

void motorDirection()
{
while (b < 6) {
myMotor->run(FORWARD);
readInt();
if (500 * conversion <= pulses) {
myMotor->run(RELEASE);
myMotor->run(RELEASE);
pulses = 0;
bcounter();
if (b == 6) {
stoppedAccel();
}
delay(1500);
}
//      break;

}

while (b == 6) {

myMotor->run(BACKWARD);
readInt();
if (500 * b <= pulses) {
myMotor->run(RELEASE);
myMotor->run(RELEASE);
bcounter();
stoppedAccel();
pulses = 0;
delay(500);
break;
}
}
while (b > 6) {
b = 0;
break;
}

}

// 169 forward per 1000, 171 backward

void stoppedAccel()
{
for (int a = 1; a < 150; a = a + 1) {
lis.read();      // get X Y and Z data at once
sensors_event_t event;
lis.getEvent(&event);
float angle = asin(event.acceleration.z / 9.81) * 180  / pi  ;

Serial.print("  \tAngle:  "); Serial.print(angle);
//
//  Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
//    Serial.print(" \tY: "); Serial.print(event.acceleration.y);
//    Serial.print(" \tZ: "); Serial.print(event.acceleration.z);
//      Serial.println(" m/s^2 ");

Serial.println();

//
//  char buffer[5];
//  Serial.print("#S|WRITEDATA|[");
//  Serial.print(angle); // accels
//  Serial.println("]#");
delay(100);
}
}

void readInt()
{
attachInterrupt(digitalPinToInterrupt(encoder0pinA), counter, RISING);
Serial.print("pulses = ");
Serial.println(pulses);
}

Я пробовал разные вещи, но у меня мало опыта в CS, особенно в C ++, поэтому мои попытки не были плодотворными. Любые советы будут полезны.

0

Решение

Проблема заключалась в использовании delay (). Как именно аппаратное обеспечение работает, я не уверен, но я полагаю, что блокировка таким образом отбросила аппаратные средства так, чтобы это выдало ноль. Ниже приведен исправленный код с использованием millis ().

#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_MS_PWMServoDriver.h"Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *myMotor = AFMS.getMotor(1);
#include <SPI.h>
#include <Adafruit_LIS3DH.h>
#include <Adafruit_Sensor.h>
Adafruit_LIS3DH lis = Adafruit_LIS3DH();
//The sample code for driving one way motor encoder
const byte encoder0pinA = 2;//A pin -> the interrupt pin 0
//byte encoder0PinALast;
int duration;//the number of the pulses
//unsigned long timeold;
unsigned int pulsesperturn = 56 * 64 / 2;
float widthDetector = 10; //distance needed, in cm
float circumference = 5.25 * 3.14159;
float pulses;
int count = 0;
#define pi 3.14159
float angle;
const long interval = 1000;
unsigned long previousMillis;//bool answered = 0;
//float distanceTotal = 100;
//float waitTime = 0.01;
//unsigned int pulsesper100forward = 56 * 64 ;
//unsigned int pulsesper100back = 56 * 64 ;
int b = 0;
float conversion = 171 / 169;#if defined(ARDUINO_ARCH_SAMD)
// for Zero, output on USB Serial console, remove line below if using programming port to program the Zero!
#define Serial SerialUSB
#endifvoid setup(void)
{
#ifndef ESP8266
while (!Serial);     // will pause Zero, Leonardo, etc until serial console opens
#endifSerial.begin(9600);
AFMS.begin();
Serial.println("LIS3DH test!");
if (! lis.begin(0x19)) {   // change this to 0x19 for alternative i2c address
Serial.println("Couldnt start");
while (1);
}
Serial.println("LIS3DH found!");
lis.setRange(LIS3DH_RANGE_4_G);   // 2, 4, 8 or 16 G!//  myMotor->run(FORWARD);
myMotor->setSpeed(255); // this will end up changing but is constant for testing validation purposes
}

void loop() {
motorDirection();
//    stoppedAccel();
}

void counter()
{
pulses++;
}

void bcounter()
{
b++;
}

void motorDirection()
{
//serial.write
while (b < 6) {
myMotor->run(FORWARD);
readInt();
if (500 * conversion <= pulses) {
myMotor->run(RELEASE);
bcounter();
previousMillis = millis();
timing();
//      previousMillis = currentMillis;

pulses = 0;

if (b == 6) {
stoppedAccel();
}
}
break;

}

while (b == 6) {
myMotor->run(BACKWARD);
readInt();
if (500 * b <= pulses) {
myMotor->run(RELEASE);
pulses = 0;
bcounter();
stoppedAccel();

break;
}
}
while (b > 6) {
b = 0;
break;
}

}

// 169 forward per 1000, 171 backward

void stoppedAccel()
{
for (int a = 1; a < 200; a = a + 1) {
lis.read();      // get X Y and Z data at once
sensors_event_t event;
lis.getEvent(&event);
angle = asin(event.acceleration.z / 9.81) * 180  / pi  ;

Serial.print("  \tAngle:  "); Serial.print(angle);
//
//  Serial.print("\t\tX: "); Serial.print(event.acceleration.x);
//    Serial.print(" \tY: "); Serial.print(event.acceleration.y);
//    Serial.print(" \tZ: "); Serial.print(event.acceleration.z);
//      Serial.println(" m/s^2 ");
Serial.println();
//
//  char buffer[5];
//  Serial.print("#S|WRITEDATA|[");
//  Serial.print(angle); // accels
//  Serial.println("]#");
delay(10);
}
}

void readInt()
{
attachInterrupt(digitalPinToInterrupt(encoder0pinA), counter, RISING);
Serial.print("pulses = ");
Serial.println(pulses);
}

void timing()
{
while (millis() - previousMillis <= interval) {
myMotor->run(RELEASE);
}
}
0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]