This project uses the Arduino PWM Uno or other systems to realize a fully isolated analog output with a range of 0-5 volts or more, changing only the reference voltage.
Introduction
This project completes the series of my articles about the Arduino analog I/O with the aim to use it as a controller of small automation systems.
In control systems of the industrial plants it is always advisable to isolate both the inputs and the outputs coming from the field. This prevents disturbances caused by power surges, lightning strikes or other EMI sources and also by ground potential differences.
Arduino Uno, or systems based on the ATmega328 chip has no a true analog output, but it may be realized using a PWM output averaged with a low-pass filter.
The use of an averaged PWM signal with 8-bit setting is not comparable with a real DAC, but in the insulation case presents undoubted advantages of simplicity since it is sufficient to use an optocoupler for isolating the PWM digital signal. Recently I designed another circuit to generate a 4-20 mA current with Arduino, that experience gave me the idea for this new project.
The Arduino PWM
Arduino Uno has several pins (3, 5, 6, 9, 10, and 11) that can be configured for PWM output. For this project I used pin 9 because the others were used by various devices (LCD, SD and RTC) in my Arduino system.
The PWM signal on pins D9 and D10 is generated by Timer# 1 of ATmega328. It has a prescaler which divides by 1, 8, 64, 256, 1024, controlled by the three least significant bits of the register TCCR1B. The default value of the prescaler set by the Arduino IDE is equal to Np= 64 (TCCR1B, bits 2-0= 110), which provides an output frequency:
PWM frequency = CPUClock/(2´Np´TOP) = 16000000/(2´64´255)= 490.196 Hz
Where the TOP value is he maximum Timer/Counter value.
The following table shows the frequencies generated by Timer# 1 of an Arduino Uno (Atmega 328) on pins 9 and 10, with a 16 MHz clock and in “phasecorrect PWM” mode. In this mode, the timer counts from 0 to 255 and then back down to 0.
Prescaler divider (Np) | Prescaler code | PWM frequency |
1 | B001 | 31372.549 |
8 | B010 | 3921.569 |
64 | B011 | 490.196 |
256 | B100 | 122.549 |
1024 | B101 | 30.637 |
The prescaler code must be put in the three least significant bits of the register TCCR1B – Timer/Counter1 Control Register B. For example, to generate a PWM of 3921 Hz, the following instruction must be inserted in the setup function:
For more detail: An isolated analog output for Arduino Uno