Gas Chromatograph

Hi to all.
I would like to present you with my gas chromatograph machine.
It uses a 9mm borosilicate glass pipe filled with silica gel to separate and identify halogenated alkanes, like dichloromethane and refrigeration gas.
This glass pipe or "column" is placed in an "oven" controlled by an arduino. The oven consists of the physical copper jacket, a power mosfet to switch a 2.5 ohm (when cold) coil of nichrome wire, and a lm35 temperature sensor.
Sample is fed to the column by injecting 0.1-0.3ml of gas containing the substance of interest into some silicone tubing attached to an aquarium pump and to the column.
One of dem fancy arduino witchcraft thingies controls the oven, with a PID controller, and senses the intense blue light made when the column output is fed into a gas flame containing a loop of copper. (Copper gives a beautiful blue flame with halogenated alkanes - quite different to the green you get from a copper salt in a flame).
Output is collected from the serial monitor, and cut and pasted into an OpenOffice spreadsheet (MS Excel would be just as good too, but I haven't tried it) for graphing.

A picture of the setup is shown below:

And a circuit diagram can be seen here:

Code will follow, due to post size limits.

Do enjoy!

And here is the code

#include <LiquidCrystal.h> // library for AC1602 type 16x2 lcd display

#include <FlexiTimer2.h> // timer library

#include <PID_v1.h> // proportional integral/derivative library for heater

#include <EEPROM.h> // used to store last column temperature

/* Arduino halogenated hydrocarbon Gas Chromatograph
const char version[]="0.2";

/* by Leon Harris
 GC performs the following simple functions:
 1)   Displays welcome message
 2)   reads default set temperature
 3)   prompts user to enter set temperature
 4)   warms column to required temperature then
 5) waits for "inject button" to be pushed, then
 6) Start timing, and report ldr value, temperature and time
 7) Write out value to serial port
 8) Reports conditions to lcd
 ldr: infinity to 30k
 lm35 sensor for column temperature
 push button to detect start
 red led for running indicator
 green led for ready indicator
 lcd 2 line Hitachi HD44780 type
 Pin Assignments

A0    column temperature sensor lm35
A1    LDR detector
A2    up/down push buttons; up to 27k, down to 10k pulldown 10k
      this gives ADC down = 512 counts, up =  276 counts, 
      both simultaneously = 592 counts. Use +/-5% in logic

D2    Run/Stop button 
D3    Ready LED (Red)
D4    Busy LED (Green)

D5    lcd DB7, pin 14 of lcd
D6    lcd DB6, pin 13 of lcd
D7    LCD DB5, pin 12 of lcd
D8    LCD DB4, pin 11 of lcd

D10   PWM drive for mosfet heater controller

D11   Enable, pin 6 of lcd
D12   Register Select, pin 4 of lcd

//Globals -> I have the programming equivalent of poor hygiene with my globals:TODO clean up

const int buttonPin = 2; //use an interupt on pin 2 for start button
const int readyLED = 3;           // digital pin the heartbeat led is on
const int busyLED = 4;             // digital pin the BUSY LED is on
const int columnTempSensor = A0;  // front LM35 column sensor
const int detectorLDR = A1;  // ldr for detecting green flame
const int setButtons = A2;  // ldr for detecting green flame
const int mosfetDrive = 10;  // drive pin for heater

volatile int flashpin =1;
volatile int serviceInterrupt = 0;
double temperature;

double epromTemperature;  // holds the temperature read from the eprom
int epromaddy=0;   // just writes to address 0. Uses var in case I upgrade to a better save record like a struct (ie for multi-temp runs)   

double settemperature;  
double input,output;  // needed for pid for column heater

 int photoDetector;
 int runFlag = 1;
unsigned long time;
unsigned long startTime;
 int serInLen = 25;  // used for Gobetwino
char serInString[25]; // used for Gobetwino

LiquidCrystal lcd(12, 11, 8, 7, 6, 5);
PID myPID(&temperature, &output, &settemperature,2.5,0.2,0, DIRECT);    // Kp,Ki,Kd values generated from autotune sketch run previously 

10            Mosfet pwm drive pin for heater

enum stat {
stat Status;

float getTemp ()

  float tempTemp;
  int aRead=0;
  int span=5;
  // Temperature is so noisy, this damps it down
  for (int i=1; i< span; i++) {
    aRead = aRead + analogRead(columnTempSensor);

  //tempTemp=(5.0 * aRead *100) /1024;
  tempTemp=(aRead* 0.4882812) /5; 
  return (tempTemp);	     //convert voltage to temperature


void controlTemp() {
  // runs PID controller to keep temperature constant

int readLDR () {
  int numReadings=10;
  int rawLight=0;
  for (int i=0; i<numReadings; i++) {
    rawLight=rawLight + analogRead(detectorLDR);
  return (rawLight);

void changeStatus()

// Prints data to console, incsv, where it can be picked up by mouse and fed into excel

void logData( long unsigned value1, int value2, float value3 ) 

 // readSerialString(serInString,1000);
  // There ought to be a check here for a non 0 return value indicating an error and some error handeling

//read a string from the serial and store it in an array
//you must supply the array variable - return if timeOut ms passes before the sting is read
void readSerialString (char *strArray,long timeOut) 
  long startTime=millis();
  int i;

  while (!Serial.available()) {
    if (millis()-startTime >= timeOut) {
  while (Serial.available() && i < serInLen) {
    strArray[i] =;

void flashWaitStatus ()
  digitalWrite(readyLED, flashpin);
  flashpin = !flashpin;

void flashBusyStatus ()
  digitalWrite(readyLED, flashpin);
    digitalWrite(busyLED, flashpin);
  flashpin = !flashpin;

void flashRunStatus ()

  digitalWrite(busyLED, flashpin);
  digitalWrite(readyLED, 0);
  flashpin = !flashpin;

void servicePID() {
      analogWrite(mosfetDrive, output);

void setup()

   // Set initial welcome message
  lcd.begin(16, 2);
  // Print Banner
  lcd.print("G Chromatograph");
  lcd.setCursor(0, 1);
  lcd.print("by L Harris V");
  pinMode(readyLED, OUTPUT);
  pinMode(busyLED, OUTPUT);
  pinMode(mosfetDrive,OUTPUT);   // setup pin 9 for pwm

  attachInterrupt(0, changeStatus, CHANGE); // interupt 0 sits on pin D2

  Serial.print("Gas Chromatograph version " );

// set up  column temperature
 epromTemperature = double(; // get the last stored temp
 settemperature = epromTemperature;
while (Status==INITIALISING){
  int button=0;  // initial value for inc and dec buttons
    lcd.setCursor(0, 0);
    lcd.print("temp? press both");
    lcd.setCursor(0, 1);
    lcd.print ("to save)");
    lcd.setCursor(12, 1);
    if (button != 0) {
      if (button > 500 && button < 530) {  // down pressed
       settemperature -=1; 
      delay(200); // for debounce

     else if (button > 250 && button < 300) {  // up pressed 
      settemperature +=1;
     else if ( button > 580 && button < 600) { //both pressed - save
     if (settemperature != epromTemperature) {
lcd.print("set temp =");
lcd.print(" oC");
lcd.setCursor(0, 1);
lcd.print("warming column");

  //create a pid object to control the column temperature


  Status = BUSY;
   FlexiTimer2::set(500, flashBusyStatus); // 500ms period
  // just lock us out until the column heats up
  while (Status == BUSY) {
      if (temperature > settemperature ){
        Status = WAITING;
    FlexiTimer2::set(500, flashWaitStatus); // 500ms period
      lcd.print("column= ");
      lcd.print(" oC");
      lcd.setCursor(0, 1);
      lcd.print("Press run");
      lcd.blink();  // wants input from us, so blink
  Serial.println("we have reached column temp");  


void loop()
  while (Status==WAITING) {
    if ( runFlag == 1) {

      Serial.print("column temperature is ");
      Serial.print("photodetector reading is ");

    digitalWrite(readyLED, LOW);

  if (runFlag==1) {  

    FlexiTimer2::set(1000, flashRunStatus); // 500ms period
    lcd.noBlink(); // doesn't want anything, so stop blinking
    while (Status == RUNNING) 
    //main running loop goes here
    //wait 1 sec
//read ldr
//read temp

if (serviceInterrupt ==1 ){
  logData(time, photoDetector, temperature);
  lcd.print(" oC");
  lcd.setCursor(0, 1);
  lcd.print(" units");

    //log time since start, ldr, and temp to csv file via Gobetweeno
    // later write time and ldr to lcd
    //do it all again until status is stopped


Never seen gas chromatography before ! (There are a few nice liquid chromatograph sketches around)

Can you post some "screen shots" of results (xls files) ?

Sure. A chromatogram of dichloromethane at 22 degrees (room temp) and at 55 degrees can be seen here:

More details of the detection system can be seen here:

Some more details on the Chemistry and other details can be found here:

Thanks for the interest!

I know this topic is a little old but wanted to ask if you have explored other detector methods.

In particular, SAW technology, (Surface Acoustic Wave) might be an elegant way to improve/expand the GC project.
Any thoughts on this?

Great project, by the way.


Hi Nitrous,
good comment, and yes.
I have been working on integrating into excel with PLX-DAQ - this has mostly been done, and I now have real time output.

I don't know enough about SAW technologies, but I am interested in the tin oxide types of resistive sensors, such as Figaro 822 and MCQ-3. They work by an analyte of interest sticking to the SnO (SnO2?) and changing its resistance. There is also a heater in such devices so that detected substances don't just "bind, stick and clog" the sensor. It occurs to me that as such a range of substances such as methane to methanol can be detected by different sensors, that the major difference in these sensors is the possibly just the temperature that the chip is held at by the resistive heater. My current work is to see if a very polar sensor (such as Figaro 822, or MCQ-3) can be tuned by "pwm 'ing" the heater pin so that they are good for testing for other substances. If this is so, you can have a very cheap general sensor for many, many substances. Other detectors such as FID (thoriated welding rod, methan flame, 2x 9v batteries in series and a MPS63 or similar high gain darlington) are also possible, but my experiments with these (not coupled to a column) show a lot of drift, and I have abandoned them for this time while I pursue the more promising Sn/O sensors.

One thing is for sure: GC, Thin Layer Chromatography and paper chromatography have made their way into Year 11 Chemistry syllabus in the Australian National Curriculum (2016). I will probably run another Arduino workshop for my local Science Teachers association on how to build a GC - so I better get off my bum and finish the project! I am waiting for boards to arrive from ebay right now!
Thanks for your interest.

Excellent work. Thanks for sharing it.

Do you believe that a variation on your work could identify elements in CMNS reactor ash?

Could a variation measure temperature?

I know that spectra vary by temperature and that this fact is used by astronomers.

My reason for asking is that I am helping amateur scientists worldwide to investigate thermogenerator reactors. Simple alumina tubes filled with metal powders which exhibit as yet unexplained heating.

See the early days of my blog at

Hi Harristotle
thank you for your great work, just I have some question about the schematic, about D11 and D12 of arduino where they are connected in LCD.
and about Gas sensor where is the Pins in arduino?
best regards

Dear Sir
when I like to upload your code of arduino gas chromo is not work there are problem in your code.
pleas help me

Make sure that you are using the correct lcd library for the HD44780, there are a couple of versions out there and they are not all compatible. Secondly, try adjusting the 10k pot to get good contrast on the screen.

D12 is RS
D11 is enable

the others are the 4 bit data bus

finally, I don’t often visit this thread, so I don’t always get replies.

Have fun now!

Hi there Harristottle,
a fascinating journey into "do-it-yourself" science. Well done! You have my admiration. For the moment, my own interest is at the thought-process level, but I'm tempted to begin experimentation, and your exploits are a super reference point for me!

A question:
I've thought about doing something similar, from scratch, to your own venture. I started by thinking in terms of using a small flow rate of propane (cheap, available) as a carrier gas; column = a long copper tube, with inside coated stationary phase (I thought maybe copper brake pipe?). Coil it, put it in a heated vessel (air heated, oil bath etc etc) and then "play around" with various detection ideas on the output gas stream. Perhaps flame ionisation because there's a built-in flammable carrier?!
I also play around with Arduinos and have a lot of fun with them. My primary hobby interest is analysis of Scotch Whiskey (I know, I know! What a strange interest!)
Such spirits contain small quantities of a large number of "congeners" - various organic compounds. And it would be highly interesting to begin to understand their distribution/quantity vs the source/fermentation/distillation conditions.
I have one of those Chinese USB storage 'scopes, so capturing and examination of output changes (even fast ones from a short column) is unlikely to be a problem!
Your thoughts are most welcome?
As you can see, I have thought much more about the basic structure than the detection mechanism. For the time being anyway! Though I expect that with the availability of the storage 'scope, own-designed detectors is probably wide-open territory for experimentation......

How about a DIY spectrometer?


GS-IR machines....I used them plenty in my time as an analytical chemist.

The UV-VIS-IR stuff is not as bad as you may think!

A diffraction grating that is moved through an axis to get different wavelengths of light filtered.
Your detector can then read the individual wavelengths and produce a "graph"/Spectrum of the sample.

You can feed the output of your GC along a sample glass tube. This gives a "live" full spectrum analysis of what you have separated.

The first peak is your usual carrier gas, then you can time the following peaks as they come off to give retention times. Having the IR/UV/VIS spec gives a better analysis as you can identify multiple chemicals in one sample.

I also have thought about FID, and the possibility of hacking a small smoke detector as my source for this !!

I have really enjoyed playing around with ionisation chambers (like this guy: Make a Cheap and Effective Radiation Detector ( Ion Chamber )) but I found I had considerable drift with those darlingtons! My wife wont let me anywhere near a milo tin these days! There are better, temperature compensated circuits though. These chambers go nuts when you put a candle in them- all those 1+ carbon nanotubes flying around there. It makes you wonder if you could make a crude, carbon nanotube/buckyball "mass spectrometer" out of a candle and do some cool chemistry. There is still a lot of fun for the home guy in the shed!

I wondered about taking my silica gel and soaking it in palmitic acid (reflux dilute H2SO4 and soap then extract into white spirits/pet ether) and then esterify to the -OH groups on the silica gel with concentrated H2SO4! Voila! C16 column, cheap, cheap.

Sadly I have run out of time to play with this project. I appreciate your interest, and am glad that your post corresponded to my annual visit back here !!!