PWM as analog output

In the introduction we talked about the average value of a PWM signal. That average can be considered an analog value for the signal as long as the frequency is high enough that the circuits do not notice it. Many circuits will have voltage regulators to compensate for the variations on the input and in that case it will be in fact an analog output. This analog value is directly proportional to the duty cycle.

Since we only have one PWM available we will use a single color LED to visually understand how analog outputs work. In the case of the LED, the intensity of the brightness will be proportional to the value of the duty cycle.

We will use a red LED for this example, connected as shown in the following diagram. We connect the LED to the PWM pin, add a 330 Ω resistor to take care of the extra voltage, and then we connect again to ground. A mini breadboard should be enough to do this circuit:

We could use this same circuit to blink the LED using GPIO, but, since it is connected to PWM, it will allow us to modify the voltage, which will have an impact on the intensity of the current passing through the resistor and hence on the intensity of the LED.

For this example, we will make the LED oscillate following a sinusoid signal. Let's look at the code:

class LedBrightnessActivity: Activity() {

private val initialTime = System.currentTimeMillis()
private lateinit var pwm: Pwm
private val handler = Handler()

private val ledRunnable = object : Runnable {
override fun run() {
val currentTime = System.currentTimeMillis()
val elapsedSeconds = (currentTime - initialTime) / 1000.0
val dutyCycle = Math.cos(elapsedSeconds) * 50.0 + 50
pwm.setPwmDutyCycle(dutyCycle)
handler.post(this)
}
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

val pm = PeripheralManager.getInstance()
pwm = pm.openPwm(BoardDefaults.servoPwm)

pwm.setPwmFrequencyHz(50.0)
pwm.setEnabled(true)

handler.post(ledRunnable)
}

override fun onDestroy() {
super.onDestroy()
handler.removeCallbacks(ledRunnable)
pwm.close()
}
}

Inside onCreate we open the PWM using PeripheralManager, set the frequency to 50 Hz, and enable it. A frequency of 50 Hz is enough for the LED to assimilate the voltage as an average instead of a square wave. As usual, we have our cleanup code inside onDestroy.

Once again, remember that while the duty cycle has a default value, the frequency does not, and it must be set before calling setEnabled, otherwise the system will throw an exception.

In the same way as other examples in this book, we use a handler and a runnable to take some code and run it continuously without blocking the main thread.

The runnable itself calculates the value of the voltage based on a cos function with the center at 50%. The value of the duty cycle is shown in the following diagram. Note that the unit of x is radians:

When we run this example, we can see how the intensity of the LED fluctuates following the timing of this chart, proving that PWM indeed works as an analog output.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.252.140