Un microcontrolador es, por decirlo suavemente, estúpido, incapaz de pensar e improvisar, y solo capaz de seguir instrucciones precisas. La comunicación con el microcontrolador se realiza por escrito en un lenguaje de programación, el lenguaje es muy claro, estricto y tiene una sintaxis propia y unos estándares de diseño. Y si un error de sintaxis conduce a un error en la compilación del código o al funcionamiento incorrecto del dispositivo que ha flasheado, entonces el diseño del código no sirve para la conveniencia del programador, así como para aquellos que intentarán lidiar con su código.
El código de máquina binario se carga directamente en el propio microcontrolador, que parece un conjunto caótico de letras y números. Este código se puede obtener de cualquier lenguaje de programación, todo depende del entorno de desarrollo y de un intérprete. El entorno de desarrollo oficial es Arduino IDE, donde la programación se realiza en C++, uno de los lenguajes más populares y poderosos. Los propios desarrolladores llaman al lenguaje Arduino Wiring, ya que la biblioteca estándar arduino.h usa funciones y herramientas del marco Wiring. Pero el lenguaje, el lenguaje del cual se toma la sintaxis, es C++, por lo tanto, en paralelo con el estudio de funciones estándar, es recomendable estudiar cualquier libro de referencia sobre las programación C++. En él puedes encontrar mucha más información sobre el idioma que en todas las lecciones de Arduino combinadas (estamos hablando del idioma y la sintaxis, y no de las funciones de Wiring). Además de C, existen entornos de desarrollo que le permiten escribir en Java, por ejemplo Espruino WEB IDE, o B4R– en Basic. O XOD: tendrás que programar con bloques visuales. Pero francamente hablando, tal para mí, solo consideraremos C.
Sintaxis.
- Los cuerpos de funciones se encierran entre llaves { }.
- Cada comando termina con un punto y coma ;
- El método se aplica al objeto a través de un punto. Ejemplo: Serial.begin();
- Una llamada a una función o método siempre termina entre paréntesis, incluso si la función no toma parámetros. Ejemplo: loop().
- El separador decimal es un punto. Ejemplo: 0.25 La coma tiene un uso diferente aquí.
- Los argumentos de las funciones y métodos, así como los miembros de una matriz, se enumeran con comas. Ejemplo: digitalWrite(3, HIGH); matriz – int myArray[] = {3, 4, 5, 6}; Además, la coma es un operador independiente, pero hablaremos de esto por separado en otra lección.
- Los caracteres aislados se encierran entre comillas simples ‘а’.
- Las cadenas y las matrices de caracteres se incluyen entre comillas dobles «línea«.
- Los nombres de las variables pueden contener letras latinas mayúsculas y minúsculas, números y guiones bajos. Ejemplo: myVal_35.
- Los nombres de las variables no pueden comenzar con un dígito. Solo con letra o subrayado
- Es case sensitive, es decir la mayúscula es diferente a la minúscula. Ejemplo: las variables val y Val No son lo mismo.
La sintaxis también puede incluir comentarios, ya que se destacan de manera diferente en diferentes idiomas. Un comentario es texto sin formato que se ignora durante la compilación. Se necesitan comentarios para explicar el código, tanto para usted como para otros posibles lectores. En C++, tenemos dos tipos de comentarios:
- Comentario de una sola línea.
// comentario de una línea // el compilador me ignora = (
- Comentario de varias líneas.
/ * Multilínea comentario * /
Registro.
Formateo.
Existe el formateo (alineación) del código, es decir, respetar los espacios y el espaciado. Por ejemplo, compare estos dos códigos. ¿Cuál se ve más claro y visual?
No temas, todos los IDE serios tienen formateo de código automático, funciona tanto en el proceso de escritura como de guardia. Arduino IDE – no es una excepción, tiene el formateo de código y combinaciones de teclas calientes Ctrl + T.
- Hay un espacio entre las operaciones matemáticas, los signos de comparación, la asignación y todo eso.
- Como en el texto ordinario, se coloca un espacio después y no antes de una coma, dos puntos y un punto y coma.
- La sangría del borde izquierdo de la pantalla es un carácter de tabulación, el código se desplaza hacia la derecha y los comandos se forman a partir de un bloque de código a la misma distancia. En Arduino IDE, una tabulación equivale a dos espacios.
- Cada acción, sentencia, se realiza en una nueva línea (el formato automático no soluciona esto).
- Es habitual escribir llaves al principio y al final de un bloque de código en una línea separada. Además, muchas personas escriben un paréntesis abierto en una línea con un operador, esto ahorra espacio.
Nombres de Variables.
- Es costumbre escribir los nombres de las variables comenzando con una letra minúscula, para nombrarlas de manera que quede claro. Sí, sería bueno mejorar nuestro inglés. Ejemplo: value.
- Si un nombre de variable consta de dos o más palabras, están separadas por la primera letra mayúscula de cada nueva palabra, o las palabras están separadas por guiones bajos. Ejemplo: myButtonState, button_flag.
- Es costumbre escribir los nombres de los tipos y clases de datos con mayúscula inicial. Ejemplo: Signal, Servo.
- Es costumbre escribir los nombres de las constantes en mayúsculas, la separación es el subrayado. Ejemplo: MOTOR_SPEED.
- Al escribir bibliotecas y clases, se acostumbra escribir los nombres de las variables internas comenzando con el carácter de subrayado. Ejemplo: _position.
- Hay varias abreviaturas comunes para los nombres de variables, a menudo las verá en el firmware y las bibliotecas de otras personas:
- button – btn, botón
- índex – idx – i, índice
- búffer – buf, búfer
- value – val, valor
- variable – var, variable
- pointer – ptr, puntero
- Es habitual comenzar los nombres de funciones y métodos con un verbo que describa brevemente la acción de la función. Estos son los que verá todo el tiempo:
- get – obtener el valor (getValue)
- set – establecer valor (setTime)
- print, show – mostrar algo
- read– leer
- write – escribir
- change – cambiar
- clear – borrar
- begin, start – empezar
- end, stop – terminar, detener
- Una pregunta común: ¿la longitud del nombre de la variable afecta la memoria ocupada por el firmware? El peso del archivo de firmware en la placa se ve afectado?. El peso del firmware cargado en el microcontrolador no se ve afectado, porque el código se convierte en código máquina y no hay nombres, solo direcciones.
Estructura de código.
Antes de pasar a la estructura y el orden de las piezas de código, hay algunas cosas para recordar:
- Se debe llamar a una variable de cualquier tipo después de su declaración. De lo contrario, habrá un error.
- La declaración y el uso de clases o tipos de datos de una biblioteca / archivo deben realizarse después de incluir la biblioteca / archivo.
- La función se puede llamar tanto antes como después de la declaración, porque C++ es un lenguaje compilado, la compilación se lleva a cabo en varias etapas y las funciones se «asignan» por separado, por lo que se pueden llamar en cualquier parte del programa.
Al iniciar el IDE de Arduino, nos da un espacio en blanco en forma de dos funciones requeridas: setup() y loop().
El código en bloque setup() se ejecuta una vez cada vez que se inicia el microcontrolador. El código en el bloque loop() se realiza «en círculo» durante todo el funcionamiento del microcontrolador, a partir del momento de finalización de setup().
Para los curiosos: si ya está familiarizado con el lenguaje C++, probablemente se pregunte «¿dónde está int main () y generalmente el archivo main.cpp?. Todo es muy sencillo: int main() ya han escrito para usted dentro del archivo main.cpp, que se encuentra en lo profundo de los archivos de Arduino.
// main.cpp // en algún lugar de las profundidades del núcleo de Arduino int main () { setup () ; for ( ;; ) { loop () ; } return 0; }
En el transcurso de varios años de trabajo con Arduino, me he formado la siguiente estructura de boceto:
- Descripción del firmware, enlaces útiles, notas, autoría.
- Constantes de ajuste (definidas y regulares).
- Constantes de servicio (que solo deben cambiarse con pleno conocimiento del tema).
- Bibliotecas conectadas y archivos externos, declaración de los tipos y clases de datos correspondientes.
- Variables globales.
- setup().
- loop().
- Las funciones.
Código de muestra:
// -------- AJUSTES --------- #define SERVO_PIN 13 // El servo está conectado aquí #define SERVO_SPEED 3 // velocidad del servo #define MIN_ANGLE 50 // min. ángulo #define MAX_ANGLE 120 // máx. ángulo // ------- BIBLIOTECAS ------- #include <Servo.h> Servo myservo; // ------- VARIABLES ------- uint32_t servoTimer; servoDirection boolean; int servoAngle; // --------- SETUP ---------- void setup() { myservo.attach(SERVO_PIN); } // ---------- LOOP ---------- void loop() { turnServo(); } // --------- FUNCIONES -------- void turnServo() { if (millis() - servoTimer >= 50) { servoTimer = millis(); if (servoDirection) { servoAngle += SERVO_SPEED; if (servoAngle >= MAX_ANGLE) { servoAngle = MAX_ANGLE; servoDirection = false; } } else { servoAngle -= SERVO_SPEED; if (servoAngle <= MIN_ANGLE) { servoAngle = MIN_ANGLE; servoDirection = true; } } myservo.write(servoAngle); } }
Esta es una estructura adecuada para «bosquejar», no se recomienda escribir proyectos grandes como ese y debe acostumbrarse a los enfoques más maduros descritos en la lección sobre el desarrollo de proyectos grandes.
Conectando bibliotecas y archivos.
En el trabajo real, muy a menudo usará bibliotecas o solo archivos externos, están conectados al archivo principal (archivo de firmware) usando la directiva #include, esta directiva le dice al preprocesador que busque e incluya el archivo especificado en la compilación. El archivo especificado puede extraer otros archivos junto con él, pero todo ya está escrito allí y conectado automáticamente. Consideremos un ejemplo:
#include <Servo.h> // incluye la biblioteca Servo.h #include "Servo.h" // también incluye la biblioteca Servo.h
Cual es la diferencia <> y » «? Cuando indicamos el nombre «entre comillas», el compilador busca primero el archivo en la carpeta de bocetos y luego en la carpeta de bibliotecas. Utilizando < > ¡el compilador solo busca el archivo en la carpeta de la biblioteca!
Hablando de carpetas con bibliotecas: hay dos de ellas, en ambas se buscarán bibliotecas.
- Mis documentos / Arduino / libraries
- C: / Archivos de programa (x86) / Arduino / bibliotecas (o C: / Archivos de programa / Arduino / libraries, para Windows de 32 bits).
Las bibliotecas llegan a la primera carpeta (en documentos) cuando se instalan mediante el comando «incluir biblioteca.zip». No se recomienda conectar las bibliotecas de esta manera, porque la biblioteca no siempre llega a usted en el archivo y será más fácil copiarla manualmente en archivos de programa. Además, si en ambas carpetas hay bibliotecas con el mismo nombre, esto dará lugar a un conflicto, por lo que simplemente copiamos las bibliotecas a la carpeta de bibliotecas en Archivos de programa / Arduino.
Nota importante: la carpeta de la biblioteca ubicada en C: / Archivos de programa (x86) / Arduino / libraries, debe contener los archivos y carpetas de la biblioteca, no una carpeta con el mismo nombre que la biblioteca en sí. Esto dará lugar a un error, ¡el compilador no puede encontrar los archivos!
¡No uses tu ratón!
Probablemente haya notado cómo los programadores y los piratas informáticos hacen su trabajo en las películas tocando el teclado y sin tocar demasiado el mouse. Esto es cierto, cuanto más programe, menos usará el mouse para colocar el cursor en el lugar correcto y seleccionar palabras / líneas, ¡porque puede hacerlo mucho más rápido desde el teclado!
- Formato automático: el IDE de Arduino puede ordenar automáticamente su código (es decir, sangrías, saltos de línea y espacios). Para formateo automático, use la combinación CTRL + T en su teclado, o Herramientas / Autoformato en la ventana IDE. Úselo con más frecuencia para hacer que su código sea vistoso (canon, clásico) y más legible para los demás.
- Ocultar partes de código: contraiga funciones largas y otras partes de código para ahorrar espacio y tiempo para el desplazamiento. Incluido aquí: Archivo / Preferencias / Habilitar plegado de código.
- ¡No uses tu ratón! Cuanto mayor sea tu habilidad de programación, menos usarás el mouse (sí, como en las películas de hackers). Use ambas manos para escribir y navegar por el código, aquí hay algunas combinaciones y trucos útiles que uso CONSTANTEMENTE:
- Ctrl + ←, Ctrl + → – mueve el cursor a la izquierda / derecha UNA PALABRA
- Inicio, fin: mueva el cursor al principio / final de la línea
- Shift + ←, Shift + → – selecciona un carácter a la izquierda / derecha del cursor
- Shift + Ctrl + ←, Shift + Ctrl + → – seleccionar una palabra a la izquierda / derecha del cursor
- Mayús + Inicio, Mayús + Fin: selecciona todos los caracteres desde la posición actual del cursor hasta el principio / final de la línea
- Ctrl + Z – deshacer la última acción
- Ctrl + Y – rehacer la acción deshecha
- Ctrl + C – copiar texto seleccionado
- Ctrl + X – cortar el texto seleccionado
- Ctrl + V – pega texto del portapapeles
- Combinaciones locales:
- Ctrl + U – Cargar firmware a Arduino
- Ctrl + R – compilar
- Ctrl + Shift + M – Monitor de puerto serie abierto. Además, use TAB en lugar de SPACE para mover comentarios al lado derecho del código. Al presionar TAB se mueve el cursor sobre alguna tabla, lo que hará que sus comentarios se establezcan bien a la misma distancia en la mitad de la cantidad de clics.