Saltar al contenido principal
LibreTexts Español

9.3: Salida LED

  • Page ID
    83112
  • \( \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}}\)

    Ahora que se ha verificado el sensor y la función de entrada analógica, combinemos esto con una pantalla LED. En lugar de imprimir valores en el Monitor Serial, encenderemos una cadena de LEDs. Esto requerirá código de salida digital (escritura) tal como se exploró en un ejercicio previo. Para mantener el esfuerzo simple y simplemente mostrar “prueba de concepto”, encenderemos hasta cuatro LEDs. Cada LED requerirá un circuito controlador de transistor apropiado (o considere una matriz de controladores Darlington como el ULN2003 que contiene siete controladores en un solo IC). Utilizaremos los cuatro bits inferiores del puerto B para las señales de salida, pines Arduino 8 a 11. Considera el siguiente código:

    /* Read analog V2. Uses FSR (lower) and 10k (to +5V) on pin A0. Lights 4 LEDs
     off of port B.0:3 to indicate force. Active high drivers. */
    
    #define ANALOG_IN_PIN 0
    
    // These are the bits to be used on port B for the LEDs
    #define LEDMASK0      0x01
    #define LEDMASK1      0x02
    #define LEDMASK2      0x04
    #define LEDMASK3      0x08
    #define LEDMASK       (LEDMASK0 | LEDMASK1 | LEDMASK2 | LEDMASK3)
    
    void  lightLEDsBar( int a );
    
    int prior=0;
    
    void setup()
    {
      Serial.begin(9600);
      analogReference( DEFAULT );
      // set LED driver bits to output mode
      DDRB |= LEDMASK;
    }
    
    void loop()
    {
      int a;
    
      a = analogRead( ANALOG_IN_PIN );
      if( a != prior )
      {
        Serial.println(a);
        lightLEDsBar( a );
        prior = a;
      }
    }
    
    void  lightLEDsBar( int a )
    {
    
      if( a > 820 )
        PORTB |= LEDMASK; // light everything
      else
      {
        if( a > 615 )
        {
          PORTB &= (~LEDMASK3); // extinguish top
          PORTB |= (LEDMASK2 | LEDMASK1 | LEDMASK0); // light everything below
        }
        else
        {
          if( a > 410 )
          {
            PORTB &= (~(LEDMASK3 | LEDMASK2));
            PORTB |= (LEDMASK1 | LEDMASK0);
          }
          else
          {
            if( a > 205 )
            {
              PORTB &= (~(LEDMASK3 | LEDMASK2 | LEDMASK1));
              PORTB |= LEDMASK0;
            }
            else
              PORTB &= (~LEDMASK);
          }
        }
      }
    }
    

    De interés principal aquí es el requisito de inicializar DDRB para la salida en bits 0:3 que se utilizará para accionar los LEDs. Se definen máscaras de bits separadas para cada pin de salida para facilitar el mantenimiento del código. Se ha creado una nueva función para manejar las tareas de iluminación, LightLedsBar (). Esta función creará un gráfico de barras basado en el valor del argumento que se le haya pasado. Como hay cuatro LEDs, podemos dividir el rango 1024 en cinco segmentos. Si el valor está por debajo del 20% (aproximadamente 205) no se encienden los LEDs. Si está entre 20% y 40% solo se enciende el LED más bajo. A medida que aumenta el valor se encienden más LEDs hasta que, al 80% o más, se encienden todos los LEDs. La función es poco más que una gran cascada si/else. En cualquier región dada primero se apagan los LEDs superiores y luego se encienden los ledes restantes de abajo. Tenga en cuenta que la técnica anterior es más eficiente que usar la función digitalWrite () porque podemos establecer el estado de varios bits a la vez accediendo directamente a PORTB. En contraste, DigitalWrite () requeriría una llamada por cada bit/LED. El código Serial Monitor se ha dejado adentro para que pueda monitorear los resultados para asegurarse de que todo esté funcionando correctamente.

    Al dejar el FSR en su lugar, conecte cuatro controladores LED a los pines Arduino 8 a 11. Una corriente LED de 10 miliamperios debería ser suficiente. Ingresa el código anterior, compilarlo y transferirlo. Para probar, simplemente abra el Serial Monitor y presione el FSR. A medida que aumenta la fuerza, los valores en el Monitor Serial deberían disminuir y deberían encenderse menos LEDs. Se puede pensar en esto como un medidor de “ausencia de fuerza”. Si bien esto puede sonar al revés, puede ser bastante útil. Hay momentos en los que queremos que algo esté bajo presión y la falta de fuerza sirve como advertencia (es decir, más LEDs encendidos significa un problema mayor).

    A veces se dispone una cadena de LEDs para imitar un medidor analógico. En tal caso, podríamos desear solo encender un solo LED en lugar de todos los LEDs debajo de él. Podríamos llamar a esto “modo punto” versus “modo barra”. La versión tres del programa muestra el modo punto con un giro interesante. Además, se ha eliminado el código Serial Monitor. Tenga en cuenta la disminución en el tamaño del programa.

    /* Read analog V3. Uses FSR (lower) and 10k (to +5V) on pin A0. Lights 4 LEDs 
    off of port B.0:3 to indicate force. Dot display mode. Active high drivers. */
    
    #define ANALOG_IN_PIN 0
    
    // These are the bits to be used on port B for the LEDs
    #define LEDMASK0      0x01
    #define LEDMASK1      0x02
    #define LEDMASK2      0x04
    #define LEDMASK3      0x08
    #define LEDMASK       (LEDMASK0 | LEDMASK1 | LEDMASK2 | LEDMASK3)
    
    void  lightLEDsDot( int a );
    
    int prior=0;
    
    int thresh[] = {820, 615, 410, 205};
    void setup()
    {
      analogReference( DEFAULT );
      DDRB |= LEDMASK;  // set LED driver bits to output mode
    }
    
    void loop()
    {
      int a;
    
      a = analogRead( ANALOG_IN_PIN );
      if( a != prior )
      {
        lightLEDsDot( a );
        prior = a;
      }
    }
    
    void  lightLEDsDot( int a )
    {
      int *p;
      p = thresh;
    
      if( a > *p++ )
      {
        PORTB &= (~(LEDMASK2 | LEDMASK1 | LEDMASK0)); // turn off bottom 3
        PORTB |= (LEDMASK3);                          // light only topmost
      }
      else
      {
        if( a > *p++ )
        {
          PORTB &= (~(LEDMASK3 | LEDMASK1 | LEDMASK0));
          PORTB |= (LEDMASK2);
        }
        else
        {
          if( a > *p++ )
          {
            PORTB &= (~(LEDMASK3 | LEDMASK2 | LEDMASK0));
            PORTB |= LEDMASK1;
          }
          else
          {
            if( a > *p )
            {
              PORTB &= (~(LEDMASK3 | LEDMASK2 | LEDMASK1));
              PORTB |= LEDMASK0;
            }
            else
              PORTB &= (~LEDMASK);
          }
        }
      }
    }
    

    La variante Dot es similar a la versión Bar excepto que todos los LED se apagan con la excepción del LED único “top most”. Quizás se pregunte por qué nos metemos en la molestia de extinguir los bits individuales afectados en lugar de simplemente configurarlos todos en off (ANDing con 0xf0) y luego poner el bit deseado encendido. La razón es porque esto podría crear un encendido/apagado rápido del bit deseado “top most”. En esta aplicación probablemente nunca verás la diferencia pero puede haber aplicaciones donde esta alternación puede ser un problema. En cualquier caso, la cantidad total de código de máquina generado es aproximadamente la misma de cualquier manera.

    La alteración más interesante de la función es que se utiliza una matriz de valores para los umbrales en lugar de valores fijos codificados. Esto hace que el programa sea mucho más flexible en caso de que se requieran otros niveles en el futuro. Para usar un conjunto diferente de umbrales, todo lo que se necesita hacer es una asignación de puntero a la base de la matriz de umbrales apropiada al inicio de la función. También, tenga en cuenta en particular el uso del operador post-incremento en el puntero p. Esto es generalmente más eficiente que el método típico de indexación de matrices.


    This page titled 9.3: Salida LED 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.