I've been trying to merge the code of the stepper motor and gyroscope together after I tested them in separate codes. Sadly it does not work. I still obtain gyro values, but the stepper just does not turn, it only clicks.
I'm using an Arduino mega, Ramps 1.4, DRV8825, Nema 17, the NXP precision (FXOS8700+FXAS21002) and an AC adapter outputting 12V at 2.1 Amps coding on a m1 mac.
Firstly I'm using this gyroscope code, which combines the gyro, accelero and magnetometer data for orientation. This is the example code of adafruit AHRS --> orientation.
// Full orientation sensing using NXP/Madgwick/Mahony and a range of 9-DoF
// sensor sets.
// You *must* perform a magnetic calibration before this code will work.
//
// To view this data, use the Arduino Serial Monitor to watch the
// scrolling angles, or run the OrientationVisualiser example in Processing.
// Based on https://github.com/PaulStoffregen/NXPMotionSense with adjustments
// to Adafruit Unified Sensor interface
#include <Adafruit_Sensor_Calibration.h>
#include <Adafruit_AHRS.h>
Adafruit_Sensor *accelerometer, *gyroscope, *magnetometer;
// uncomment one combo 9-DoF!
//#include "LSM6DS_LIS3MDL.h" // can adjust to LSM6DS33, LSM6DS3U, LSM6DSOX...
//#include "LSM9DS.h" // LSM9DS1 or LSM9DS0
#include "NXP_FXOS_FXAS.h" // NXP 9-DoF breakout
// pick your filter! slower == better quality output
//Adafruit_NXPSensorFusion filter; // slowest
//Adafruit_Madgwick filter; // faster than NXP
Adafruit_Mahony filter; // fastest/smalleset
#if defined(ADAFRUIT_SENSOR_CALIBRATION_USE_EEPROM)
Adafruit_Sensor_Calibration_EEPROM cal;
#else
Adafruit_Sensor_Calibration_SDFat cal;
#endif
#define FILTER_UPDATE_RATE_HZ 100
#define PRINT_EVERY_N_UPDATES 10
//#define AHRS_DEBUG_OUTPUT
uint32_t timestamp;
void setup() {
Serial.begin(115200);
while (!Serial) yield();
if (!cal.begin()) {
Serial.println("Failed to initialize calibration helper");
} else if (! cal.loadCalibration()) {
Serial.println("No calibration loaded/found");
}
if (!init_sensors()) {
Serial.println("Failed to find sensors");
while (1) delay(10);
}
accelerometer->printSensorDetails();
gyroscope->printSensorDetails();
magnetometer->printSensorDetails();
setup_sensors();
filter.begin(FILTER_UPDATE_RATE_HZ);
timestamp = millis();
Wire.setClock(400000); // 400KHz
}
void loop() {
float roll, pitch, heading;
float gx, gy, gz;
static uint8_t counter = 0;
if ((millis() - timestamp) < (1000 / FILTER_UPDATE_RATE_HZ)) {
return;
}
timestamp = millis();
// Read the motion sensors
sensors_event_t accel, gyro, mag;
accelerometer->getEvent(&accel);
gyroscope->getEvent(&gyro);
magnetometer->getEvent(&mag);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("I2C took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
cal.calibrate(mag);
cal.calibrate(accel);
cal.calibrate(gyro);
// Gyroscope needs to be converted from Rad/s to Degree/s
// the rest are not unit-important
gx = gyro.gyro.x * SENSORS_RADS_TO_DPS;
gy = gyro.gyro.y * SENSORS_RADS_TO_DPS;
gz = gyro.gyro.z * SENSORS_RADS_TO_DPS;
// Update the SensorFusion filter
filter.update(gx, gy, gz,
accel.acceleration.x, accel.acceleration.y, accel.acceleration.z,
mag.magnetic.x, mag.magnetic.y, mag.magnetic.z);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Update took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
// only print the calculated output once in a while
if (counter++ <= PRINT_EVERY_N_UPDATES) {
return;
}
// reset the counter
counter = 0;
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Raw: ");
Serial.print(accel.acceleration.x, 4); Serial.print(", ");
Serial.print(accel.acceleration.y, 4); Serial.print(", ");
Serial.print(accel.acceleration.z, 4); Serial.print(", ");
Serial.print(gx, 4); Serial.print(", ");
Serial.print(gy, 4); Serial.print(", ");
Serial.print(gz, 4); Serial.print(", ");
Serial.print(mag.magnetic.x, 4); Serial.print(", ");
Serial.print(mag.magnetic.y, 4); Serial.print(", ");
Serial.print(mag.magnetic.z, 4); Serial.println("");
#endif
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
Serial.print("Orientation: ");
Serial.print(heading);
Serial.print(", ");
Serial.print(pitch);
Serial.print(", ");
Serial.println(roll);
float qw, qx, qy, qz;
filter.getQuaternion(&qw, &qx, &qy, &qz);
Serial.print("Quaternion: ");
Serial.print(qw, 4);
Serial.print(", ");
Serial.print(qx, 4);
Serial.print(", ");
Serial.print(qy, 4);
Serial.print(", ");
Serial.println(qz, 4);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
}
I've got the smoothest rotation for the stepper motor with
#include <AccelStepper.h>
//Pin selection for stepper motor
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define X_MIN_PIN 3
#define X_MAX_PIN 2
#define SDPOWER -1
#define SDSS 53
#define LED_PIN 13
//ChipSelect, Hardware SS Pin on Mega, 10 for Arduino Boards, always kept as output
#define SDCS_PIN 53
#define SD_DETECT_PIN -1 //currently not implementedne
void setup() {
// put your setup code here, to run once:
//For Stepper motor
pinMode(X_STEP_PIN , OUTPUT);
pinMode(X_DIR_PIN , OUTPUT);
pinMode(X_ENABLE_PIN , OUTPUT);
digitalWrite(X_ENABLE_PIN , LOW);
}
void loop() {
// put your main code here, to run repeatedly:
//For the stepper motor
if (millis() %1000 <500)
digitalWrite(LED_PIN, HIGH);
else
digitalWrite(LED_PIN, LOW);
if (millis() %10000 <5000) {
digitalWrite(X_DIR_PIN , HIGH);
}
else {
digitalWrite(X_DIR_PIN , LOW);
}
digitalWrite(X_STEP_PIN , HIGH);
delay(1);
digitalWrite(X_STEP_PIN , LOW);
}
Also the following also works, however the turning is not as smooth as with the previous code, it is more tacky
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define X_MIN_PIN 3
#define X_MAX_PIN 2
#include <AccelStepper.h>
AccelStepper stepper(1, X_STEP_PIN, X_DIR_PIN);
void setup()
{
// My way of enabling the enable pin... probably very wrong
pinMode(X_ENABLE_PIN , OUTPUT);
digitalWrite(X_ENABLE_PIN , LOW);
}
void loop()
{
stepper.setMaxSpeed(500);
stepper.setAcceleration(100);
stepper.runToNewPosition(0);
stepper.moveTo(500);
while (stepper.currentPosition() != 300)
stepper.run();
// cause an overshoot as we whiz past 300
stepper.setCurrentPosition(600);
}
What I did to combine the two codes is by simply copying the stepper motor code into the gyro code and placing the parts at the correct places (like void setup, void loop). But yeah, it doesn't work.
This project will eventually need to track an object using a pixicam and two stepper motors, however, only moving to an object using a pixicam and the two motors will also suffice.
I'm kinda a noob in all this arduino so I've not really a clue what to do. I've been working on this for hours, looking at all different kinds of forums, but nothing works.
Could you help me with combining these two codes? Thanks in advance!
Quick note, I've just put in the code again like I said, maybe a bit different than before, as I have no strategy for combining the codes. Now I still get gyro data and the stepper is turning correctly. However the turning is very tacky and the motor vibrates a lot. I've tried to tune the driver (precise) but it does not improve.
This is the code:
// Full orientation sensing using NXP/Madgwick/Mahony and a range of 9-DoF
// sensor sets.
// You *must* perform a magnetic calibration before this code will work.
//
// To view this data, use the Arduino Serial Monitor to watch the
// scrolling angles, or run the OrientationVisualiser example in Processing.
// Based on https://github.com/PaulStoffregen/NXPMotionSense with adjustments
// to Adafruit Unified Sensor interface
#include <Adafruit_Sensor_Calibration.h>
#include <Adafruit_AHRS.h>
Adafruit_Sensor *accelerometer, *gyroscope, *magnetometer;
// uncomment one combo 9-DoF!
//#include "LSM6DS_LIS3MDL.h" // can adjust to LSM6DS33, LSM6DS3U, LSM6DSOX...
//#include "LSM9DS.h" // LSM9DS1 or LSM9DS0
#include "NXP_FXOS_FXAS.h" // NXP 9-DoF breakout
// pick your filter! slower == better quality output
//Adafruit_NXPSensorFusion filter; // slowest
//Adafruit_Madgwick filter; // faster than NXP
Adafruit_Mahony filter; // fastest/smalleset
#if defined(ADAFRUIT_SENSOR_CALIBRATION_USE_EEPROM)
Adafruit_Sensor_Calibration_EEPROM cal;
#else
Adafruit_Sensor_Calibration_SDFat cal;
#endif
#define FILTER_UPDATE_RATE_HZ 100
#define PRINT_EVERY_N_UPDATES 10
//#define AHRS_DEBUG_OUTPUT
#include <AccelStepper.h>
//Pin selection for stepper motor
#define X_STEP_PIN 54
#define X_DIR_PIN 55
#define X_ENABLE_PIN 38
#define X_MIN_PIN 3
#define X_MAX_PIN 2
#define SDPOWER -1
#define SDSS 53
#define LED_PIN 13
//ChipSelect, Hardware SS Pin on Mega, 10 for Arduino Boards, always kept as output
#define SDCS_PIN 53
#define SD_DETECT_PIN -1 //currently not implementedne
uint32_t timestamp;
void setup() {
pinMode(X_STEP_PIN , OUTPUT);
pinMode(X_DIR_PIN , OUTPUT);
pinMode(X_ENABLE_PIN , OUTPUT);
digitalWrite(X_ENABLE_PIN , LOW);
Serial.begin(115200);
while (!Serial) yield();
if (!cal.begin()) {
Serial.println("Failed to initialize calibration helper");
} else if (! cal.loadCalibration()) {
Serial.println("No calibration loaded/found");
}
if (!init_sensors()) {
Serial.println("Failed to find sensors");
while (1) delay(10);
}
accelerometer->printSensorDetails();
gyroscope->printSensorDetails();
magnetometer->printSensorDetails();
setup_sensors();
filter.begin(FILTER_UPDATE_RATE_HZ);
timestamp = millis();
Wire.setClock(400000); // 400KHz
}
void loop() {
if (millis() %1000 <500)
digitalWrite(LED_PIN, HIGH);
else
digitalWrite(LED_PIN, LOW);
if (millis() %10000 <5000) {
digitalWrite(X_DIR_PIN , HIGH);
}
else {
digitalWrite(X_DIR_PIN , LOW);
}
digitalWrite(X_STEP_PIN , HIGH);
delay(1);
digitalWrite(X_STEP_PIN , LOW);
float roll, pitch, heading;
float gx, gy, gz;
static uint8_t counter = 0;
if ((millis() - timestamp) < (1000 / FILTER_UPDATE_RATE_HZ)) {
return;
}
timestamp = millis();
// Read the motion sensors
sensors_event_t accel, gyro, mag;
accelerometer->getEvent(&accel);
gyroscope->getEvent(&gyro);
magnetometer->getEvent(&mag);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("I2C took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
cal.calibrate(mag);
cal.calibrate(accel);
cal.calibrate(gyro);
// Gyroscope needs to be converted from Rad/s to Degree/s
// the rest are not unit-important
gx = gyro.gyro.x * SENSORS_RADS_TO_DPS;
gy = gyro.gyro.y * SENSORS_RADS_TO_DPS;
gz = gyro.gyro.z * SENSORS_RADS_TO_DPS;
// Update the SensorFusion filter
filter.update(gx, gy, gz,
accel.acceleration.x, accel.acceleration.y, accel.acceleration.z,
mag.magnetic.x, mag.magnetic.y, mag.magnetic.z);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Update took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
// only print the calculated output once in a while
if (counter++ <= PRINT_EVERY_N_UPDATES) {
return;
}
// reset the counter
counter = 0;
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Raw: ");
Serial.print(accel.acceleration.x, 4); Serial.print(", ");
Serial.print(accel.acceleration.y, 4); Serial.print(", ");
Serial.print(accel.acceleration.z, 4); Serial.print(", ");
Serial.print(gx, 4); Serial.print(", ");
Serial.print(gy, 4); Serial.print(", ");
Serial.print(gz, 4); Serial.print(", ");
Serial.print(mag.magnetic.x, 4); Serial.print(", ");
Serial.print(mag.magnetic.y, 4); Serial.print(", ");
Serial.print(mag.magnetic.z, 4); Serial.println("");
#endif
// print the heading, pitch and roll
roll = filter.getRoll();
pitch = filter.getPitch();
heading = filter.getYaw();
Serial.print("Orientation: ");
Serial.print(heading);
Serial.print(", ");
Serial.print(pitch);
Serial.print(", ");
Serial.println(roll);
#if defined(AHRS_DEBUG_OUTPUT)
Serial.print("Took "); Serial.print(millis()-timestamp); Serial.println(" ms");
#endif
}