¿Vieron esas situaciones en que realmente quieren prender dos pines del Arduino (poner en alto, ejem…) pero al mismo tiempo, onda, sin ningún retraso pero posta posta? ¿Nunca les pasó?
Bromas aparte, vamos a realizar un caso hipotético en el que quiero prender y apagar al mismo tiempo, dos leds conectados a los pines 2 y 3 (ya resuelta la electrónica, claro, ¡led con sus resistencia!). Con referencia al programa (código) en la IDE de Arduino seria algo como:
void
setup
() {
// Ponemos los pines 2 y 3 como salida
pinMode
(
2
,
OUTPUT
);
pinMode
(
3
,
OUTPUT
);
}
void
loop
() {
//Predemos y esperamos
digitalWrite
(
2
,
HIGH
);
digitalWrite
(
3
,
HIGH
);
delayMicroseconds
(
1000
);
//Apagamos y esperamos
digitalWrite
(
2
,
LOW
);
digitalWrite
(
3
,
LOW
);
delayMicroseconds
(
1000
);
}
¡La lógica es inapelable! prendo + prendo + espero + apago + apago + espero + repito el ciclo…
¿Qué
sucede con esto? Voy a armar un protoboard con unos leds y...
¡Y
claro, prenden y apagan al mismo tiempo! Probemos, midamos, hagamos:
voy a usar el osciloscopio para sacarme las dudas y voy a conectar
cada canal a un led.
En cada canal existe, según la medición, un microsegundo (cada división vertical equivale a un microsegundo) entre su estado bajo y su estado alto (prendido y apagado) con lo cual, no prenden y apagan los leds al mismo tiempo: hay un problema…
En algunos casos, yo necesito que ambos pines cambien su estado al mismo tiempo. Puedo solucionarlo usando el mismo pin para ambos leds, agregar un transistor, etc. Pero esto se puede solucionar por programación:
void
setup
() {
// Setear el puerto de pines 8 al 0 como salida, sin tocar los modos pre-existentes
DDRD
=
DDRD
|
0B00001100
;
}
void
loop
() {
// Escribir todos los pines al mismo tiempo
PORTD
=
DDRD
|
0B00001100
;
delayMicroseconds
(
50
);
// Poner todos los pines en cero
PORTD
=
0B00000000
;
delayMicroseconds
(
50
);
}
¡Ahora si!
¡Poco intuitivo este blink Marcelo! Pero los pines cambian de estado al mismo tiempo, menos de un microsegundo desde su estado bajo hasta su estado alto.
Vamos a ver el tema del código, porque es medio inentendible:
void
setup
() {
// Setear el puerto de pines 8 al 0 como salida, sin tocar los modos pre-existentes
DDRD
=
DDRD
|
0B00001100
;
}
Lo que hice acá fue, usando la manipulación directa del puerto D (el puerto es el conjunto de pines, en este caso, del 0 al 7) definir pines 2 y 3 como salida.
void
loop
() {
// Escribir todos los pines al mismo tiempo
PORTD
=
DDRD
|
0B00001100
;
delayMicroseconds
(
50
);
// Poner todos los pines en cero
PORTD
=
0B00000000
;
delayMicroseconds
(
50
);
}
Usando la misma técnica de manipulación directa del puerto, prendo (1) y apago (0) dos pines específicos, con su tiempo de espera correspondiente.
La manipulación directa de los puertos es una técnica usada en la programación avanzada de Arduino (y de microcontroladores en general) y también se la llama » bare metal manipulation» o «port manipulation»
De hecho, en la referencia de Arduino se habla de este tema.
Si bien este es un caso hipotético de poca utilidad en el mundo real, existen varias aplicaciones, entre ellas, hacer un rudimentario generador de onda sinusoidal...
¡A divertirse y probar, que Arduino es para eso!