Just finished the basic building goals of this robot octopus.
video: Youtube video of robot Octopus in action
The project goals:
3-D print an adaptable servo frame in sketchup
Adapt my ongoing animation code to the creature with chained movement
Auto wiggle servos when no gyro input is there
build a comfortable head frame that doesn't give me a headache after 10 min
find a way to filter the gyro's rotation value acceleration up and then ignore the acceleration down so I get single direction with magnitude signal
The intentionally dropped goals for time sake:
speedy reaction
wire neatening
hide the mega arduino in head
print with black PLA -had temperature trouble apparently I need a slightly higher temp on my extruder, so I went with the natural PLA to keep the productivity up.
It is running off an arduino mega with DFrobot I/o shield. The code is running all the servos simultaneously with some servos shadowing the movement of their neighbor and servos at the root of the tentacle getting information from a gyroscope so when the head piece moves the servos follow. Two tentacles with axles in the vertical plain get the z readings from the gyro, the two top tentacles get the y reading from the gyro. Each swing of the servo from one position to the next follows a sin curve to do soft start/stops. The movement is somewhat randomized to make it more lifelike. Latter I will add a tentacle specific tag to the servos in the code so I can call out specific movement types for the tentacles at large.
My main problem is with the gyroscope taking too much resources from the loop. I am using a L3G4200D PARALAX gyroscope from parallax with the sample code used Microcontroller KickStarts | LEARN.PARALLAX.COM
The code they have works but it seems like a resource hog. I must skip some loop runs between gyro signal reads or else the loop gets bogged down with the process.
I am going to pick up some other IMU's and try them.
#include <Wire.h>
#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23
int Addr = 105; // I2C address of gyro
int x, y, z;
void setup(){
Wire.begin();
Serial.begin(9600);
writeI2C(CTRL_REG1, 0x1F); // Turn on all axes, disable power down
writeI2C(CTRL_REG3, 0x08); // Enable control ready signal
writeI2C(CTRL_REG4, 0x80); // Set scale (500 deg/sec)
delay(100); // Wait to synchronize
}
void loop(){
getGyroValues(); // Get new values
// In following Dividing by 114 reduces noise
Serial.print("Raw X:"); Serial.print(x / 114);
Serial.print(" Raw Y:"); Serial.print(y / 114);
Serial.print(" Raw Z:"); Serial.println(z / 114);
delay(500); // Short delay between reads
}
void getGyroValues () {
byte MSB, LSB;
MSB = readI2C(0x29);
LSB = readI2C(0x28);
x = ((MSB << 8) | LSB);
MSB = readI2C(0x2B);
LSB = readI2C(0x2A);
y = ((MSB << 8) | LSB);
MSB = readI2C(0x2D);
LSB = readI2C(0x2C);
z = ((MSB << 8) | LSB);
}
int readI2C (byte regAddr) {
Wire.beginTransmission(Addr);
Wire.write(regAddr); // Register address to read
Wire.endTransmission(); // Terminate request
Wire.requestFrom(Addr, 1); // Read a byte
while(!Wire.available()) { }; // Wait for receipt
return(Wire.read()); // Get result
}
void writeI2C (byte regAddr, byte val) {
Wire.beginTransmission(Addr);
Wire.write(regAddr);
Wire.write(val);
Wire.endTransmission();
}