Using Arduino Uno for voltammetry

Hello all,

I'm fairly new to Arduino, so forgive any ignorance.

I'm working on a project where I need specific DC voltages ranging from [0, 1] in a 5mV interval. I've gotten this setup with generating a PWM signal with the corresponding voltages duty cycle and then using a low-pass filter to generate the DC value from the PWM. The problem I'm hitting is that it doesn't generate every value I need, i.e. it skips some values. For example, it will output 1v, .995v, and then jump to .975v instead of outputting .990v. I'm starting to think that it's just because of the rounding in the desired voltage -> duty cycle percentage conversion and maybe it's not possible to get all the values I need on this board. Any help/insight that you guys could provide would be much appreciated!

Here's the sketch I've been using:

int PWM_out_pin = 11; // Must be one of 3, 5, 6, 9, 10, or 11
double Veff = 0; //The DC voltage wanted at the output pin
double stepSize = .005;
void setup() {
  Serial.begin(9600);
  pinMode(PWM_out_pin, OUTPUT);
}

void loop() {
long double PWM_out_level;

for (Veff = 1; Veff >= 0; Veff = Veff - stepSize)
{
  PWM_out_level = (255/5)*Veff; // Code logic to set output level
  analogWrite( PWM_out_pin, PWM_out_level); // Write the desired voltage to the output pin
  delay(5000); // Hold the current voltage for 5 seconds
  Serial.println(Veff, 4);
}
}

Think about it: You're only using 51 different values in the analogWrite() function (255/5 is 51). You're never going to get the values you want that way.

Try setting up a resistor divider on the output of your filter to divide by five. That way you can use the full output range (0 to 255).

Next, go down from 255 to 0 in steps of 1, look at the output voltages. That's the best you can do with the Arduino PWM output. Whether it's good enough or not is up to you.

There are only 255 different steps meaning there is only 19.6mV of resolution.

The only way to get more resolution is to either rapidly switch between two PWM duty cycles or use feedback from the ADC to set the duty cycle.

I have made voltage regulators with some pass transistors and the latter method and could achieve 10mv precision over a wide load level.

For that sort of precision you should be looking at something like the MCP4821

It is controlled by SPI, and outputs a voltage at 12-bit resolution. That's either between 0 and 2047.5mv at 0.5mV steps, or between 0 and 4095mV at 1mV steps depending on settings.

Adafruit has an MCP4725 (I2C, 12bit) breakout for $5.

If you set timer1 to 10 bit mode you'll have 1024 PWM levels available to pins 9 and 10 (it goes up to 16 bits,
but that could make the cycle time very long. You will need to drive the timer1 registers directly to do this,
try searching for "TCCR1A" for posts about this.

There is also a library for more advanced use of timers I believe, it might help.