I am using Arduino Mega, MOS Module, Air valve FA0520D and FA0520E. I would like to gradually increase and decrease the pneumatic pressure. There is a 6DoF IMU (MPU 6050) to measure the angular deformation for extension and contraction of the actuated object. I found that while pressure increases, IMU can read almost the exact amount of angular increment. But when the pressure decreases, IMU cannot show the right amount. There is always a lag although the actuated object reaches to its initial position after contraction. This is the part of the code I wrote:
void loop() {
float t_cycle = 100; // total period of PWM in ms
float ki = 0.1;
float t1i = ki*t_cycle;
float t2i = (1-ki)*t_cycle;
float kr = 0.35;
float t1r = kr*t_cycle;
float t2r = (1-kr)*t_cycle;
}
// for increasing the pressure:
digitalWrite(5,LOW); //keep 2 way valve off
digitalWrite(3,HIGH); //keep 3 way valve on
delay(t1i);
digitalWrite(3,LOW); //keep 3 way valve off
delay(t2i);
digitalWrite(3,HIGH); //keep 3 way valve on
// for decreasing the pressure:
digitalWrite(3,LOW); //keep 3 way valve off
digitalWrite(5,HIGH); //keep 2 way valve on
delay(t1r);
digitalWrite(5,LOW); //keep 2 way valve off
delay(t2r);
digitalWrite(5,HIGH); //keep 2 way valve on
Can anyone please help? Is it the problem of the code or the problem of IMU? And how can I fix it? The following figure could be helpful to understand my problem. The left one is the result of the IMU reading and the right one is the result obtained by a camera:
From your code, it would appear that the pressure is vented from the actuated device through the 2 way valve. Are you certain it is being opened? If open, does it have enough capacity to vent in the time required? Can you provide a sketch of how all the valves and the activated device are connected?
Your system looks reasonable and I don't understand why the imu data does not match the camera position. If the camera is correct, then the issue is not with the valve and venting, but with the response of the IMU.
It would help if you posted the code reading the IMU as well as driving the valves.
One observation: For different Ki and Kr values (thus different amounts of delay), the IMU reading changes. For ki=0.1 and kr=0.35, I have obtained comparatively less amount of lag ( while decreasing the pressure, the IMU reading does not reach zero). If I put kr=0.25, the lag is more ( i.e. the plot starts from 0 and ends at -15, forming a cascade shape). Although the actuated object reaches its initial position, just IMU could not read it. What could be the possible reason?
Can You give some figures to the pressure being used? Pressure when incressing? Is there any spring involved?
Is the 1 bar atmospheric pressure an actor on the scene?
You show a 2 way valve with only 1 air connection. Do we assume that the second connection is an exhaust vent to atmosphere? Why aren't you using manual throttle valves for flow rate control?
No spring is involved here. The pressure is measured by the MPRLS pressure sensor. The range of pressure is 14 to 22 Psi. This is the part of the code where I increase and decrease the pressure:
#include "Wire.h"
#include <MPU6050_light.h>
#define TCAADDR 0x70
#include "Adafruit_MPRLS.h"
#include <Wire.h>
#define RESET_PIN -1 // set to any GPIO pin # to hard-reset on begin()
#define EOC_PIN -1 // set to any GPIO pin to read end-of-conversion by pin
Adafruit_MPRLS mpr0 = Adafruit_MPRLS(RESET_PIN, EOC_PIN);
unsigned long startMillis;
unsigned long runTime = 1000; // in milliseconds
unsigned long timer;
void tcaselect(uint8_t i) {
if (i > 7) return;
Wire.beginTransmission(TCAADDR);
Wire.write(1 << i);
Wire.endTransmission();
}
MPU6050 mpu2(Wire);
MPU6050 mpu3(Wire);
void setup() {
while (!Serial);
delay(1000);
Wire.begin();
Serial.begin(115200);
Serial.println("\nTCAScanner ready!");
for (uint8_t t=0; t<7; t++) {
tcaselect(t);
Serial.print("TCA Port #"); Serial.println(t);
for (uint8_t addr = 0; addr<=127; addr++) {
if (addr == TCAADDR) continue;
Wire.beginTransmission(addr);
if (!Wire.endTransmission()) {
Serial.print("Found I2C 0x"); Serial.println(addr,HEX);
}
}
}
Serial.println("\ndone");
pinMode(3,OUTPUT); // 1st 3 way valve
pinMode(5,OUTPUT); // 1st 2 way valve
digitalWrite(3,LOW);
digitalWrite(5,HIGH);
delay(15000);
digitalWrite(5,LOW);
Serial.begin(115200);
tcaselect(0);
Serial.println("MPRLS0 Simple Test");
if (! mpr0.begin()) {
Serial.println("Failed to communicate with MPRLS0 sensor, check wiring?");
while (1) {
delay(10);
}
}
Serial.println("Found MPRLS0 sensor");
tcaselect(5);
byte status2 = mpu2.begin();
Serial.print(F("MPU6050 status: "));
Serial.println(status2);
while(status2!=0){ } // stop everything if could not connect to MPU6050
Serial.println(F("Calculating offsets, do not move MPU6050"));
delay(1000);
mpu2.calcOffsets(); // gyro and accelero
Serial.println("Done!\n");
tcaselect(6);
byte status3 = mpu3.begin();
Serial.print(F("MPU6050 status: "));
Serial.println(status3);
while(status3!=0){ } // stop everything if could not connect to MPU6050
Serial.println(F("Calculating offsets, do not move MPU6050"));
delay(1000);
mpu3.calcOffsets(); // gyro and accelero
Serial.println("Done!\n");
}
void loop() {
float t_cycle = 100; // total period of PWM in ms
float ki = 0.1;
float t1i = ki*t_cycle;
float t2i = (1-ki)*t_cycle;
float kr = 0.35;
float t1r = kr*t_cycle;
float t2r = (1-kr)*t_cycle;
//Geting the IMUs reading when the object is stationary
startMillis = millis(); // mark time
while (millis() - startMillis < runTime)
{
timer = millis();
Serial.print(timer*0.001);
Serial.print("\t");
tcaselect(5);
mpu2.update();
Serial.print(mpu2.getAngleX());
Serial.print("\t");
tcaselect(6);
mpu3.update();
Serial.print(mpu3.getAngleX());
Serial.print("\t");
Serial.print("\n");
}
tcaselect(0);
float pressure_hPa_0 = mpr0.readPressure();
float pressure_PSI_0 = pressure_hPa_0 / 68.947572932;
float pressure_Set = 22;
//Geting the IMUs reading when the object is pressurized
while (abs(pressure_PSI_0 - pressure_Set) > 0.25 && pressure_PSI_0 <pressure_Set ){
tcaselect(0);
pressure_hPa_0 = mpr0.readPressure();
pressure_PSI_0 = pressure_hPa_0 / 68.947572932;
Serial.print("Pressurized");
Serial.print("\t");
timer = millis();
Serial.print(timer*0.001);
Serial.print("\t");
tcaselect(5);
mpu2.update();
Serial.print(mpu2.getAngleX());
Serial.print("\t");
tcaselect(6);
mpu3.update();
Serial.print(mpu3.getAngleX());
Serial.print("\t");
Serial.print(pressure_hPa_0 / 68.947572932);
Serial.print("\t");
Serial.println(' ');
digitalWrite(5,LOW);
digitalWrite(3,HIGH);
delay(t1i);
digitalWrite(3,LOW);
delay(t2i);
digitalWrite(3,HIGH);
}
//Geting the IMUs reading when the object is stationary after being pressurized
startMillis = millis(); // mark time
while (millis() - startMillis < runTime)
{Serial.print("MCP");
Serial.print("\t");
timer = millis();
Serial.print(timer*0.001);
Serial.print("\t");
tcaselect(5);
mpu2.update();
Serial.print(mpu2.getAngleX());
Serial.print("\t");
tcaselect(6);
mpu3.update();
Serial.print(mpu3.getAngleX());
Serial.print("\t");
Serial.print("\n");
}
//Geting the IMUs reading when the object is being de-pressurized
pressure_Set = 14;
while (abs(pressure_PSI_0 - pressure_Set) > 0.25 && pressure_PSI_0 >pressure_Set){
tcaselect(0);
pressure_hPa_0 = mpr0.readPressure();
pressure_PSI_0 = pressure_hPa_0 / 68.947572932;
Serial.print("De-Pressurized");
Serial.print("\t");
timer = millis();
Serial.print(timer*0.001);
Serial.print("\t");
tcaselect(5);
mpu2.update();
Serial.print(mpu2.getAngleX());
Serial.print("\t");
tcaselect(6);
mpu3.update();
Serial.print(mpu3.getAngleX());
Serial.print("\t");
Serial.print(pressure_hPa_0 / 68.947572932);
Serial.print("\t");
Serial.println(' ');
digitalWrite(3,LOW);
digitalWrite(5,HIGH);
delay(t1r);
digitalWrite(5,LOW);
delay(t2r);
digitalWrite(5,HIGH);
}
//Geting the IMUs reading when the object is stationary after being depressurized
startMillis = millis(); // mark time
while (millis() - startMillis < runTime)
{
timer = millis();
Serial.print(timer*0.001);
Serial.print("\t");
tcaselect(5);
mpu2.update();
Serial.print(mpu2.getAngleX());
Serial.print("\t");
tcaselect(6);
mpu3.update();
Serial.print(mpu3.getAngleX());
Serial.print("\t");
Serial.print("\n");
}
}
I tied the IMU with the actuated object with Velcro. The IMU is in its vertical position. The rotation is along the x-axis. The actuated object is a human finger shaped object made with silicone. So, when actuated, it bends like a human finger. Considering 3 joints in our fingers, I am taking 2 IMUs readings attached in 2 links of each joints. My original post's figure is for the last joint's scenario, when 1st 2 joints are rigid.
I am not sure I understand your last question correctly. But, I don't think the angle measurement by the IMU is correct. When it is pressurized, it bends for 6 degrees. When it is depressurized, it reaches to its original position. So, the IMU should show that it reaches to 0 degrees. I can see it actually reaches to its initial position, just IMU is not reading it properly.