Solución:
const int led = 13;
Ese es el método correcto. O incluso:
const byte led = 13;
¿Cuántos pines tienes?
Algunos de los tutoriales no pasaron por tanto control de calidad como podrían haberlo hecho.
El rendimiento será mejor usando const byte
, comparar con int
sin embargo, el compilador puede ser lo suficientemente inteligente como para darse cuenta de lo que está haciendo.
Lo que puede hacer es animar a las personas a utilizar técnicas más eficientes utilizándolas en su propio código.
Respuestas a comentarios
-
Un comentarista sugirió que
byte
no es estándar C. Esto es correcto, sin embargo, este es un sitio Arduino StackExchange, y creo que el uso de tipos estándar proporcionados por Arduino IDE es aceptable.En Arduino.h hay esta línea:
typedef uint8_t byte;
Tenga en cuenta que esto no es exactamente lo mismo que
unsigned char
. Vea uint8_t vs unsigned char y ¿Cuándo es uint8_t ≠ unsigned char ?. -
Otro comentarista ha sugerido que el uso de bytes no necesariamente mejorará el rendimiento, porque los números menores que
int
será promovido aint
(consulte las Reglas de promoción de números enteros si desea obtener más información al respecto).Sin embargo, en el contexto de una constante identificador, el compilador generará código eficiente en cualquier caso. Por ejemplo, al desmontar “blink” se obtiene esto en la forma original:
00000086
: 86: 8d e0 ldi r24, 0x0D ; 13 88: 61 e0 ldi r22, 0x01 ; 1 8a: 1b d1 rcall .+566 ; 0x2c2 De hecho, genera el mismo código si el
13
:- Es un literal
- Es un
#define
- Es un
const int
- Es un
const byte
El compilador sabe cuándo puede caber un número en un registro y cuándo no. sin embargo lo és buena práctica utilizar codificación que indique su intención. Haciendolo const
deja en claro que el número no cambiará, y lo hace byte
(o uint8_t
) deja en claro que está esperando una pequeña cantidad.
Mensajes de error confusos
Otra razón importante para evitar #define
son los mensajes de error que recibe si comete un error. Considere este boceto “parpadeante” que tiene un error:
#define LED = 13;
void setup()
pinMode(LED, OUTPUT); // <---- line with error
void loop()
digitalWrite(LED, HIGH); // <---- line with error
delay(1000);
digitalWrite(LED, LOW); // <---- line with error
delay(1000);
En la superficie, se ve bien, pero genera estos mensajes de error:
Blink.ino: In function ‘void setup()’:
Blink:4: error: expected primary-expression before ‘=’ token
Blink:4: error: expected primary-expression before ‘,’ token
Blink:4: error: expected `;' before ‘)’ token
Blink.ino: In function ‘void loop()’:
Blink:8: error: expected primary-expression before ‘=’ token
Blink:8: error: expected primary-expression before ‘,’ token
Blink:8: error: expected `;' before ‘)’ token
Blink:10: error: expected primary-expression before ‘=’ token
Blink:10: error: expected primary-expression before ‘,’ token
Blink:10: error: expected `;' before ‘)’ token
Miras la primera línea resaltada (línea 4) y ni siquiera veo un símbolo "=". Además, la línea se ve bien. Ahora es bastante obvio cuál es el problema aquí (= 13
está siendo sustituido por LED
), pero cuando la línea está 400 líneas más abajo en el código, no es obvio que el problema está en la forma en que se define el LED.
He visto a gente enamorarse de esto muchas veces (incluyéndome a mí).
Como bien ha dicho Ignacio, es básicamente porque no conocen mejor. Y no saben mejor porque las personas que les enseñaron (o los recursos que usaron para aprender) no sabían mejor.
Gran parte del código y los tutoriales de Arduino están escritos por personas que nunca han tenido ningún entrenamiento en programación y son muy "autodidactas" a partir de recursos de personas que son muy autodidactas sin una formación adecuada en programación.
Muchos de los fragmentos de código de tutoriales que veo en el lugar (y especialmente aquellos que solo están disponibles dentro de los videos de YouTube --- urgh) serían una calificación reprobada si los estuviera calificando en un examen.
Sí un const
se prefiere sobre una no constante, e incluso sobre una #define
, porque:
- A
const
(como un#define
, a diferencia de un no constante) no asigna RAM - A
const
(como una no constante, pero a diferencia de una#define
) le da al valor un explícito escribe
El segundo punto es de especial interés. A menos que se indique específicamente lo contrario con fundición tipográfica incrustada ((long)3
) o un sufijo de tipo (3L
) o la presencia de un punto decimal (3.0
), a #define
de un número siempre será un número entero y todas las matemáticas realizadas en ese valor serán como si fuera un número entero. La mayoría de las veces eso no es un problema, pero puede encontrarse con escenarios interesantes cuando intenta #define
un valor mayor que el que puede almacenar un entero, como #define COUNT 70000
y luego realizar una operación matemática con otros int
valores en él. Usando un const
puede decirle al compilador "Este valor debe tratarse como este tipo de variable", por lo que en su lugar usaría: const long count = 70000;
y todo funcionaría como se esperaba.
También tiene el efecto dominó de que verifica el tipo al pasar el valor por el lugar. Intenta pasar un const long
a una función que espera un int
y se quejaría de la reducción del rango de variables (o incluso fallaría por completo en la compilación según el escenario). Haz eso con un #define
y en silencio seguiría dándote resultados incorrectos y te dejaría rascándote la cabeza durante horas.
Como novato de 2 semanas en Arduino, retomaría la idea general de que Arduino está ocupado por no programadores. La mayoría de los bocetos que he examinado, incluidos los del sitio de Arduino, muestran una falta total de orden, con bocetos que no funcionan y apenas un comentario coherente a la vista. Los diagramas de flujo son inexistentes y las "Bibliotecas" son un revoltijo no moderado.
Comentarios y calificaciones del artículo
Al final de la post puedes encontrar las críticas de otros desarrolladores, tú además eres capaz insertar el tuyo si te gusta.