Puede parecer una banalidad , pero la idea detrás de este prototipo es muy interesante ya que puede suponer una ayuda importante a la movilidad, pues esta assietncia puede ser especialmente importante para los ancianos y otras personas que necesitan este tipo de ayuda en la vida cotidiana.
El sistema que sugieren sus creadores destaca por su simplicidad : una estructura de aluminio para sujetar el brazo, un motor y una placa Arduino con su correspondiente escudo (cuyos detalles, por cierto, han publicado en hackaday.com) ,
Nos explican que en la construcción del exo-brazo buscaban que fuese relativamente barato, sencillo y potente que permitiera un uso fácil del mismo , por lo cual construir su prototipo no deberia costar mas de 100$ , lo cual es un precio bastante razonable ,sobre todo si nos vamos a soluciones que se estan desarrollando la industria.
El desarrollo de este proyecto comenzó centrándose más en el control del brazo y luego en el propio diseño, por lo que tal vez el objetivo número de sus creadores es hacer que el control de ExoArm sea tan barato y tan intuitivo como sea posible.
En el siguiente video podemos verlo en acción:
Como podemos apreciar, hay una estructura articulada de aluminio y precisamente en la articulación esta el motor (en el codo) , aunque sugieren que en otros diseños futuros también proveen implementar un actuador en el hombro( de hecho el shield empleado admite dos motores).
Este exo-brazo tiene tambien apoyo trasero, de modo que todo el peso se distribuye uniformemente a su cuerpo siendo la capacidad de elevación alrededor de 10 kg máximo o 22 libras.
Electrónica
Ademas de la placa Arduino, un componente básico es el driver del motor VNH2SP30 ,el cual es esencialmente una versión en rampa del escudo de motor Ardumoto. Esta placa se presenta como un escudo que se conecta encima de Arduino y es de bajo coste ( unos 6,5€ en Amazon).
Para este Shield se usa un par de drivers de motor de puente completo VNH2SP30. También incluye los circuitos de soporte para que esta placa sea capaz de controlar un par de motores de alta corriente , aunque para esta aplicacion solo se usa uno .
El VIN y el motor son lanzados para terminales de tornillo de 5mm , lo que facilita la conexión de cables de mayor calibre.
Al utilizar este escudo en aplicaciones de alta demanda extrema puede ser necesario mejorar el rendimiento térmico con un disipador de calor o ventilador y soldar los cables directamente a la placa en lugar de usar un terminal de tornillo (tenga en cuenta la alta corriente de este) , aunque cuando se utiliza el escudo en corrientes de hasta 6A los chips apenas llegarán a ser perceptiblemente calientes.
Resumidamente esta son algunas de las características del escudo empleado:
- Voltaje: max. 16V
- Regimen de corriente: 30A maximo
- Corriente permanente: 14 A
- Resistencia MOSFET (solo ida): 19 m & OHgr;
- Frecuencia PWM: 20 kHz Max.
- Tamano placa: 6 * 5,2 * 2cm / 2,4 * 2 * 0,8pulg
- Peso : 23 g / 0,8 oz
Una vez resuelto el driver, respecto a Arduino , los pines que se requieren , en la aplicación son los pines siguientes:
- Pines 3 y 4 como salidas binarias para configurar el motor vía el driver del motor VNH2SP30
- Pin 5 como salida analógica para escribir el dato en el el driver del motor VNH2SP30
- Pin 2 como entrada analógica para el encoder solidario al eje del motor para saber la posición de la articulación
- Pines 8 como entrada binaria para ordenar subir la articulación via el motor
- Pines 9 como entrada binaria para ordenar bajar la articulación vía el motor
Antes de ver el codigo final , es interesante apreciar como el control del motor se hace fijando los pins 3 y 4 a un valor y luego sacando un valor analogico en el pin 5, por ejemplo, parar mover arriba el motor se usa esta función:
void moveup(float writemotor){ /
writemotor = map(writemotor, 0, -80, 255, 0);
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
analogWrite(5, writemotor);
Y de forma similar para mover hacia abajo :
void movedown(float writemotor){
writemotor = map(writemotor, 0,-255, 0, 255);
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
analogWrite(5, writemotor);
}
Simplemente para parar el moto,r sacamos un valor cero en el pin 5 usan esta otra función:
void stopmove(){ //parar el motor
digitalWrite(3, LOW);
digitalWrite(4, LOW);
analogWrite(5, 0);
}
Una función muy importante es conocer la posición de la articulación gracias a que hay conectado un potenciómetro solidario al aje de modo que capturando el valor de la salida del potenciómetro podemos conocer el angulo ,gracias al siguiente código:
float errorSum;
float Kp = 2;
float Ki = 0;
float computePID(int setpoint){
angle = analogRead(2);
angle = map(angle, 0, 344, 0, 90);
double time_elapsed = micros();
dtrate = (time_elapsed – last) / 1000.f;
last = time_elapsed;
float error = setpoint – angle;
errorSum += error * dtrate;
errorSum = constrain(errorSum, -255, 255);
return (Kp * error) + (Ki * errorSum);
}
Por ultimo, en la función loop miramos continuamente los valores binarios de los pines 8 y 9 ,y en función de su estado, llamaremos a alguna de las rutinas anteriores:
void loop() //bucle principal de ejecución
{
int program_runtime = millis();
int readingUp = digitalRead(8);
int readingDown = digitalRead(9);
if(readingUp == 1 && readingDown == 0){
if(program_runtime – previousMillis > interval) {
previousMillis = program_runtime;
Step -= 5;
}
}
if(readingDown == 1 && readingUp == 0) {
if(program_runtime – previousMillis > interval) {
previousMillis = program_runtime;
Step += 5;
}
Código arduino
El procesamiento de control como decíamos se hace con un Arduino, por lo que el código es bastante fácil de entender y modificar cuanto se quiera para mejorarlo o adaptarlo a cada necesidad:
#include <ArduinoTimer.h>
#include <CircularBuffer.h>
#include <CommandHandler.h>
#include <CommandProcessor.h>
#include <DataStore.h>
#include <DeviceAddress.h>
#include <EEPROMStore.h>
#include <Filter.h>
#include <MegunoLink.h>
#include <MessageHeaders.h>
#include «MegunoLink.h» // Funciones útiles para comunicarse con MegunoLink Pro.
#include «filter.h»
#include «Servo.h»
TimePlot plot;
int potVal;
int angle;
float dtrate;
double last;
ExponentialFilter FilteredMuscleValue(5, 20); // peso de la derecha, valor de inicio izquierdo
void moveup(float writemotor){ //mover arriba el motor
writemotor = map(writemotor, 0, -80, 255, 0);
digitalWrite(3, HIGH);
digitalWrite(4, LOW);
analogWrite(5, writemotor);
}
void stopmove(){ //parar el motor
digitalWrite(3, LOW);
digitalWrite(4, LOW);
analogWrite(5, 0);
}
void movedown(float writemotor){ //mover hacia abajo
writemotor = map(writemotor, 0,-255, 0, 255);
digitalWrite(3, LOW);
digitalWrite(4, HIGH);
analogWrite(5, writemotor);
}
float errorSum;
float Kp = 2;
float Ki = 0;
float computePID(int setpoint){ //función de calculo de la posición del encoder
angle = analogRead(2);
angle = map(angle, 0, 344, 0, 90); // dejanski kot
Serial.print(angle);
double time_elapsed = micros();
dtrate = (time_elapsed – last) / 1000.f;
last = time_elapsed;
float error = setpoint – angle;
errorSum += error * dtrate;
errorSum = constrain(errorSum, -255, 255);
//Serial.println(error);
return (Kp * error) + (Ki * errorSum);
// Serial.println(time_elapsed, 5);
}
int Step = 0;
void setup() //inicializacion del brazo
{
pinMode(8, INPUT);
pinMode(9, INPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
Serial.begin(9600);
Step = 0;
}
int k = 1;
int previousMillis = 0;
int interval = 50;
void loop() //bucle principal de ejecución
{
int program_runtime = millis();
int readingUp = digitalRead(8);
int readingDown = digitalRead(9);
if(readingUp == 1 && readingDown == 0){
if(program_runtime – previousMillis > interval) {
previousMillis = program_runtime;
Step -= 5;
}
}
if(readingDown == 1 && readingUp == 0) {
if(program_runtime – previousMillis > interval) {
previousMillis = program_runtime;
Step += 5;
}
}
Step = constrain(Step, -150, 150);
if(readingDown == 0 && readingUp == 0) Step = 0;
//plot.SendData(«pid», writemotor);
Serial.println(Step);
if(Step > 0) moveup(Step);
if(readingUp == 0 && readingDown == 0) stopmove();
if(Step < 0) movedown(Step);
}
Componentes necesarios
1 × calibrador de tensión con el amplificador de celda de carga
1 × Aluminio 4 x 30 x al menos 2000 mm
1 × Arduino Uno / Nano
1 × controlador de motor VNH2SP30
1 × Motor del limpiador del parabrisas del coche
1 × cables largos
1 × Potenciómetro
1 × Li-Po batería 3S 5500mAh
1 × Tornillos y tuercas. M4 y M6
1 × Cinta adhesiva
1 × Zipties
1 × Correas
1 × Placas de madera
1 × Tubo termorretráctil
En el siguiente vídeo el autor describe mas detalles de construcción de este excelente exo-brazo:
Mas información en https://hackaday.io/project/20663-assistive-exoskeleton-arm-exoarm#menu-description
Debe estar conectado para enviar un comentario.