|
setup diary |
電気抵抗を測定するシステムが不安定になっていたので、システムの更新を計画している。そのシステムは、限られた用途にしか使わないので、1ミリオーム程度から1オーム程度まで測定できれば良い。これまでは、GPIBで電源とデジボルを制御して測定していたが、抵抗の値が限定されるのであれば、安価なICを組み合わせれば、ほぼ同等のシステムを構築できるのでは無いかと考えられる。
そこで、計装アンプとADコンバーターとarduino UNOを使って、抵抗測定システムを作ることにした。仕様としては、白金抵抗温度計以外に4つの試料を同時に測定できるようにした。arduinoのピンから供給する0Vと5Vを使って、抵抗と直列に繋いだ試料に電流を流す。電流は標準抵抗にかかっている電圧から求め、それと試料にかかっている電圧から、抵抗が計算できる。熱起電力を打ち消すためには、arduinoのピンの電圧を反転させれば良い。
ADコンバーターとしては、MCP3425を用いた。このICは、プラスマイナスの電圧をそれぞれ15bitで読み取ることが出来、2/4/8倍のアンプも内蔵しているので、ダイナミックレンジは18bitと言える。温度計を測るには十分であるが、試料には5mA程度の電流を流すことにすると、電圧が小さすぎるので、計測アンプで増幅する必要がある。計装アンプはLT1167を使って200倍程度の増幅することにした。
最終的には、MCP3425を10個とLT1167を4個使って、arduinoで4つの試料を同時に測定できるシステムが完成した。測定時間も片側0.5秒ぐらいで測定しても、ノイズはそれほど大きくなかったので、1秒程度で測定ができる。まだ、試運転の段階で、本格稼働はしていないが、予定程度の性能を持つシステムができた気がする。
#include <string.h> // GND-6.8kOhm-PIN-3.3kOhm-5V #define DIO1 2 // GPIB 1 : I/O data bit 1 #define DIO2 4 // GPIB 2 : I/O data bit 2 #define DIO3 6 // GPIB 3 : I/O data bit 3 #define DIO4 8 // GPIB 4 : I/O data bit 4 #define DIO5 3 // GPIB 13 : I/O data bit 5 #define DIO6 5 // GPIB 14 : I/O data bit 6 #define DIO7 7 // GPIB 15 : I/O data bit 7 #define DIO8 9 // GPIB 16 : I/O data bit 8 #define EOI 11 // GPIB 5 : End Or Identify #define REN 12 // GPIB 17 : Remote ENable #define DAV A0 // GPIB 6 : DAta Valid #define NRFD A1 // GPIB 7 : Not Ready For Data #define NDAC A2 // GPIB 8 : Not Data ACcepted #define IFC A3 // GPIB 9 : InterFace Clear #define SRQ A4 // GPIB 10 : Service ReQuest #define ATN A5 // GPIB 11 : ATteNtion #define GPIBTIMEOUT 200000 //200ms char com[256] = ""; char delim[3]="\r\n"; int p=0; // counter void setup() { Serial.begin(115200); digitalWrite(DIO1, LOW); digitalWrite(DIO2, LOW); digitalWrite(DIO3, LOW); digitalWrite(DIO4, LOW); digitalWrite(DIO5, LOW); digitalWrite(DIO6, LOW); digitalWrite(DIO7, LOW); digitalWrite(DIO8, LOW); digitalWrite(EOI, LOW); digitalWrite(REN, LOW); digitalWrite(DAV, LOW); digitalWrite(NRFD, LOW); digitalWrite(NDAC, LOW); digitalWrite(IFC, LOW); digitalWrite(SRQ, LOW); digitalWrite(ATN, LOW); set_num(EOI,0); set_num(DAV,0); set_num(NDAC,1); set_num(NRFD,1); } void loop() { if (Serial.available()==0){return;} if (0x0a != (com[p++] =Serial.read())) {return;} com[p]=0; if(com[0]<'a'){ // upper case com[3]=0; if (0 == strcmp("IFC", com)){ gpibIFC();} // InterFace Clear else if (0 == strcmp("SRQ", com)){ gpibSRQ();} // Service ReQuest else if (0 == strcmp("REN", com)){ gpibREN(1);} // Remote ENable else if (0 == strcmp("RDA", com)){ gpibREN(0);} // Remote DisAble else if (0 == strcmp("LLO", com)){ gpibCmd(0x11,"LLO");} // Local Lock Out else if (0 == strcmp("DCL", com)){ gpibCmd(0x14,"DCL");} // Device CLear else if (0 == strcmp("STA", com)){ gpibLineStatus();} }else{ // lower case p=(com[1]-'0')*10+com[2]-'0'; //address or paremeter if(p<0 || p>31){Serial.println("address error");p=0;return;} if ('c' == com[0]){gpibAdr(p,0x04,"SDC");} //c99 Selected Device Clear else if ('l' == com[0]){gpibAdr(p,0x01,"GTL");} //l99 Go To Local else if ('d' == com[0]){gpibDelim(p);} //d00-02 delimiter else if ('w' == com[0]){gpibTalk(p, com+3);} //w99option else if ('r' == com[0]){gpibListen(p, com); //r99 Serial.print(com); } } p=0; } void gpibLineStatus(void) { Serial.print("ATN="); Serial.print(set_num(ATN,0)); Serial.print(", DAV="); Serial.print(set_num(DAV,0)); Serial.print(", NRFD="); Serial.print(set_num(NRFD,0)); Serial.print(", NDAC="); Serial.print(set_num(NDAC,0)); Serial.print(", EOI="); Serial.print(set_num(EOI,0)); Serial.print(", SRQ="); Serial.print(set_num(SRQ,0)); Serial.print(", DIO8-1="); Serial.print(set_num(DIO8,0)); Serial.print(set_num(DIO7,0)); Serial.print(set_num(DIO6,0)); Serial.print(set_num(DIO5,0)); Serial.print(set_num(DIO4,0)); Serial.print(set_num(DIO3,0)); Serial.print(set_num(DIO2,0)); Serial.println(set_num(DIO1,0)); } byte get_dio() { byte x = 0; bitWrite(x, 0, !set_num(DIO1,0)); bitWrite(x, 1, !set_num(DIO2,0)); bitWrite(x, 2, !set_num(DIO3,0)); bitWrite(x, 3, !set_num(DIO4,0)); bitWrite(x, 4, !set_num(DIO5,0)); bitWrite(x, 5, !set_num(DIO6,0)); bitWrite(x, 6, !set_num(DIO7,0)); bitWrite(x, 7, !set_num(DIO8,0)); return x; } void set_dio(byte x) { set_num(DIO1,bitRead(x,0)); set_num(DIO2,bitRead(x,1)); set_num(DIO3,bitRead(x,2)); set_num(DIO4,bitRead(x,3)); set_num(DIO5,bitRead(x,4)); set_num(DIO6,bitRead(x,5)); set_num(DIO7,bitRead(x,6)); set_num(DIO8,bitRead(x,7)); } boolean gpibWrite(byte data) {// true if error pinMode(NDAC, INPUT); if(gpibWait(NDAC,HIGH)){return true;} //until (LOW == NDAC) set_dio(data); // output data to DIO pinMode(NRFD, INPUT); if(gpibWait(NRFD,LOW)){return true;} //until (HIGH == NRFD) set_num(DAV,1); // validate data if(gpibWait(NDAC,LOW)){return true;} //until (HIGH == NDAC) set_num(DAV,0); set_dio(0); delayMicroseconds(30); return false; } boolean gpibRead(byte *data) { boolean ret; set_num(NRFD,0); // prepare to listen pinMode(DAV, INPUT); if(gpibWait(DAV,HIGH)){*data=0;return true;} //until (LOW == DAV) set_num(NRFD,1); // Ready for data *data = get_dio(); // read from DIO pinMode(EOI, INPUT); ret=(LOW == digitalRead(EOI)); // check EOI set_num(NDAC,0); // data accepted if(gpibWait(DAV,LOW)){*data=0;return true;} //until (HIGH == DAV) set_num(NDAC,1); return ret; // return true when EOI==LOW } void gpibTalk(byte addr, char *str) { set_num(EOI,0); gpibAttention(); if(gpibWrite(0x5F)){gpibAttentionEnd();return;} // untalk if(gpibWrite(0x3F)){gpibAttentionEnd();return;} // unlisten if(gpibWrite(0x40)){gpibAttentionEnd();return;} // talker address if(gpibWrite(0x20+addr)){gpibAttentionEnd();return;} // listener address gpibAttentionEnd(); // write string while (0 != *str) { if(0==*(str+1)){set_num(EOI,1);} if(gpibWrite(*(str++))){set_num(EOI,0);return;}; } set_num(EOI,0); Serial.println("OK"); } void gpibListen(byte addr, char *str) { *str=0; set_num(EOI,0); gpibAttention(); if(gpibWrite(0x5F)){gpibAttentionEnd();return;} // untalk if(gpibWrite(0x3F)){gpibAttentionEnd();return;} // unlisten if(gpibWrite(0x40+addr)){gpibAttentionEnd();return;} // talker address if(gpibWrite(0x20)){gpibAttentionEnd();return;} // listener address set_num(NRFD,1); set_num(NDAC,1); delayMicroseconds(10); gpibAttentionEnd(); // recieve data p = strlen(delim); do { if(gpibRead(str++)){*str=0;break;} *str=0; } while (strcmp(str-p, delim)); } void gpibIFC(void) { set_num(IFC,1); set_num(REN,0); delayMicroseconds(128); set_num(IFC,0); Serial.println("IFC"); } void gpibREN(int value) { set_num(REN,value); Serial.println("REN"); } void gpibSRQ(void) { Serial.print("SRQ="); Serial.println(set_num(SRQ,0)); } void gpibCmd(char cmd,char *str){ gpibAttention(); if(gpibWrite(cmd)){gpibAttentionEnd();return;} gpibAttentionEnd(); Serial.println(str); } void gpibAdr(char addr,char cmd,char *str){ gpibAttention(); if(gpibWrite(0x3F)){gpibAttentionEnd();return;} // unlisten if(gpibWrite(0x20+addr)){gpibAttentionEnd();return;} // listener address if(gpibWrite(cmd)){gpibAttentionEnd();return;} gpibAttentionEnd(); Serial.println(str); } void gpibDelim(char par){ if(par==0){delim[0]=10,delim[1]=0;} // LF else if(par==1){delim[0]=13,delim[1]=0;} // CR else if(par==2){delim[0]=13,delim[1]=10;} // CR LF Serial.println("change delimiter"); } void gpibAttention(){ // attention set_num(ATN,1); delayMicroseconds(20); } void gpibAttentionEnd(){ // end of attention set_num(ATN,0); delayMicroseconds(20); } boolean gpibWait(int ch, char hl){ unsigned long count=GPIBTIMEOUT; while(hl == digitalRead(ch) && --count){delayMicroseconds(1);} if(count==0){Serial.println("timeout error");} return count==0; } int set_num(uint8_t ch,char num){ if(num==0){pinMode(ch, INPUT); return digitalRead(ch);} //high else {pinMode(ch, OUTPUT);return 0;} //low }