PWM, DAC, and timers on the ATtiny

miniMO’s brain is an Atmel AVR ATtiny85. This guide explains how to use ATtiny’s timers to create a train of pulses of variable width, itself translated into sound via a digital-to-analog converter.

  • DAC stands for Digital to Analog Converter, that is, a device that converts a series of discrete (individual) binary data items to continuous voltage
  • PWM stands for Pulse Width Modulation, that is, changing the width of a pulse over time
    • A pulse is a wave that looks like a rectangle. Narrow pulses are much taller than they are wide; a pulse as tall as it is wide is a square wave
  • Some MCUs (short for Micro Controller Units) include DACs in their designs, but not the ATtiny85, or my Arduino for that sake
    • These MCUs do include timers, which count from 0 to a value
      • If the timer is 8 bit-based, it counts from 0 to a maximum of 255, for 256 possible values
      • If the timer is 16 bit-based, it counts from 0 to 65535
    • The timers can count at various speeds, ratios of the speed of a reference clock, each set using a prescaler
      • Usually the reference for their ticking is the processor speed, say 8 MHz (8 million Herzts, or ticks per second)
      • You can use timers to generate pulses, and you can set the width of each pulse
      • You can use timers to interrupt the processor once they reach a certain value, and force an activity
  • If an MCU doesn’t feature a DAC, you can still make one using its timers
    • Imagine several cycles of a Pulse wave, each with different widths
    • Now rotate each one 90 degrees so that in your mind they look like brackets of various heights:  ]]]]]]]]]]]]]]]]]]]]]]]]
    • What was the width of the pulses is now the value of something else
    • The “something else” is the output of the DAC
      • If you generate the base pulses fast enough (the faster the better), it is easy to filter their heights out (their heights before you rotated them in your mind!)
        • The simplest filter is made of  a condenser and a resistor
        • What persists are the pulses’ widths (again, their widths before the mind exercise), expressed as output voltages
      • In a nutshell, you use the PWM to make a DAC
    • Some timers feature “fast PWM”, twice as fast as regular PWM and therefore able to give twice the resolution, which is why ATMEL recommends to use it for DAC applications. Their reference is still the processor speed, say 8 or 16 MHz
      • Arduino can do fast PWM
      • The ATtiny85’s timer0 can also do fast PWM
    • Some MCUs give you the ability to link a timer to the PLL (Phase-Locked Loop) clock, which runs at 32 or 64 MHz
      • This is faster than the fast PWM
      • The ATtiny85’s timer1 is one of those MCUs
  • Once you have a DAC, you can generate arbitrary signals with it, including audio waves
    • A wavetable describes a period (a complete cycle) of a wave as an array of values
      • If you feed those values over time to the base pulse, the output will be the wave
    • The faster you generate the base pulse, the better the resolution
      • With the ATtiny85, I use timer1 linked to the 64Mhz PLL
    • The faster you feed the base pulse timer with the values in the wavetable, the higher the frequency of the resulting wave
    • How do you feed the base pulse timer with values? Using interrupts
      • You set a timer to generate interrupts
        • The same timer can both generate the base pulses, and the interrupts
        • You can make an interrupt happen whenever the timer reaches the maximum value
          • That’s an Overflow, and if your timer is 8 bit and counting up it will happen when it reaches 255
        • You can make an interrupt happen whenever the timer reaches any value between 0 and a value of your choice, up to 255
          • That’s a Compare Match
      • When the timer generates an interrupt, The MCU pauses whatever it was doing and executes the code within the corresponding ISR
        • ISR is short for Interrupt Service Routine
      • After the code in the ISR is executed, the MCU resumes its former activity
        • It’s advisable to keep the code within the ISRs as short as possible
      • Within the interrupt, you can set the pulse width to advance through the wavetable one step at a time, producing your wave
        • Changing the interruption speed goes through the wavetable faster, thus changing the frequency of the output wave
          • It also has the potential to alter the base time for any delay you use in code, if it depends on the same timer
            • If you keep it constant you can compensate for the change
        • You can also set the pulse length to advance through the wave table skipping steps
          • This is a phase accumulator
          • The more steps you skip, the faster you go through the cycle, thus changing the frequency of the output wave
      • As an aside, there are several Interrupt Vectors (events that trigger interrupts), organized on a hierarchy
        • A Pin Change interrupt is more important than timer-related interrupts
          • The Pin Change will trigger its related interruption even if a timer-related interrupt is already happening
          • You can use the Pin Change interrupt to track button presses accurately and reliably

To put these things in context, you can take a look at the DCO sketch in the repository. I will add links to several information sources in the links section of the site.

The information above is to my knowledge correct, but if it is not, please me tell me so and I’ll amend it. Also, there are still a few things that I can’t understand, such as why if I generate both PWM and interrupts using timer 1 I don’t get higher frequencies out of the DCO. Even so, I’m certain I took the right choices when deciding on the timer and outputs, and I’m not concerned anymore that the ATtiny only does fast PWM in pins 0 and 1, because, you know, it also does High Speed PWM in pin 4 ^_^

Posted in Blog, Tutorials and tagged , , , , .

3 Comments

    • Hi! you can buy a miniMO from this site, or you can take a look at the github repository where you’ll find all the schematics and parts to make one from scratch.
      –now in spanish–
      Hola! puedes comprar un miniMO desde esta página, o puedes ir al repositorio de github, donde está publicada toda la información sobre la placa y componentes, para hacer uno por tu cuenta 🙂

  1. Pingback: Programming a MiniMO Synth | Kevin's Blog

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.