Saltar al contenido principal

# 24.2: Un ejemplo práctico: conmutador Round-Robin

$$\newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} }$$

$$\newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}}$$

$$\newcommand{\id}{\mathrm{id}}$$ $$\newcommand{\Span}{\mathrm{span}}$$

( \newcommand{\kernel}{\mathrm{null}\,}\) $$\newcommand{\range}{\mathrm{range}\,}$$

$$\newcommand{\RealPart}{\mathrm{Re}}$$ $$\newcommand{\ImaginaryPart}{\mathrm{Im}}$$

$$\newcommand{\Argument}{\mathrm{Arg}}$$ $$\newcommand{\norm}[1]{\| #1 \|}$$

$$\newcommand{\inner}[2]{\langle #1, #2 \rangle}$$

$$\newcommand{\Span}{\mathrm{span}}$$

$$\newcommand{\id}{\mathrm{id}}$$

$$\newcommand{\Span}{\mathrm{span}}$$

$$\newcommand{\kernel}{\mathrm{null}\,}$$

$$\newcommand{\range}{\mathrm{range}\,}$$

$$\newcommand{\RealPart}{\mathrm{Re}}$$

$$\newcommand{\ImaginaryPart}{\mathrm{Im}}$$

$$\newcommand{\Argument}{\mathrm{Arg}}$$

$$\newcommand{\norm}[1]{\| #1 \|}$$

$$\newcommand{\inner}[2]{\langle #1, #2 \rangle}$$

$$\newcommand{\Span}{\mathrm{span}}$$ $$\newcommand{\AA}{\unicode[.8,0]{x212B}}$$

$$\newcommand{\vectorA}[1]{\vec{#1}} % arrow$$

$$\newcommand{\vectorAt}[1]{\vec{\text{#1}}} % arrow$$

$$\newcommand{\vectorB}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} }$$

$$\newcommand{\vectorC}[1]{\textbf{#1}}$$

$$\newcommand{\vectorD}[1]{\overrightarrow{#1}}$$

$$\newcommand{\vectorDt}[1]{\overrightarrow{\text{#1}}}$$

$$\newcommand{\vectE}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash{\mathbf {#1}}}}$$

$$\newcommand{\vecs}[1]{\overset { \scriptstyle \rightharpoonup} {\mathbf{#1}} }$$

$$\newcommand{\vecd}[1]{\overset{-\!-\!\rightharpoonup}{\vphantom{a}\smash {#1}}}$$

Necesitaremos tres variables para los estados, a saber, los estados de pulsador actual y anterior y otra para los LED (que indican la velocidad del ventilador). Los pulsadores pueden considerarse como variables booleanas (0/1) mientras que la variable LED oscilará entre 0 y 3, siendo 0 “apagada” y 3 “alta”. Por simplicidad, usaremos globals para estos, los caracteres sin firmar funcionarán muy bien. Los cuatro LEDs se posicionarán fuera de los pines 8 a 11 de Arduino Uno (PORTB. 0:3) y el pulsador se conectará al pin 12 (PORTB.4). La función setup () tendrá que establecer las direcciones adecuadas para estos bits de puerto. Esto requeriría cinco llamadas separadas a PinMode () pero solo dos operaciones simples si operamos directamente. Aquí está la porción inicial:

// declare the state variables and initialize at 0 for “off”
unsigned char currentstate=0;
unsigned char priorstate=0;
unsigned char ledstate=0;

// define some values for the LED/fan state. These are conveniently
// chosen to be the FAN/LED bit positions in PORTB
#define FAN_OFF     0
#define FAN_LO      1
#define FAN_MED     2
#define FAN_HIGH    3

// declare bit masks for the four LED bits and pushbutton
#define LED_OFF  0x01
#define LED_LOW  0x02
#define LED_MED  0x04
#define LED_HIGH 0x08
#define PBUTTON  0x10

// the LED_XXX masks could also be defined like so:
// #define LED_OFF (1<<FAN_OFF)

// a convenience
#define LED_ALL  (LED_OFF|LED_LOW|LED_MED|LED_HIGH)

setup()
{
// set for output
DDRB |= LED_ALL;
// set for input
DDRB &= ~PBUTTON;

// light up the “off” LED
PORTB |= LED_OFF;
// by default, outputs are 0 but if for some reason the other
// LEDs could be on, be sure to set them to off before continuing
// PORTB &= ~(LED_LOW|LED_MED|LED_HIGH);
}


El código de bucle necesita verificar el par correcto de estado/estado anterior actual. Si no se encuentra, no hay nada que hacer. Si se encuentra, necesitamos apagar el LED existente y luego verificar el estado actual del LED/ventilador, incrementar al siguiente estado y encender ese LED. Hay un par de formas de hacer esto. La primera es quizás una solución obvia usando una construcción de interruptor/caso. El segundo método es un poco más compacto (juego de palabras intencionado).

loop()
{
// get current button state
currentstate = PINB & PBUTTON;

// do we have a positive going edge?
if( currentstate && !priorstate )
{
switch( ledstate )
{
case FAN_OFF:
PORTB &= ~LED_OFF;    // turn off old LED
PORTB |= LED_LOW;     // turn on new
ledstate = FAN_LOW;   // increment speed
break;

case FAN_LOW:
PORTB &= ~LED_LOW;
PORTB |= LED_MED;
ledstate = FAN_MED;
break;

case FAN_MED:
PORTB &= ~LED_MED;
PORTB |= LED_HIGH;
ledstate = FAN_HIGH;
break;

case FAN_HIGH:
PORTB &= ~LED_HIGH;
PORTB |= LED_OFF;
ledstate = FAN_OFF;
break;
}
}

// update state for next loop iteration
priorstate = currentstate;
}


La versión alternativa se puede encontrar en la página siguiente. Tenga en cuenta el ahorro de código. En lugar de verificar el estado de cada ventilador, apagamos todos los LED e incrementamos el estado del ventilador. Si el estado se incrementara más allá del máximo entonces nos aseguramos de establecerlo en el estado apagado. Este nuevo estado nos dice qué LED encender. Esta versión funciona con poco código debido a la forma en que elegimos nuestras posiciones de bits. Esto no siempre es posible (o incluso deseable) pero puede ser una técnica práctica de vez en cuando.

loop()
{
// get current button state
currentstate = PINB & PBUTTON;

// do we have a positive going edge?
if( currentstate && !priorstate )
{
// increment to new state
if( ledstate < FAN_HIGH )
ledstate++;
else
ledstate = FAN_OFF;

// lazy: turn off all LEDs
PORTB &= ~LED_ALL;
// turn on new LED
PORTB |= (1<<ledstate);
}

// update state for next loop iteration
priorstate = currentstate;
}


This page titled 24.2: Un ejemplo práctico: conmutador Round-Robin is shared under a CC BY-NC-SA 4.0 license and was authored, remixed, and/or curated by James M. Fiore via source content that was edited to the style and standards of the LibreTexts platform; a detailed edit history is available upon request.