{"id":1577,"date":"2014-06-19T10:31:24","date_gmt":"2014-06-19T08:31:24","guid":{"rendered":"http:\/\/guimi.net\/blogs\/hiparco\/?page_id=1577"},"modified":"2014-07-29T11:44:48","modified_gmt":"2014-07-29T09:44:48","slug":"un-robot-con-arduino","status":"publish","type":"page","link":"http:\/\/guimi.net\/blogs\/hiparco\/tutoriales\/un-robot-con-arduino\/","title":{"rendered":"Un robot con Arduino"},"content":{"rendered":"<h1>1st Robot &#8211; C\u00f3mo se hizo<\/h1>\n<p>Hay un monton de informaci\u00f3n de robots econ\u00f3micos realizados con Arduino.<br \/>\nEste es el mio.<br \/>\n<img decoding=\"async\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot.jpg\" alt=\"\" \/><\/p>\n<p>Con unos 320 gramos, este robot qued\u00f3 tercero en la prueba de velocidad (sigue-lineas) del <a href=\"http:\/\/orchallenge.es\/\">Olympic Robotic Challenge<\/a> 2.14.<br \/>\nTambi\u00e9n hizo el tercer mejor tiempo en el laberinto (4.1 segundos), aunque al segundo intento, por lo que qued\u00f3 quinto (penalizaci\u00f3n de 5 segundos, total 9.1 segundos).<br \/>\nPuedes ver el <a href=\"#video\">v\u00eddeo de la evoluci\u00f3n del robot<\/a> al final del art\u00edculo.<\/p>\n<p>&nbsp;<\/p>\n<h2>A qui\u00e9n va dirigido este escrito<\/h2>\n<p>Si lo que quieres es simplemente construir un robot econ\u00f3mico, te recomiendo que compres alguno de los m\u00faltiples packs que se venden en tiendas y en internet. Est\u00e1n bien de precio y funcionan bien.<\/p>\n<p>Por otra parte, si ya has construido tus propios robots antes, este art\u00edculo no te aportar\u00e1 mucho.<\/p>\n<p>Pero si quieres aprender a construir tu propio robot, si quieres saber el tipo de problemas a los que te vas a enfrentar y c\u00f3mo es el proceso, entonces este art\u00edculo es para ti.<\/p>\n<p>La idea no es que construyas exactamente este robot. La idea es que construyas TU robot, con tus propias soluciones. Este art\u00edculo es una introducci\u00f3n a c\u00f3mo hacer un robot, presentando los problemas que me encontr\u00e9, no unas instrucciones para hacer un robot (aunque podr\u00eda usarse como tal).<\/p>\n<p>Si necesitas una introducci\u00f3n a Arduino puedes consultar las entradas sobre <a href=\"http:\/\/guimi.net\/blogs\/hiparco\/category\/arduino\/\">Arduino en Hiparco<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<h2>Primeras consideraciones sobre el robot<\/h2>\n<h3>Comportamiento<\/h3>\n<p>Lo primero a considerar, aunque parezca evidente, es \u00bfqu\u00e9 queremos hacer?<br \/>\nParece obvio: &#8220;un robot&#8221;.<br \/>\nPero eso no es suficiente. \u00bfQu\u00e9 tipo de robot? \u00bfQu\u00e9 esperas que haga? \u00bfDe que componentes dispones o est\u00e1s dispuesto a comprar?<br \/>\nPor ejemplo hay robots sigue-l\u00edneas, luchadores, buscadores, vagabundos&#8230; terrestre, volador, acu\u00e1tico&#8230; m\u00f3vil, quieto&#8230; y tambi\u00e9n puede ser teledirigido (controlado remotamente) o aut\u00f3nomo (act\u00faa por su cuenta).<\/p>\n<p>En mi caso nos vamos a centrar en un robot <b>terrestre<\/b>, con ruedas, <b>aut\u00f3nomo<\/b> de tipo <b>sigue-lineas<\/b>.<br \/>\nEsto es, un robot que actuando por su cuenta en base a sensores, sigue una l\u00ednea negra sin dejarla.<br \/>\nLos sensores disponen de un emisor de luz y un receptor. Si la luz rebota en una superficie cercana y blanca el receptor la capta. En teor\u00eda, en otro caso el sensor no capta nada. As\u00ed podemos distinguir una l\u00ednea negra sobre fondo blanco. En la pr\u00e1ctica los reflejos y la alta iluminaci\u00f3n en la competici\u00f3n nos causaron muchos problemas a un gran n\u00famero de participantes.<\/p>\n<p>Otras consideraciones que pesaron a la hora de realizar el robot fue que intent\u00e9 utilizar material reciclado o muy barato y que era un proyecto ef\u00edmero que iba a deshacer al acabar la participanci\u00f3n en el <a href=\"http:\/\/orchallenge.es\/\">ORC<\/a>. De hecho cada d\u00eda montaba y desmontaba el robot.<br \/>\nPor tanto el robot es facilmente mejorable con mejores ruedas, optimizando el tama\u00f1o y forma del chasis, utilizando engranajes para la transmisi\u00f3n&#8230;<\/p>\n<p><a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/19.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/19.jpg\" class=\"alignnone\" \/><\/a><br \/>\nSi todav\u00eda no te queda claro puedes ver un <a href=\"#video\">v\u00eddeo de la evoluci\u00f3n del robot<\/a> al final del art\u00edculo.<\/p>\n<p>&nbsp;<\/p>\n<h3>Motores<\/h3>\n<p>Lo que m\u00e1s me cost\u00f3 fue decidir el tipo de motores a utilizar.<br \/>\nB\u00e1sicamente hay tres tipos:<\/p>\n<ol>\n<li>Motores de corriente continua (Motores DC) que seg\u00fan la diferencia de voltaje aplicada se mueven m\u00e1s deprisa o m\u00e1s lentos (dos cables).<\/li>\n<li>Motores Servos de rotaci\u00f3n continua que permiten indicar al motor la velocidad deseada mediante una se\u00f1al (tres cables).<\/li>\n<li>Motores de pasos (Stepper) que permiten un control muy fino del movimiento, con un control m\u00e1s complicado (al menos cuatro cables).<\/li>\n<\/ol>\n<p>De arriba abajo, cada tipo de motor permite un control m\u00e1s fino de la velocidad del mismo.<\/p>\n<p>Y aqu\u00ed nos topamos con una m\u00e1xima: <strong>cu\u00e1nto m\u00e1s velocidad menos control, cu\u00e1nto m\u00e1s control menos velocidad<\/strong> (a precios\/calidades similares).<\/p>\n<p>Esto quiere decir que para motores similares, los DC son los m\u00e1s r\u00e1pidos y los stepper los de mayor control.<br \/>\nObviamente un motor stepper de gran calidad (y precio) puede ser mucho m\u00e1s r\u00e1pido que un motor barato DC.<\/p>\n<p><strong>Nota 1<\/strong>: Algunos participantes no consiguieron acabar la prueba porque el robot no reaccionaba suficientemente r\u00e1pido y perd\u00eda la pista. En la competici\u00f3n mi robot era el m\u00e1s lento, pero no perd\u00eda la pista. As\u00ed que de forma lenta y segura qued\u00f3 tercero :-) <\/p>\n<p><strong>Nota 2<\/strong>: Los motores servo de rotaci\u00f3n continua deben calibrarse. Para ello se env\u00eda a los motores la se\u00f1al de &#8220;parados&#8221; (90) y mediante un regulador incorporado, utilizando un destornillador, se ajustan los motores para que queden efectivamente quietos.<\/p>\n<p>&nbsp;<\/p>\n<h3>Tracci\u00f3n y direcci\u00f3n<\/h3>\n<p>Existen dos formas b\u00e1sicas de gobernar el movimiento de un robot, una carretilla, un coche&#8230;<\/p>\n<p>Una opci\u00f3n es usar un motor para generar el empuje de motor y otro motor para controlar la direcci\u00f3n.<br \/>\nEste es el sistema habitual de los coches, las motos, los camiones&#8230;<\/p>\n<p>Si nos fijamos en un coche teledirigido (o RC: radio-control), normalmente tienen la tracci\u00f3n (el empuje, la fuerza motriz) en el eje trasero (ruedas motrices), y gobiernan la direcci\u00f3n con las ruedas del eje delantero (ruedas directrices).<br \/>\nEn cambio las carretillas, en cuanto son un poco grandes, suelen tener las ruedas directrices detr\u00e1s, algo que confunde a mucha gente.<\/p>\n<p>Algunos coches &#8220;de verdad&#8221; tambi\u00e9n tienen tracci\u00f3n trasera, pero lo habitual es que las ruedas motrices y directrices sean las del eje delantero. A\u00fan as\u00ed, lo importante es que se utiliza un \u00fanico motor para imprimir la misma velocidad a ambas ruedas motrices (el motor del veh\u00edculo) y otro motor para controlar la direcci\u00f3n (el propio conductor, usando el volante o manillar, habitualmente de forma asistida).<\/p>\n<p>En definitiva este sistema utiliza dos motores -uno para empuje y otro para direcci\u00f3n-, tienen habitualmente un par de ejes y son &#8220;alargados&#8221;.<br \/>\nLa cuesti\u00f3n es que el veh\u00edculo no puede girar sobre si mismo y maniobrar es algo complicado (piensa en las maniobras t\u00edpicas de aparcamiento de un coche).<\/p>\n<p>La otra forma de gobernar el veh\u00edculo es mediante lo que se denomina empuje diferencial (differential drive).<br \/>\nEste sistema utiliza dos ruedas con motores independientes. De nuevo tenemos dos motores pero con funciones diferentes, pero en este caso cada motor proporciona fuerza motriz independiente a una rueda (o conjunto de ruedas) en un lado del veh\u00edculo.<br \/>\nPara que el veh\u00edculo vaya recto se aplica la misma velocidad en ambos lados. Para que el veh\u00edculo gire, cada rueda establece una velocidad diferente. Incluso puede girar una rueda en una direcci\u00f3n y la otra al rev\u00e9s, realizando un giro sobre si mismo sin desplazamiento.<br \/>\nEste comportamiento es similar a una canoa o barca en la que remas a ambos lados de la misma. Seg\u00fan la diferencia de fuerza aplicada en cada lado, la nave avanzar\u00e1 recto, girar\u00e1 m\u00e1s o menos, o ir\u00e1 hacia atr\u00e1s.<\/p>\n<p>Este tipo de control es m\u00e1s sencillo y proporciona la mejor maniobrabilidad, especialmente con solo dos ruedas. En este caso, que es el habitual, el eje debe estar bastante centrado, lo que a su vez obliga a dise\u00f1os de planta &#8220;cuadrada&#8221;.<\/p>\n<p>Como se trataba de mi primer robot y pretend\u00eda hacerlo sencillo, al final opt\u00e9 por el empuje diferencial con dos ruedas.<\/p>\n<p>&nbsp;<\/p>\n<h2>Primeras pruebas<\/h2>\n<h3>Primera prueba de concepto: Motores DC<\/h3>\n<p><a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/01.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/01.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>Para mi primera prueba de concepto utilic\u00e9 dos motores DC y comprobe que para el empuje diferencial no son la mejor opci\u00f3n.<br \/>\nLos motores DC giran a la m\u00e1xima velocidad que les permite la diferencia de tensi\u00f3n. Cuando reduces la tensi\u00f3n para reducir la velocidad, la inercia de los motores hace que por un momento giren m\u00e1s r\u00e1pido de lo indicado por el voltaje. C\u00f3mo dec\u00eda: m\u00e1s velocidad = menos control.<br \/>\nLos motores de DC pueden ser una buena opci\u00f3n para el modelo tracci\u00f3n\/direcci\u00f3n.<\/p>\n<p>Por cierto, uno de los motores DC de la primera prueba, proced\u00eda de una mu\u00f1eca que llevaba 25 a\u00f1os sin funcionar (una mu\u00f1eca patinadora), pero el motor pude reutilizarlo.<\/p>\n<p>&nbsp;<\/p>\n<h3>Seguna prueba de concepto: Motores servo<\/h3>\n<p><a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/02.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/02.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>En esta imagen muestro adem\u00e1s el tercer punto de apoyo. Lo ideal es poner un rodamiento (sirve una bola de desodorante roll-on). En mi caso los motores Servo no eran muy r\u00e1pidos pero s\u00ed suficientemente potentes. As\u00ed que use un tornillo como tercer apoyo. El rozamiento era m\u00ednimo y me permit\u00eda regular la altura de la plataforma para los sensores de l\u00edneas.<\/p>\n<p>En mi caso el tama\u00f1o del robot lo marc\u00f3 el tama\u00f1o de la tabla de madera en que ten\u00eda atornillado el Arduino, porque no me apetec\u00eda desmontarlo de ah\u00ed.<br \/>\nAdem\u00e1s, como se aprecia en la imagen superior, la disposici\u00f3n elegida me permit\u00eda dejar la pila de 9V entre los motores.<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/04.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/04.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>Por otra parte el dise\u00f1o de la electr\u00f3nica ya estaba bastante terminado (ver al final del art\u00edculo).<br \/>\nLe incorpor\u00e9 luces y un altavoz por dos motivos: porque soy un hortera y porque las luces y los sonidos me permit\u00edan saber en qu\u00e9 parte del programa se encontraba el robot, haciendo &#8220;debug&#8221; del programa.<br \/>\nEl potenci\u00f3metro me permit\u00eda establecer una velocidad de motor m\u00e1s alta o m\u00e1s baja sin tener que modificar el programa.<br \/>\nEl programa que utilic\u00e9 en la prueba est\u00e1 al final, pero se basa en mi programa b\u00e1sico que muestro aqu\u00ed:<br \/>\n<a href=\"http:\/\/guimi.net\/blogs\/hiparco\/arduino-sensores-de-linea\/\">Arduino: Sensores de linea<\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>Notas sobre Chasis y Ruedas<\/h3>\n<p>Hasta la elecci\u00f3n de ruedas puede ser dificil.<br \/>\nPrimero us\u00e9 un chasis de cart\u00f3n y unas ruedas de pl\u00e1stico duro de un juguete (se ven en &#8220;Motores DC&#8221;). Estas ruedas no ten\u00edan ninguna tracci\u00f3n. Es decir, &#8220;resbalaban&#8221; en el suelo y giraban sin mover apenas el robot.<\/p>\n<p>Despu\u00e9s realic\u00e9 un chasis y us\u00e9 unas ruedas de goma de una caja de <a href=\"http:\/\/www.meccano.com\/\">Meccano<\/a> que ten\u00eda \u00a1hace m\u00e1s de 20 a\u00f1os! (ver fotos del punto anterior).<\/p>\n<p>Pero no consegu\u00eda fijar adecuadamente las ruedas a los motores as\u00ed que en la siguiente versi\u00f3n utilic\u00e9 de ruedas uno de los propios enganches de los motores.<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/05.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/05.jpg\" class=\"alignnone\" \/><\/a><br \/>\nAdem\u00e1s se aprecia que cambi\u00e9 la parte delantera del chasis para poder incorporar m\u00e1s facilmente los sensores.<\/p>\n<p>En todo caso el problema segu\u00eda siendo la baja velocidad de giro de las ruedas. Adem\u00e1s como las &#8220;ruedas&#8221; no eran tales tampoco ten\u00edan tracci\u00f3n.<br \/>\nA grandes males, grandes remedios.<br \/>\nLa soluci\u00f3n m\u00e1s sencilla fue aumentar el tama\u00f1o de rueda. Para ello hice ruedas de cartulina, dibujandolas con un CD y recort\u00e1ndolas. Adem\u00e1s dej\u00e9 intencionadamente un corte &#8220;sucio&#8221; de los bordes de la cartulina para mejorar la tracci\u00f3n.<br \/>\nAl tener el eje m\u00e1s alto, tuve que modificar ligeramente el chasis.<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/06.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/06.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/07.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/07.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>El dise\u00f1o final<\/h2>\n<p>Este fue el primer prototipo del robot final.<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/09.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/09.jpg\" class=\"alignnone\" \/><\/a><br \/>\nPara las primeras pruebas puse los sensores arriba del robot. Son las luces moradas, que curiosamente a simple vista no se ven, pero la c\u00e1mara s\u00ed que las capta.<\/p>\n<p>Para la versi\u00f3n final de las ruedas utilic\u00e9 cart\u00f3n procedente de una caja de leche (una caja de las que contienen seis tetrabricks de un litro), utilizando dos capas pegadas de cart\u00f3n para cada rueda, y le ped\u00ed a mis hijos que las decoraran. Este fue el resultado:<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/15.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/15.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/16.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/16.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h2>Solventando problemas<\/h2>\n<p>Como se puede apreciar en el video, me encontr\u00e9 principalmente con dos problemas: sensores err\u00e1ticos y problemas de tensi\u00f3n.<\/p>\n<p>&nbsp;<\/p>\n<h3>Problemas con los sensores<\/h3>\n<p>Al realizar pruebas, los sensores a veces funcionaban y a veces no.<br \/>\nEl problema era que la altura de los sensores y, sobretodo, las condiciones de iluminaci\u00f3n afectaban mucho a los sensores. As\u00ed que tras varios intentos solvent\u00e9 el problema encapsulando los sensores y dejandolos a ras de suelo.<br \/>\nElimin\u00e9 el tercer punto de apoyo (el tornillo) y con cartulina y cinta aislante negra encapsule por separado los sensores. Aunque en la foto no se aprecia bien, entre ambos sensores hay una cartulina separ\u00e1ndolos para evitar interferencias.<br \/>\nEl propio encapsulamiento de cartulina hace de tercer apoyo, dejando los sensores a un mil\u00edmetro del suelo y totalmente a oscuras.<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/18.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/18.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>&nbsp;<\/p>\n<h3>Problemas con la tensi\u00f3n<\/h3>\n<p>Los motores que utilic\u00e9 eran motores Servo que permiten una tensi\u00f3n de entrada de entre 4V y 6V.<br \/>\nLa pila que usaba era de 9V, por lo que no pod\u00eda alimentarlos directamente.<\/p>\n<p>As\u00ed que todos los elementos, incluidos los motores, estaban alimentados desde la placa Arduino a 5V. Teniendo en cuenta adem\u00e1s que las pilas de 9V tienen una capacidad de unos 400 mAh, esto hac\u00eda que la pila se fundiese a gran velocidad, y que cuando la pila no rend\u00eda al 100% los picos de tensi\u00f3n producidos por los motores reseteasen la placa.<\/p>\n<p>Intent\u00e9 reducir el problema a\u00f1adiendo capacitadores, pero no era suficiente.<\/p>\n<p><strong>Soluci\u00f3n buena<\/strong>: alimentar los motores por separado, no desde la placa Arduino.<br \/>\nPara ello una opci\u00f3n es utilizar un grupo de 5 bater\u00edas AA que sumasen 6V (1,2Vx5), modificando el chasis para hacer sitio.<br \/>\nOtra opci\u00f3n es utilizar una bater\u00eda con otro voltaje y utilizar un regulador de tensi\u00f3n.<\/p>\n<p>Para seleccionar una buena bater\u00eda (o conjunto) debemos tener en cuenta el voltaje y la corriente que necesitamos. As\u00ed una bater\u00eda de 9V de menos de 500 mAh no es una buena opci\u00f3n para alimentar dos motores servos como los que lleva 1st Robot.<br \/>\nVer <a href=\"http:\/\/guimi.net\/blogs\/hiparco\/baterias\/\">informaci\u00f3n sobre bater\u00edas<\/a>.<\/p>\n<p><strong>Soluci\u00f3n adoptada<\/strong>: Dado que part\u00edamos de un fallo de dise\u00f1o (usar una bater\u00eda de 9V y menos de 500 mAh), la \u00fanica opci\u00f3n el d\u00eda de la competici\u00f3n era cambiar la pila para cada prueba y modificar el programa para que acelerara y frenara poco a poco. Adem\u00e1s los cambios al programa los hice el d\u00eda mismo de la competici\u00f3n, por lo que no tuve mucho tiempo de optimizar y limpiar el c\u00f3digo. As\u00ed que el programa final es algo farragoso.<br \/>\nSi quieres usar mi c\u00f3digo, recomiendo partir del programa base (<a href=\"http:\/\/guimi.net\/blogs\/hiparco\/arduino-sensores-de-linea\/\">Arduino: Sensores de linea<\/a>) y no del programa final que utilic\u00e9.<\/p>\n<p>&nbsp;<\/p>\n<h1>1st Robot &#8211; Resultado<\/h1>\n<p>En plena participaci\u00f3n:<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/19.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/19.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>1st Robot desde diferentes \u00e1ngulos:<br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/10.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/10.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/11.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/11.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/12.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/12.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/13.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/13.jpg\" class=\"alignnone\" \/><\/a><br \/>\n<a href=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/14.jpg\"><img decoding=\"async\" alt=\"\" src=\"\/imgs\/blog\/hiparco\/arduino\/1stRobot\/14.jpg\" class=\"alignnone\" \/><\/a><\/p>\n<p>&nbsp;<br \/>\n<a name=\"video\"><\/a><\/p>\n<h2>V\u00eddeo de la evoluci\u00f3n de 1st Robot<\/h2>\n<p>V\u00eddeo de 4 minutos. <a href=\" http:\/\/youtu.be\/Gd9kvCIvuPE\">Ver 1st Robot en Youtube<\/a>.<br \/>\n<iframe loading=\"lazy\" width=\"560\" height=\"315\" src=\"\/\/www.youtube.com\/embed\/Gd9kvCIvuPE\" frameborder=\"0\" allowfullscreen><\/iframe><\/p>\n<p>&nbsp;<\/p>\n<h1>Nth Robot &#8211; El futuro<\/h1>\n<p>Para pr\u00f3ximas versiones del robot, como ya he dicho probablemente utilice alimentaci\u00f3n independiente para los motores, ya sea mediante un regulador de tensi\u00f3n o utilizando un conjunto que sume 6V.<\/p>\n<p>Tambi\u00e9n es probable que utilice m\u00e1s sensores de l\u00ednea y as\u00ed tener m\u00e1s flexibilidad a la hora de localizar la l\u00ednea y reaccionar.<\/p>\n<p>Quiz\u00e1 utilice ruedas m\u00e1s grandes o engranajes para obtener m\u00e1s velocidad, ya que los motores tienen fuerza de sobra para mover el robot con su peso actual e incluso para transportar peque\u00f1as cargas.<\/p>\n<p>Definitivamente necesito una forma mejor de conectar las ruedas a los motores que un poco de cinta islante.<\/p>\n<p>Adem\u00e1s estoy preparando una versi\u00f3n del <a href=\"http:\/\/guimi.net\/blogs\/hiparco\/arduino-modulo-bluetooth\/\">robot por control remoto utilizando un m\u00f3dulo Bluetooth<\/a> hc-05 y un m\u00f3vil con Android.<\/p>\n<p>&nbsp;<\/p>\n<h1>Anexos<\/h1>\n<h2>Anexo I: Componentes<\/h2>\n<ul>\n<li>2 IR Infrared Line Track Tracker Follower Sensor 5V Shield\n<\/li>\n<li>1 Arduino UNO board rev.3\n<\/li>\n<li>1 Breadboard\n<\/li>\n<li>20-30 jumper wires\n<\/li>\n<li>1 Potentiometer 10kilohm\n<\/li>\n<li>3 LEDs (2 yellow, 1 green)\n<\/li>\n<li>Un poco de Cinta aislante\n<\/li>\n<li>1 Piezo capsule [PKM17EPP-4001-B0]\n<\/li>\n<li>2 Capacitors 100uF\n<\/li>\n<li>3 Resistors 220 ohm\n<\/li>\n<li>1 Madera de montaje\n<\/li>\n<li>2 Servo digital de rotaci\u00f3n cont\u00ednua 360\u00ba\n<\/li>\n<li>1 Pila de 9V + conector\n<\/li>\n<li>2 Ruedas de cart\u00f3n (decoradas por Pau y L\u00faa)\n<\/li>\n<li>1 Chasis realizado con viejas piezas de <a href=\"http:\/\/www.meccano.com\/\">Meccano<\/a>\n<\/li>\n<li>2 Gomas de pelo (aportadas por L\u00faa)\n<\/li>\n<li>1 encapsulamiento para sensores realizado con cartulina y cinta aislante<\/li>\n<\/ul>\n<p>Coste aproximado: Entre 60 y 70 \u20ac<\/p>\n<p>As\u00ed es como se conecta todo esto:<br \/>\n<img decoding=\"async\" src=\"\/imgs\/blog\/hiparco\/arduino\/015-Robot_sigue_lineas_Servo_bb.png\" alt=\"\" \/><\/p>\n<p>&nbsp;<\/p>\n<h2>Anexo II: El programa<\/h2>\n<p>El c\u00f3digo final, como ya he comentado, lo realic\u00e9 el mismo d\u00eda de las pruebas por lo que no qued\u00f3 muy limpio.<br \/>\nUtiliza mi libreria <a href=\"http:\/\/guimi.net\/blogs\/hiparco\/arduino-libreria-tocamelodia-para-tocar-melodias-predeterminadas\/\">TocaMelodia<\/a>, para tocar melodias, pero puede eliminarse f\u00e1cilmente comentado las lineas correspondientes.<\/p>\n<p>Adem\u00e1s tiene dos modos de funcionamiento. Para alternar entre ellos hay que modificar por c\u00f3digo el valor de la variable modo y cargar el programa.<br \/>\nEl modo 0 es el programa sigue-lineas utilizado en la prueba. Ambos sensores se encuentran delante y juntos, sobre la l\u00ednea negra.<br \/>\nEl modo 2 permite probar y calibrar los motores. En este modo el robot var\u00eda la velocidad de los motores en base a la lectura del potenci\u00f3metro, indicando adem\u00e1s con luces el sentido de giro. Esto permite calibrar los motores cuando el potenci\u00f3metro env\u00eda la se\u00f1al de parado (90), lo que se aprecia porque los dos LEDs de giro quedan encendidos (ver nota 2 en la secci\u00f3n de motores).<\/p>\n<p>El c\u00f3digo fuente final:<\/p>\n<pre class=\"brush: cpp; title: ; notranslate\" title=\"\">\r\n\/*\r\n * 1st Robot by Guimi\r\n *\r\n * Este programa implemente un robot que permite varios modos de funcionamiento:\r\n * &#x5B;0 sigue-lineas; 2 prueba de motores]\r\n *\r\n * Dispone de dos ruedas con un motor servo cada uno (differential drive)\r\n * \r\n * Dispone de dos sensores de linea que indican cuando se detecta la linea.\r\n *\r\n * Tambien dispone de dos LEDs (derecho e izquierdo) para indicar adelante (ambos apagados), giro a un lado o parado (ambos encendidos).\r\n *\r\n * Por ultimo utiliza un altavoz o piezoelectrico para emitir melodias predeterminadas.\r\n *\r\n * 2014 - Guimi (http:\/\/guimi.net)\r\n *\r\n *\/\r\n\r\n\r\n\/\/ LIBRERIAS\r\n\/\/----------\r\n#include &lt;TocaMelodia.h&gt; \/\/ Libreria para tocar melodias pre-determninadas (disponible en http:\/\/guimi.net\/blogs\/hiparco\/arduino-libreria-tocamelodia-para-tocar-melodias-predeterminadas\/)\r\n#include &lt;Servo.h&gt; \/\/ Incluimos la libreria de gestin de los motores servo\r\n\r\n\r\n\/\/ CONSTANTES\r\n\/\/----------\r\nconst byte sensorDer=2; \/\/ Pin del sensor Derecho\r\nconst byte sensorIzq=3; \/\/ Pin del sensor Izquierdo\r\n\r\nconst byte pinMotorDer=6; \/\/ Pin &#x5B;PWM] de la se\u00f1al de velocidad del motor Derecho\r\nconst byte pinMotorIzq=9; \/\/ Pin &#x5B;PWM] de la se\u00f1al de velocidad del motor Izquierdo\r\n\r\nconst byte pinGiroDer=10; \/\/ Pin del LED derecho\r\nconst byte pinGiroIzq=11; \/\/ Pin del LED izquierdo\r\nconst byte pinAltavoz=12; \/\/ Pin del altavoz\r\nconst byte pinEstado=13; \/\/ Pin del LED que marca el estado\r\n\r\nconst byte pinPotenciometro=A0; \/\/ Pin del potenciometro (que establece en el setup la variacin de velocidad)\r\n\r\n\r\n\/\/ VARIABLES\r\n\/\/----------\r\nbyte valorIzq=0; \/\/ Variable para guardar el valor del sensor Izquierdo &#x5B;0 Negro; 1 Blanco]\r\nbyte valorDer=0; \/\/ Variable para guardar el valor del sensor Derecho &#x5B;0 Negro; 1 Blanco]\r\n\r\nbyte modo=0; \/\/ Variable para guardar el modo del programa &#x5B;0 sigue-lineas; 1 camino complejo; 2 prueba de motores]\r\nbyte direccion=2; \/\/ Variable para guardar la ultima direccion valida &#x5B;0 recto, 1 izquierda; 2 derecha]\r\n\r\nint valorPotenciometro = 0; \/\/ Variable para guardar el valor del potenciometro &#x5B;0-1023]\r\nint variacionVelocidad = 90; \/\/ &#x5B;0 - 90] Variable que indica la variacion de velocidad de giro a imprimir en los motores. Cuanto mas alto el valor, mayor la velocidad.\r\n\r\nunsigned long tiempoDesde = 0; \/\/ Variables para medir tiempos\r\nunsigned long tiempoHasta = 0; \/\/ Variables para medir tiempos\r\nlong tiempoLinea = 3000; \/\/ Indica el tiempo que se tarda en recorrer una linea corta (para la larga tarda 3500 aprox)\r\n\r\nServo motorIzq; \/\/ Gestor del motor izquierdo\r\nServo motorDer; \/\/ Gestor del motor derecho\r\n\r\nTocaMelodia tocaMelodia(pinAltavoz); \/\/ Inicializamos el altavoz, indicando el pin\r\n\r\n\r\n\/\/ FUNCION SETUP\r\n\/\/--------------\r\nvoid setup(){\r\n  \/\/ Definimos cada pin como entrada o salida\r\n  pinMode(sensorDer,INPUT);\r\n  pinMode(sensorIzq,INPUT);\r\n\r\n  pinMode(pinGiroDer,OUTPUT);\r\n  pinMode(pinGiroIzq,OUTPUT);\r\n  pinMode(pinAltavoz,OUTPUT);\r\n  pinMode(pinEstado,OUTPUT);\r\n\r\n  \/\/ Conectamos los motores a sus pines\r\n  motorIzq.attach(pinMotorIzq);\r\n  motorDer.attach(pinMotorDer);\r\n  \/\/ Paramos los motores\r\n  velocidadMotores(90, 90);\r\n\r\n  \/\/ Apagamos la luz de estado mientras esperamos un tiempo inicial para ajustarnos a la normativa del concurso\r\n  digitalWrite(pinEstado, LOW);\r\n  for (int i = 0; i&lt;4; i++) {\r\n    \/\/ Indicamos el estado mediante una intermitencia del pin de estado\r\n    digitalWrite(pinEstado, LOW);\r\n    digitalWrite(sensorDer, LOW);\r\n    digitalWrite(sensorIzq, LOW);\r\n    delay(250);\r\n    digitalWrite(pinEstado, HIGH);\r\n    digitalWrite(sensorDer, HIGH);\r\n    digitalWrite(sensorIzq, HIGH);\r\n    delay(250);\r\n  }\r\n  \/\/ Iniciamos con un poco de fanfarria ;-P  Esto permite detectar facilmente cuando el sistema se resetea.\r\n  tocaMelodia.melodia(MELODIA_PODER_PERRUNO);\r\n\r\n  \/\/ Indicamos el inicio\r\n  digitalWrite(pinEstado, HIGH);\r\n\r\n  \/\/ Leemos el valor del potenciometro &#x5B;0-1023]\r\n  valorPotenciometro=analogRead(pinPotenciometro);\r\n  \/\/ Establecemos una variacion de velocidad a utilizar\r\n  \/\/ Esto nos permite ajustar la velocidad efectiva segun sea necesario por el angulo de las curvas del circuito\r\n  variacionVelocidad=map(valorPotenciometro,0,1023,0,89);\r\n\r\n  \/\/ Leemos el valor de los sensores &#x5B;0-1]\r\n  valorIzq=digitalRead(sensorIzq);\r\n  valorDer=digitalRead(sensorDer);\r\n\r\n  \/\/ Preparamos la comunicacion mediante el puerto serie\r\n  \/\/Serial.begin(9600);\r\n}\r\n\r\n\r\n\/\/ FUNCION LOOP\r\n\/\/-------------\r\nvoid loop(){\r\n  \/\/*****************************************************************************************************************\r\n  \/\/-----------------------------------------------------------------------------------------------------------------\r\n  \/\/ S I G U E   L I N E A S   (modo == 0)\r\n  \/\/-----------------------------------------------------------------------------------------------------------------\r\n  \/\/*****************************************************************************************************************\r\n  \/\/ Mientras el modo sea &quot;sigue-lineas&quot;\r\n  while (modo == 0) {\r\n    \/\/ Mientras detectamos linea con algun sensor, la seguimos\r\n    while (!valorIzq || !valorDer) {\r\n      \/\/ Establecemos direccion en base a las lecturas\r\n      if (!valorIzq &amp;&amp; !valorDer) { \/\/ Recto\r\n        direccion=0;\r\n        indicaDireccion(direccion);\r\n  \r\n        \/\/ Si hace poco que nos hemos reincorpordao a la linea, avanzamos despacio\r\n        \/\/ por dos motivos: como en las curvas este proceso (dentro-fuera de linea) se repite muchas veces\r\n        \/\/ lo normal es que si venimos de fuera nos volvamos a salir y ademas muchos cambios bruscos seguidos resetean la placa (problemas de tension)\r\n        tiempoHasta = millis();\r\n        if (tiempoHasta - tiempoDesde &lt; 1000) {\r\n          velocidadMotores(90 - (variacionVelocidad\/4), 90 + (variacionVelocidad\/4));\r\n        } else { \/\/ Si llevamos un tiempo en la linea vamos a toda velocidad\r\n          velocidadMotores(90 - variacionVelocidad, 90 + variacionVelocidad);\r\n        }\r\n        \r\n      } else if (!valorDer) { \/\/ Derecha\r\n        direccion=2;\r\n        indicaDireccion(direccion);\r\n        velocidadMotores(90 - variacionVelocidad, 90 + (variacionVelocidad\/4));\r\n      } else { \/\/ Izquierda\r\n        direccion=1;\r\n        indicaDireccion(direccion);\r\n        velocidadMotores(90 - (variacionVelocidad\/4), 90 + variacionVelocidad);\r\n      }\r\n      \/\/ Esperamos un tiempo de reaccion para los componentes\r\n      delay(50);\r\n  \r\n      \/\/ Leemos el valor de los sensores &#x5B;0-1]\r\n      valorIzq=digitalRead(sensorIzq);\r\n      valorDer=digitalRead(sensorDer);\r\n    }\r\n  \r\n    \/\/ Reducimos velocidad antes de parar, para evitar que la placa se resetee por problemas de potencia\r\n    velocidadMotores(90 - (variacionVelocidad\/8), 90 + (variacionVelocidad\/8)); delay(50);\r\n    \/\/ Paramos\r\n    Parar(); delay(80);\r\n  \r\n    \/\/ Si no detectamos linea la buscamos en la ultima direccion conocida (o al inicio en la predeterminada)\r\n    while (valorIzq &amp;&amp; valorDer) {\r\n      indicaDireccion(direccion);\r\n      if (direccion == 1) { \/\/ Rotacion a Izquierda\r\n        velocidadMotores(90 + (8), 90 + (8));\r\n      } else if (direccion == 2) { \/\/ Rotacion a Derecha\r\n        velocidadMotores(90 - (8), 90 - (8));\r\n      } else  if (direccion == 0) { \/\/ Recto\r\n      \/\/   \/\/ Hemos localizado el final de linea\r\n      \/\/   \/\/ Dejamos el robot quieto hasta que los sensores vuelvan a detectar linea\r\n      \/\/  tocaMelodia.melodia(MELODIA_FANFARRIA);\r\n      \/\/  direccion = 3; \/\/ Solo suena la melodia la primera vez\r\n        \/\/ En este circuito no hay final de linea, buscamos una linea\r\n        direccion = 1; \/\/ Indicamos que busque hacia la izquierda\r\n      }\r\n      \/\/ Esperamos un tiempo de reaccion para los componentes\r\n      delay(30);\r\n  \r\n      tiempoDesde = millis(); \/\/ Tomamos el tiempo en el que retomamos la pista\r\n  \r\n      \/\/ Leemos el valor de los sensores &#x5B;0-1]\r\n      valorIzq=digitalRead(sensorIzq);\r\n      valorDer=digitalRead(sensorDer);\r\n    }\r\n  \r\n    delay(30); \/\/ Mantenemos el giro un poco para que se centren los sensores en la linea\r\n    Parar(); delay(80); \/\/ Paramos para dar tiempo a la tesion a estabilizarse\r\n\r\n  } \/\/ while (modo == 0)\r\n\r\n\r\n\r\n  \/\/*****************************************************************************************************************\r\n  \/\/-----------------------------------------------------------------------------------------------------------------\r\n  \/\/ P R U E B A   D E   M O T O R E S   (modo == 2)\r\n  \/\/-----------------------------------------------------------------------------------------------------------------\r\n  \/\/*****************************************************************************************************************\r\n  \/\/ Mientras el modo sea &quot;prueba de motores&quot;\r\n  while (modo == 2) {\r\n    \/\/ Leemos el valor del potenciometro &#x5B;0-1023]\r\n    valorPotenciometro=analogRead(pinPotenciometro);\r\n    valorPotenciometro=map(valorPotenciometro,0,1023,0,179);\r\n    \/\/Serial.println(variacionVelocidad);\r\n    \/\/ Usamos los LEDs de giro para indicar la lectura del potenciometro\r\n    if (valorPotenciometro == 90) {\r\n      digitalWrite(pinGiroIzq, HIGH);\r\n      digitalWrite(pinGiroDer, HIGH);\r\n    } else if (valorPotenciometro &gt; 90) {\r\n      digitalWrite(pinGiroIzq, LOW);\r\n      digitalWrite(pinGiroDer, HIGH);\r\n    } else {\r\n      digitalWrite(pinGiroIzq, HIGH);\r\n      digitalWrite(pinGiroDer, LOW);\r\n    }\r\n    \/\/ Variamos la velocidad de los motores en base a la lectura del potenciometro\r\n    velocidadMotores(valorPotenciometro, valorPotenciometro);\r\n    delay(100);\r\n  } \/\/ while (modo == 2) \r\n\r\n} \/\/ LOOP\r\n\r\n\r\n\/\/ MOVIMIENTOS\r\n\/\/-------------\r\n\/\/ Ambos motores son iguales, pero se montan simetricamente (uno a cada lado)\r\n\/\/ Asi por ejemplo, para ir adelante cada motor debe girar en una direccion\r\n\/\/ En este caso el motor izquierdo avanza con &#x5B;90-180] y el derecho con &#x5B;0-90]\r\n\/\/ en ambos casos cuanto mas alejado de 90 sea el valor, mas deprisa\r\n\/\/----------------------------------------------------------------------------\r\nvoid indicaDireccion(int direccion) {\r\n  switch (direccion) {\r\n  case 0:\r\n    \/\/Serial.println(&quot;Adelante&quot;);\r\n    \/\/ Apagamos las luces de giro\r\n    digitalWrite(pinGiroIzq, LOW);\r\n    digitalWrite(pinGiroDer, LOW);\r\n    break;\r\n  case 1:\r\n    \/\/Serial.println(&quot;Izquierda&quot;);\r\n    \/\/ Encendemos la luz de giro\r\n    digitalWrite(pinGiroIzq, HIGH);\r\n    digitalWrite(pinGiroDer, LOW); \r\n    break;\r\n  case 2:\r\n    \/\/Serial.println(&quot;Derecha&quot;);\r\n    \/\/ Encendemos la luz de giro\r\n    digitalWrite(pinGiroIzq, LOW);\r\n    digitalWrite(pinGiroDer, HIGH); \r\n    break;\r\n  } \r\n}\r\n\r\nvoid Parar(){\r\n  \/\/Serial.println(&quot;Parar&quot;);\r\n  \/\/ Encendemos las luces de giro\r\n  digitalWrite(pinGiroIzq, HIGH);\r\n  digitalWrite(pinGiroDer, HIGH);\r\n\r\n  \/\/ Indicamos la velocidad\r\n  \/\/velocidadMotores(90, 90);\r\n  \/\/ Si paramos los dos motores a la vez el pico de corriente hace que se resetee la placa\r\n  \/\/ Asi que paramos uno un poco antes que el otro.\r\n  motorIzq.write(90);\r\n  delay(100);\r\n  motorDer.write(90);\r\n  delay(20);\r\n}\r\n\r\n\/\/ Establece la velocidad solicitada en los motores\r\nvoid velocidadMotores(int izquierda, int derecha) {\r\n  \/\/Serial.print(&quot;Velocidad Motores:&quot;);\r\n  \/\/Serial.println(variacionVelocidad);\r\n  motorIzq.write(izquierda);\r\n  delay(20);\r\n  motorDer.write(derecha);\r\n  delay(20);\r\n}\r\n\r\n<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>1st Robot &#8211; C\u00f3mo se hizo Hay un monton de informaci\u00f3n de robots econ\u00f3micos realizados con Arduino. Este es el mio. Con unos 320 gramos, este robot qued\u00f3 tercero en la prueba de velocidad (sigue-lineas) del Olympic Robotic Challenge 2.14. Tambi\u00e9n hizo el tercer mejor tiempo en el laberinto (4.1 segundos), aunque al segundo intento, [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"parent":965,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","meta":{"footnotes":""},"class_list":["post-1577","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/pages\/1577","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/comments?post=1577"}],"version-history":[{"count":98,"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/pages\/1577\/revisions"}],"predecessor-version":[{"id":1732,"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/pages\/1577\/revisions\/1732"}],"up":[{"embeddable":true,"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/pages\/965"}],"wp:attachment":[{"href":"http:\/\/guimi.net\/blogs\/hiparco\/wp-json\/wp\/v2\/media?parent=1577"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}