Entrada. Letras, puedes saltarte
Hola de nuevo En esta historia, me gustaría continuar con el tema de la "construcción de robots" en el hogar, esta es una especie de
continuación de la publicación anterior .
Te advertiré de inmediato: no soy un experto en esta industria, solo estoy aprendiendo y durante mucho tiempo he estado "avergonzado" de expresar mis pensamientos y exponer cosas hechas en casa aquí. He estado leyendo publicaciones sobre Habr durante mucho tiempo, ¡a veces te preguntas qué está pasando en el mundo! ¡Lees una publicación, no entiendes de dónde sabe el autor! ¿Cómo puedes resolver esto? A la luz de todo esto, pensé que mi presentación "torpe" no sería de interés para nadie, pero más de 9k personas vieron la historia anterior, para mí sin duda es un éxito, creo que muchas personas como yo son "personas comunes" sin diplomas del Instituto de Tecnología de Massachusetts , para que esta información sea más accesible para ellos. Entonces vamos ...
Alteración de la estructura.
Como base de mi proyecto, tomé la "creación" anterior, una chupocabra, que estaba vestida y bajo una actuación de sonido ligero, realizó unas vacaciones. Lo hice por el bien de un día y por medios improvisados, que se pueden rastrear en su apariencia, la actuación fue satírica. Se parecía a esto:
En primer lugar, eliminé todo lo innecesario, compré perfiles de aluminio y esquinas perforadas para un nuevo diseño.
Realmente me gustó el rendimiento del robot de telepresencia de la compañía extranjera "Origibot"


Su aspecto ascético tiene varias ventajas, juzgue usted mismo, el peso no es grande, esto es principalmente ahorro de energía, ergonomía, ahorro de batería, un accionamiento eléctrico menos potente. Imagine una situación así, hipotéticamente, seguimos adelante y en ese momento problemas de comunicación, si el peso del robot es de varias decenas de kilogramos, las consecuencias pueden ser fatales. La segunda ventaja de esta forma considero la capacidad de doblar el manipulador entre las ruedas, es posible levantar algo del piso.
Oh bueno, inspirado y listo! Rehaciendo "su", decidió dividir la producción en etapas:
- La fabricación de una distancia entre ejes basada en dos ruedas motrices y una trasera de apoyo.
- Escribir un boceto para la gestión.
- Montaje de una cámara o teléfono. La altura de colocación se eligió en función de la altura de la estufa en la cocina para que pudiera mirar dentro de la sartén y ver de qué se cocinaba el borsch.
- Instalar un servo en la cámara para que pueda mirar debajo de las "patas" y el techo. No me molesté con el movimiento horizontal, puedes girar la base.
- Instalación en el "producto" del manipulador con agarre
La puesta en servicio adicional, en lo que respecta al concepto general del robot, en el caso ideal que aún no se ha implementado, el dispositivo de telecomunicaciones principal debe ser un teléfono. Skype está instalado en él, que está configurado para recibir videollamadas automáticamente, y el teléfono también será un punto de acceso para una tarjeta basada en el módulo ESP, esto permitirá controlar el robot y la videoconferencia. Por que skype ¿Por qué crear algo si ya tiene servicios que funcionan perfectamente y cambian la calidad automáticamente, dependiendo del ancho de banda de la red?
No hubo problemas con el primer elemento, la base estaba lista de la nave anterior, eliminó todo lo superfluo, el enrutador TPlink MR3020 con una antena remota casera. En el discurso anterior había paredes "gruesas", tuve que cultivar colectivamente, el resultado es + 9db. Los comandos de control de tráfico llegaron al enrutador, firmware cyberWRT.
Con el segundo punto fue más interesante, mi nivel en la programación de arduino "LED Blinker", encontré un boceto listo en Internet, desafortunadamente no recuerdo al autor, no lo hice mucho por mí mismo usando el método científico de poke, es usado por aquellos que poco entienden la teoría. Dado que la programación en lenguajes incluso de nivel inferior es un bosque oscuro para mí, tuve que elegir una plataforma en la que pudiera construir mi propio panel de control. Un aspecto importante para mí fue la capacidad de controlar el robot a través de un servicio en la nube, ya que el control será desde las "direcciones grises". El servicio Blynk se ha convertido en una plataforma de este tipo, no describiré las ventajas, hay mucha información en la red. En la primera versión, utilicé el widget de joystick para controlar el movimiento, el código se muestra a continuación:
#define BLYNK_PRINT Serial #include <ESP8266_Lib.h> #include <BlynkSimpleShieldEsp8266.h> #include <AccelStepper.h> #include <Servo.h> #include <SimpleTimer.h> // You should get Auth Token in the Blynk App. // Go to the Project Settings (nut icon). char auth[] = "****"; // Your WiFi credentials. // Set password to "" for open networks. char ssid[] = "****"; char pass[] = "****"; #define EspSerial Serial3 #define ESP8266_BAUD 115200 ESP8266 wifi(&EspSerial); BlynkTimer timer; Servo servo; Servo servo2; // These are used to set the direction of the bridge driver. #define ENB 5 //ENB monstr motor shield 5 6 #define MOTORB_1 4 //IN3 #define MOTORB_2 9 //IN4 #define MOTORA_1 8 //IN1 #define MOTORA_2 7 //IN2 #define ENA 6 //ENA int motor_right_speed = 0; int motor_left_speed = 0; AccelStepper Stepper1(4, 10, 11, 12, 13); //4 , int steeps = 192; // , , // SETUP void setup() { Serial.begin(9600); delay(10); EspSerial.begin(ESP8266_BAUD); delay(10); // Connect Blynk Blynk.begin(auth, wifi, ssid, pass); Blynk.connect(); // Configure pins pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT); digitalWrite(ENA,LOW); digitalWrite(ENB,LOW); Stepper1.setMaxSpeed(10000); // (/) Stepper1.setAcceleration(10000); // (/^2) servo.attach(1); servo2.attach(3); servo2.write(55); timer.setInterval(500L, StopServo); // Start serial communication } BLYNK_WRITE(V1) / , , / { if (param.asInt() == 1) { servo.attach(1); servo.write(165); // High gear timer.setTimeout(500L, StopServo); } else { servo.attach(1); servo.write(115); // Low gear timer.setTimeout(500L, StopServo); } } BLYNK_WRITE(V2) { servo2.write(param.asInt()); } void StopServo() / { servo.detach(); } // JOYSTICK BLYNK_WRITE(V0) { int nJoyY = param[0].asInt(); // read x-joystick int nJoyX = param[1].asInt(); // read y-joystick // OUTPUTS int nMotMixL; // Motor (left) mixed output int nMotMixR; // Motor (right) mixed output // CONFIG // - fPivYLimt : The threshold at which the pivot action starts // This threshold is measured in units on the Y-axis // away from the X-axis (Y=0). A greater value will assign // more of the joystick's range to pivot actions. // Allowable range: (0..+127) float fPivYLimit = 1023.0; // TEMP VARIABLES float nMotPremixL; // Motor (left) premixed output float nMotPremixR; // Motor (right) premixed output int nPivSpeed; // Pivot Speed float fPivScale; // Balance scale between drive and pivot // Calculate Drive Turn output due to Joystick X input if (nJoyY >= 0) { // Forward nMotPremixL = (nJoyX>=0)? 1023.0 : (1023.0 + nJoyX); nMotPremixR = (nJoyX>=0)? (1023.0 - nJoyX) : 1023.0; } else { // Reverse nMotPremixL = (nJoyX>=0)? (1023.0 - nJoyX) : 1023.0; nMotPremixR = (nJoyX>=0)? 1023.0 : (1023.0 + nJoyX); } // Scale Drive output due to Joystick Y input (throttle) nMotPremixL = nMotPremixL * nJoyY/900.0; // nMotPremixR = nMotPremixR * nJoyY/1023.0; // Now calculate pivot amount // - Strength of pivot (nPivSpeed) based on Joystick X input // - Blending of pivot vs drive (fPivScale) based on Joystick Y input nPivSpeed = nJoyX; fPivScale = (abs(nJoyY)>fPivYLimit)? 0.0 : (1.0 - abs(nJoyY)/fPivYLimit); // Calculate final mix of Drive and Pivot nMotMixL = (1.0-fPivScale)*nMotPremixL + fPivScale*( nPivSpeed); nMotMixR = (1.0-fPivScale)*nMotPremixR + fPivScale*(-nPivSpeed)/ 1.1; motor_left_speed = nMotMixL; motor_right_speed = nMotMixR; if (motor_right_speed > 20) { digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW); } else if (motor_right_speed < -20) { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2, HIGH); } else { digitalWrite(MOTORA_1, LOW); digitalWrite(MOTORA_2, LOW); } if (motor_left_speed > 20) { digitalWrite(MOTORB_1, LOW); digitalWrite(MOTORB_2, HIGH); } else if (motor_left_speed < -20) { digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW); } else { digitalWrite(MOTORB_1, LOW); digitalWrite(MOTORB_2, LOW); } analogWrite(ENB, abs(motor_left_speed)); analogWrite(ENA, abs(motor_right_speed)); } BLYNK_WRITE(V3) { // Motor Speed - Slider set with 0-100 and Send On Relese OFF int pinValue = param.asInt(); Stepper1.move(pinValue); } // MAIN CODE void loop() { Blynk.run(); timer.run(); Stepper1.run(); }
Luego, la instalación de una cámara o teléfono, probé ambos.

En la foto, el manipulador se coloca por separado.
¡Ahora es el momento de probar! Aproveché la oportunidad para dividir la pantalla del teléfono (disponible en el último firmware de Android), la parte superior del video, el control inferior. Para comenzar todo al mismo tiempo, descargué la aplicación Screens desde Play Market y fui ...
Durante el primer "pokatushek" se revelaron las siguientes deficiencias, los motores que en su pasado alemán, solían girar algo en alguna atracción, tienen diferentes salidas como resultado de una línea recta, el movimiento no funciona. Todo el tiempo tira en una de las direcciones, hizo un ajuste para calcular la velocidad de los motores en el código, ayudó, pero decidió rehacer el código en botones, es más conveniente para mí, y los movimientos en el apartamento serán en su mayoría lineales.
Esto fue seguido por la etapa más lenta, ya que resultó que ahora está claro por qué muchos robots de telepresencia en el mercado no tienen un manipulador. No hace mucho tiempo, al profundizar en el estudio del tema, leí sobre métodos para calcular unidades de rotación que no están divididas equitativamente a lo largo del eje de carga, recordé cómo me senté en el instituto en una conferencia sobre mecánica teórica hace quince años y me puse a pensar: "¿Por qué necesito un futuro # ingeniero - un electricista # esta basura ". Bueno, está bien, como dicen: "La práctica sin teoría es ciega". Aproximadamente diez veces rehice el manipulador, quemé varios servos, que se suponía que levantarían la carga principal.
Si prestó atención a la foto de Origibot, hay algo terrible allí como unidad, en su sitio web leí que el manipulador es capaz de levantar hasta 1 kg, ¡fantástico!
Si aplicamos, por ejemplo, un servoaccionamiento con una fuerza de 20 kg / cm, a una distancia de 2 cm, se puede elevar una carga de 10 kg, y si el peso de esta carga se distribuye de manera desigual a lo largo del eje y el eje es de aproximadamente un metro, entonces incluso menos.
Es bueno que la vieja cámara rotativa de CCTV estuviera a la mano, le saqué dos motores paso a paso, ¡genial! Un motor elevará el eje, y el segundo lo uso en una cortina automática. Hace tiempo que quería hacer un hogar, pero al mismo tiempo, ¡sé cómo trabajar con lombrices! Por así decirlo, dos pájaros de un tiro, a la vez. Si! El principal "problema" era esperar, olvidé decir que usé el controlador Wemos D1 R1 para mi producto casero, se parece a Arduino Uno, solo que hay wifi a bordo. Si bien no había manipulador, había suficientes pines en el tablero, un motor paso a paso agregado, para controlar los devanados, necesita cuatro pines, ¿dónde puedo obtenerlo? Resultó que los pines de la placa son los pines del CES en sí mismo, que proporciona comunicación, los pines del 0 al 8 se repiten aún más. Bueno, como dicen: "¡Una mala cabeza no da paz a tus manos!"
El precio del error: al transferir los resultados del trabajo a la placa Wemos 2560 esp8266, esta placa es una Mega y Esp. Lo tomé para la automatización del invernadero, por supuesto, no salió de inmediato, el bosquejo no se compiló, los errores salieron volando. Encontró una solución en el sitio:
community.alexgyver.ru/threads/robotdyn-mega-wifi-r3-connect-blynk.1270/#post-16746A continuación se muestra un boceto de un Mega operado por botón:
#define BLYNK_PRINT Serial #include <ESP8266_Lib.h> #include <BlynkSimpleShieldEsp8266.h> #include <AccelStepper.h> #include <Servo.h> #include <SimpleTimer.h> #define EspSerial Serial3 #define ESP8266_BAUD 115200 ESP8266 wifi(&EspSerial); #define ENB 5 //ENB monstr motor shield 5 6 #define MOTORB_1 4 //IN3 #define MOTORB_2 9 //IN4 #define MOTORA_1 8 //IN1 #define MOTORA_2 7 //IN2 #define ENA 6 //ENA BlynkTimer timer; Servo servo; Servo servo2; AccelStepper Stepper1(4, 10, 11, 12, 13); //4 , char auth[] = "****"; char ssid[] = "****"; char pass[] = "****"; // SETUP void setup() { Serial.begin(9600); delay(10); EspSerial.begin(ESP8266_BAUD); delay(10); // Connect Blynk Blynk.begin(auth, wifi, ssid, pass); Blynk.connect(); // Configure pins pinMode(ENA, OUTPUT); pinMode(MOTORA_1, OUTPUT); pinMode(MOTORA_2, OUTPUT); pinMode(ENB, OUTPUT); pinMode(MOTORB_1, OUTPUT); pinMode(MOTORB_2, OUTPUT); Stepper1.setMaxSpeed(100); // (/) Stepper1.setAcceleration(96); // (/^2) servo.attach(2); // servo.write(115); // servo2.attach(3); // servo2.write(55); // //timer.setInterval(500L, StopServo); // Start serial communication } BLYNK_WRITE(V6) { servo.write(param.asInt()); //timer.setTimeout(2500L, StopServo); } BLYNK_WRITE(V7) { servo2.write(param.asInt()); } //void StopServo() { // servo.detach(); //} BLYNK_WRITE(V8) { int pinValue = param.asInt(); Stepper1.move(pinValue); } BLYNK_WRITE(V4) { int speedL = param.asInt(); // . 1,13 analogWrite(ENA, speedL); analogWrite(ENB, speedL* 1.13); } / FORWARD BLYNK_WRITE(V0) { int button = param.asInt(); // read button if (button == 1) { digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW); } else { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,LOW); } } // RIGHT BLYNK_WRITE(V1) { int button = param.asInt(); // read button if (button == 1) { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH); digitalWrite(MOTORB_1,HIGH); digitalWrite(MOTORB_2,LOW); } else { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,LOW); } } // LEFT BLYNK_WRITE(V2) { int button = param.asInt(); // read button if (button == 1) { digitalWrite(MOTORA_1,HIGH); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH); } else { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,LOW); } } // BACKWARD BLYNK_WRITE(V3) { int button = param.asInt(); // read button if (button == 1) { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,HIGH); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,HIGH); } else { digitalWrite(MOTORA_1,LOW); digitalWrite(MOTORA_2,LOW); digitalWrite(MOTORB_1,LOW); digitalWrite(MOTORB_2,LOW); } } // MAIN CODE void loop() { Blynk.run(); timer.run(); Stepper1.run();
Como resultado, el poder del sustantivo chino era aún menor: 5 kg / cm, decidí probar a través del cinturón:

La correa se resbaló a pesar del tensor conectado al rodillo (no se muestra en la imagen). La psicosis y el nerviosismo excepcionales causados por una serie de contratiempos técnicos fueron interrumpidos por una nueva idea. Es necesario reducir el peso de la estructura: abandonar los dos servos al final del eje, para obtener grados adicionales de libertad y reducir la longitud del eje del manipulador. (Espero que el fusible permanezca y esta decisión es temporal).

También en la foto, instalé un altavoz externo, que fue soldado a la cámara ds-2cd2432f-iw por el fabricante Hikvizhn. El orador a tiempo completo parecía débil.
Ahora la apariencia es la siguiente.

Resumen
Tenemos una cámara sobre ruedas, ¿por qué hasta ahora he rechazado el teléfono? Skype no funciona correctamente en el modo de ventanas múltiples en mi teléfono, cuando el control de la imagen de video se minimiza al tamaño de una ventana pequeña, lo que no es muy conveniente cuando el robot se mueve. Por lo tanto, paré mientras estaba en la cámara, todavía uso la versión paga del programa Tiny cam pro para acceder al video, acceder desde cualquier parte del mundo, la cámara está conectada de forma inalámbrica a un enrutador en el que se reenvían sus puertos y se utiliza el servicio de nombre de dominio No-Ip. Es bueno que hasta ahora el proveedor proporcione una dirección "blanca". Se pregunta por qué no uso Blynk para la transmisión de video, porque hay un widget estándar para transmitir el protocolo rtsp. Respondo, quiero usar toda la funcionalidad de la cámara, es decir, la comunicación bidireccional. Incluso si tiene la forma en que lo proporciona una aplicación en la que se utilizan códecs de audio que reducen en gran medida la calidad del sonido. El protocolo rtsp más importante en la aplicación Blynk funciona con un ligero retraso, que es crítico para viajar en un mecanismo que pesa 10 kg.
Nutrición, un tema interesante aparte. El problema de una estación de carga autónoma aún no se ha resuelto; En el modelo anterior, utilicé baterías de iones de litio soldadas en pares en paralelo, para aumentar el voltaje a 12V y aumentar la capacidad, trabajando a través del controlador de carga. En este proyecto, rechazó el litio, ¡las baterías explotaron terriblemente por una mala experiencia! Se instala una batería de plomo-ácido de 7 A / h en la parte posterior de la unidad, para una distribución uniforme de la carga cuando el manipulador levanta la carga, se conecta un convertidor de CC a la batería, que reduce el voltaje de 5 V, para alimentar el controlador y la lógica de los dos controladores del motor MonstrmotorShield, uno para cada rueda, porque solo el piso del conductor funcionaba en ambas tablas, muy probablemente un matrimonio de fábrica, no podía pensar, bueno, ¿no lo tiró a la basura? ... El controlador de motor ln298 es necesario para que funcionen dos motores paso a paso.
De los problemas aún no resueltos, carga autónoma, quiero repetirlo así
Tampoco entendí bien la biblioteca AccelStepper, si suministra energía a los devanados del motor, después de que finaliza el manipulador, la energía permanece, lo que aumenta la corriente de descarga de la batería en aproximadamente 400 mA, lo que no es económico, debe encontrar la lógica cuando el manipulador está en la posición más baja, la alimentación de los devanados está apagada. También me gustaría recibir comentarios para que la posición de los servos y los gusanos de paso lleguen a Blynk cuando se enciende el robot. Y, por supuesto, la batería debe desconectar la carga cuando el voltaje cae a 10.5V, lo que evitará su degradación prematura. No hay forma de controlar desde una computadora. Y, por supuesto, el código necesita optimización.
Los que no tienen miedo de muchos libros y leen hasta el final, gracias, buena suerte a todos, ¡todo bien!
¡Finalmente, haremos un poco!