{"id":285,"date":"2017-09-11T07:31:20","date_gmt":"2017-09-11T12:31:20","guid":{"rendered":"https:\/\/drmad.org\/blog\/?p=285"},"modified":"2019-03-09T23:04:15","modified_gmt":"2019-03-10T04:04:15","slug":"servomotor-sg90-con-raspberry-pi","status":"publish","type":"post","link":"https:\/\/drmad.org\/blog\/servomotor-sg90-con-raspberry-pi.html","title":{"rendered":"Servomotor SG90 con Raspberry PI"},"content":{"rendered":"<p><iframe loading=\"lazy\" width=\"810\" height=\"608\" src=\"https:\/\/www.youtube.com\/embed\/wsGBS3ZP1FM?feature=oembed\" frameborder=\"0\" allow=\"accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture\" allowfullscreen><\/iframe><\/p>\n<p>Mi amigo Jorge me \u00abpresent\u00f3\u00bb los servomotores <a href=\"http:\/\/akizukidenshi.com\/download\/ds\/towerpro\/SG90.pdf\">SG90<\/a>. Son lindos, chiquitos, baratos, y f\u00e1ciles de operar. Me traje un pack de 20 de AliExpress para hacer algunas pruebas, y hace unos d\u00edas llegaron.<\/p>\n<p><!--more--><\/p>\n<p>Este servo recibe un pulso por uno de sus pines. El ancho del pulso determina el \u00e1ngulo de rotaci\u00f3n (de -90\u00ba a 90\u00ba) al cual el motor debe llegar. Ya que debe enviarse el pulso constantemente dentro un rango de tiempo (20ms en caso del SG90), se puede usar cualquier librer\u00eda para crear una\u00a0<a href=\"https:\/\/es.wikipedia.org\/wiki\/Modulaci%C3%B3n_por_ancho_de_pulsos\">modulaci\u00f3n por ancho de pulsos<\/a>. El RPi tiene la librer\u00eda <a href=\"https:\/\/sourceforge.net\/p\/raspberry-gpio-python\/wiki\/PWM\/\">PWM<\/a>\u00a0de Python para ello. El\u00a0<em>duty cycle<\/em> es el porcentaje de tiempo que el pin elegido estar\u00e1 en 1 l\u00f3gico. El resto del tiempo estar\u00e1 en cero. El c\u00f3digo para moverlo es bastante sencillo:<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"python\">#!\/usr\/bin\/env python3\r\n\r\nfrom RPi import GPIO\r\nfrom time import sleep\r\n\r\n# El pin del GPIO que estar\u00e1 conectado al pin de PWM del servo.\r\nPIN = 2\r\n\r\n# Configuramos el pin del RPi\r\nGPIO.setmode(GPIO.BCM)\r\nGPIO.setup(PIN, GPIO.OUT)\r\n\r\n# El 2do par\u00e1metro es la frecuencia del ciclo en Hertz. El manual del SG90\r\n# indica un periodo del ciclo de 20ms (0,02s), entonce la frecuencia es \r\n# 1\/0,02 = 50 Hz\r\nservo = GPIO.PWM(PIN, 50)\r\n\r\n# Iniciamos el PWM, colocando el servo en 0\u00ba. Para ello, debemos enviarle\r\n# un pulso de 1.5ms de ancho. La librer\u00eda de Python requiere especificar el \r\n# 'duty cycle' ('ciclo de trabajo', el tiempo que el pulso estar\u00e1 en 1) en \r\n# porcentaje del ciclo. 1.5ms de 20ms es el 7.5%\r\nservo.start(7.5)\r\n\r\n# Le damos un segundo para que se mueva\r\nsleep(1)\r\n\r\n# Cambiamos el duty cycle para mover el servo completamente a la derecha, -90\u00ba.\r\n# Para ello, el SG90 espera un pulso de 2ms = 10%. Cambiamos el duty cycle.\r\nservo.ChangeDutyCycle(10)\r\n\r\n# Esperamos un segundo\r\nsleep(1)\r\n\r\n# Ahora, completamente a la izquierda, 90\u00ba, cambiamos el DC a 1ms = 5%\r\nservo.ChangeDutyCycle(5)\r\nsleep(1)\r\n\r\n# Detenemos el PWM y reseteamos los pins del RPi\r\nservo.stop()\r\nGPIO.cleanup()<\/pre>\n<p>En la pr\u00e1ctica encontr\u00e9 que completamente a la derecha no es un\u00a0<em>duty cycle<\/em> de 10%, sino 12%. Igual a la izquierda, no es 5%, sino 3%. Es cuesti\u00f3n de jugar un poco para llegar a los valores exactos.<\/p>\n<p>El servo requiere 5V para trabajar. El RPi tiene un pin de 5v, pero prefer\u00ed usar una fuente externa de energ\u00eda. No quisiera sobrcargar el RPi y malograrlo \ud83d\ude41<\/p>\n<p>A este c\u00f3digo le a\u00f1ad\u00ed un <a href=\"https:\/\/docs.python.org\/3.3\/library\/socketserver.html\">socketserver<\/a>\u00a0para la comunicaci\u00f3n desde Dorothy, donde hice un programa en JavaScript\/PHP para el control que uso con el celular. El JavaScript env\u00eda el \u00e1ngulo via Ajax al PHP, quien se lo env\u00eda al RPi via socket UDP, <em>et voil\u00e0<\/em>. M\u00e1s emocionante fue ver a mi amigo Oscar, que est\u00e1 en Estados Unidos, mover el servo desde all\u00e1 \ud83d\ude00<\/p>\n<p>Al inicio del v\u00eddeo el servo no responde bien. A veces tiembla, a veces se mueve solo. Pienso que puede ser por el hecho que el <a href=\"https:\/\/www.raspberrypi.org\/\">Raspberry PI<\/a> corre un Linux completo (con interrupciones y todo), es lento, y por defecto no trae (ni estoy usando la librer\u00edas para) un kernel con soporte para <a href=\"https:\/\/es.wikipedia.org\/wiki\/Sistema_de_tiempo_real\">trabajo en tiempo real<\/a>. Ya que el ancho del pulso enviado al servo es entre 1 y 2 milisegundos, es probable que a veces el RPi se distraiga y demore m\u00e1s en apagar la se\u00f1al del pulso,\u00a0<em>ergo<\/em>\u00a0enviando valores al azar al servo. Pero hey&#8230; funciona \ud83d\ude00<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Mi amigo Jorge me \u00abpresent\u00f3\u00bb los servomotores SG90. Son lindos, chiquitos, baratos, y f\u00e1ciles de operar. Me traje un pack<\/p>\n","protected":false},"author":1,"featured_media":293,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[24,7],"tags":[],"class_list":["post-285","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-hacks","category-raspberry-pi"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/drmad.org\/blog\/wp-content\/uploads\/2017\/09\/microservo.jpg?fit=1920%2C540&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p6p3z1-4B","jetpack-related-posts":[],"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/285","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/comments?post=285"}],"version-history":[{"count":6,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/285\/revisions"}],"predecessor-version":[{"id":294,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/posts\/285\/revisions\/294"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/media\/293"}],"wp:attachment":[{"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/media?parent=285"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/categories?post=285"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/drmad.org\/blog\/wp-json\/wp\/v2\/tags?post=285"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}