Ejecute su propio Arduino PWM

Pedro Molina
Pedro Molina

La mayoría de los proyectos se basan en abstracciones. En última instancia, pocos de nosotros podemos crear nuestro propio cable, nuestros propios transistores o nuestros propios circuitos integrados. Hace pocos meses, [Julian Ilett] encontró un problema al usar la biblioteca Arduino para PWM. Recientemente, revisó el problema y usó su propio código PWM para resolver el problema. Puedes ver el video a continuación.

Por supuesto, ni la biblioteca Arduino ni [Julian’s] el código en realidad produce PWM. El hardware de la CPU Atmel funciona. La biblioteca Arduino le ofrece un contenedor llamado analogWrite, especialmente útil si no está utilizando una CPU Atmel, donde la misma abstracción hará el mismo trabajo. El problema surgió cuando [Julian] rompió la abstracción para revertir la salida PWM.

El video enmarca muy bien el problema. Establecer el hardware PWM en cero todavía causa una salida de tick. Es decir, el cálculo real es el cálculo que proporciona más uno. Genial en el rango alto, donde 255 se trata como 256 de 256. Pero en el nivel bajo, cero contra intuitivamente le da 1/256. Los autores de la biblioteca Arduino optaron por detectar ese caso de borde y solo forzar el pin de salida a bajar en ese caso. Sin embargo, si se invierte, el pasador aún baja cuando es necesario levantarlo. Puede ver el código fuente responsable a continuación.

pinMode(pin, OUTPUT);
if (val == 0)
  {
  digitalWrite(pin, LOW);
  }
else if (val == 255)
  {
  digitalWrite(pin, HIGH);
  }
else
{ ...

Curiosamente, el caso 255 parece ser superfluo en el caso normal, pero también es al revés si revierte el resultado. Es cierto que la biblioteca de Arduino no le brinda una forma de revertir el resultado, por lo que ya ha roto la abstracción y es por eso que técnicamente no es un error en la biblioteca.

[Julian’s] el código es bastante simple. Existe una disposición inicial de los registros TCCR1A y ​​TCCR1B junto con ICR1. El registro DDRB establece el pin como salida. Después de eso, escribir en OCR1A y ​​OCR1B establece el valor de PWM. El video explica todo con gran detalle.

Hemos analizado PWM en FPGA al menos una vez, y esa publicación brinda algunos antecedentes sobre PWM en cualquier aplicación. También tenemos nuestro propio video de 2011 en PWM.

  • jhnopisdop dice:

    ¿Artículo para la señal PWM de impacto de bits? ¿En serio?

    • Vadear dice:

      No muerde, usa hardware PWM.

      • Pensador dice:

        ¿Cómo estableces la frecuencia (o la perdí)?

        • Dax dice:

          La frecuencia se establece con otro registro, que establece la división de frecuencia entre el reloj del sistema y el temporizador / calculadora utilizado para generar la señal PWM.

          Luego, hay otras cosas que puede hacer, como cuál es el número más alto que calcula la calculadora antes de reiniciarse, o si calcula hacia arriba y hacia abajo para crear una forma de onda simétrica donde la diferencia de fase entre dos canales PWM permanece constante, etc. que no está disponible con la función de escritura analógica arduine.

      • Nathan McCorkle dice:

        El artículo parece contradecirse … al principio dice “no [Julian’s] el código en realidad produce PWM. “entonces definitivamente se trata de registros periféricos de temporizador (hardware PWM) … al menos estoy confundido

        • Vadear dice:

          Vi el video original el otro día, usa los temporizadores. La redacción del artículo es pedante sin ninguna razón en particular.

        • Al Williams dice:

          Lo que significa que no está un poco atascado. El código no produce PWM algorítmicamente.

  • Andrés dice:

    Simplemente use un micrófono moderno con mucho PWM …
    O mejor aún, use PSoC, que facilita hacer lo que quiera.

    • Ene. dice:

      o simplemente agregue (usando I2C) PCA9685, que le brinda 16 canales PWM con una resolución de 12 bits cada uno.

      La resolución PWM de 12 bits le permite implementar el controlador PWM como un controlador de servicio de 16 canales, simplemente configure los valores cíclicos y repetidos requeridos en los rangos correctos y estará listo para comenzar. Lo usé muchas veces para crear múltiples señales de servicio sin problemas en un microcontrolador con un resultado de cálculo bajo.

      • Peso dice:

        ¡Gracias por el consejo de PCA9685!

  • Ragnar dice:

    ¡Muy buen hallazgo!

  • Septilion dice:

    La manera difícil es simplemente terminar

    invertedAnalogWrite(byte pin, byte val){
      if(val == 255){
        analogWrite(pin, 0);
      }
      else if(val == 0){
        analogWrite(pin, 255);
      }
      else{
        analogWrite(pin, val);
      }
    }

    Y eso es lo que le dije entonces …

    • Al Williams dice:

      ¿No le gustaría 256-val en la última escritura analógica? ¿O crees que todavía lo está revirtiendo afuera? Si hiciera ese cambio, simplemente se voltearía y tendría que ser portátil para cualquier cosa que tenga un rango de 0-255 PWM conectado a analogWrite. De hecho, si lo ha hecho, tampoco necesita el primero. Algo como:

      if (val) analogWrite (pin, 256-val) else analogWrite (pin, 255);

    • Dax dice:

      Tal vez el punto no sea solo invertir los valores, sino invertir la forma de onda para que sea inexacta con otro canal.

      Considere, por ejemplo, si coloca un pequeño motor de CC entre dos pines de salida y los opera a un ciclo de trabajo del 50% en una fase opuesta. ¿Que esta pasando? Ahora bien, ¿qué sucede si el ciclo de trabajo cambia al 20% o al 80%?

      Es un controlador de velocidad reversible por hardware.

  • Nathan McCorkle dice:

    ¿Cómo es esta noticia? La página de hardware PWM “Arduino” ha existido durante al menos 5 años:
    https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM

  • Jaime dice:

    La razón del control 0/255 es simplemente que usando Fast PWM no puede ir a cero cuando dice que está usando LED debajo de PWM que no va a cero, es muy notable, en realidad es un pulso ruso, según recuerdo (no completo 1/256) cuando el contador llega a cero. No necesitaban verificar 255, pero sea lo que sea, hay muchas cosas en el kernel de Arduino que no son necesarias.

    Pero los desarrolladores de Arduino (cableado tal vez, esto es algo antiguo) podrían resolver esto fácilmente de manera mucho más eficiente simplemente usando el modo Fast PWM invertido en lugar de no invertido. Entonces, en lugar de “no estar completamente al 100% de descuento”, obtienes “no estar completamente al 100%”, esto es menos difícil en casi todas las situaciones, es muy difícil notar cuando algo no está completamente al 100%, pero es muy fácil darse cuenta, cuando algo no está completamente descontado al 100%.

    Por supuesto, no requiere la intervención del codificador si analogWrite solo invierte el valor que se le asigna, de modo que 255 se convierte en 0 cuando se opera en modo inverso. Hice exactamente eso en una bifurcación ATTInyCore para el Tiny 4/5/9/10, donde cada byte que puedo almacenar importa.

  • Hardware dice:

    Extraigo el programa más fácilmente porque la memoria es casi libre y los codificadores se han convertido en una mercancía. Ya no vale la pena aprender a codificar.

  • Y nodo dice:

    Básicamente, una gran solución para algunos se me ocurrió el código.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *