Я использую 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 ++, поэтому мои попытки не были плодотворными. Любые советы будут полезны.
Проблема заключалась в использовании 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);
}
}
Других решений пока нет …