Punteros a función y structs con Arduino
En este artículo presentamos una extensión al programa de Control remoto Arduino + LCD aprovechando el uso de punteros a función. Es recomendable darle una mirada al programa de ese artículo para comparar con este, y entender cómo evolucionó. De todas formas se puede leer este artículo en forma independiente para tener un ejemplo de uso de punteros a función. Pero el circuito está explicado en ese artículo y no se repetirá aquí.
En el programa utilizamos una estructura cuyo tipo llamamos State y de la cual creamos una sola global variable state. En ella encapsulamos el estado de la lógica del display. En el programa anterior el objeto de control del display era una variable global. Ahora lo incluimos en la estructura state para encapsular la información. Si bien es común en los programas de Arduino tener muchas variables globales, eso no es una buena práctica de programación. En este caso al encapsular las variables que tienen que ver con la lógica del display en una estructura, el código queda más ordenado. Aunque la estructura en sí siga siendo global. Pero ese punto es imposible de solucionar porque Arduino llama constantemente a la función loop() y carece de punto de entrada como una aplicación estándar de C/C++.
Además del objeto de control del display en la estructura state guardamos los caracteres que se mostrarán en el segundo renglón del display, limitado a 16 posiciones. Y la posición del cursor de escritura. Esto permitirá responder a las teclas del control escribiendo en la posición que corresponda. Y mover el cursor a la posición siguiente cada vez.
|
|
Cada tecla que se acepta del control remoto se configura en una posición del array record. El array es recorrido cuando se recibe un código desde el receptor infrarrojo. Si el código coincide con el valor ID del índice revisado en la línea 107, se procede a usar los datos de ese índice. Esto se hace llamando a la función apuntada por el campo cmd de la estructura Key. En la función setup() se configuró el campo cmd de cada ítem para que apunte a alguna de las funciones definidas a partir de la línea 119. Para las teclas del 0 al 9 se apunta a la función cmd_write que escribe el valor de value como un caracter ASCII en la posición actual. Para la tecla de “reset” se apunta a la función cmd_clear que borra el contenido de toda la línea. Las teclas de avanzar y retroceder del control se apuntan a la función cmd_move que suma el valor de value a la posición actual del cursor (por eso se asigna -1 a la tecla de retroceso y 1 a la de avance).
Al utilizar el tipo puntero a función definido en la línea 24 podemos crear varias funciones que comparten la firma. Y esto facilita agregar funciones en el futuro sin necesidad de realizar muchos cambios en el código general. La función siempre recibe la información de la tecla (puntero a la tecla, sólo lectura) y la de estado (puntero a state, lectura escritura). De esta manera cada función realiza su trabajo con la información recibida y modificando el estado.
Para visualizar las ventajas de los punteros a función se puede comparar este programa con el del artículo anterior y ver cómo el programa tiene una funcionalidad mucho más compleja con relativamente pocos cambios. También podemos ejemplificar qué pasaría si quisiéramos usar las teclas + y - del control remoto para incrementar o decrementar el valor de la posición actual: simplemente sería necesario agregar ambas teclas al array key y definir una función nueva cmd_plus que sume el valor de value al valor numérico de la posición actual. En cada tecla, para el campo value, pondríamos 1 y -1 respectivamente de forma que cuando la función sume el valor resulte en un incremento o decremento. El nombre de la función es arbitrario, claro. Si tuviésemos que agregar otra funcionalidad más compleja que requiriese guardar más información de estado, simplemente agregaríamos campos a la estructura state. Sin necesidad de modificar la firma del tipo puntero a función. Es decir que sería transparente a las funciones que existen actualmente.