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;
}




