Current-Voltage Characteristic Plotter


The Arduino can easily be used as a simple current-voltage characteristic plotter. To do it properly, you need a variable DC source. Everybody knows that analogWrite does not give a DC voltage but a PWM signal. Luckily, with a low pass filter (R1/C1) you can suppress the ripple. What else do you need? Well, you have to measure the current. That can be done easily by means of a resistor (R2).

All you have to do is apply different PWM values to a port, read the voltage at C1 and the voltage at the test device which is the difference of the voltages at A0 and A1.

As floating point handling by Arduino is not always satisfying, all calculations are performed in millivolts. To enable the spreadsheet software to import the values, the procedure insertComma converts the strings. If your software needs a decimal point, you have to change this character.

The program also plots a graph in text mode to the serial terminal window.

/*
This project will read the characteristic of a linear 
or non-linear device such as a resistor or a LED.
The PWM output of PIN-5 gets averaged by an RC of 180 Ohms and 1200 µF.
This goes to the device under test.
Then it goes through a 47 Ohms resistor to the ground to find the current.
Both ends of the device under test go to A0 and A1 respectively to find the voltage.
The PWM value goes from 0 to 255 in steps.
*/

const byte pwmPin = 5;           // LED connected to digital pin 5
const byte current = A1;
const byte voltage = A0;
const long Aref = 5000000;       // microvolts
const long uStep = Aref / 1024;  // microvolts
const int Ri = 47;               // Ohms

String insertComma(long x) {
  String s0 = "000000" + String(x);
  byte l = s0.length();
  String s1 = s0.substring(0,l-6);
  String s2 = s0.substring(l-6,l);
  String s3 = s1 + ',' + s2;
  byte k = s3.indexOf(",");
  return s3.substring(k-1);
}

void setup()  { 
  Serial.begin(9600);
  Serial.println("U/V I/A");
  analogWrite(pwmPin,0);
  delay(1000);
  long X[64];
  long Y[64];
  byte nr = 0;
  for (int pwmValue = 0; pwmValue <= 255; pwmValue = pwmValue + 4) {
    analogWrite(pwmPin,pwmValue);
    delay(200); // let the voltage reach the final value
    long v0 = 0;
    long v1 = 0;
    const byte avg = 50;
    for (int j = 1; j <= avg; j++) {
      v0 += analogRead(current);
      v1 += analogRead(voltage);
    }
    long U = (v1 - v0) * uStep / avg;
    long I = (v0 / Ri) * uStep / avg;
    X[nr] = U;
    Y[nr] = I;
    nr++;
    Serial.print(insertComma(U)); 
    Serial.print(" ");
    Serial.print(" ");
    Serial.print(insertComma(I)); 
    Serial.println();
  } 
  // the plot:
  // find max:
  long maxX = 0;
  long maxY = 0;
  for (int i = 0; i < 64; i++) {
    if (X[i] > maxX) maxX = X[i];
    if (Y[i] > maxY) maxY = Y[i];
  }
  // normalize:
  byte x[64];
  byte y[64];
  for (int i = 0; i < 64; i++) {
    x[i] = X[i] * 64 / maxX;
    y[i] = Y[i] * 64 / maxY;
  }
  Serial.println("\"mark all above, press Ctrl-C and insert it into your spreadsheet\"");
  Serial.println();
  Serial.print(insertComma(maxY));
  Serial.println(" A");
  Serial.println("+----------------------------------------------------------------+");
  for (int j = 63; j >= 0; j--) {
    Serial.print("|");
    String s = "                                                                ";
    for (byte i = 0; i < 64; i++) {
      if (y[i] == j) {
        s.setCharAt(x[i],'x');
      }
    }
    Serial.print(s);
    Serial.println("|");
  }
  Serial.println("+----------------------------------------------------------------+");
  Serial.print("0                                                               ");
  Serial.print(insertComma(maxX));
  Serial.println(" V");
  Serial.println("\"finished - quit or press RESET to restart\"");
} 

void loop()  { }

The data for this graph (5 LEDs of different colors) were sampled by this project:




Date: 15.04.2014

Actually, rgco published an improved version dated 04.03.2017.



contact: nji(at)gmx.de