0

I'm using an Arduino Uno with an Adafruit Motor Shield (v2) in order to power and control a motor and a LIS3DH accelerometer. With a simpler code in which the motor just goes forward for a certain number of pulses (output by the encoder), the identical function for the accelerometer outputs correct values. The code is shown below.

#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);
  }
}

In this code, which runs the motor forward for a distance 6 times and then runs it backward for the same distance it went forward, the motor runs correctly and the accelerometer says that it has been found but it outputs exclusively null values.

#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
#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!


  //  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);
}

I have tried various things but I have little background in CS, especially in C++, so my attempts haven't been fruitful. Any advice would be helpful.

  • I had to stop reading in line 7 where you #define pi. the last four digits are off. it might not matter if you don't need this precision, but where'd you get that value from? – Cee McSharpface Apr 23 '18 at 21:06
  • I saw some other user have that, so I just copy pasted it. I'll just use the first few digits. – Luke Matkovic Apr 23 '18 at 21:08
  • What part of that was minimal? Half of that code was commented out. Only show the bare minimum to aid those that want to help. – Matt Apr 24 '18 at 02:13

1 Answers1

0

The issue was using delay(). How exactly the hardware works, I'm not sure, but I believe blocking it in such a way threw off the hardware so that it was outputting null. Below is the corrected code using 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
#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!


  //  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);
  }
}