Hardware components | ||||||
| × | 2 | ||||
| × | 3 | ||||
| × | 3 | ||||
| × | 3 | ||||
| × | 3 | ||||
| × | 1 | ||||
| × | 1 | ||||
| × | 2 | ||||
| × | 1 | ||||
Hand tools and fabrication machines | ||||||
| ||||||
|
I wanted to make a simple soft robot. The soft robot has 3 chambers inflated by air pumps. Once made I created a small wrist mounted accelerometer (Arduino nano 33 ble sense), to control the movements of the tentacle in a fun way. The tentacle mold was made with a mixture of ecoflex 00-30 & dragonskin 10 (ecoflex 00-50 may be enough, so that the cost goes down..... but it wasn't tested). The air pumps & the the air valves are all controlled with one relay each (making that part of the code super simple).
Tentacle base
The base of the tentacle, solder the two pieces together. Once your silicone tentacle has been made, put some silicone on the 3 circles and press the tentacle together with the pla. 3 small square holes in the bigger piece are for you to feed the air tubes through. The bottom of the smaller piece contains a small tube for you to connect the air tube to.
#include <ArduinoBLE.h>
#include <Arduino_LSM9DS1.h>
const char* deviceServiceUuid = "19b10000-e8f2-537e-4f6c-d104768a1214";
const char* deviceServiceCharacteristicUuid = "19b10001-e8f2-537e-4f6c-d104768a1214";
const int R_LED_PIN = 22;
const int G_LED_PIN = 23;
const int B_LED_PIN = 24;
long tiempo_prev = 0;
float pitch_prev = 0;
float roll_prev = 0;
// Sensibilidad del giroscopio 2000 dps -> 70
// Sensibilidad del acelermetro 4g -> 0.122
const float A_S = 0.122;
const float G_S = 70.0;
void setup() {
Serial.begin(9600);
setColor("RED");
if (!IMU.begin()) {
//Serial.println("Failed to initialize IMU!");
while (1);
}
// begin ble initialization
if (!BLE.begin()) {
//Serial.println("starting BLE failed!");
while (1);
}
//Serial.println("BLE Central - gesture control");
}
void loop() {
connectToPeripheral();
}
void connectToPeripheral(){
BLEDevice peripheral;
do
{
// start scanning for peripherals
BLE.scanForUuid(deviceServiceUuid);
peripheral = BLE.available();
} while (!peripheral);
if (peripheral) {
// discovered a peripheral, print out address, local name, and advertised service
//Serial.print("Found ");
//Serial.print(peripheral.address());
//Serial.print(" '");
//Serial.print(peripheral.localName());
//Serial.print("' ");
//Serial.print(peripheral.advertisedServiceUuid());
//Serial.println();
// stop scanning
BLE.stopScan();
controlPeripheral(peripheral);
}
}
void controlPeripheral(BLEDevice peripheral) {
// connect to the peripheral
//Serial.println("Connecting ...");
if (peripheral.connect()) {
//Serial.println("Connected");
setColor("BLUE");
} else {
//Serial.println("Failed to connect!");
return;
}
// discover peripheral attributes
//Serial.println("Discovering attributes ...");
if (peripheral.discoverAttributes()) {
//Serial.println("Attributes discovered");
} else {
//Serial.println("Attribute discovery failed!");
peripheral.disconnect();
return;
}
BLECharacteristic gestureCharacteristic = peripheral.characteristic(deviceServiceCharacteristicUuid);
if (!gestureCharacteristic) {
//Serial.println("Peripheral does not have gesture characteristic!");
peripheral.disconnect();
return;
} else if (!gestureCharacteristic.canWrite()) {
//Serial.println("Peripheral does not have a writable gesture characteristic!");
peripheral.disconnect();
return;
}
while (peripheral.connected()) {
String command = calculoAngulos();
//Serial.print("comando: ");
//Serial.println(command);
if (command != "")
{
setColor("PURPLE");
int n = command.length();
// declaring character array
char char_array[n + 1];
// copying the contents of the string to char array
strcpy(char_array, command.c_str());
gestureCharacteristic.writeValue((const char*)char_array);
delay(1);
}
}
//Serial.println("Peripheral disconnected!");
}
String calculoAngulosConFiltroComplementario()
{
float ax, ay, az;
float gx, gy, gz;
float pitch,_pitch;
float roll,_roll;
float dt;
String _command = "";
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(ax, ay, az);
}
if (IMU.gyroscopeAvailable()) {
IMU.readGyroscope(gx, gy, gz);
}
// Ratios
ax = ax/A_S;
ay = ay/A_S;
az = az/A_S;
gx = gx/G_S;
gy = gy/G_S;
gz = gz/G_S;
dt = (millis() - tiempo_prev) / 1000.0;
tiempo_prev = millis();
// Calcular los ngulos con el acelerometro
_pitch = atan2(ax, sqrt(ay*ay + az*az));
_roll = atan2(ay, sqrt(ax*ax + az*az));
// Convertimos de radianes a grados
_pitch *= (180.0 / PI);
_roll *= (180.0 / PI);
// Aplicar el filtro complementario
pitch = 0.98*(pitch_prev + gx*dt) + (0.02*_pitch);
roll = 0.98*(roll_prev + gy*dt) + (0.02*_roll);
//Serial.print(F("Rotacion en X: "));
//Serial.print(pitch);
//Serial.print(F("\t Rotacion en Y: "));
//Serial.println(roll);
pitch_prev = pitch;
roll_prev = roll;
_command = String(pitch, DEC) + "," + String(roll, DEC);
return _command;
}
String calculoAngulos()
{
float ax, ay, az;
float gx, gy, gz;
float pitch,roll;
String _command = "";
if (IMU.accelerationAvailable()) {
IMU.readAcceleration(ax, ay, az);
}
// Calcular los ngulos con el acelerometro
pitch = atan2(ax, sqrt(ay*ay + az*az));
roll = atan2(ay, sqrt(ax*ax + az*az));
// Convertimos de radianes a grados
pitch *= (180.0 / PI);
roll *= (180.0 / PI);
Serial.print(F("Rotacion en X: "));
Serial.print(pitch);
Serial.print(F("\t Rotacion en Y: "));
Serial.println(roll);
_command = String(pitch, DEC) + "," + String(roll, DEC);
return _command;
}
void setColor(String color)
{
if (color == "RED")
{
digitalWrite(R_LED_PIN, LOW); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, HIGH);
}else if (color == "GREEN")
{
digitalWrite(R_LED_PIN, HIGH); // High values -> lower brightness
digitalWrite(G_LED_PIN, LOW);
digitalWrite(B_LED_PIN, HIGH);
}else if (color == "BLUE")
{
digitalWrite(R_LED_PIN, HIGH); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, LOW);
}else if (color == "PURPLE")
{
digitalWrite(R_LED_PIN, LOW); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, LOW);
}
}
#include <ArduinoBLE.h>
const int R_LED_PIN = 22;
const int G_LED_PIN = 23;
const int B_LED_PIN = 24;
int relay7SOLELEFT = 7;
int relay10PUMPLEFT = 10;
int relay8SOLEMIDDLE = 8;
int relay11PUMPMIDDLE = 11;
int relay9SOLERIGHT = 9;
int relay12PUMPRIGHT = 12;
const char* deviceServiceUuid = "19b10000-e8f2-537e-4f6c-d104768a1214";
const char* deviceServiceCharacteristicUuid = "19b10001-e8f2-537e-4f6c-d104768a1214";
String command = "";
static int dutyX = 0;
static int dutyY = 0;
static int duty1 = 0;
static int duty2 = 0;
// BLE gesture Service
BLEService gestureService(deviceServiceUuid);
// BLE gesture Switch Characteristic
BLEStringCharacteristic gestureCharacteristic(deviceServiceCharacteristicUuid, BLERead | BLEWrite,512);
void setup() {
Serial.begin(9600);
pinMode(relay7SOLELEFT, OUTPUT);
pinMode(relay10PUMPLEFT, OUTPUT);
pinMode(relay8SOLEMIDDLE, OUTPUT);
pinMode(relay11PUMPMIDDLE, OUTPUT);
pinMode(relay9SOLERIGHT, OUTPUT);
pinMode(relay12PUMPRIGHT, OUTPUT);
// begin ble initialization
if (!BLE.begin()) {
Serial.println("starting BLE ");
while (1);
}
// set advertised local name and service UUID:
BLE.setLocalName("Mini Robot 4x4 peripheral");
BLE.setAdvertisedService(gestureService);
// add the characteristic to the service
gestureService.addCharacteristic(gestureCharacteristic);
// add service
BLE.addService(gestureService);
// set the initial value for the characeristic:
gestureCharacteristic.writeValue("");
// start advertising
BLE.advertise();
//Serial.println("Mini Robot 4x4 peripheral");
setColor("GREEN");
}
void loop() {
// listen for BLE peripherals to connect:
BLEDevice central = BLE.central();
// if a central is connected to peripheral:
if (central) {
//Serial.print("Connected to central: ");
// print the central's MAC address:
//Serial.println(central.address());
// while the central is still connected to peripheral:
while (central.connected()) {
// if the remote device wrote to the characteristic,
if (gestureCharacteristic.written()) {
command = gestureCharacteristic.value();
Serial.print(F("commmand value: "));
Serial.println(command);
sendInstruction(command);
}
}
// when the central disconnects, print it out:
//Serial.print(F("Disconnected from central: "));
//Serial.println(central.address());
}
}
void sendInstruction(String str) {
if (str.length() == 0)
return;
// split
int pos = str.indexOf(",");
int strLength = str.length();
dutyX = str.substring(0,pos).toInt();
dutyY = str.substring(pos+1,strLength).toInt();
Serial.print(F("valor en X: "));
Serial.print(dutyX);
Serial.print(F("\t valor en Y: "));
Serial.println(dutyY);
if ((dutyY >= 30) && (dutyX > -20) && (dutyX < 20)) // left
{
digitalWrite(relay9SOLERIGHT, HIGH);
digitalWrite(relay12PUMPRIGHT, HIGH);
digitalWrite(relay7SOLELEFT, LOW);
digitalWrite(relay10PUMPLEFT, LOW);
digitalWrite(relay8SOLEMIDDLE, LOW);
digitalWrite(relay11PUMPMIDDLE, LOW);
setColor("RED");
}
else if ((dutyY <= -30) && (dutyX > -20) && (dutyX < 20)) //right
{
digitalWrite(relay7SOLELEFT, HIGH);
digitalWrite(relay10PUMPLEFT, HIGH);
digitalWrite(relay9SOLERIGHT, LOW);
digitalWrite(relay12PUMPRIGHT, LOW);
digitalWrite(relay8SOLEMIDDLE, LOW);
digitalWrite(relay11PUMPMIDDLE, LOW);
setColor("BLUE");
}
else if ((dutyX >= 20) && (dutyY > -30) && (dutyY < 30)) //back
{digitalWrite(relay8SOLEMIDDLE, LOW);
digitalWrite(relay11PUMPMIDDLE, LOW);
digitalWrite(relay7SOLELEFT, LOW);
digitalWrite(relay10PUMPLEFT, LOW);
digitalWrite(relay9SOLERIGHT, LOW);
digitalWrite(relay12PUMPRIGHT, LOW);
setColor("YELLOW");
}
else if ((dutyX <= -20) && (dutyY > -30) && (dutyY < 30)) //foward
{
digitalWrite(relay8SOLEMIDDLE, HIGH);
digitalWrite(relay11PUMPMIDDLE, HIGH);
digitalWrite(relay7SOLELEFT, LOW);
digitalWrite(relay10PUMPLEFT, LOW);
digitalWrite(relay9SOLERIGHT, LOW);
digitalWrite(relay12PUMPRIGHT, LOW);
setColor("PURPLE");
}
else if ((dutyY >= 30) && (dutyX >= 20)) // adelante + izquierda
{
}
else if ((dutyY >= 30) && (dutyX <= -20)) // adelante + derecha
{
}
else if ((dutyY <= -30) && (dutyX >= 20)) // atras + izquierda
{ }
else if ((dutyY <= -30) && (dutyX <= -20)) // atras + derecha
{
}
else
{
}
}
void setColor(String color)
{
if (color == "RED")
{
digitalWrite(R_LED_PIN, LOW); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, HIGH);
}else if (color == "GREEN")
{
digitalWrite(R_LED_PIN, HIGH); // High values -> lower brightness
digitalWrite(G_LED_PIN, LOW);
digitalWrite(B_LED_PIN, HIGH);
}else if (color == "BLUE")
{
digitalWrite(R_LED_PIN, HIGH); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, LOW);
}else if (color == "PURPLE")
{
digitalWrite(R_LED_PIN, LOW); // High values -> lower brightness
digitalWrite(G_LED_PIN, HIGH);
digitalWrite(B_LED_PIN, LOW);
}else if (color == "YELLOW")
{
digitalWrite(R_LED_PIN, LOW); // High values -> lower brightness
digitalWrite(G_LED_PIN, LOW);
digitalWrite(B_LED_PIN, HIGH);
}
}
Comments