PROJECT NAME: HIGH PERFORMANCE LIQUID CHROMATOGRAPHY
High Performance Liquid Chromatography (HPLC) is one mode of chromatography; the most widely used analytical technique. HPLC utilizes a liquid mobile phase to separate the components of a mixture. These components (or analytes) are first dissolved in a solvent, and then forced to flow through a chromatographic column under a high pressure. In the column, the mixture is resolved into its components. The interaction of the solute with mobile and stationary phases can be manipulated through different choices of both solvents and stationary phases. As a result, HPLC acquires a high degree of versatility not found in other chromatographic systems and it has the ability to easily separate a wide variety of chemical mixtures.
There are two elution types: isocratic and gradient. In the first type constant eluent composition is pumped through the column during the whole analysis. This is ISOCRATIC ELUTION. In the second type, eluent composition (and strength) is steadily changed during the run. This is GRADIENT ELUTION. DAS FLOW FOR UV – VIS DETECTOR FOR HPLC
Initial Software flow: 1.Check communication synchronization 2.Send function code to micro controller 3.Send integration time to micro controller (2 bytes) 4.Wait for conversion to complete 5.Get the readings from controller 6.Convert the values to bipolar 7.Convert ADC count to float 8.Multiply the count with resolution (mV = Count *2.4420) 9.Calculate absorbance (Log (ref/smp)) 10.Display absorbance on LCD 11.Send the absorbance value to PC Disad: Overhead of 80 mSec Modified software flow: Micro processor: 1.Check communication synchronization 2.Send function code to micro controller 3.Send integration time to micro controller (2 bytes) 4.Wait for RST7.5 interrupt from controller Micro controller: 1.Check for communication synchronization 2.Receive function code 3.Receive integration time 4.Initiate ADC 5.Acquire ADC readings for the given integration time – 10 mSec 6.Interrupt Micro Processor after completion of ADC acquisition The tasks of microprocessor and micro controller are done in parallel. Hence the overhead time of 80 mSec has been overcome.
ADC Acquisition: Initially, set DG508 to reference path
Bank 0 – Reference Bank 1 – Sample
Only 2 regions – Ref and sample
DAS Flow:
Configure Timer 2 to 2 msec
Timer 2 Routine:
It interrupts for every 2 msec.
Yes
Detailed hardware flow:
1.Switch on the system.
2.System initialization is done i.e, lamp, grating and filter homing
3.Enter the required wavelength and integration time.
4.Move the grating and filter to the desired positions.
5.Initially set DG508 to reference path
6.Output of DG 508 is given to CA3140 op amp. Output of Op Amp is fed to ADC and readings are taken. The buffering is done to avoid loading.
7.Accumulate the readings in Bank 0
8.Now switch DG 508 to sample path and take the readings from ADC.
9.Accumulate these readings in Bank1
10.Continue till the completion of integration time – 10 msec.
11.Calculate mV and absorbance
12.Display absorbance on LCD and send it to PC.
13.Continue till scan has been stopped.
Observations:
a) With initial software flow:
S.No.
Integration time (sec)
Data acquisition time (sec)
Display calc. (mSec)
Time taken (sec)
1
1
1.010
130
1.140
2
2
2.010
130
2.140
3
3
3.010
130
3.140
Individual times
S.No Task Time taken
1
Data Acquisition
Int. time + 10 mSec
2
Absorbance calculation
60 mSec
3
Displaying on LCD
60 mSec
4
Sending to PC
12 mSec
5
Total time taken for one data point
Int. time +142 mSec
b) With new software flow: S.No. Integration time (sec) Data acquisition time (sec) Display calc. (mSec) Time taken (sec) 1 1 1.0 130 1.0 2 2 2.0 130 2.0 3 3 3.0 130 3.0 Since the two tasks are done in parallel with each other, there’s no overhead of 130 mSec
Individual times
S.No Task Time taken
1
Data Acquisition
Int. time - 10 mSec
2
Absorbance calculation
60 mSec
3
Displaying on LCD
60 mSec
4
Sending to PC
12 mSec
5
Total time taken for one data point
Int. time
/*------------------------------------------------------------------------------ AD8Input.C: MSC 1210 A/D Conversion for 8 single ended channels.
Uses 0-5V on inputs AIN0 to AIN7 and AINCOM = 2.5V.
date : 02-06-07 sign on , sign off, time scan and channel select commands functionality is achieved. external trigger input is enabled.
*/
- include <REG1210.H>
- include <stdio.h>
- define XTAL 11059200 // XTAL frequency
// defines for UART BAUDRATE
- define BAUDRATE 9600 // 9600bps communication baudrate
- define T2RELOAD (65536-(XTAL/32/BAUDRATE))
// defines for A/D Converter setup
- define A_CLK 10 // about 1MHz Analog Clock
- define ANA_CLK 1000000 // precise Analog Clock
- define DECIMATION 1562 // 10 Hz Decimation
/******* defines for commands *************/
- define STX 0x02
- define ETX 0x03
- define NAK 0x0F
- define ACK 0x06
/*********** USB definitions **************/
- define TXE P1_5
- define RXF P1_4
- define USB_RD P1_7
- define USB_WR P1_6
- define TRG P3_2
- define ENB P3_4
sbit P1_4 = P1^4; sbit P1_5 = P1^5; sbit P1_6 = P1^6; sbit P1_7 = P1^7; sbit P1_2 = P1^2; sbit P3_2 = P3^2; sbit P3_4 = P3^4; sbit P3_3 = P3^3; sbit P3_5 = P3^5; sbit P3_7 = P3^7; sbit P3_6 = P3^6;
void Delay (void); void Delay1(void);
unsigned char read; unsigned char abort;
/******** Writes character into transmit buffer ******************/
void USB_send_char( char dat)
{
while(1) { while (!TXE) { USB_WR = 1; //pull WR line high Delay(); // put some delay
P2 = dat; //write P2 USB_WR = 0; return;
} }
}
/*************Reads character from the receive buffer ***********/ unsigned char USB_read_char() {
while(1) { while (!RXF) { unsigned char bBYTE;
P2 = 0xFF;
P2DDRH = 0x00; //port2 all inputs
P2DDRL = 0x00; USB_RD = 0; //pull RD line low
Delay1(); //put some delay
bBYTE = P2; //read P2 USB_RD = 1; //pull RD line high
return bBYTE; } }
}
/****************** Flushes the USB recieve buffer *************/ void Purge_USBFIFO( void) {
//P2 = 0xFF; P2DDRH = 0x00; // set P2 for input P2DDRL = 0x00; P2 = 0xFF; if (!RXF) { USB_RD = 0; // Delay1(); USB_RD = 1; }
}
/*****************timer interrupt routine *********************/ static unsigned long ovf_cnt = 0;
void timer0_ISR( void) interrupt 1 {
// TR0 = 0; // stop timer 0 TL0 = 0xFE; //reload value for 50msec TH0 = 0x4B; // TR0 = 1; // start timer 0 */ ovf_cnt++ ;
}
void timer1_ISR( void) interrupt 3
{
TR1 = 0;
TL1 = 0xFE; //0x32; //reload value for 3msec TH1 = 0x4B; //0xF5;
while(!RXF) { P2 = 0xFF;
P2DDRH = 0x00; //port2 all inputs
P2DDRL = 0x00; USB_RD = 0; //pull RD line low
Delay1(); //put some delay
read = P2; //read P2 USB_RD = 1; //pull RD line high if(read == 0X04) abort = 1; } TR1 = 1; }
/***********************Initializes ADC **********************/ void init_ADC( void) {
ADMUX = 0x08; // (AIN+ = AIN0),(AIN- = AINCOM) Voltage from DAC ACLK = A_CLK; // set ACLK factor for about 1MHz ADCON0 = 0x10; // disable internal vref //0x30; // Vref On, Vref Hi, Buff off, BOD off, PGA=1
ADCON2 = DECIMATION & 0xFF; // LSB of decimation ADCON3 =(DECIMATION>>8) & 0x07; // MSB of decimation ADCON1 = 0x01; // bipolar, auto, self calibration (offset, gain)
}
/****************Initializes serial**************************/ void init_UART( void) {
T2CON = 0x34; // Use Timer 2 as baudrate generator */ RCAP2H = (T2RELOAD >> 8); // baudrate reload factor RCAP2L = T2RELOAD; SCON0 = 0x53; // enable serial uart & receiver P3DDRL &= 0xF0; // set port pins of UART to input/strong drive output P3DDRL |= 0x07; // set port pins of UART to input/strong drive output
}
/****************Timer Initialize **********************/ void timer0_initialize( void) {
EA = 0; // disable all interrupts TR0 = 0; // stop timer 0 TMOD = (TMOD & 0xF0) | 0x01; TL0 = 0xFE; TH0 = 0x4B; ET0 = 1; // enable timer 0 interrupt TR0 = 0; // start timer 0 EA = 1; // enable interrupts */
}
void timer1_initialize( void) {
TR1 = 0; EA = 0; // disable all interrupts TR1 = 0; // stop timer 1 TMOD = (TMOD & 0x0F) | 0x10; TL1 = 0x32; TH1 = 0xF5; // timer 1 interrupt is set for 3 msec ET1 = 1; // enable timer1 interrupt EA = 1; // enable interrupts */
// TR1 = 1; }
/*******Ext. Interrupt init********/ void ex0_isr_init(void) {
IT0 = 1; EX0 = 1; EA = 1;
}
/********External interrupt routine********/
//unsigned char ex0_isr_counter = 0;
void ex0_isr (void) interrupt 0 { //ex0_isr_counter++; // Increment the count }
/*****Helper structure to read in ADC values*****/
union
{
unsigned char c[4]; // bytes unsigned long l; // unsigned long
} res;
/***********Main Function*****************/ void main(void) { unsigned char chk_sum1,chk_sum2,fcode_stat = 0xFF,c2,j1,c,time_scan,count,chan_ID = 0x00; unsigned char chan_sel=0x34,k; unsigned int xdata size = 0 ; unsigned int i,j,sum2, sum3, timer_cnt, scan_cnt, cnt =0,sum,sum1,interval; unsigned int a[10], temp[10]; unsigned long tot;
CKCON = 0; // 0 MOVX cycle stretch make movx machine cycle = 2
PDCON = 0x14; // turn on ADC-Vref, SPI and Systimers make power down mode and
// watchdog timer in powerdown mode
init_UART(); // Setup Serial Interface P1DDRH = 0x5F; // set port pins
init_ADC(); // Setup ADC USB_RD = 1; // init usb WR USB_WR = 1; // init usb RD
timer0_initialize(); // init timer0
timer1_initialize(); // init timer1
ex0_isr_init(); // initialize external interrupt
Purge_USBFIFO(); // flush usb buffer
for (i=0;i<10;i++) // dump 3 conversions
{ while(!(AIE&0x20)) {} j1=ADRESL; }
while (1) { while (!RXF) { c = USB_read_char(); //reading STX 0x02
if(c == STX) //else { c = USB_read_char(); //reading first byte of length 0x00
c = USB_read_char(); //reading second byte of length can be 0x00 or 0x05
if(c == 0x02) //connect,disconnect or channel select cmd { c = USB_read_char(); //reading function code fcode_stat = c; } else if( c == 0x05) { if(TRG != 0 ) USB_send_char(NAK);
else { c = USB_read_char(); //READING FUNCTION CODE time_scan = c;
c = USB_read_char(); //reading first byte of scan count sum1 = 0; sum1 += (int)c; scan_cnt = 0; c2 = c;
c = USB_read_char(); //reading second byte of scan count
sum1 += (int)c; scan_cnt += (int)((c2 << 8) | c); if( scan_cnt <= 0) USB_send_char(NAK);
c = USB_read_char(); //reading first byte of time interval
sum1 += (int)c; timer_cnt = 0; c2 = c;
c = USB_read_char(); //reading second byte of time interval sum1 += (int)c; sum1 += 2; timer_cnt = (int) ((c2 << 8) | c); interval = timer_cnt * 4;
if( timer_cnt <= 0) USB_send_char(NAK);
sum = sum1/256; // mod256 sum = sum1 - (256 * sum); chk_sum1 = (char) (sum & 0xFF); chk_sum1 = (~(chk_sum1) + 1); //calculating check sum
if((c = USB_read_char()) != chk_sum1) {
USB_send_char(NAK); } if((c = USB_read_char()) != ETX) USB_send_char(NAK);
else { USB_send_char(ACK); TR0 = 1; TR1 = 1; } cnt = 0; ovf_cnt = 0; } } //end of time scan cmd } //end of else
if(fcode_stat != 0xFF) { switch(fcode_stat) { case 0x00: //SIGNON command c = USB_read_char(); //reading data block sum = c; sum1 = sum/256; sum1 = sum - (256*sum1); chk_sum1 = (char) (sum1 & 0xFF); chk_sum1 = (~(chk_sum1)+1); if((c = USB_read_char())!= chk_sum1) USB_send_char(NAK); if((c = USB_read_char())!= ETX) USB_send_char(NAK); else USB_send_char(ACK); fcode_stat = 0xFF; break;
case 0x01: //CHANNEL SELECT command sum = fcode_stat; chan_sel = USB_read_char(); //reading the selected channels
sum += (int)chan_sel; for(i=0;i<8;i++) { a[i] = chan_sel % 2; chan_sel = chan_sel/2; } count = 0; j = 0;
for(i=0;i<8;i++) { if(a[i] == 1) { count++; temp[j] = i; j++; } } i = 0; sum1 = sum/256; sum1 = sum - (256*sum1); chk_sum1 = (char) (sum1 & 0xFF); chk_sum1 = (~(chk_sum1)+1);
if((c = USB_read_char())!= chk_sum1) USB_send_char(NAK);
if((c = USB_read_char())!= ETX) USB_send_char(NAK);
else USB_send_char(ACK);
fcode_stat = 0xFF; // printf("channel ID : %d ", temp[i]); break;
case 0x03: //SIGNOFF command // printf("SIGN OFF CMD RECEIVED \n"); c = USB_read_char(); //reading data block sum = c + fcode_stat; sum1 = sum/256; sum1 = sum - (256*sum1); chk_sum1 = (char) (sum1 & 0xFF); chk_sum1 = (~(chk_sum1)+1); if((c = USB_read_char())!= chk_sum1) USB_send_char(NAK); if((c = USB_read_char())!= ETX) USB_send_char(NAK);
else USB_send_char(ACK); fcode_stat = 0xFF; break;
default:
break; } // end of switch } } // end of while(!RXF)
while( time_scan == 0x02) //time scan mode { chan_ID = temp[i];
ADMUX = (temp[i]<<4) | 1;
while( (cnt <= scan_cnt && ovf_cnt == timer_cnt/50)|(ovf_cnt == 0&&cnt == 0) ) { // AINP = chan, AINN = AINCOM if(cnt == 0) { for (k=0;k<3;k++) // dump 3 conversions { while(!(AIE&0x20)) {} j1=ADRESL; } } USB_send_char(STX); USB_send_char(0x00); USB_send_char(0x05);
while (!(AIE & 0x20)); // Read Input Voltage Wait for data ready
res.c[0] = ADRESH ^ 0x80; // Invert the Most significant bit (only positive inputs) res.c[1] = ADRESM; res.c[2] = ADRESL; res.c[3] = 0;
tot = 0x00;
tot = res.c[0];
tot = tot << 8; tot += res.c[1];
tot = tot << 8; tot += res.c[2];
if(tot >= 0x00208D)
tot += 0x00208D;
res.c[2] = tot % 256; tot = tot/256; res.c[1] = tot % 256; tot = tot/256; res.c[0] = tot % 256;
USB_send_char(chan_ID); //channel ID USB_send_char(0x00); //byte to check data sent is valid data or an error
USB_send_char(res.c[0]);
sum2 = 0; sum2 += (int) res.c[0];
USB_send_char(res.c[1]);
sum2 += (int) res.c[1];
USB_send_char(res.c[2]);
sum2 += (int) res.c[2];
sum3 = 0; sum3 = sum2/256;
sum3 = sum2 - (256 * sum3);
chk_sum2 = (char) (sum3 & 0xFF);
chk_sum2 = (~(chk_sum2) + 1);
USB_send_char(chk_sum2);
USB_send_char(ETX);
ovf_cnt = 0; cnt++; i++;
if(i == count) i = 0; if(abort == 1) { abort = 0; TR0 = 0; TR1 = 0; time_scan = 0x00; Purge_USBFIFO(); // flush usb buffer }
if(cnt == scan_cnt) {
TR0 = 0; TR1 = 0; time_scan = 0x00; Purge_USBFIFO(); // flush usb buffer } } //end of outer while } // end of if condition
} // end of while(1)
} // end of main
void Delay(void) {
// unsigned int i, j;
//for(i=0; i<20/*100*/; i++)
// for(j=0; j<10; j++) // i = i + 0;
}
void Delay1(void) { // unsigned int i, j;
// for(i=0; i<50/*500*/; i++)
// for(j=0; j<10/*50*/; j++) // i = i + 0;
}