C言語とgnuplotで負荷線を引く
ダイオードのIf-Vf特性が既知で曲線の数値データが入手できたとする。
RとVccを与えたときに、If-Vf特性のグラフに重ねて負荷線If=(Vcc-Vf)/Rを引き、
その交点からIf、Vfの値を得ることができる。
Vcc=5[V]、R=100~1000[ohm]として負荷線を引いてみた。IV特性はRPR-220のフォトダイオードの値を用いた。
グラフ右下に表示したVf、Ifが求められた値である。
/* コマンドラインで ivload (引数1:R[ohm]) (引数2:Vcc[ohm]) (iv特性の入ったファイル名) のようにして実行 I-V特性の入ったファイルを同ディレクトリに入れる 中身は 各行 V[V](半角スペース)I[mA] とする 負荷線を書いたグラフをpngで出力 環境:コンパイラcygwin gcc, gnuplotインストール&パス必要 */ #include <stdio.h> #include <stdlib.h> #include <string.h> int main(int argc, char *argv[]) { FILE *fin; FILE *gp; double R,Vcc; double *Vf,*If; int i; int size; //ファイルサイズ char ss[256]; double err=1e10; //err = Vcc-Vf-If*R int tmp; char *ivfname; char graphfname[30]="R"; /* 引数の数をチェック */ if(argc != 4){ puts("引数の数が違います\n"); exit(1); } R=atoi(argv[1]); Vcc=atoi(argv[2]); ivfname=argv[3]; /* グラフの名前 */ strcat(graphfname,argv[1]); strcat(graphfname,"Vcc"); strcat(graphfname,argv[2]); strcat(graphfname,".png"); printf("%s\n",graphfname); /* ファイルサイズを数える */ size=0; if((fin=fopen(ivfname,"r"))==NULL){ printf("入力ファイルをオープンできない.\n"); exit(1); } while(fgets(ss,256,fin)!=NULL){ size++; } fclose(fin); /* 数えたファイルサイズをもとにメモリ確保 */ Vf=(double*)calloc(size,sizeof(double)); if(Vf==NULL){ printf("メモリ確保ができません.\n"); exit(1); } If=(double*)calloc(size,sizeof(double)); if(If==NULL){ printf("メモリ確保ができません.\n"); exit(1); } /* ファイルの値を配列にコピー */ if((fin=fopen(ivfname,"r"))==NULL){ printf("入力ファイルをオープンできない.\n"); exit(1); } for(i=0;i<size;i++){ fscanf(fin,"%lf %lf\n",Vf+i,If+i); } /* err = Vcc-Vf-If*R がいちばん小さくなるiを探す*/ for(i=0;i<size;i++){ if(fabs(err) > fabs(Vcc-Vf[i]-If[i]*R/1000)){ err = Vcc-Vf[i]-If[i]*R/1000; tmp = i; } } printf("Vf=%f If=%f\n",Vf[tmp],If[tmp]); fclose(fin); free(Vf); free(If); /* グラフ描画 */ gp = popen("gnuplot -persist","w"); fprintf(gp,"R=%f\n",R); fprintf(gp,"Vcc=%f\n",Vcc); fprintf(gp,"set term png\n"); fprintf(gp,"set size square\n"); fprintf(gp,"set log y\n"); fprintf(gp,"set grid xtics ytics mytics\n"); fprintf(gp,"set xrange [0.8:2.0]\n"); fprintf(gp,"set yrange [0.1:1000]\n"); fprintf(gp,"set xlabel 'FORWARD VOLTAGE:V_F(V)'\n"); fprintf(gp,"set ylabel 'FORWARD CURRENT:I_F(mA)'\n"); fprintf(gp,"set label 1 'Vf=%4.3f If=%4.2f' at graph 0.6,graph 0.05\n",Vf[tmp],If[tmp]); fprintf(gp,"set output '%s'\n",graphfname); fprintf(gp,"plot '%s' using 1:2 w l lw 2 notitle,(Vcc-x)/R*1000 w l lw 2 title 'load line R=%3.0f Vcc=%1.1f'\n",ivfname,R,Vcc); fprintf(gp,"unset output\n"); pclose(gp); printf("get a graph in '%s'!\n",graphfname); return 0; }