[caption id="attachment_902" align="alignright" width="115"] Sinclair ZX81[/caption]
Tanto me fascina que en mi tiempo libre sigo ampliando conocimientos y habilidades en programación, realizando software para la creación de comportamientos para robots.
Esta fascinación me lleva también a compartir lo aprendido y ayudar a otras personas a que se animen a programar, especialmente robots, y de aquí todos estos artículos y mi participación en distintos foros de robótica.
Un poco de perspectiva: programación y desarrollo de software
Una parte fundamental del desarrollo de software es la programación, durante la cual se crea el código fuente con el que se generará el ejecutable a utilizar. Pero para crear este código fuente hemos de tener muy claro:
- qué ha de hacer y cómo sabemos que lo hace correctamente
- cómo vamos a estructurar este código fuente
- qué pruebas hacer para asegurarnos que el programa funciona correctamente
Sin obtener unas respuestas claras y reales a estas preguntas la programación se complicará tanto que en lugar de disfrutar programando nos parecerá un suplicio; probablemente sin conseguir que el programa funcione correctamente.
¿Qué necesito aprender para poder programar?
Igual que en un iceberg, la mayor parte no está a la vista.
1.- La parte obvia y más visible es aprender a utilizar:
- un lenguaje de programación, como C, C++, C# o Java, por mencionar sólo los más conocidos,
- las herramientas necesarias para crear un ejecutable con el programa escrito, como, por ejemplo, GNU C/C++ o Visual Studio de Microsoft
2.- Pero, realmente, mientras se aprende el lenguaje escogido es imprescindible aprender algunas cuestiones básicas y comunes a todos ellos:
- cómo secuenciar las instrucciones a ejecutar (condiciones, bucles, etc.)
- cómo guardar los datos (variables, objetos, arrays, listas, etc.)
3.- Y, donde empieza realmente la diversión, buscando el resultado correcto con sencillez, eficiencia y/o eficacia:
- qué pasos ha de realizar el programa para que el resultado sea correcto (algoritmos)
- cual es la mejor forma de estructurar el programa (arquitectura general del programa, diseño de clases y métodos o funciones)
Un ejemplo muy sencillo
[caption id="attachment_921" align="alignright" width="126"] Dynamixel AX12[/caption]
Ejemplo extraído de leyendo y moviendo Dynamixel AX-12 (I) (Dynamixel son servomotores fabricados por Robotis)
Respecto el punto anterior 1:
- El lenguaje utilizado es C
- la herramienta utilizada para generar el ejecutable (un .hex para un microcontrolador en este caso) es Win AVR que utiliza, a su vez, GNU C.
[sourcecode language="c"]
int main(void)
{
init();
while(true) // repetiremos eternamente este bucle
{
int id=obtenerId(); // obtenemos el ID del AX-12 a utilizar
int posicion=obtenerPosicion(); // obtenemos la posición en la que situar el AX-12 seleccionado
dxl_write_word( id, P_GOAL_POSITION_L, posicion); // enviamos la orden al Dynamixel
}
return 0;
}
[/sourcecode]
Respecto el punto 2:
- La secuencia principal es muy sencilla. Una repetición eterna ejecutando tres funciones: obtenerId, obtenerPosicion y dxl_write_word. Pero revisando qué hacen estas funciones veréis que a su vez incluyen, cada una de ellas, otras secuencias y llamadas a otras funciones. La estructura general es como un árbol, donde del tronco (main o parte principal) salen diversas ramas de las cuales pueden aparecer otras nuevas y así hasta varios niveles.
- Los datos utilizados en este nivel principal son muy sencillos, guardaremos números enteros, uno con el identificador del servo a utilizar, id y otro con la posición donde lo situaremos, posicion.
Veamos el contenido de obtenerId:
[sourcecode language="c"]
int obtenerId()
{
/*
Creamos una variable de un tamaño amplio, 256 bytes (posiciones de un carácter), aunque con 4
valdría, pero si se introdujeran más carácteres de los definidos provocaría un error.
*/
char cadena[256];
/*
Y otra variable de tipo entero, es recomendable asignar siempre un valor, en este caso
la inicializamos con el valor mínimo, 1
*/
int ax12Id=1;
// puts es muy similar a printf, muestra la cadena que recibe como parámetro por la pantalla
puts ("nVamos a mover un Dynamixel a voluntad. V02");
do
{// inicio del bucle
puts ("Introduce el ID del servo a mover, entre 1 y 18, ");
ax12Id=leerEnteroComoCadena(cadena); // llamamos a esta función; para entrar por pantalla el valor
// la admiración (!) es el operador lógico NOT. Repetiremos el bucle mientras el rango NO sea valido
}while(!enRangoValido(ax12Id, 1, 18));
// Mostramos el valor introducido
printf("ID del AX12: %in", ax12Id);
return ax12Id;
}
[/sourcecode]
Y, finalmente, respecto el punto 3:
- como el ejemplo es muy sencillo el algoritmo utilizado también lo es:
- inicializar (init)
- eternamente hacer:
- obtener datos del usuario (obtenerId y obtenerPosicion)
- posicionar el servomotor con el identificador y posición introducidas (dxl_write_word)
- el programa está estructurado en distintas funciones que encapsulan el trabajo a realizar en pequeñas tareas, compartiendo información a través de los parámetros que reciben y el valor que retornan.
- estas funciones están estructuradas en tres ficheros:
- moviendoDynamixel.c
- entrarDatos.c
- myCM510.c
¿Por qué dividir en ficheros .c (módulos) y clases o funciones? Porque cuanto más modularizada y lógica sea la estructura más fácil es crearla, mantenerla y corregirla, pudiéndose reutilizar los elementos (módulos, clases, métodos y funciones) en distintos programas o partes de un mismo programa. - un detalle importante, la función init. Esta función está pensada para ser utilizada en muchos programas, no sólo en éste, ya que inicializa el controlador CM-510. Está incluida en el fichero myCM510.c , que contiene las funciones básicas necesarias para utilizar el controlador CM-510 (LEDs, teclas, zumbador,...)
Esquema del orden de la la ejecución de las funciones:
- main
- init
- <inicio bucle eterno>
- obtenerId
- leerEnteroComoCadena
- enRangoValido
- obtenerPosicion
- leerEnteroComoCadena
- enRangoValido
- dxl_write_word
- <fin bucle eterno>
Tutoriales más detallados
Robomind, programa gratuito, para uso personal, para empezar a programar de una forma muy fácil. Se puede utilizar con Lego Mindstorms.
[caption id="attachment_2279" align="aligncenter" width="150"] RoboMind[/caption]
Introducción a la programación con C, libro/curso de la UOC (Universidad abierta de Cataluña) práctico y muy fácil de seguir.
La UPV /EHU tiene publicado este fantástico tutorial de programación (web. pdfs, zips,...)
Aprenda ANSI C como si estuviera en primero (pdf)
Curso de introducción a C de 13 páginas
Impresionante explicación sobre algoritmos (pdf)
Libros gratuitos y libres
Impresionante colección de libros gratuitos y libres, sobre programación y otros temas. Dos que me han parecido especialmente interesantes son:
- Introducción a la programación utilizando C, libro/curso de la UOC (Univ. Abierta de Cataluña)
- Programación orientada a objetos
- Práctica introducción a C++
- Divertido tutorial de C++
¿Y la programación Orientada a Objetos?
La programación orientada a objetos es un paso más para alcanzar una mejor concepción y estructuración del código fuente. Fundamentalmente consiste en encapsular en clases, y los objetos que se generan de ellas, agrupando datos y las operaciones que los manejan. Pero la riqueza que se puede alcanzar es mucho mayor de lo que puede parecer. Ver, por ejemplo, los famosos patrones de diseño
Artículo continuación: Programación orientada a objetos y robótica
[caption id="attachment_929" align="aligncenter" width="464"] Design patterns (patrones de diseño)[/caption]
No hay comentarios:
Publicar un comentario