<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="es">
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leticiavp</id>
		<title>Proyecto Butiá - Contribuciones del usuario [es]</title>
		<link rel="self" type="application/atom+xml" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Leticiavp"/>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php/Especial:Contribuciones/Leticiavp"/>
		<updated>2026-04-05T22:26:18Z</updated>
		<subtitle>Contribuciones del usuario</subtitle>
		<generator>MediaWiki 1.26.2</generator>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3345</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3345"/>
				<updated>2012-10-15T15:30:35Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Ejemplos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 2 - Seguidor de líneas con eventos, utilizando un sensor de grises|Ejemplo 2: Seguidor de líneas con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 6: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 7: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 8: Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3344</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3344"/>
				<updated>2012-10-15T15:30:15Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Ejemplos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 2 - Seguidor de líneas con eventos, utilizando un sensor de grises|Ejemplo 2: Seguidor de líneas conn eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 6: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 7: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 8: Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3343</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3343"/>
				<updated>2012-10-15T15:28:17Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Integrantes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 6: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 7: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 8: Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3342</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3342"/>
				<updated>2012-10-15T15:26:02Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt; local COLOR_NEGRO = 20000 local MOTOR_VEL = 500 local MOTOR_GIRO_VEL = 500 local TIEMPO_CENTRADO = 0.1 local INTERVALO_CHEQUEO = 0.1 local DISTANCIA...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local COLOR_NEGRO = 20000&lt;br /&gt;
local MOTOR_VEL = 500&lt;br /&gt;
local MOTOR_GIRO_VEL = 500&lt;br /&gt;
local TIEMPO_CENTRADO = 0.1&lt;br /&gt;
local INTERVALO_CHEQUEO = 0.1&lt;br /&gt;
local DISTANCIA_OBSTACULO = 34000&lt;br /&gt;
local TIEMPO_RETROCESO = 0.1&lt;br /&gt;
local TIEMPO_AVANCE = 1.7&lt;br /&gt;
local TIEMPO_GIRO_90_GRADOS = 1.7&lt;br /&gt;
local sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
local tiempo&lt;br /&gt;
&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    -- Se inicializa el tiempo en 0.5 segundo&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
	tiempo_girando = 0&lt;br /&gt;
	girar()&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
	-- El robot gira hasta encontrar el color negro o si no por x tiempo&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
	end&lt;br /&gt;
	-- Si es negro no se debe seguir iterando&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    -- Retroceder unos centímetros&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    -- Girar 90 grados hacia la derecha&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar unos centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    -- Girar 90 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar el doble de centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    -- Girar 120 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    -- Avanzar hasta encontrar el negro&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    -- Fin: restaurar el sentido al estado previo&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
        esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3341</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3341"/>
				<updated>2012-10-15T15:25:37Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Código */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la variable DISTANCIA_OBSTACULO que refiera a la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        invertir_sentido()&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''hay_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot ha detectado la presencia de un obstáculo, según el valor obtenido por el sensor de distancia y su comparación con la constante DISTANCIA_OBSTACULO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''esquivar_obstaculo'''&lt;br /&gt;
Al detectar la presencia de un obstáculo, el robot deberá actuar de la siguiente forma:&lt;br /&gt;
1) Retroceder un tiempo determinado hasta alejarse lo suficiente como para poder girar.&lt;br /&gt;
2) Girar a la derecha 90°.&lt;br /&gt;
3) Avanza un tiempo determinado para poder pasar el obstáculo.&lt;br /&gt;
4) Girar a la izquierda 90°.&lt;br /&gt;
5) Avanza para volver a retomar la línea.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano al suelo, pero siempre sin tocarlo, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras del suelo.&lt;br /&gt;
&lt;br /&gt;
Además se debe colocar un sensor de distancia al frente, en la parte de adelante del Butiá también encastrando piezas.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;maY-Xjjofp4&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3340</id>
		<title>Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3340"/>
				<updated>2012-10-15T15:23:32Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local COLOR_NEGRO = 20000&lt;br /&gt;
local MOTOR_VEL = 500&lt;br /&gt;
local MOTOR_GIRO_VEL = 500&lt;br /&gt;
local TIEMPO_CENTRADO = 0.1&lt;br /&gt;
local INTERVALO_CHEQUEO = 0.1&lt;br /&gt;
local DISTANCIA_OBSTACULO = 34000&lt;br /&gt;
local TIEMPO_RETROCESO = 0.1&lt;br /&gt;
local TIEMPO_AVANCE = 1.7&lt;br /&gt;
local TIEMPO_GIRO_90_GRADOS = 1.7&lt;br /&gt;
local sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
local tiempo&lt;br /&gt;
&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    -- Se inicializa el tiempo en 0.5 segundo&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
	tiempo_girando = 0&lt;br /&gt;
	girar()&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
	-- El robot gira hasta encontrar el color negro o si no por x tiempo&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
	end&lt;br /&gt;
	-- Si es negro no se debe seguir iterando&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    -- Retroceder unos centímetros&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    -- Girar 90 grados hacia la derecha&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar unos centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    -- Girar 90 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar el doble de centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    -- Girar 120 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    -- Avanzar hasta encontrar el negro&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    -- Fin: restaurar el sentido al estado previo&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
        esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3339</id>
		<title>Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia_-_C%C3%B3digo&amp;diff=3339"/>
				<updated>2012-10-15T15:22:20Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con 'local COLOR_NEGRO = 20000 local MOTOR_VEL = 500 local MOTOR_GIRO_VEL = 500 local TIEMPO_CENTRADO = 0.1 local INTERVALO_CHEQUEO = 0.1 local DISTANCIA_OBSTACULO = 34000 local TIEM...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;local COLOR_NEGRO = 20000&lt;br /&gt;
local MOTOR_VEL = 500&lt;br /&gt;
local MOTOR_GIRO_VEL = 500&lt;br /&gt;
local TIEMPO_CENTRADO = 0.1&lt;br /&gt;
local INTERVALO_CHEQUEO = 0.1&lt;br /&gt;
local DISTANCIA_OBSTACULO = 34000&lt;br /&gt;
local TIEMPO_RETROCESO = 0.1&lt;br /&gt;
local TIEMPO_AVANCE = 1.7&lt;br /&gt;
local TIEMPO_GIRO_90_GRADOS = 1.7&lt;br /&gt;
local sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
local tiempo&lt;br /&gt;
&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    -- Se inicializa el tiempo en 0.5 segundo&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
	tiempo_girando = 0&lt;br /&gt;
	girar()&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
	-- El robot gira hasta encontrar el color negro o si no por x tiempo&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
	end&lt;br /&gt;
	-- Si es negro no se debe seguir iterando&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    -- Retroceder unos centímetros&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    -- Girar 90 grados hacia la derecha&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar unos centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    -- Girar 90 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    -- Avanzar el doble de centímetros&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    -- Girar 120 grados a la izquierda&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    -- Avanzar hasta encontrar el negro&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    -- Fin: restaurar el sentido al estado previo&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
        esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3338</id>
		<title>Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3338"/>
				<updated>2012-10-15T15:16:33Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 3.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica si el color sensado se corresponde con el de la mesa (COLOR_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces dos estados posibles según la condición sea verdadera o falsa. Si se cumple la condición, el robot deberá retroceder en un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO.&lt;br /&gt;
En caso contrario, el robot deberá avanzar.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;gt;=', COLOR_MESA,retroceder_y_girar_aleatorio)&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;lt;', COLOR_MESA, avanzar)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_y_girar_aleatorio'''&lt;br /&gt;
Retrocede y luego gira de forma aleatoria.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_y_girar_aleatorio()&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_aleatorio'''&lt;br /&gt;
Utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y así definir el tiempo durante el cual el robot estará retrocediendo. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_aleatorio()&lt;br /&gt;
    local tiempo_retroceso = math.random(MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO)&lt;br /&gt;
    Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO)&lt;br /&gt;
    util.wait(tiempo_retroceso)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_4.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;MmQjJZjHFgQ&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3337</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3337"/>
				<updated>2012-10-15T15:11:08Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''moverse'''&lt;br /&gt;
Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function moverse()&lt;br /&gt;
    local sentido = chequear_avance_o_retrocedo();&lt;br /&gt;
    if(sentido) then&lt;br /&gt;
        Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
    if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
        ret = ADELANTE_FUERA_MESA&lt;br /&gt;
    else&lt;br /&gt;
        if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
            ret = ATRAS_FUERA_MESA&lt;br /&gt;
        else&lt;br /&gt;
            ret = EN_LA_MESA&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_eventos,_utilizando_dos_sensores_de_grises_-_C%C3%B3digo&amp;diff=3336</id>
		<title>Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises - Código</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_eventos,_utilizando_dos_sensores_de_grises_-_C%C3%B3digo&amp;diff=3336"/>
				<updated>2012-10-15T15:09:22Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local COLOR_NEGRO = 35000&lt;br /&gt;
local MOTOR_VEL = 500&lt;br /&gt;
local MOTOR_GIRO_VEL = 500&lt;br /&gt;
local NEGRO_IZQUIERDO, NEGRO_DERECHO, NEGRO_AMBOS, BLANCO = 0, 1, 2, 3&lt;br /&gt;
local negro_izquierda&lt;br /&gt;
local negro_derecha&lt;br /&gt;
&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function detener()&lt;br /&gt;
    Motors.setvel2mtr(0, 0, 0, 0)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function es_negro(valor)&lt;br /&gt;
    return (valor &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar_derecha()&lt;br /&gt;
    Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar_izquierda()&lt;br /&gt;
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function obtener_estado()&lt;br /&gt;
    negro_izquierda = es_negro(Grey_1.getValue())&lt;br /&gt;
    negro_derecha = es_negro(Grey_2.getValue())&lt;br /&gt;
    if (negro_izquierda and negro_derecha) then&lt;br /&gt;
	return NEGRO_AMBOS&lt;br /&gt;
    elseif (negro_izquierda) then&lt;br /&gt;
	return NEGRO_IZQUIERDO&lt;br /&gt;
    elseif (negro_derecha) then&lt;br /&gt;
	return NEGRO_DERECHA&lt;br /&gt;
    else&lt;br /&gt;
	return BLANCO&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)&lt;br /&gt;
events.add(obtener_estado, '==', BLANCO, detener)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3335</id>
		<title>Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3335"/>
				<updated>2012-10-15T15:01:48Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (43000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 43000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_aleatorio'''&lt;br /&gt;
Utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y así definir el tiempo durante el cual el robot estará retrocediendo. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_aleatorio()&lt;br /&gt;
    local tiempo_retroceso = math.random(MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO)&lt;br /&gt;
    Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO)&lt;br /&gt;
    util.wait(tiempo_retroceso)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_3.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3331</id>
		<title>Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3331"/>
				<updated>2012-10-15T14:38:27Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea Implementar un seguidor de líneas básico que permite al robot Butiá seguir el rastro de una línea de color negro sobre el suelo, utilizando un sensor de grises.&lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma, girar para poder encontrar nuevamente una zona oscura.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Antes de describir cómo es la solución, es menester decir que el sensor de escala de grises debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites de color negro y color blanco.&lt;br /&gt;
&lt;br /&gt;
Para tomar estos valores, colocamos el sensor sobre una zona negra y utilizamos la función Grey_1.getValue() que nos brinda el entorno Butialo (en este caso, se conectó el sensor al puerto 1, por eso su nombre es “Grey_1”). Nos arrojará un valor que tendremos identificado como “valor sobre zona oscura”. Posteriormente, se hizo lo mismo sobre una zona de color blanco, mediante lo cual obtuvimos un “valor sobre zona clara”. &lt;br /&gt;
&lt;br /&gt;
Con dichos valores, sabemos en forma aproximada cuál es el entorno de valores en los cuales el sensor de grises detectará el color blanco o el color negro. A partir de esto, calculamos el valor medio y así es que obtuvimos el valor de la variable COLOR_NEGRO (35000 para las pruebas realizadas). Es decir, si el valor arrojado por el sensor es mayor o igual a 35000, sabemos que nos encontramos sobre una zona oscura o negra; y si es menor a 35000 asumimos que se trata del color blanco.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
Consiste en avanzar el robot hasta tanto el color de la línea sea negro, en caso contrario deberá buscar dicho color realizando un movimiento en forma de abanico. Luego de que se busca el color negro, y se encuentra, se utiliza la función invertir_sentido() para que la siguiente vez que se busque el color negro, se haga en el sentido más probable de que esté.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro()) do&lt;br /&gt;
        util.wait(0.1)&lt;br /&gt;
    end&lt;br /&gt;
    buscar_negro()&lt;br /&gt;
    util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
    invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
     if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
         Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
     else&lt;br /&gt;
         Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
     end&lt;br /&gt;
     invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()        	&lt;br /&gt;
        while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
            util.wait(0.1)&lt;br /&gt;
            tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
        if es_negro() then&lt;br /&gt;
            break&lt;br /&gt;
        else&lt;br /&gt;
            tiempo = tiempo * 2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Invierte el valor de la variable global sentido, de izquierda a derecha y viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
        sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano al piso posible, pero siempre sin tocarlo, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras del piso.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_1.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;rKINEFBUZVE&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3328</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3328"/>
				<updated>2012-10-15T14:23:03Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''moverse'''&lt;br /&gt;
Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function moverse()&lt;br /&gt;
    local sentido = chequear_avance_o_retrocedo();&lt;br /&gt;
    if(sentido) then&lt;br /&gt;
        Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá. También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3327</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3327"/>
				<updated>2012-10-15T14:22:55Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''moverse'''&lt;br /&gt;
Esta función permite que el robot avance o retroceda dependiendo del sentido que deba tomar. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function moverse()&lt;br /&gt;
    local sentido = chequear_avance_o_retrocedo();&lt;br /&gt;
    if(sentido) then&lt;br /&gt;
        Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
    if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
        ret = ADELANTE_FUERA_MESA&lt;br /&gt;
    else&lt;br /&gt;
        if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
            ret = ATRAS_FUERA_MESA&lt;br /&gt;
        else&lt;br /&gt;
            ret = EN_LA_MESA&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3326</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3326"/>
				<updated>2012-10-15T14:14:46Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
    if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
        ret = ADELANTE_FUERA_MESA&lt;br /&gt;
    else&lt;br /&gt;
        if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
            ret = ATRAS_FUERA_MESA&lt;br /&gt;
        else&lt;br /&gt;
            ret = EN_LA_MESA&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3325</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3325"/>
				<updated>2012-10-15T14:13:26Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
    if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
        ret = ADELANTE_FUERA_MESA&lt;br /&gt;
    else&lt;br /&gt;
        if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
            ret = ATRAS_FUERA_MESA&lt;br /&gt;
        else&lt;br /&gt;
            ret = EN_LA_MESA&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial. Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3324</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3324"/>
				<updated>2012-10-15T14:09:36Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, a adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
    if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
        ret = ADELANTE_FUERA_MESA&lt;br /&gt;
    else&lt;br /&gt;
        if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
            ret = ATRAS_FUERA_MESA&lt;br /&gt;
        else&lt;br /&gt;
            ret = EN_LA_MESA&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3323</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3323"/>
				<updated>2012-10-15T14:08:15Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá. También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3322</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3322"/>
				<updated>2012-10-15T13:53:36Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de dos condiciones que le indican si el color sensado se corresponde con el de la mesa (COLOR_MESA) o si la distancia sensada es distinta a la distancia que hay entre el sensor y la mesa (DISTANCIA_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles según las diferentes condiciones (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA) sean verdaderas o falsas. Si se cumple la condición ADELANTE_FUERA_MESA (ATRAS_FUERA_MESA), el robot deberá retroceder (avanzar) un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, a adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    -- Avanzar = true, Retroceder = false&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
&lt;br /&gt;
   if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
     --retroceder&lt;br /&gt;
     ret = ADELANTE_FUERA_MESA&lt;br /&gt;
   else&lt;br /&gt;
     if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
       --avanzar&lt;br /&gt;
       ret = ATRAS_FUERA_MESA&lt;br /&gt;
     else&lt;br /&gt;
       --puedo seguir&lt;br /&gt;
       ret = EN_LA_MESA&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   return ret   &lt;br /&gt;
	 &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
   if (debe_avanzar) then&lt;br /&gt;
	    Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
	else&lt;br /&gt;
	   Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
	end&lt;br /&gt;
	util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
	girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3321</id>
		<title>Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_7_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3321"/>
				<updated>2012-10-15T13:44:49Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Descripción */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, DISTANCIA_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 6.&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR.&lt;br /&gt;
Cambiará su estado dependiendo de dos condiciones que le indica si el color sensado se corresponde con el de la mesa (COLOR_MESA)o si la distncia sensada es distinta a la distancia que que hay entre el sensor y la mesa (DISTANCIA_MESA) .&lt;br /&gt;
Distinguimos entonces tres estados posibles según (ADELANTE_FUERA_MESA, ATRAS_FUERA_MESA, EN_LA_MESA). Si se cumple la condiciones ADELANTE_FUERA_MESA o ATRAS_FUERA_MESA, el robot deberá retroceder o avanzar  un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO. En caso contrario, el robot deberá desplazarse en la mesa.&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', ADELANTE_FUERA_MESA, volver_inicio)&lt;br /&gt;
events.add(puedo_seguir, '==', EN_MESA, moverse)&lt;br /&gt;
&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, a adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    -- Avanzar = true, Retroceder = false&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_seguir()&lt;br /&gt;
&lt;br /&gt;
   if Grey_2.getValue() &amp;gt; COLOR_MESA then&lt;br /&gt;
     --retroceder&lt;br /&gt;
     ret = ADELANTE_FUERA_MESA&lt;br /&gt;
   else&lt;br /&gt;
     if Distanc_6.getValue() &amp;lt; DISTANCIA_MESA then&lt;br /&gt;
       --avanzar&lt;br /&gt;
       ret = ATRAS_FUERA_MESA&lt;br /&gt;
     else&lt;br /&gt;
       --puedo seguir&lt;br /&gt;
       ret = EN_LA_MESA&lt;br /&gt;
     end&lt;br /&gt;
   end&lt;br /&gt;
   return ret   &lt;br /&gt;
	 &lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
   if (debe_avanzar) then&lt;br /&gt;
	    Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
	else&lt;br /&gt;
	   Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
	end&lt;br /&gt;
	util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
	girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_7.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 7 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3320</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3320"/>
				<updated>2012-10-15T13:40:08Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá. También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3319</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3319"/>
				<updated>2012-10-15T13:37:32Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable debe_avanzar, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva al centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retroceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3318</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3318"/>
				<updated>2012-10-15T13:34:19Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. También define el valor de la variable &amp;quot;debe_avanzar&amp;quot;, la cual dependiendo de quién detecte que el robot se encuentra en peligro de caer definirá los valores para distinguir la acción a tomar: el valor será false si se detectó con el sensor de grises y será true si se detectó con el sensor de distancia.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3317</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3317"/>
				<updated>2012-10-15T13:26:09Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, adelante o atrás, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento será hacia adelante, retornando True y en caso contrario deberá desplazarse hacia atrás retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3316</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3316"/>
				<updated>2012-10-15T13:20:54Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazar el robot de forma aleatoria, para adelante o para atrás, hasta tanto no se encuentre en peligro de caer de la mesa. En caso contrario, deberá retroceder o avanzar dependiendo de cuál sensor detectó que el robot se encuentra en peligro de caer de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para que el siguiente movimiento del mismo se realice en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    moverse()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
        util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, para adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    -- Avanzar = true, Retroceder = false&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    local ret&lt;br /&gt;
    if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
        ret = true&lt;br /&gt;
    else&lt;br /&gt;
        ret = false&lt;br /&gt;
    end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA) then&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
    return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
    if (debe_avanzar) then&lt;br /&gt;
        Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
    end&lt;br /&gt;
    util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3315</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3315"/>
				<updated>2012-10-15T13:06:37Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también. Para ello, colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso su nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. &lt;br /&gt;
&lt;br /&gt;
Posteriormente, colocamos el sensor fuera de la mesa y obtenemos un nuevo valor. Con dicho valor y el anterior, calculamos el valor medio (21000 para las pruebas realizadas). De esta forma obtenemos el valor de la variable DISTANCIA_MESA que refiere a la distancia a partir de la cual el robot detecta la presencia de la mesa. Determinamos entonces que si el valor arrojado por el sensor es menor a 21000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazarse el robot de forma aleatoria, para adelante o para atras, hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder o avanzar, dependiendo de con cual sensor se detecto que el robot se esta por salir de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para el siguiente movimiento de este, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
	moverse()&lt;br /&gt;
	while (puedo_avanzar()) do&lt;br /&gt;
		util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
	end&lt;br /&gt;
	volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, para adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    -- Avanzar = true, Retroceder = false&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
 local ret&lt;br /&gt;
   if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
    ret = true&lt;br /&gt;
   else&lt;br /&gt;
     ret = false&lt;br /&gt;
   end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA ) then&lt;br /&gt;
           --se esta por caer desde la parte de adelante&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
	 return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
   if (debe_avanzar) then&lt;br /&gt;
	    Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
	else&lt;br /&gt;
	   Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
	end&lt;br /&gt;
	util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
	girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3314</id>
		<title>Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_6_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3314"/>
				<updated>2012-10-15T12:47:47Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Descripción */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
Inicialmente el robot sorteará hacia dónde desplazarse (avanzar o retroceder). En caso de detectar un color distinto al de la mesa o bien detectar una distancia mayor a la separación con la mesa el robot deberá volver al centro de la misma&lt;br /&gt;
para regresar al estado inicial y luego comenzar otra vez.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (55000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 55000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
Además usaremos un sensor de distancia, el cual debe ser calibrado previamente también.&lt;br /&gt;
 &lt;br /&gt;
Vamos a explicar como realizamos esto, para calibrar colocamos el sensor sobre la mesa y utilizamos la función Distanc_6.getValue() que nos brinda el entorno Butialo (en este caso se colocó el sensor de distancia en el puerto 6, por eso el nombre es Distanc_6). Nos arrojará un valor que tendremos identificado como “DISTANCIA_MESA”. Posteriormente, se hizo lo mismo con el sensor fuera de la mesa, comparamos estos dos valores, obtenemos cual es la relación de estos. &lt;br /&gt;
&lt;br /&gt;
De esta forma obtenemos el valor de la variable DISTANCIA_MESA que se refiere a la distancia a partir de la cual el robot detecta la presentacia de la mesa y la relación con respecto a esta, con lo cual el robot detecta que esta por caerse de le mesa, entonces deberá evitar la caida .&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
El robot deberá desplazarse por la mesa, de forma aleatoria para adelante o para atras, cuando este detecte que esta por caerse de la mesa, deberá avanzar o retroceder dependiendo de con cual de los sensores lo detecte, por un tiempo determinado. Dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande y tratando de volver siempre al centro de la misma, que es su estado inicial. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado los sensores y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en desplazarse el robot de forma aleatoria, para adelante o para atras, hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder o avanzar, dependiendo de con cual sensor se detecto que el robot se esta por salir de la mesa. Luego de que el robot se encuentra lo más cercano a su posición inicial, el centro de la mesa, se utiliza la función girar_aleatorio() para el siguiente movimiento de este, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
	moverse()&lt;br /&gt;
	while (puedo_avanzar()) do&lt;br /&gt;
		util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
	end&lt;br /&gt;
	volver_inicio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_avance_o_retrocedo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe avanzar. Para desplazarse de forma aleatoria, para adelante o atras, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el desplazamiento hacia adelante, retornando True y en caso contrario deberá dsplazarse hacia atras retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_avance_o_retrocedo()&lt;br /&gt;
    -- Avanzar = true, Retroceder = false&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA y el valor obtenido por el sensor de distancia y su comparación con la variable DISTANCIA_MESA. Define el valor de la variable debe_avanzar que será false si se detectó con el sensor de grises (sensor se encuentra en la parte de adelante del robot) peligro de caerse de la mesa, entonces este debera retroceder o en caso de que detectó peligro de caerse con el sensor de distancia (sensor se encuentra en la parte de atras del robot), este debe avanzar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
 local ret&lt;br /&gt;
   if Grey_2.getValue() &amp;lt; COLOR_MESA and Distanc_6.getValue() &amp;gt;= DISTANCIA_MESA then&lt;br /&gt;
    ret = true&lt;br /&gt;
   else&lt;br /&gt;
     ret = false&lt;br /&gt;
   end&lt;br /&gt;
    if(not ret) then&lt;br /&gt;
        if(Grey_2.getValue() &amp;gt; COLOR_MESA ) then&lt;br /&gt;
           --se esta por caer desde la parte de adelante&lt;br /&gt;
           debe_avanzar = false&lt;br /&gt;
        else&lt;br /&gt;
           debe_avanzar = true&lt;br /&gt;
        end&lt;br /&gt;
    end    &lt;br /&gt;
	 return ret&lt;br /&gt;
end&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''volver_inicio'''&lt;br /&gt;
Esta función se encarga de que el robot vuelva la centro de la mesa, que es su posición inicial.&lt;br /&gt;
Para esto utiliza la variable debe_avanzar que indica si el robot debe avanzar o retoceder dependiendo su posición actual.  &lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function volver_inicio()&lt;br /&gt;
   if (debe_avanzar) then&lt;br /&gt;
	    Motors.setvel2mtr(0, VELOCIDAD_RETROCESO, 0, VELOCIDAD_RETROCESO)&lt;br /&gt;
	else&lt;br /&gt;
	   Motors.setvel2mtr(1, VELOCIDAD_RETROCESO, 1, VELOCIDAD_RETROCESO) &lt;br /&gt;
	end&lt;br /&gt;
	util.wait(TIEMPO_VOLVER_INICIO)&lt;br /&gt;
	girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.También debemos colocar un sensor de distancia a una distancia de la mesa mayor a 3cm pero no mucho más, debido que a una distancia menor el sensor no sensa correctamente.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_6.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;H3Ri7VNSrM8&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 6 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3262</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3262"/>
				<updated>2012-10-11T01:43:45Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la variable DISTANCIA_OBSTACULO que refiera a la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        invertir_sentido()&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''hay_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot ha detectado la presencia de un obstáculo, según el valor obtenido por el sensor de distancia y su comparación con la constante DISTANCIA_OBSTACULO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''esquivar_obstaculo'''&lt;br /&gt;
Al detectar la presencia de un obstáculo, el robot deberá actuar de la siguiente forma:&lt;br /&gt;
1) Retroceder un tiempo determinado hasta alejarse lo suficiente como para poder girar.&lt;br /&gt;
2) Girar a la derecha 90°.&lt;br /&gt;
3) Avanza un tiempo determinado para poder pasar el obstáculo.&lt;br /&gt;
4) Girar a la izquierda 90°.&lt;br /&gt;
5) Avanza para volver a retomar la línea.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano al suelo, pero siempre sin tocarlo, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras del suelo.&lt;br /&gt;
&lt;br /&gt;
Además se debe colocar un sensor de distancia al frente, en la parte de adelante del Butiá también encastrando piezas.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3261</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3261"/>
				<updated>2012-10-11T01:41:23Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la variable DISTANCIA_OBSTACULO que refiera a la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        invertir_sentido()&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''hay_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot ha detectado la presencia de un obstáculo, según el valor obtenido por el sensor de distancia y su comparación con la constante DISTANCIA_OBSTACULO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''esquivar_obstaculo'''&lt;br /&gt;
Al detectar la presencia de un obstáculo, el robot deberá actuar de la siguiente forma:&lt;br /&gt;
1) Retroceder un tiempo determinado hasta alejarse lo suficiente como para poder girar.&lt;br /&gt;
2) Girar a la derecha 90°.&lt;br /&gt;
3) Avanza un tiempo determinado para poder pasar el obstáculo.&lt;br /&gt;
4) Girar a la izquierda 90°.&lt;br /&gt;
5) Avanza para volver a retomar la línea.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3260</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3260"/>
				<updated>2012-10-11T01:04:43Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        invertir_sentido()&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''hay_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''esquivar_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3259</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3259"/>
				<updated>2012-10-11T01:04:00Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        invertir_sentido()&lt;br /&gt;
	while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
	    util.wait(0.1)&lt;br /&gt;
	    tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
	if es_negro() then&lt;br /&gt;
	    break&lt;br /&gt;
	else&lt;br /&gt;
	    tiempo = tiempo * 2&lt;br /&gt;
	end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''hay_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function hay_obstaculo()&lt;br /&gt;
    local distancia = Distanc_2.getValue()&lt;br /&gt;
    return (distancia &amp;gt; DISTANCIA_OBSTACULO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''esquivar_obstaculo'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function esquivar_obstaculo()&lt;br /&gt;
    local sentido_previo = sentido&lt;br /&gt;
    retroceder()&lt;br /&gt;
    util.wait(TIEMPO_RETROCESO)&lt;br /&gt;
    sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    util.wait(TIEMPO_AVANCE * 3)&lt;br /&gt;
    sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    girar()&lt;br /&gt;
    util.wait(TIEMPO_GIRO_90_GRADOS * 4 / 3)&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (not es_negro()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    sentido = sentido_previo&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3258</id>
		<title>Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3258"/>
				<updated>2012-10-11T00:58:34Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea Implementar un seguidor de líneas básico que permite al robot Butiá seguir el rastro de una línea de color negro sobre el suelo, utilizando un sensor de grises.&lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma, girar para poder encontrar nuevamente una zona oscura.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Antes de describir cómo es la solución, es menester decir que el sensor de escala de grises debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites de color negro y color blanco.&lt;br /&gt;
&lt;br /&gt;
Para tomar estos valores, colocamos el sensor sobre una zona negra y utilizamos la función Grey_1.getValue() que nos brinda el entorno Butialo (en este caso, se conectó el sensor al puerto 1, por eso su nombre es “Grey_1”). Nos arrojará un valor que tendremos identificado como “valor sobre zona oscura”. Posteriormente, se hizo lo mismo sobre una zona de color blanco, mediante lo cual obtuvimos un “valor sobre zona clara”. &lt;br /&gt;
&lt;br /&gt;
Con dichos valores, sabemos en forma aproximada cuál es el entorno de valores en los cuales el sensor de grises detectará el color blanco o el color negro. A partir de esto, calculamos el valor medio y así es que obtuvimos el valor de la variable COLOR_NEGRO (35000 para las pruebas realizadas). Es decir, si el valor arrojado por el sensor es mayor o igual a 35000, sabemos que nos encontramos sobre una zona oscura o negra; y si es menor a 35000 asumimos que se trata del color blanco.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
Consiste en avanzar el robot hasta tanto el color de la línea sea negro, en caso contrario deberá buscar dicho color realizando un movimiento en forma de abanico. Luego de que se busca el color negro, y se encuentra, se utiliza la función invertir_sentido() para que la siguiente vez que se busque el color negro, se haga en el sentido más probable de que esté.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro()) do&lt;br /&gt;
        util.wait(0.1)&lt;br /&gt;
    end&lt;br /&gt;
    buscar_negro()&lt;br /&gt;
    util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
    invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
     if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
         Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
     else&lt;br /&gt;
         Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
     end&lt;br /&gt;
     invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()        	&lt;br /&gt;
        while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
            util.wait(0.1)&lt;br /&gt;
            tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
        if es_negro() then&lt;br /&gt;
            break&lt;br /&gt;
        else&lt;br /&gt;
            tiempo = tiempo * 2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano al piso posible, pero siempre sin tocarlo, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras del piso.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_1.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;rKINEFBUZVE&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3257</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3257"/>
				<updated>2012-10-11T00:52:45Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro() and not hay_obstaculo()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    if hay_obstaculo() then&lt;br /&gt;
	esquivar_obstaculo()&lt;br /&gt;
    else&lt;br /&gt;
	buscar_negro()&lt;br /&gt;
	util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
	invertir_sentido()&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''invertir_sentido'''&lt;br /&gt;
Cambia el sentido de izquierda a derecha o viceversa.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
	sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
	sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder'''&lt;br /&gt;
Retrocede el Butiá haciendo que los motores giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder()&lt;br /&gt;
    Motors.setvel2mtr(1, MOTOR_VEL, 1, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3256</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3256"/>
				<updated>2012-10-11T00:44:56Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Solución */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1. Además, debemos calibrar el valor de la distancia mínima a partir de la cual el robot detecta la presentacia de un obstáculo y por lo tanto deberá esquivar el mismo utilizando una técnica de rodeo.&lt;br /&gt;
&lt;br /&gt;
El robot deberá seguir el rastro de la línea de color negro de la misma forma que se realizó en el Ejemplo 1, chequeando además la presencia de un obstáculo que deberá esquivar para luego regresar a línea negra.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrados los valores de los sensores, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3255</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3255"/>
				<updated>2012-10-11T00:34:53Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar un seguidor de líneas de nivel avanzado que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo eludiendo obstáculos. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y no detecte la proximidad de un obstáculo. En caso de salirse de la línea, deberá girar para poder encontrar nuevamente una zona oscura y en caso de detectar un obstáculo procederá a aplicar una técnica de rodeo poder continuar avanzando por la línea de color negro.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (43000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 43000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3254</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3254"/>
				<updated>2012-10-11T00:32:56Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (43000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 43000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_8.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3253</id>
		<title>Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_8_-_Seguidor_de_l%C3%ADneas_con_obst%C3%A1culos,_sin_eventos,_utilizando_un_sensor_de_grises_y_uno_de_distancia&amp;diff=3253"/>
				<updated>2012-10-11T00:32:37Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '__TOC__  ==Descripción== Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.   El robot deberá avanzar mientras ...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (43000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 43000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_3.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3252</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3252"/>
				<updated>2012-10-11T00:30:58Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Ejemplos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta Ferradini&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 8 - Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia|Ejemplo 8: Seguidor de líneas con obstáculos, sin eventos, utilizando un sensor de grises y uno de distancia]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3251</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3251"/>
				<updated>2012-10-11T00:29:23Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Ejemplos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta Ferradini&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises_-_C%C3%B3digo&amp;diff=3250</id>
		<title>Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises - Código</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises_-_C%C3%B3digo&amp;diff=3250"/>
				<updated>2012-10-11T00:26:08Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt; local COLOR_NEGRO = 35000 local MOTOR_VEL = 500 local MOTOR_GIRO_VEL = 500 local TIEMPO_CENTRADO = 0.1 local sentido = &amp;quot;D&amp;quot; local tiempo  local funct...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local COLOR_NEGRO = 35000&lt;br /&gt;
local MOTOR_VEL = 500&lt;br /&gt;
local MOTOR_GIRO_VEL = 500&lt;br /&gt;
local TIEMPO_CENTRADO = 0.1&lt;br /&gt;
local sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
local tiempo&lt;br /&gt;
&lt;br /&gt;
local function invertir_sentido()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
        sentido = &amp;quot;D&amp;quot;&lt;br /&gt;
    else&lt;br /&gt;
        sentido = &amp;quot;I&amp;quot;&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function girar()&lt;br /&gt;
    if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
        Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
    else&lt;br /&gt;
        Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
    end&lt;br /&gt;
    invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    -- Se inicializa el tiempo en 0.5 segundo&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()&lt;br /&gt;
        -- El robot gira hasta encontrar el color negro o si no por x tiempo&lt;br /&gt;
        while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
            util.wait(0.1)&lt;br /&gt;
            tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
        -- Si es negro no se debe seguir iterando&lt;br /&gt;
        if es_negro() then&lt;br /&gt;
            break&lt;br /&gt;
        else&lt;br /&gt;
            tiempo = tiempo * 2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro()) do&lt;br /&gt;
        util.wait(0.1)&lt;br /&gt;
    end&lt;br /&gt;
    buscar_negro()&lt;br /&gt;
    util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
    invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_eventos,_utilizando_dos_sensores_de_grises&amp;diff=3249</id>
		<title>Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_eventos,_utilizando_dos_sensores_de_grises&amp;diff=3249"/>
				<updated>2012-10-11T00:24:23Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '__TOC__  ==Descripción==  Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo.   El rob...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma se tendrán tres alternativas posibles para poder encontrar nuevamente una zona oscura, dependiendo de cuál sensor detectó que el robot se ha salido de la zona.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el Ejemplo 1, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica para cada sensor si el color sensado se corresponde con el color negro (COLOR_NEGRO).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles: NEGRO_AMBOS, NEGRO_IZQUIERDO y NEGRO_DERECHO. &lt;br /&gt;
Cuando ambos sensores detectan el color negro, el robot se encuentra en el estado NEGRO_AMBOS. Por lo cual el robot deberá avanzar.&lt;br /&gt;
Si el sensor izquierdo detecta el color negro y el sensor derecho no, entonces el robot se encuentra en el estado NEGRO_IZQUIERDO. El robot aquí deberá girar en sentido izquierdo para tratar de no salirse de la línea.&lt;br /&gt;
Si el sensor derecho detecta el color negro y el sensor izquierdo no, entonces el robot se encuentra en el estado NEGRO_DERECHO. Análogamente, el robot deberá girar en sentido derecho.&lt;br /&gt;
En caso contrario, el estado será BLANCO y al perder la línea con ambos sensores el robot se detiene.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)&lt;br /&gt;
events.add(obtener_estado, '==', BLANCO, detener)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''detener'''&lt;br /&gt;
Detiene los motores.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function detener()&lt;br /&gt;
    Motors.setvel2mtr(0, 0, 0, 0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro(valor)&lt;br /&gt;
    return (valor &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_derecha'''&lt;br /&gt;
Gira el robot hacia la derecha con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_derecha()&lt;br /&gt;
    Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_izquierda'''&lt;br /&gt;
Gira el robot hacia la izquierda con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_izquierda()&lt;br /&gt;
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''obtener_estado'''&lt;br /&gt;
Retorna el estado correspondiente, dependiendo de los valores obtenidos en cada uno de los sensores de grises.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function obtener_estado()&lt;br /&gt;
    negro_izquierda = es_negro(Grey_1.getValue())&lt;br /&gt;
    negro_derecha = es_negro(Grey_2.getValue())&lt;br /&gt;
    if (negro_izquierda and negro_derecha) then&lt;br /&gt;
	return NEGRO_AMBOS&lt;br /&gt;
    elseif (negro_izquierda) then&lt;br /&gt;
	return NEGRO_IZQUIERDO&lt;br /&gt;
    elseif (negro_derecha) then&lt;br /&gt;
	return NEGRO_DERECHA&lt;br /&gt;
    else&lt;br /&gt;
	return BLANCO&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se deben colocar dos sensores de escala de grises lo más cercano al suelo, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir los sensores al Butiá, quedando dichos sensores a ras del suelo.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_5.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3248</id>
		<title>Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3248"/>
				<updated>2012-10-11T00:23:38Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Código */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 3.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica si el color sensado se corresponde con el de la mesa (COLOR_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces dos estados posibles según la condición sea verdadera o falsa. Si se cumple la condición, el robot deberá retroceder en un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO.&lt;br /&gt;
En caso contrario, el robot deberá avanzar.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;gt;=', COLOR_MESA,retroceder_y_girar_aleatorio)&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;lt;', COLOR_MESA, avanzar)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_y_girar_aleatorio'''&lt;br /&gt;
Retrocede y luego gira de forma aleatoria.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_y_girar_aleatorio()&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_4.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3247</id>
		<title>Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Robot_que_no_se_caiga_de_la_mesa_con_eventos,_utilizando_un_sensor_de_grises&amp;diff=3247"/>
				<updated>2012-10-11T00:22:49Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '__TOC__  ==Descripción== Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.   El robot deber...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 3.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica si el color sensado se corresponde con el de la mesa (COLOR_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces dos estados posibles según la condición sea verdadera o falsa. Si se cumple la condición, el robot deberá retroceder en un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO.&lt;br /&gt;
En caso contrario, el robot deberá avanzar.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;gt;=', COLOR_MESA,retroceder_y_girar_aleatorio)&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;lt;', COLOR_MESA, avanzar)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_y_girar_aleatorio'''&lt;br /&gt;
Retrocede y luego gira de forma aleatoria.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_y_girar_aleatorio()&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_4.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor con eventos - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3246</id>
		<title>Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_3_-_Robot_que_no_se_caiga_de_la_mesa_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3246"/>
				<updated>2012-10-11T00:21:21Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '__TOC__  ==Descripción== Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma.   El robot deberá avanzar mientras ...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Como fue explicado en ejemplos anteriores, el sensor de escala de grises (en este caso, se conectó el sensor al puerto 2, por eso su nombre es “Grey_2”) debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites a partir del cual definimos que el robot se encuentra sobre la mesa.&lt;br /&gt;
&lt;br /&gt;
Calculando el valor medio, obtuvimos el valor de la variable COLOR_MESA (43000 para las pruebas realizadas).&lt;br /&gt;
Determinamos entonces que si el valor arrojado por el sensor es menor a 43000, el robot puede continuar avanzando sin peligro de caer de la mesa, en caso contrario se deberá evitar la caída.&lt;br /&gt;
&lt;br /&gt;
El robot deberá retroceder en un tiempo aleatorio, dicho valor deberá ser calibrado en las variables MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO de forma de contemplar que no se caiga de la mesa en caso de que el tiempo sea muy grande. Para ello el robot se colocará en el centro de la mesa. De la misma forma, se calibrará los valores de MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO, considerando aquí los posibles valores entre 1° y 90° aproximadamente. &lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor y obtenidos los respectivos valores de tiempo máximo y mínimo de giro y retroceso, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (puedo_avanzar()) do&lt;br /&gt;
	util.wait(INTERVALO_CHEQUEO)&lt;br /&gt;
    end&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''puedo_avanzar'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot se encuentra en peligro de caerse, según el valor obtenido por el sensor de grises y su comparación con la variable COLOR_MESA.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function puedo_avanzar()&lt;br /&gt;
    return (Grey_2.getValue() &amp;lt; COLOR_MESA)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_3.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3245</id>
		<title>Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_1_-_Seguidor_de_l%C3%ADneas_sin_eventos,_utilizando_un_sensor_de_grises&amp;diff=3245"/>
				<updated>2012-10-11T00:20:13Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: Página creada con '__TOC__  ==Descripción== Se desea Implementar un seguidor de líneas básico que permite al robot Butiá seguir el rastro de una línea de color negro sobre el suelo, utilizand...'&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea Implementar un seguidor de líneas básico que permite al robot Butiá seguir el rastro de una línea de color negro sobre el suelo, utilizando un sensor de grises.&lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma, girar para poder encontrar nuevamente una zona oscura.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Antes de describir cómo es la solución, es menester decir que el sensor de escala de grises debe ser calibrado previamente a la ejecución del programa a desarrollar para poder obtener los respectivos valores límites de color negro y color blanco.&lt;br /&gt;
&lt;br /&gt;
Para tomar estos valores, colocamos el sensor sobre una zona negra y utilizamos la función Grey_1.getValue() que nos brinda el entorno Butialo (en este caso, se conectó el sensor al puerto 1, por eso su nombre es “Grey_1”). Nos arrojará un valor que tendremos identificado como “valor sobre zona oscura”. Posteriormente, se hizo lo mismo sobre una zona de color blanco, mediante lo cual obtuvimos un “valor sobre zona clara”. &lt;br /&gt;
&lt;br /&gt;
Con dichos valores, sabemos en forma aproximada cuál es el entorno de valores en los cuales el sensor de grises detectará el color blanco o el color negro. A partir de esto, calculamos el valor medio y así es que obtuvimos el valor de la variable COLOR_NEGRO (35000 para las pruebas realizadas). Es decir, si el valor arrojado por el sensor es mayor o igual a 35000, sabemos que nos encontramos sobre una zona oscura o negra; y si es menor a 35000 asumimos que se trata del color blanco.&lt;br /&gt;
&lt;br /&gt;
Una vez calibrado el sensor, se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
Consiste en avanzar el robot hasta tanto el color de la línea sea negro, en caso contrario deberá buscar dicho color realizando un movimiento en forma de abanico. Luego de que se busca el color negro, y se encuentra, se utiliza la función invertir_sentido() para que la siguiente vez que se busque el color negro, se haga en el sentido más probable de que esté.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
while true do&lt;br /&gt;
    avanzar()&lt;br /&gt;
    while (es_negro()) do&lt;br /&gt;
        util.wait(0.1)&lt;br /&gt;
    end&lt;br /&gt;
    buscar_negro()&lt;br /&gt;
    util.wait(TIEMPO_CENTRADO)&lt;br /&gt;
    invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro()&lt;br /&gt;
    local color = Grey_1.getValue()&lt;br /&gt;
    return (color &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar'''&lt;br /&gt;
Gira el robot en el sentido correspondiente, el cual estará definido por la variable sentido&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar()&lt;br /&gt;
     if sentido == &amp;quot;I&amp;quot; then&lt;br /&gt;
         Motors.setvel2mtr(1,MOTOR_GIRO_VEL,0,MOTOR_GIRO_VEL)&lt;br /&gt;
     else&lt;br /&gt;
         Motors.setvel2mtr(0,MOTOR_GIRO_VEL,1,MOTOR_GIRO_VEL)&lt;br /&gt;
     end&lt;br /&gt;
     invertir_sentido()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''buscar_negro'''&lt;br /&gt;
Si el robot no encuentra color negro entonces deberá buscarlo. El robot hace un abanico, girando determinado tiempo en un sentido, para luego girar el doble de tiempo en el sentido opuesto. Esta acción culminará cuando se detecte que el robot está en una zona oscura.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function buscar_negro()&lt;br /&gt;
    tiempo = 0.5&lt;br /&gt;
    local tiempo_girando&lt;br /&gt;
    while true do&lt;br /&gt;
        tiempo_girando = 0&lt;br /&gt;
        girar()        	&lt;br /&gt;
        while (not es_negro() and tiempo_girando &amp;lt;= tiempo) do&lt;br /&gt;
            util.wait(0.1)&lt;br /&gt;
            tiempo_girando = tiempo_girando + 0.1&lt;br /&gt;
        end&lt;br /&gt;
        if es_negro() then&lt;br /&gt;
            break&lt;br /&gt;
        else&lt;br /&gt;
            tiempo = tiempo * 2&lt;br /&gt;
        end&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano al piso posible, pero siempre sin tocarlo, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras del piso.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_1.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;youtube&amp;gt;rKINEFBUZVE&amp;lt;/youtube&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3244</id>
		<title>Ejemplos de Aplicaciones en Butialo</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Ejemplos_de_Aplicaciones_en_Butialo&amp;diff=3244"/>
				<updated>2012-10-11T00:19:22Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Ejemplos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Integrantes==&lt;br /&gt;
&lt;br /&gt;
* Vicente Acosta Ferradini&lt;br /&gt;
* Leticia Vilariño&lt;br /&gt;
* Lourdes Cairelli&lt;br /&gt;
&lt;br /&gt;
==Introducción==&lt;br /&gt;
Butialo es un entorno fácil de usar que permite programar a Butiá en el lenguaje Lua.&lt;br /&gt;
&lt;br /&gt;
Lua es un lenguaje de scripting imperativo simple pero que a la vez permite crear programas sofisticados. Es un lenguaje dinámico, con manejo de memoria automático y es extremadamente rápido.&lt;br /&gt;
&lt;br /&gt;
Butialo es un IDE derivado de Pippy (el entorno para Python provisto con las XO), que simplifica la creación de programas para Butiá autodetectando la presencia de componentes Butiá conectados y ofreciendo snippets de código para accederlos.&lt;br /&gt;
&lt;br /&gt;
==Objetivos==&lt;br /&gt;
Crear programas que sirvan de ejemplo e inspiración. Además del clásico seguidor de línea, se pueden crear ejemplos que saquen provecho de la mayor potencia y expresividad de Lua comparado con TortugArte.&lt;br /&gt;
&lt;br /&gt;
==Ejemplos==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas con un sensor sin eventos|Ejemplo 1: Seguidor de líneas con un sensor sin eventos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Butiá que no se cae de la mesa con un sensor sin eventos|Ejemplo 3: Butiá que no se cae de la mesa con un sensor sin eventos]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor con eventos|Ejemplo 4: Butiá que no se cae de la mesa con un sensor con eventos]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con dos sensores con eventos|Ejemplo 5: Seguidor de líneas con dos sensores con eventos]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 1 - Seguidor de líneas sin eventos, utilizando un sensor de grises|Ejemplo 1: Seguidor de líneas sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 3 - Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises|Ejemplo 3: Robot que no se caiga de la mesa sin eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises|Ejemplo 4: Robot que no se caiga de la mesa con eventos, utilizando un sensor de grises]]&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 5 - Seguidor de líneas con eventos, utilizando dos sensores de grises|Ejemplo 5: Seguidor de líneas con eventos, utilizando dos sensores de grises]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_dos_sensores_con_eventos&amp;diff=3243</id>
		<title>Butialo: Ejemplo 5 - Seguidor de líneas con dos sensores con eventos</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_dos_sensores_con_eventos&amp;diff=3243"/>
				<updated>2012-10-11T00:07:09Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma se tendrán tres alternativas posibles para poder encontrar nuevamente una zona oscura, dependiendo de cuál sensor detectó que el robot se ha salido de la zona.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el Ejemplo 1, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica para cada sensor si el color sensado se corresponde con el color negro (COLOR_NEGRO).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles: NEGRO_AMBOS, NEGRO_IZQUIERDO y NEGRO_DERECHO. &lt;br /&gt;
Cuando ambos sensores detectan el color negro, el robot se encuentra en el estado NEGRO_AMBOS. Por lo cual el robot deberá avanzar.&lt;br /&gt;
Si el sensor izquierdo detecta el color negro y el sensor derecho no, entonces el robot se encuentra en el estado NEGRO_IZQUIERDO. El robot aquí deberá girar en sentido izquierdo para tratar de no salirse de la línea.&lt;br /&gt;
Si el sensor derecho detecta el color negro y el sensor izquierdo no, entonces el robot se encuentra en el estado NEGRO_DERECHO. Análogamente, el robot deberá girar en sentido derecho.&lt;br /&gt;
En caso contrario, el estado será BLANCO y al perder la línea con ambos sensores el robot se detiene.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)&lt;br /&gt;
events.add(obtener_estado, '==', BLANCO, detener)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''detener'''&lt;br /&gt;
Detiene los motores.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function detener()&lt;br /&gt;
    Motors.setvel2mtr(0, 0, 0, 0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro(valor)&lt;br /&gt;
    return (valor &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_derecha'''&lt;br /&gt;
Gira el robot hacia la derecha con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_derecha()&lt;br /&gt;
    Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_izquierda'''&lt;br /&gt;
Gira el robot hacia la izquierda con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_izquierda()&lt;br /&gt;
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''obtener_estado'''&lt;br /&gt;
Retorna el estado correspondiente, dependiendo de los valores obtenidos en cada uno de los sensores de grises.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function obtener_estado()&lt;br /&gt;
    negro_izquierda = es_negro(Grey_1.getValue())&lt;br /&gt;
    negro_derecha = es_negro(Grey_2.getValue())&lt;br /&gt;
    if (negro_izquierda and negro_derecha) then&lt;br /&gt;
	return NEGRO_AMBOS&lt;br /&gt;
    elseif (negro_izquierda) then&lt;br /&gt;
	return NEGRO_IZQUIERDO&lt;br /&gt;
    elseif (negro_derecha) then&lt;br /&gt;
	return NEGRO_DERECHA&lt;br /&gt;
    else&lt;br /&gt;
	return BLANCO&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se deben colocar dos sensores de escala de grises lo más cercano al suelo, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir los sensores al Butiá, quedando dichos sensores a ras del suelo.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_5.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor sin eventos - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_dos_sensores_con_eventos&amp;diff=3242</id>
		<title>Butialo: Ejemplo 5 - Seguidor de líneas con dos sensores con eventos</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_5_-_Seguidor_de_l%C3%ADneas_con_dos_sensores_con_eventos&amp;diff=3242"/>
				<updated>2012-10-10T23:59:38Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá seguir el rastro de una línea de color negro sobre el suelo. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras se encuentre en una zona oscura y en caso de salirse de la misma se tendrán tres alternativas posibles para poder encontrar nuevamente una zona oscura, dependiendo de cuál sensor detectó que el robot se ha salido de la zona.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos el valor de la variable COLOR_NEGRO de la misma forma que lo hicimos en el Ejemplo 1.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el Ejemplo 1, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica para cada sensor si el color sensado se corresponde con el color negro (COLOR_NEGRO).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces tres estados posibles: NEGRO_AMBOS, NEGRO_IZQUIERDO y NEGRO_DERECHO. &lt;br /&gt;
Cuando ambos sensores detectan el color negro, el robot se encuentra en el estado NEGRO_AMBOS. Por lo cual el robot deberá avanzar.&lt;br /&gt;
Si el sensor izquierdo detecta el color negro y el sensor derecho no, entonces el robot se encuentra en el estado NEGRO_IZQUIERDO. El robot aquí deberá girar en sentido izquierdo para tratar de no salirse de la línea.&lt;br /&gt;
Si el sensor derecho detecta el color negro y el sensor izquierdo no, entonces el robot se encuentra en el estado NEGRO_DERECHO. Análogamente, el robot deberá girar en sentido derecho.&lt;br /&gt;
En caso contrario, el estado será BLANCO y al perder la línea con ambos sensores el robot se detiene.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se cumpla alguna de las condiciones para cambiar de estado y en tal caso, se ejecutará la función asociada al evento correspondiente.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_IZQUIERDO, girar_izquierda)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_DERECHO, girar_derecha)&lt;br /&gt;
events.add(obtener_estado, '==', NEGRO_AMBOS, avanzar)&lt;br /&gt;
events.add(obtener_estado, '==', BLANCO, detener)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''detener'''&lt;br /&gt;
Detiene los motores.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function detener()&lt;br /&gt;
    Motors.setvel2mtr(0, 0, 0, 0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''es_negro'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot está parado sobre la zona oscura, según el valor obtenido por el sensor de grises y su comparación con la constante COLOR_NEGRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function es_negro(valor)&lt;br /&gt;
    return (valor &amp;gt; COLOR_NEGRO)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_derecha'''&lt;br /&gt;
Gira el robot hacia la derecha con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_derecha()&lt;br /&gt;
    Motors.setvel2mtr(0,MOTOR_GIRO_VEL,0,0)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_izquierda'''&lt;br /&gt;
Gira el robot hacia la izquierda con una velocidad definida por la variable MOTOR_GIRO_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_izquierda()&lt;br /&gt;
    Motors.setvel2mtr(0,0,0,MOTOR_GIRO_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''obtener_estado'''&lt;br /&gt;
Retorna el estado correspondiente, dependiendo de los valores obtenidos en cada uno de los sensores de grises.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function obtener_estado()&lt;br /&gt;
    negro_izquierda = es_negro(Grey_1.getValue())&lt;br /&gt;
    negro_derecha = es_negro(Grey_2.getValue())&lt;br /&gt;
    if (negro_izquierda and negro_derecha) then&lt;br /&gt;
	return NEGRO_AMBOS&lt;br /&gt;
    elseif (negro_izquierda) then&lt;br /&gt;
	return NEGRO_IZQUIERDO&lt;br /&gt;
    elseif (negro_derecha) then&lt;br /&gt;
	return NEGRO_DERECHA&lt;br /&gt;
    else&lt;br /&gt;
	return BLANCO&lt;br /&gt;
    end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_5.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor sin eventos - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Archivo:Config_butialo_problema_4.png&amp;diff=3241</id>
		<title>Archivo:Config butialo problema 4.png</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Archivo:Config_butialo_problema_4.png&amp;diff=3241"/>
				<updated>2012-10-10T23:58:37Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	<entry>
		<id>http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Buti%C3%A1_que_no_se_cae_de_la_mesa_con_un_sensor_con_eventos&amp;diff=3240</id>
		<title>Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor con eventos</title>
		<link rel="alternate" type="text/html" href="http://164.73.124.35/inco/proyectos/butia/mediawiki/index.php?title=Butialo:_Ejemplo_4_-_Buti%C3%A1_que_no_se_cae_de_la_mesa_con_un_sensor_con_eventos&amp;diff=3240"/>
				<updated>2012-10-10T23:57:58Z</updated>
		
		<summary type="html">&lt;p&gt;Leticiavp: /* Configuración */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__TOC__&lt;br /&gt;
&lt;br /&gt;
==Descripción==&lt;br /&gt;
Se desea implementar utilizando eventos un programa que permita al robot Butiá poder desplazarse en una mesa sin caerse de la misma. &lt;br /&gt;
&lt;br /&gt;
El robot deberá avanzar mientras detecte un color semejante al de la mesa. En caso de detectar un color distinto al de la mesa, procederá a retroceder por un tiempo aleatorio para luego cambiar de sentido (izquierda o derecha), y así poder avanzar nuevamente.&lt;br /&gt;
&lt;br /&gt;
==Solución==&lt;br /&gt;
&lt;br /&gt;
'''Descripción'''&lt;br /&gt;
&lt;br /&gt;
Obtenemos los valores de la variable COLOR_MESA, MIN_TIEMPO_RETROCESO, MAX_TIEMPO_RETROCESO, MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO de la misma forma que lo hicimos en el Ejemplo 3.&lt;br /&gt;
&lt;br /&gt;
Como podemos apreciar en el ejemplo anterior, el robot tiene un comportamiento que claramente se adapta al paradigma reactivo. Esto es, SENSAR - ACTUAR. Cambiará su estado dependiendo de una condición que le indica si el color sensado se corresponde con el de la mesa (COLOR_MESA).&lt;br /&gt;
&lt;br /&gt;
Distinguimos entonces dos estados posibles según la condición sea verdadera o falsa. Si se cumple la condición, el robot deberá retroceder en un tiempo aleatorio definido entre el rango MIN_TIEMPO_RETROCESO y MAX_TIEMPO_RETROCESO y luego girar de forma aleatoria también por un tiempo entre el rango MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO.&lt;br /&gt;
En caso contrario, el robot deberá avanzar.&lt;br /&gt;
&lt;br /&gt;
Finalmente se organiza la estructura de la solución en diferentes funciones de forma de modularizar y distinguir fácilmente las acciones. El programa principal quedaría de la siguiente forma:&lt;br /&gt;
&lt;br /&gt;
* '''programa principal'''&lt;br /&gt;
&lt;br /&gt;
Consiste en avanzar el robot hasta tanto no se encuentre en peligro de caer de la mesa, en caso contrario deberá retroceder de forma aleatoria. Luego de que se retrocede aleatoriamente, por un tiempo determinado, se utiliza la función girar_aleatorio() para que la siguiente vez que se avance, se haga en un sentido aleatorio.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;gt;=', COLOR_MESA,retroceder_y_girar_aleatorio)&lt;br /&gt;
events.add(Grey_2.getValue, '&amp;lt;', COLOR_MESA, avanzar)&lt;br /&gt;
events.go()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''avanzar'''&lt;br /&gt;
Activa los motores haciendo que los mismos giren a una velocidad prefijada en la constante MOTOR_VEL.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function avanzar()&lt;br /&gt;
    Motors.setvel2mtr(0, MOTOR_VEL, 0, MOTOR_VEL)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''retroceder_y_girar_aleatorio'''&lt;br /&gt;
Retrocede y luego gira de forma aleatoria.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function retroceder_y_girar_aleatorio()&lt;br /&gt;
    retroceder_aleatorio()&lt;br /&gt;
    girar_aleatorio()&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''chequear_giro_izquierda'''&lt;br /&gt;
Retorna un valor booleano que indica si el robot debe girar hacia la izquierda. Para girar de forma aleatoria, a izquierda o derecha, obtenemos un valor entre 0 y 1 con la función random de la bibloteca math. Si el valor randómico obtenido es mayor a 0.5 definimos que el giro será hacia la izquierda, retornando True y en caso contrario deberá girar a la derecha retornando False.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function chequear_giro_izquierda()&lt;br /&gt;
    local sentido = math.random (0, 1)&lt;br /&gt;
    return sentido &amp;gt; 0.5&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
* '''girar_aleatorio'''&lt;br /&gt;
Nuevamente utilizamos la función random para obtener un número aleatorio entre MIN_TIEMPO_GIRO y MAX_TIEMPO_GIRO y así definir el tiempo durante el cual el robot estará girando. Luego chequeamos con la función chequear_giro_izquierda() si el giro será en sentido izquierdo o derecho, dependiendo de ese valor se procederá entonces a girar en ese sentido con una velocidad definida por la variable VELOCIDAD_GIRO.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;lua&amp;quot;&amp;gt;&lt;br /&gt;
local function girar_aleatorio()&lt;br /&gt;
    local tiempo_giro = math.random(MIN_TIEMPO_GIRO, MAX_TIEMPO_GIRO)&lt;br /&gt;
    local izquierda = chequear_giro_izquierda()&lt;br /&gt;
    if (izquierda) then&lt;br /&gt;
	Motors.setvel2mtr(0, VELOCIDAD_GIRO, 1, VELOCIDAD_GIRO)&lt;br /&gt;
    else&lt;br /&gt;
	Motors.setvel2mtr(1, VELOCIDAD_GIRO, 0, VELOCIDAD_GIRO)&lt;br /&gt;
    end&lt;br /&gt;
    util.wait(tiempo_giro)&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Configuración==&lt;br /&gt;
&lt;br /&gt;
Se debe colocar un sensor de escala de grises lo más cercano a la mesa, pero siempre sin tocarla, en la parte de adelante del Butiá.&lt;br /&gt;
&lt;br /&gt;
En nuestro caso encastramos piezas de forma de generar el soporte para adherir el sensor al Butiá, quedando dicho sensor a ras de la mesa.&lt;br /&gt;
&lt;br /&gt;
Se muestra a continuación una imagen ilustrativa de la configuración del robot vista desde arriba.&lt;br /&gt;
&lt;br /&gt;
[[Archivo:config_butialo_problema_4.png|300px|thumb|center|Configuración]]&lt;br /&gt;
&lt;br /&gt;
==Video==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
==Código==&lt;br /&gt;
&lt;br /&gt;
[[Butialo: Ejemplo 4 - Butiá que no se cae de la mesa con un sensor sin eventos - Código]]&lt;/div&gt;</summary>
		<author><name>Leticiavp</name></author>	</entry>

	</feed>