Automated Electrochemistry Setup
by Onyx Ibex in Circuits > Assistive Tech
5117 Views, 21 Favorites, 0 Comments
Automated Electrochemistry Setup
This is a guide for how to fix an electrochemistry instrument for performing cyclic voltammetry and rotating disc electrode techniques. The instrument modification I am demonstrating is very particular to a specific instrument but the modification device can be used in a multitude of different applications. The basic operating principle is to output a controlled variable voltage from our microcontroller (a simple task). A similar controller can be expensive if bought (between $60 and $300 is what this company wanted), or you can make it yourself for about $1.
A little background: The lab group that I am working in has an electrochemistry setup for doing all sorts of analysis but one of the outputs from the instrument does not correctly transmit the signal to determine how fast of of the motors turns for use in rotating disc analysis. As the name suggests, rotation is a crucial component and not rotating correctly can destroy all of your data. On the instrument it is possible to dial-in to a specific rotation speed with a dial, but this is hard to reach and it is very sensitive, making it hard to get exactly correct. After several attempts to fix the communication to the motor controller, I decided to make a makeshift speed controller.
What it is: This is essentially a variable DC voltage supply or square wave pulse generator if you decide to tweak it slightly. It acts as a speed controller for our electrochemistry setup because the (un-communicative) motor controller in our lab accepts DC voltage as an input that it can (if calibrated) directly translate into RPM of the motor. The overall function of the circuit will be to produce a voltage for a set amount of time (the experiment length) and then to switch to a different voltage for the next experiment and continue repeating this for all experiments. In the electrochemical experiments I am performing, the higher the rplm of the motor, the greater the diffusion of the solution onto the material becomes, so this is a technique to observe efficiency while base-lining out the effect of diffusion. If you are curious as to what this type of electrochemistry experiment is, you can read more about it here: Electrochem wiki.
A little background: The lab group that I am working in has an electrochemistry setup for doing all sorts of analysis but one of the outputs from the instrument does not correctly transmit the signal to determine how fast of of the motors turns for use in rotating disc analysis. As the name suggests, rotation is a crucial component and not rotating correctly can destroy all of your data. On the instrument it is possible to dial-in to a specific rotation speed with a dial, but this is hard to reach and it is very sensitive, making it hard to get exactly correct. After several attempts to fix the communication to the motor controller, I decided to make a makeshift speed controller.
What it is: This is essentially a variable DC voltage supply or square wave pulse generator if you decide to tweak it slightly. It acts as a speed controller for our electrochemistry setup because the (un-communicative) motor controller in our lab accepts DC voltage as an input that it can (if calibrated) directly translate into RPM of the motor. The overall function of the circuit will be to produce a voltage for a set amount of time (the experiment length) and then to switch to a different voltage for the next experiment and continue repeating this for all experiments. In the electrochemical experiments I am performing, the higher the rplm of the motor, the greater the diffusion of the solution onto the material becomes, so this is a technique to observe efficiency while base-lining out the effect of diffusion. If you are curious as to what this type of electrochemistry experiment is, you can read more about it here: Electrochem wiki.
Instrument and Materials Needed
The instrument our lab uses is made by Pine Instruments and the software is called AfterMath. This ible will focus on these instruments but is simple enough that it could be applied to any use.
First off, the datasheet for the instrument we will be interfacing with: User Manual
Components needed:
First off, the datasheet for the instrument we will be interfacing with: User Manual
Components needed:
- Either and Arduino or any microcontroller (I use an ATtiny85 chip, so the code will work for that)
- Button for reset
- Jumper cables / banana plugs / alligator clips / wires of any sort
- [optional if going the 555 method]
- 555 timer IC
- resistors
- capacitors
If you are having trouble with coding the microcontroller and you are finding that it just isn't producing the correct timing, consider using an astable 555 circuit to give out a constant pulse as close as you can to 1Hz (or whatever you choose). The next step will focus just on this.
Circuitry
I had 2 ideas for how to do this that I was willing to try and to see which was better. One method used a 555 timer to produce a 1Hz pulse that would be counter by the microcontroller to decide when to switch to the next mode. The other method was to just use the internal timers on the microcontroller. This was new for me to rely on the internal timers and they ended up being a lot less accurate with just the MCU on its own. This is because I had decided to use the PWM output to create an analog output and thus would not be able to use simultaneous delay functions.
For the astable 555 circuit method you need a 555 chip, any microcontroller, and a selection of resistors and capacitors (it helps to have a bunch to play around with because this is one of those cases where the tolerances on your resistors makes a difference!)
The circuit shown should produce a 1Hz signal with the values shown. A very handy calculator for the frequency can be found here: 555 calculator. I found that a convenient value to achieve 1Hz is as follows: R1=33k, R2=55.65k, C1=10uF. There are many combinations, but this one allowed me to use the resistors I had extra of (using series / parallel combinations).
If you want to calculate it by hand, you can find the frequency, f, can be found by: f = 1/(ln(2)*C1*(R1+R2)). R1 controls the HIGH pulse time, while R2 controls both HIGH and LOW pulse times.
You would then need to design the code to increment with every pulse input.
A much better way to approach this is to use the internal timers on the microcontroller itself. I used an ATtiny85 microcontroller because they are cheap and I have many sitting around for stuff like this. We will use pins for Power, GND, Reset, and PWM output. That leaves a lot of room for other functionality if you want it.
Use the pinout of the microcontroller to determine the circuitry. I used PB1 (pin 6, labelled as "pin 1 (PWM, MISO)" on the diagram below). I was originally going to use RC filters to smooth the output but I found it was not needed.
For the astable 555 circuit method you need a 555 chip, any microcontroller, and a selection of resistors and capacitors (it helps to have a bunch to play around with because this is one of those cases where the tolerances on your resistors makes a difference!)
The circuit shown should produce a 1Hz signal with the values shown. A very handy calculator for the frequency can be found here: 555 calculator. I found that a convenient value to achieve 1Hz is as follows: R1=33k, R2=55.65k, C1=10uF. There are many combinations, but this one allowed me to use the resistors I had extra of (using series / parallel combinations).
If you want to calculate it by hand, you can find the frequency, f, can be found by: f = 1/(ln(2)*C1*(R1+R2)). R1 controls the HIGH pulse time, while R2 controls both HIGH and LOW pulse times.
You would then need to design the code to increment with every pulse input.
A much better way to approach this is to use the internal timers on the microcontroller itself. I used an ATtiny85 microcontroller because they are cheap and I have many sitting around for stuff like this. We will use pins for Power, GND, Reset, and PWM output. That leaves a lot of room for other functionality if you want it.
Use the pinout of the microcontroller to determine the circuitry. I used PB1 (pin 6, labelled as "pin 1 (PWM, MISO)" on the diagram below). I was originally going to use RC filters to smooth the output but I found it was not needed.
Code
After trying very hard to get my code to work properly, I eventually gave into the external-calibration-with-meaningless-numbers method :) By this I mean to say that you don't have to understand what the code does if you don't want to, simply change a value and observe its effect on either output voltage or duration. I will discuss calibration in the next step.
There are 2 variables that I want you to look at before going to the next step, those are the experiment times (t_25, t_16, t_9, t_4, and t_1) and the duty cycle on times (the number in the first _delay_ms() call in each for loop)
The code was written in Atmel Studio. To upload the code, I used avrdude. Both are free. Using avrdude, you can upload the hex file included inside the zip folder attached to this step using the following line in the command prompt after you navigate to the correct folder:
avrdude -c usbtiny -p t85 -U flash:w:rde2.hex
Using an arduino would make this a lot easier but more expensive. On an arduino you have an AnalogWrite() function that would simplify a lot of this. The flow would then become AnalogWrite(voltage_desired) --> delay(experiment_time) --> repeat...
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 800000UL
float t_25, t_16, t_9, t_4, t_1; // float type is unnecessary but I have plenty of memory
int main(void)
{
//pre-set for 1V domain @ 5mV/s rate. Change if your experiment is different.
t_25 = 207*207000/(2.1920*227); // 207000 is the experiment length in milliseconds
t_16 = 207*207000/(1.5580*227); // 207/227 is a calibration constant
t_9 = 207*304000/(1.2585*227); // 2.1920, 1.5580, etc are the lengths of the for loops corresponding to that part of the experiment
t_4 = 207*304000/(1.1000*227);
t_1 = 207*304000/(1.0220*227);
// set output pin
DDRB |= (1 << DDB0) | (1 << DDB1);
// fast PWM mode, wave form generation bit [1:0]
TCCR0A = (1 << COM0A1) | (1 << WGM00) | (1 << WGM01);
// waveform bits [2], prescalar 1024
TCCR0B = (1 << WGM02) | (1 << CS02) | (1 << CS00);
// output compare register
OCR0A = 0;
for(float t=0; t<t_25; t++)
{
PORTB |= (1 << PB1);
_delay_ms(1.192); // this defines the duty cycle and thus the analog voltage output
PORTB &= ~(1 << PB1); // a larger value gives a larger duty cycle and thus higher voltage
_delay_ms(1); // the 1 ms (off) delay is chosen arbitrarily
}
for(float t=0; t<t_16; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.558);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_9; t++)
{
PORTB |= (1 << PB1);
_delay_ms((0.2585));
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_4; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.1);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_1; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.022);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
while(1) // end state
{
PORTB |= (1 << PB1);
_delay_ms(0);
PORTB &= ~(1 << PB1);
_delay_ms(600000); // 10 mins to avoid noise on the line
}
}
There are 2 variables that I want you to look at before going to the next step, those are the experiment times (t_25, t_16, t_9, t_4, and t_1) and the duty cycle on times (the number in the first _delay_ms() call in each for loop)
The code was written in Atmel Studio. To upload the code, I used avrdude. Both are free. Using avrdude, you can upload the hex file included inside the zip folder attached to this step using the following line in the command prompt after you navigate to the correct folder:
avrdude -c usbtiny -p t85 -U flash:w:rde2.hex
Using an arduino would make this a lot easier but more expensive. On an arduino you have an AnalogWrite() function that would simplify a lot of this. The flow would then become AnalogWrite(voltage_desired) --> delay(experiment_time) --> repeat...
#include <avr/io.h>
#include <util/delay.h>
#define F_CPU 800000UL
float t_25, t_16, t_9, t_4, t_1; // float type is unnecessary but I have plenty of memory
int main(void)
{
//pre-set for 1V domain @ 5mV/s rate. Change if your experiment is different.
t_25 = 207*207000/(2.1920*227); // 207000 is the experiment length in milliseconds
t_16 = 207*207000/(1.5580*227); // 207/227 is a calibration constant
t_9 = 207*304000/(1.2585*227); // 2.1920, 1.5580, etc are the lengths of the for loops corresponding to that part of the experiment
t_4 = 207*304000/(1.1000*227);
t_1 = 207*304000/(1.0220*227);
// set output pin
DDRB |= (1 << DDB0) | (1 << DDB1);
// fast PWM mode, wave form generation bit [1:0]
TCCR0A = (1 << COM0A1) | (1 << WGM00) | (1 << WGM01);
// waveform bits [2], prescalar 1024
TCCR0B = (1 << WGM02) | (1 << CS02) | (1 << CS00);
// output compare register
OCR0A = 0;
for(float t=0; t<t_25; t++)
{
PORTB |= (1 << PB1);
_delay_ms(1.192); // this defines the duty cycle and thus the analog voltage output
PORTB &= ~(1 << PB1); // a larger value gives a larger duty cycle and thus higher voltage
_delay_ms(1); // the 1 ms (off) delay is chosen arbitrarily
}
for(float t=0; t<t_16; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.558);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_9; t++)
{
PORTB |= (1 << PB1);
_delay_ms((0.2585));
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_4; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.1);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
for(float t=0; t<t_1; t++)
{
PORTB |= (1 << PB1);
_delay_ms(0.022);
PORTB &= ~(1 << PB1);
_delay_ms(1);
}
while(1) // end state
{
PORTB |= (1 << PB1);
_delay_ms(0);
PORTB &= ~(1 << PB1);
_delay_ms(600000); // 10 mins to avoid noise on the line
}
}
Downloads
Calibration
You will need a voltmeter and a stopwatch to calibrate the output voltage and times. I used excel to plot output voltage as function of duty cycle and to plot time (duration) as a function of input experiment length (in ms). An example of these plots is shown on this step.
To gather data, I would change the code to new values and re-upload it and then measure voltage and for how long it held. There will be error in the time measurements based on how fast your reflexes are, but it should average out as you take more experiments.
The first plot shows the output voltage (in mV) as a function of the expected (coded) analog voltage (in arbitrary code units). The expected (coded) analog voltage here is given in units of time on when there is a corresponding ratio of 1 as the off time.
The second plot shows actual time (in ms) that the experiment ran as a function of the coded time value (in code units).
There are many ways to calibrate but these are the primary metrics I used to figure out the slope and more importantly the linearity (is the line straight or curved?).
To gather data, I would change the code to new values and re-upload it and then measure voltage and for how long it held. There will be error in the time measurements based on how fast your reflexes are, but it should average out as you take more experiments.
The first plot shows the output voltage (in mV) as a function of the expected (coded) analog voltage (in arbitrary code units). The expected (coded) analog voltage here is given in units of time on when there is a corresponding ratio of 1 as the off time.
The second plot shows actual time (in ms) that the experiment ran as a function of the coded time value (in code units).
There are many ways to calibrate but these are the primary metrics I used to figure out the slope and more importantly the linearity (is the line straight or curved?).
Connection to Instrument
For my instance, this is fairly straightforward. It most likely will not be as easy for other instruments. All I had to do was plug in the voltage to the plugs on the instrument for input voltage.
To run this alongside the software, all you have to do is press the reset button on the circuit to start the timers at the same time as you press the "perform" or "run" button on the software side. You can then queue up the experiments that you need on the software and they will run one after each other (this support is already available with aftermath software). In my case, I run the first experiment at 2500 rpm, the second at 1600 rpm, then 900 rpm, 400 rpm, 100 rpm, and finally 0 rpm. These numbers are just to make calculations clearer for analysis.
Everything else should run on its own from here! Just come back in half an hour or so and all your work will be done for that sample! This can save a lot of time in the lab since you are not able to switch experiments as quickly by hand and additionally it allows you to work on other things while they are running automatically. Overall, this simple device has saved me several hours per week of work!
*It is worth noting that you can change the pre-scaler in the instrument to change the ration of mV to rpm. By default this is set to 1mV=1rpm. This is what I used as well since I lost resolution in voltage as it approached zero.
*you will notice the LED and extra IC chip still on the circuit board, this is the old 55 timer. The 555 chip on there isn't doing anything except blinking at 1Hz at 50% duty cycle. It is only there because I didn't feel like taking it back out (it looks pretty).
To run this alongside the software, all you have to do is press the reset button on the circuit to start the timers at the same time as you press the "perform" or "run" button on the software side. You can then queue up the experiments that you need on the software and they will run one after each other (this support is already available with aftermath software). In my case, I run the first experiment at 2500 rpm, the second at 1600 rpm, then 900 rpm, 400 rpm, 100 rpm, and finally 0 rpm. These numbers are just to make calculations clearer for analysis.
Everything else should run on its own from here! Just come back in half an hour or so and all your work will be done for that sample! This can save a lot of time in the lab since you are not able to switch experiments as quickly by hand and additionally it allows you to work on other things while they are running automatically. Overall, this simple device has saved me several hours per week of work!
*It is worth noting that you can change the pre-scaler in the instrument to change the ration of mV to rpm. By default this is set to 1mV=1rpm. This is what I used as well since I lost resolution in voltage as it approached zero.
*you will notice the LED and extra IC chip still on the circuit board, this is the old 55 timer. The 555 chip on there isn't doing anything except blinking at 1Hz at 50% duty cycle. It is only there because I didn't feel like taking it back out (it looks pretty).