Tobor, el brazo © GPL3+

Brazo robótico manual y programable con sofisticado panel de control.

 

Componentes y suministros

Ph a000066 iso (1) ztbmubhmho
Arduino UNO
×1
Pantalla 20×4 con módulo I2C
×1
09939 01
Potenciómetro giratorio (genérico)
10kohm
×4
Pulsador de colores
con cabezas de colores
×3
boton interruptor
×1
Imagen Kingbright wp7113srd d
LED de 5 mm: rojo
×1
SG90 180 grados SG90 micro servo
Micro servomotor SG90
×4
11026 02
Alambres de unión (genérico)
×1
MeArm o cualquier otro brazo robótico 4DOF
×1
Caja LED
para un panel de control terminado
×1
Zócalo P4
para entrada de alimentación externa
×1
Fuente de alimentación externa de 5V/4A
o 4 pilas de 1,5 V para obtener 6 V
×1

Herramientas y máquinas necesarias.

09507 01
Soldador (genérico)
alicates de corte

Aplicaciones y servicios en línea

idea web
IDE de Arduino

Acerca de este proyecto

Es Tobor, el Brazo.

video de Youtube

Una aventura en los reinos de «¿Estás loco?» Oh… tal vez lo digo en serio. Después de mis otros dos proyectos ya publicados aquí en Project Hub, una especie de «confianza de codificación simple» y curiosidad por hacer algo más para llenar mi nerd vino cuando comencé a investigar y leer sobre brazos robóticos.

«Parece tan simple… Puedo hacerlo… Pero al igual que mis proyectos anteriores, me gustaría construir proyectos jugables para mi hijo pequeño, sin protoboards y conexiones de ‘prototipo’ endebles.

También soñé con construir un panel de control sofisticado, donde pueda manejar el brazo y hacerlo autónomo desde la PC, de forma segura con una fuente de alimentación externa, para dejárselo a un niño sin preocuparse por un lío con ollas delicadas, cables, botones, leds, conexiones endebles y hasta el momento.

Así que planifiquemos…

1 – El brazo sera este estilo «MeArm» con 4 mini servos (4DOF) hay tantos proyectos en internet, economicos y divertidos.

2 – Después de leer un poco, pensé que este proyecto no requeriría muchos conocimientos en electrónica… (Ojalá…). Como «fabricante novato», tengo mucho miedo de tener que aprender y usar transistores, condensadores, circuitos integrados y cualquier otro hardware electrónico que no sea la placa Arduino, potenciómetros, botones, LED y resistencias…

3 – Realmente quiero una Controlbox lo más sólida posible para operar el brazo sin conexiones a una PC.

4 – La investigación ha demostrado que el principal problema de los brazos robóticos es el sistema de alimentación correcto. El arduino en sí no puede manejar 4 servos. Decidí usar una fuente de alimentación externa de 5 V/4 A que puedo enchufar a un tomacorriente normal en casa. Es el artículo más caro del presupuesto pero puedo guardarlo para otros usos.

5 – El Controlbox necesitará una pantalla (20×4) para mostrar:

5.1 – Una pantalla de bienvenida;

5.2 -En modo manual, leyendo los ángulos cuando giro los potenciómetros, mapeados de 0 a 180 grados;

5.3 – En modo manual, la pantalla debe mostrar lo que escribo en la memoria para programar Tobor para que funcione en modo automático. (Hablaré de eso más adelante).

5.4 – Una pantalla de visualización con una especie de «Programa en curso >>>»

6 – El Controlbox controla:

6.1 – Un LED rojo para indicar que la fuente de alimentación está encendida;

6.2 – Cuatro potenciómetros para controlar cada servo;

6.3 – Un botón de cambio entre modo manual y modo automático;

6.4 – Un botón negro para seleccionar «Posiciones de memoria» para corregir errores de paso de guardado;

6.5 – Un botón verde para registrar los ángulos de los servos en una tabla de cinco variables: memPosition y ángulos de los servos (cuatro variables);

6.6 – Un botón rojo para uso futuro.

Entonces… Cómo armar esto… Intentaré hacer tantas conexiones atornilladas y enchufadas como sea posible para evitar soldar. Ok, está bien, pero realmente me gusta no tener que soldar cosas.

Pensando en la configuración física, armé un banco de conectores de 5V y GND para todo el cableado necesario con una placa universal y conectores de tornillo. Los pines de señal que uso protoboard cables y enchufes.

El I2C incorporado en la pantalla de 20×4 fue una elección fácil: solo cuatro cables para conectar.

La imagen de arriba muestra todos los elementos del Controlbox. Botones y potenciómetros ya soldados. En la parte inferior izquierda están los bancos 5V/GND. El arduino se monta con espaciadores y cinta adhesiva de doble cara 3M. En el lado izquierdo de la Controlbox, hay un orificio para el cable USB y otro para la fuente de alimentación externa P4 (¡no la de Arduino!)

Los agujeros se hicieron con herramientas de perforación adecuadas que ya tengo. El agujero de la pantalla fue el gran desafío. Se hizo con una cuchilla, muy, muy lentamente y requirió mucho tiempo y esfuerzo. Creo que al final fue aceptable. La pantalla está ligeramente desplazada debido a las conexiones del módulo I2C.

Un trozo de cinta aislante asegura los cables de señal en su lugar. Se hizo lo mismo para el cableado analógico y de alimentación en la otra placa Arduino.

¡Listo!

¿Cansado?

Ahora hablemos de la lógica del código.

Evidentemente, hay MUCHO QUE MEJORAR. Creo que para llegar al «punto B desde el punto A», un programador experimentado va directamente cuando hago esto en el modo «ZigZag». Lo siento, no tengo suficiente inglés y por la misma razón estoy escribiendo esto ya que mi conocimiento del lenguaje escrito lo permite…

Varios ejemplos para servo.write(), analogoRead(), pinMode(), jars de mapeo que podemos encontrar fácilmente en Internet y me gustaría centrarme en el problema principal, esta es la «lógica» que adopté.

Pensando en la operación manual, no hubo ningún desafío. analogRead(), map() y configuración de visualización para mostrar valores.

Un botón de cambio para cambiar entre los modos manual y automático. En modo Auto, el código lee las posiciones almacenadas de los servos una por una.

El botón verde:

Cuando se presiona, la «posición de memoria» aumenta en uno y los ángulos de los cuatro servos se almacenan en una matriz de 5 variables.

Tengo que posicionar el brazo para abrir la garra, alcanzar un objeto, agarrarlo, escalar/mover a otro punto, abrir la garra para soltarla y bloquearla para siempre. Para cada grupo de movimientos presiono el botón verde para memorizar las posiciones.

Si cometo un error al presionar el botón verde, desplazo la «posición de memoria» al paso correcto, presionando el botón negro.

El código solo permite diez posiciones de memoria de cuatro ángulos de servo. Este «Diez posiciones» es un número que entendí para un ciclo completo de movimientos de brazos antes del bucle en modo automático. Esto se puede aumentar mediante una codificación simple, agregando más tablas de posiciones de memoria y moviendo funciones de servo.

Modo automatico

Cuando el botón del interruptor se cambia al modo automático, un conjunto de funciones de código moverá los servos de acuerdo con el número total de posiciones de memoria almacenadas y lo repetirá. Aquí es donde «sucede la magia». el código es tan simple que estoy asombrado.

En la pantalla, un mensaje «Programa en ejecución» con un carácter «>»animado hace que las cosas sean «profesionales…».

Si no hay posiciones de memoria previamente almacenadas, se muestra el mensaje «Memoria vacía».

Problemas y desafíos futuros

Manejar esos mini servos endebles puede ser complicado. Freí dos. No sé exactamente por qué, pero a veces se calientan mucho. Supongo que esto puede ser un problema actual. Es importante calibrarlos antes de montar el brazo.

El movimiento de los servos también es algo a mejorar. Leí sobre la instalación de condensadores de 100 nF en los cables de señal de los potenciómetros.

También estoy a punto de probar la biblioteca «VarSpeedServo.h» para que los servos se muevan sin problemas.

No me ocupé de los problemas de «rebote». Leí sobre eso.

Arduino EEPROM

Por ahora, si se corta la energía, la memoria almacenada se pierde. Leí sobre el uso de la EEPROM de Arduino para almacenar memoria. Será muy interesante, pero necesito estudiar y aprender más para hacerlo.

brazo:

Este brazo «MeArm» es delgado y barato. Es divertido de construir y configurar. Las instrucciones están ampliamente disponibles en Internet. El material acrílico parece ser más fuerte que el mdf, supongo.

No me sorprende si en el futuro obtengo un brazo de aluminio más grande con servos más grandes… La tentación es construir 5DOF o incluso más grados de libertad, lo que significa que necesitaré una caja de control más grande…

sobre el nombre

Este brazo se llama «Tobor el Grande», una película de ciencia ficción de 1954, con esta descripción en Wikipedia:

«En una revisión de Los New York TimesTobor the Great se caracteriza como «Esta aventura de ciencia ficción para niños (que) narra la amistad entre un niño de 11 años y el robot Tobor de su abuelo, que fue diseñado para explorar el espacio profundo».

Mi «Tobor» no es tan inteligente ni dramático, pero a mi hijo le gusta mucho.

¡Espero que lo disfruten y comenten! ¡Tobor se lo agradecerá a todos!

codificado

Tobor, el brazoarduino
Comenta, mejora, comparte
/*
 * 6/2/19Versao que funcionou com o control box. apos muitos problemas de mau contato e qualidade inferior
 * dos servos azuis. Trocados por Towerpro MG90S engrenagem metal.
 * iniciar montagem do braco MeArm
 */

#include <Wire.h>
#include <Servo.h>
#include <LiquidCrystal_I2C.h> // For 20x4 lcd
LiquidCrystal_I2C lcd(0x27,20,4);

Servo s1;  // create servo object to control a servo
Servo s2;
Servo s3;
Servo s4;

int potpin1 = A0;  // analog pin used to connect the potentiometer
int potpin2 = A1;  // analog pin used to connect the potentiometer
int potpin3 = A2;  // analog pin used to connect the potentiometer
int potpin4 = A3;  // analog pin used to connect the potentiometer

int valA = 0;    // read the value from the analog pin
int valB = 0;    // read the value from the analog pin
int valC = 0;    // read the value from the analog pin
int valD = 0;    // read the value from the analog pin

int greenButton = 12; //record mem index and servo angles
int redButton = 4; //reserved for future use
int blackButton = 7; //mem index selector 
int switchAM = 8; //switch between Manual or Automatic operation
int counter = 0; //mem index
int mTime = 500;//time to move each servo in Aumtomatic mode one by one

//for now this is the way I found to store 10 * 4servo positions.
//An array of a mem counter and angles of 4 servos
int memP01[5], memP02[5], memP03[5], memP04[5], memP05[5], memP06[5], memP07[5], memP08[5], memP09[5], memP10[5];

//move ARM according to 4 angles stored in each Array 
void moveCounter1() { 
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
}

void moveCounter2() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
}

void moveCounter3() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime); 
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
}

void moveCounter4() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
}

void moveCounter5() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime); 
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime); 
s2.write(memP02[2]); delay(mTime); 
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime); 
s2.write(memP05[2]); delay(mTime);
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
}

void moveCounter6() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime);
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime); 
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
}

void moveCounter7() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime);
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
}

void moveCounter8() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime); 
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime); 
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime); 
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime); 
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime); 
s3.write(memP08[3]); delay(mTime);
s4.write(memP08[4]); delay(mTime);
}

void moveCounter9() {
s1.write(memP01[1]); delay(mTime);
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime); 
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime); 
s3.write(memP02[3]); delay(mTime); 
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime); 
s3.write(memP03[3]); delay(mTime); 
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime); 
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime); 
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime); 
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime);
s3.write(memP07[3]); delay(mTime); 
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime);
s3.write(memP08[3]); delay(mTime); 
s4.write(memP08[4]); delay(mTime);
s1.write(memP09[1]); delay(mTime); 
s2.write(memP09[2]); delay(mTime); 
s3.write(memP09[3]); delay(mTime);
s4.write(memP09[4]); delay(mTime);
}

void moveCounter10() {
s1.write(memP01[1]); delay(mTime); 
s2.write(memP01[2]); delay(mTime);
s3.write(memP01[3]); delay(mTime);
s4.write(memP01[4]); delay(mTime);
s1.write(memP02[1]); delay(mTime);
s2.write(memP02[2]); delay(mTime);
s3.write(memP02[3]); delay(mTime);
s4.write(memP02[4]); delay(mTime);
s1.write(memP03[1]); delay(mTime);
s2.write(memP03[2]); delay(mTime);
s3.write(memP03[3]); delay(mTime);
s4.write(memP03[4]); delay(mTime);
s1.write(memP04[1]); delay(mTime);
s2.write(memP04[2]); delay(mTime); 
s3.write(memP04[3]); delay(mTime);
s4.write(memP04[4]); delay(mTime);
s1.write(memP05[1]); delay(mTime);
s2.write(memP05[2]); delay(mTime);
s3.write(memP05[3]); delay(mTime);
s4.write(memP05[4]); delay(mTime);
s1.write(memP06[1]); delay(mTime);
s2.write(memP06[2]); delay(mTime);
s3.write(memP06[3]); delay(mTime);
s4.write(memP06[4]); delay(mTime);
s1.write(memP07[1]); delay(mTime);
s2.write(memP07[2]); delay(mTime); 
s3.write(memP07[3]); delay(mTime);
s4.write(memP07[4]); delay(mTime);
s1.write(memP08[1]); delay(mTime);
s2.write(memP08[2]); delay(mTime); 
s3.write(memP08[3]); delay(mTime);
s4.write(memP08[4]); delay(mTime);
s1.write(memP09[1]); delay(mTime);
s2.write(memP09[2]); delay(mTime);
s3.write(memP09[3]); delay(mTime);
s4.write(memP09[4]); delay(mTime);
s1.write(memP10[1]); delay(mTime); 
s2.write(memP10[2]); delay(mTime);
s3.write(memP10[3]); delay(mTime);
s4.write(memP10[4]); delay(mTime);
}
/*
  for(int a = 0; a < 5; a++)
{
  Serial.println(memP01[a]);
   Serial.println(memP02[a]);
    Serial.println(memP03[a]); 
    Serial.println(memP04[a]);
     }
  Serial.println("ln");
*/


void runningScreen() {
lcd.clear();  
lcd.setCursor (0,0); lcd.print("PROGRAM      ");
lcd.setCursor (0,1); lcd.print("RUNNING >    ");
delay(100); 
lcd.setCursor (0,1); lcd.print("RUNNING  >   ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING   >  ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING    > ");
delay(100);
lcd.setCursor (0,1); lcd.print("RUNNING      ");
delay(100);
}


void setup() {

// no anoying phisical  resistors to be welded...I hope it works
pinMode(switchAM, INPUT_PULLUP);
pinMode(blackButton, INPUT_PULLUP);
pinMode(greenButton, INPUT_PULLUP);
pinMode(redButton, INPUT_PULLUP);

Serial.begin(9600); // do not need this...the ctrlbox have a lcd.
lcd.init();
lcd.backlight();
  // lcd.begin(16, 2);
lcd.setCursor(0, 0); lcd.print("ROBOTIC ARM");
lcd.setCursor(0, 1); lcd.print("VERSION 001");
delay(3000);
// attaches the PWM pins to servos
s1.attach(11);  
s2.attach(10);
s3.attach(9);
s4.attach(6);

} //end setup

void loop() {
  
int switchAMState = digitalRead(switchAM);

  if (switchAMState == 0){ // Manual Mode
     lcd.clear();
     lcd.setCursor(0, 0);
     lcd.print("MANUAL OPERATION");
     
     valA = analogRead(potpin1);            // reads the value of the potentiometer (value between 0 and 1023)
     valA = map(valA, 1, 1023, 180,0);     //values acheived from testing to avoid motor creep at pot end courses
     s1.write(valA);
     delay(15);
     lcd.setCursor(0, 1);
     lcd.print("S1: ");
     lcd.print(valA); //show servo angle on lcd

     valB = analogRead(potpin2);            
     valB = map(valB, 1, 1023, 180,0);
     s2.write(valB);
     delay(15);
     lcd.setCursor(10, 1);
     lcd.print("S2: ");
     lcd.print(valB);

     valC = analogRead(potpin3);
     valC = map(valC, 1, 1023, 0, 180);
     s3.write(valC);
     delay(15);
     lcd.setCursor(0,3);
     lcd.print("S3: ");
     lcd.print(valC);
    
     valD = analogRead(potpin4);    // reads the value of the potentiometer (value between 0 and 1023)
     valD = map(valD, -25, 1023, 0, 180);     // calibrating to avois creeping

//calibration to let maximum claw opening of 90degrees and pressure excess on claws.dont know if its useful.
     if (valD > 40 || valD < 170) { 
     s4.write(valD);
     delay(15);    
     lcd.setCursor(10, 3);
     lcd.print("S4: ");
     lcd.print(valD);
     }
     else {
      valD = 41;
     }
    
    delay(100);

int  greenButtonState = digitalRead(greenButton);
   if (greenButtonState == 0) {
    counter = counter +1;
     
switch (counter) { 
  
case 1:
memP01[0] = counter; // save counter
memP01[1] = valA;
memP01[2] = valB;
memP01[3] = valC;
memP01[4] = valD;
break;

case 2:
memP02[0] = counter; // save counter
memP02[1] = valA; memP02[2] = valB; memP02[3] = valC; memP02[4] = valD;
break;

case 3:
memP03[0] = counter; // save counter
memP03[1] = valA; memP03[2] = valB; memP03[3] = valC; memP03[4] = valD;
break;

case 4:
memP04[0] = counter; // save counter
memP04[1] = valA; memP04[2] = valB; memP04[3] = valC; memP04[4] = valD; 
break;

case 5:
memP05[0] = counter; // save counter
memP05[1] = valA; memP05[2] = valB; memP05[3] = valC; memP05[4] = valD;
break;

case 6:
memP06[0] = counter; // save counter
memP06[1] = valA; memP06[2] = valB; memP06[3] = valC; memP06[4] = valD;
break;

case 7:
memP07[0] = counter; // save counter
memP07[1] = valA; memP07[2] = valB; memP07[3] = valC; memP07[4] = valD;
break;

case 8:
memP08[0] = counter; // save counter
memP08[1] = valA; memP08[2] = valB; memP08[3] = valC; memP08[4] = valD;
break;

case 9:
memP09[0] = counter; // save counter
memP09[1] = valA; memP09[2] = valB; memP09[3] = valC; memP09[4] = valD;
break;

case 10:
memP10[0] = counter; // save counter
memP10[1] = valA; memP10[2] = valB; memP10[3] = valC; memP10[4] = valD;
break;
  
case 11:
counter =1;
 
  
}//end switch
     
lcd.clear();
lcd.setCursor(0,0); lcd.print("ARM POSITION ");
lcd.setCursor(0,1); lcd.print("RECORDED     ");
lcd.setCursor(0,2); lcd.print("P  S1  S2  S3  S4");
lcd.setCursor(0,3); lcd.print(counter);
lcd.setCursor(4,3); lcd.print(valA);
lcd.setCursor(8,3); lcd.print(valB);
lcd.setCursor(12,3); lcd.print(valC);
lcd.setCursor(16,3); lcd.print(valD);
delay(2000);
       } //endgreenbt
    
//if needed to correct some  arm position       
int blackButtonState = digitalRead(blackButton);
if (blackButtonState == 0) {
  if (counter <10){ counter = counter + 1; }
  else { counter = 1; }
lcd.clear();
lcd.setCursor(0,0); lcd.print("MEM POSITION: ");
lcd.setCursor(8,1); lcd.print(counter);
delay(1000);
        }//end ifblackbt
         
    
    
 
     }//end if switchAM

else { //set ARM to Automatic Mode

if (counter > 0){
switch (counter){

case 1:
moveCounter1();
break;
case 2:
moveCounter2();
break;

case 3:
moveCounter3();
break;

case 4:
moveCounter4();
break;

case 5:
moveCounter5();
break;

case 6:
moveCounter6();
break;

case 7:
moveCounter7();
break;
 
case 8:
moveCounter8();
break;
 
case 9:
moveCounter9(); 
break;

case 10:
moveCounter10(); 
break;
} //end switch
  
  runningScreen();
 
} //end if counter>0
 
else { 
lcd.clear();  
lcd.setCursor(0,0);  
lcd.print("EMPTY MEMORY!");
delay(2000);
      
} // end else if counter

} //end else switchAM key
  
}   //end loop

diagramas

Esquema (las conexiones de la pantalla son solo para ver los cuatro cables)
Descargar
Tinkercad no tiene la pantalla I2C de 20×4. En su lugar, uso un 16×2, con solo 4 cables para representar 5V/GND y SCL/SDA
brazo005 4dqtsqwi84c

comentarios

Fuente Arduino.cc