Controlling a linear actuator

Hello everyone, I am looking for some help with my project.I need a linear actuator to extend on retract based on the direction the accelerometer it is connected to is rotating.If anyone have some ideas of how to modify the code so the gyroscopic accelerometer controls linear actuator to achieve the self-stabilizing platform prototype, please let me know how to do it.

#include <Servo.h>

Servo myservoY; // Roll
Servo myservoX; // Pitch

#include "I2Cdev.h"

#include "MPU6050_6Axis_MotionApps20.h"

#if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
    #include "Wire.h"
#endif

MPU6050 mpu;
/#define OUTPUT_READABLE_YAWPITCHROLL

#define LED_PIN 13 
bool blinkState = false;

bool dmpReady = false;  
uint8_t mpuIntStatus;   
uint8_t devStatus;      
uint16_t packetSize;    
uint16_t fifoCount;     
uint8_t fifoBuffer[64]; 


Quaternion q;           
VectorInt16 aa;         
VectorInt16 aaReal;     
VectorInt16 aaWorld;    
VectorFloat gravity;    
float euler[3];         
float ypr[3];           

uint8_t teapotPacket[14] = { '

, 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' };

volatile bool mpuInterrupt = false;    // indicates whether MPU interrupt pin has gone high
void dmpDataReady() {
    mpuInterrupt = true;
}

void setup() {
    // join I2C bus (I2Cdev library doesn't do this automatically)
    #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE
        Wire.begin();
        TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz)
    #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE
        Fastwire::setup(400, true);
    #endif

//Attach servo

myservoY.attach(9);
  myservoX.attach(10);

Serial.begin(115200);
    while (!Serial);

Serial.println(F("Initializing I2C devices..."));
    mpu.initialize();

Serial.println(F("Testing device connections..."));
    Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed"));
/*
    // wait for ready
    Serial.println(F("\nSend any character to begin DMP programming and demo: "));
    while (Serial.available() && Serial.read()); // empty buffer
    while (!Serial.available());                // wait for data
    while (Serial.available() && Serial.read()); // empty buffer again
*/
    // load and configure the DMP
    Serial.println(F("Initializing DMP..."));
    devStatus = mpu.dmpInitialize();

mpu.setXGyroOffset(220);
    mpu.setYGyroOffset(76);
    mpu.setZGyroOffset(-85);
    mpu.setZAccelOffset(1788);

if (devStatus == 0) {
       
        Serial.println(F("Enabling DMP..."));
        mpu.setDMPEnabled(true);

Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)..."));
        attachInterrupt(0, dmpDataReady, RISING);
        mpuIntStatus = mpu.getIntStatus();

Serial.println(F("DMP ready! Waiting for first interrupt..."));
        dmpReady = true;

packetSize = mpu.dmpGetFIFOPacketSize();
    } else {
                Serial.print(F("DMP Initialization failed (code "));
        Serial.print(devStatus);
        Serial.println(F(")"));
    }

pinMode(LED_PIN, OUTPUT);
}

void loop() {
    // if programming failed, don't try to do anything
    if (!dmpReady) return;

while (!mpuInterrupt && fifoCount < packetSize) {
            }

mpuInterrupt = false;
    mpuIntStatus = mpu.getIntStatus();

fifoCount = mpu.getFIFOCount();

if ((mpuIntStatus & 0x10) || fifoCount == 1024) {
        // reset so we can continue cleanly
        mpu.resetFIFO();
        Serial.println(F("FIFO overflow!"));

} else if (mpuIntStatus & 0x02) {
                while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount();

mpu.getFIFOBytes(fifoBuffer, packetSize);
       
              fifoCount -= packetSize;

#ifdef OUTPUT_READABLE_YAWPITCHROLL
                        mpu.dmpGetQuaternion(&q, fifoBuffer);
            mpu.dmpGetGravity(&gravity, &q);
            mpu.dmpGetYawPitchRoll(ypr, &q, &gravity);
            Serial.print("ypr\t");
            Serial.print(ypr[0] * 180/M_PI);
            Serial.print("\t");
            Serial.print(ypr[1] * 180/M_PI);
            myservoY.write(int(ypr[1] * -180/M_PI)+90);  // Rotation around Y
            Serial.print("\t");
            Serial.println(ypr[2] * 180/M_PI);
            myservoX.write(int(ypr[2] * -180/M_PI)+90);  // Rotation around X
        #endif

blinkState = !blinkState;
        digitalWrite(LED_PIN, blinkState);
    }
   
}

1 Like

I need a linear actuator to extend on retract based on the direction the accelerometer it is connected to is rotating.

Could you take a moment to explain what this line is supposed to mean? Maybe a diagram would help.

Typo, I meant extend or retract.

Like when the accelerometer is rotated clockwise, the actuator will extend, and when it is rotated anti-clockwise it will retract.

The required code depends on what you are getting from the IMU, and on the effect of the linear actuator moves. If you don't follow a working model and use its code, you have to implement and parametrize the regulators yourself.

How do I write the code to store the values from the first reading and compare with subsequent readings?

int reading1 = read_sensor();
int reading2 = read_sensor();
if (reading1 > reading2) {
do_something();
}

jremington:

int reading1 = read_sensor();

int reading2 = read_sensor();
if (reading1 > reading2) {
do_something();
}

I don't see that as useful. The two readings will be microseconds apart at best. Good for averaging out noise but not much else.

Maybe...

int reading1;
void setup() {
  Serial.begin(9600);
  Serial.println("Place sensor in position and hold for 5 seconds");
  delay(5000);
  reading1 = readSensor();
  Serial.println("OK");
}
void loop() {
  int reading2 = readSensor();
  doSomething(reading1, reading2);
}

The example was intended merely to show the OP how to store and compare two readings. I credit the OP with some intelligence and to interpret the example appropriately.

The two readings will be microseconds apart at best.

It is equally ridiculous (or sensible) to suggest that the OP delay for 5000 milliseconds. Please try to make helpful contributions.

Delay in setup is usually the best way to do things. From an interface chip that needs a few milliseconds to start up to "plug me in and hold me stable" there is absolutely nothing else useful that the Arduino can do at that time.