嗨,使用以下脚本将数据连续记录到.csv文件时遇到问题
int ddm(void)
{
// 96 Temp MSB, 97 Temp LSB, 98 Vcc MSB, 99 Vcc LSB
// 100 TX_BIA MSB, 101 TX_BIA LSB,
// 102 TX MSB, 103 TX LSB, 104 RX MSB, 105 RX LSB
FILE *focat;
float temperature, vcc, tx_bias, optical_tx, optical_rx, RAW_tx, RAW_rx;
char temp[10], vccc[10], txbi[10], optx[10], oprx[10], rwtx[30], rwrx[30];
int i;
//Open (or create) the csv file and write the heading row
focat=fopen("fcatdata.csv", "w");
if(focat == NULL)
{
printf("error openining filen");
exit(1);
}
fprintf(focat,"Temp, Vcc, Tx_Bias, Tx, Rx, RAWTx, RAWRxn");
fclose(focat);
focat=fopen("fcatdata.csv", "a+");
i=0;
//start infinite loop
for(;;)
{
if(!read_eeprom(0x51));
else exit(EXIT_FAILURE);
i=i+1;
//Taking MSB and LSB data and converting
temperature = (A51[96]+(float) A51[97]/256);
vcc = (float)(A51[98]<<8 | A51[99]) * 0.0001;
tx_bias = (float)(A51[100]<<8 | A51[101]) * 0.002;
optical_tx = 10 * log10((float)(A51[102]<<8 | A51[103]) * 0.0001);
optical_rx = 10 * log10((float)(A51[104]<<8 | A51[105]) * 0.0001);
RAW_tx = ((float)(A51[102]<<8 | A51[103]) * 0.0001);
RAW_rx = ((float)(A51[104]<<8 | A51[105]) * 0.0001);
//Display Diagnostics Monitoring Data in Terminal
printf ("SFP Temperature = %4.4fCn", temperature);
printf ("Vcc, Internal supply = %4.4fVn", vcc);
printf ("TX bias current = %4.4fmAn", tx_bias);
printf ("Tx, Optical Power = %4.4f dBm", optical_tx);
printf (", %6.6f mWn", RAW_tx);
printf ("Rx, Optical Power = %4.4f dBm", optical_rx);
printf (", %6.6f mWn", RAW_rx);
printf ("iteration %d n", i);
//Change the integers into strings for appending to file
sprintf(temp, "%4.4f", temperature);
sprintf(vccc, "%4.4f", vcc);
sprintf(txbi, "%4.4f", tx_bias);
sprintf(optx, "%4.4f", optical_tx);
sprintf(oprx, "%4.4f", optical_rx);
sprintf(rwtx, "%6.6f", RAW_tx);
sprintf(rwrx, "%6.6f", RAW_rx);
//Appends DDM Data into a new row of a csv file
//focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%sn",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
//fclose(focat);
}
fclose(focat);
return 0;
}
当我将代码设置为在进入循环之前打开.csv文件时,我在第 1020 次迭代中收到以下错误:
SFP 温度 = 31.9258C
Vcc, 内部电源 = 3.1374V
TX 偏置电流 = 8.0540mA
发射,光功率 = -1.8006 dBm,0.660600 mW
Rx, 光功率 = -40.0000 dBm, 0.000100 mW
无法打开 I2C 设备:打开的文件过多
当我将注释更改为代码底部时,它如下所示:
//Appends DDM Data into a new row of a csv file
focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%sn",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
fclose(focat);
然后注释掉循环之前打开的文件,随后在第 1021 次循环迭代中出现以下错误:
SFP 温度 = 31.8906C
Vcc, 内部电源 = 3.1372V
TX 偏置电流 = 8.0620mA
发射,光功率 = -1.8006 dBm,0.660600 mW
Rx, 光功率 = -40.0000 dBm, 0.000100 mW
分段错误
我认为这与ulimit - n
显示1024
的结果有关,但我需要能够连续运行此脚本一周,因此更改 ulimit 并不是该问题的真正解决方案。
我通过制作一个脚本来测试这个理论,该脚本无休止地循环并将整数 i 附加到 csv 文件中,并且远远超过 1021 行数据。这已经困扰了我一个星期了。任何帮助,不胜感激。
欢迎对格式等的批评,我不经常在这里(或任何地方)发布
<小时 />int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
return 0;
}
编辑1:阐明了文件打开和关闭的两种场景
编辑 2:添加了有关read_eeprom
中内容的信息
编辑3:通过在read_eeprom
末尾添加close(fp);
来解决
编辑4:通过在read_eeprom
末尾添加close(xio);
来正确解决 - @JohnH的学分
在此过程中只需调用wiringPiI2CSetup()
一次。 一种方法可以通过对xio
使用静态变量来实现这一点,以便它在调用之间保留值:
int read_eeprom(unsigned char address)
{
int i, value;
static int xio = -1;
if( xio == -1 ) {
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
return 0;
}
另一种方法是每次进入路由时调用wiringPiI2CSetup()
,然后在每次调用之间关闭它:
int read_eeprom(unsigned char address)
{
int xio, i, value;
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
for(i=0; i <128; i++) {
value = wiringPiI2CReadReg8 (xio,i);
if( value > 0 ) {
if (address == 0x50)
A50[i] = value;
else
A51[i] = value;
}
else {
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
close(xio);
return 1;
}
}
close(xio);
return 0;
}
通过在read_eeprom
末尾添加close(fd1);
来解决,如下所示:
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %sn",
strerror (errno));
return 1;
}
//loop through addresses and extract data from eeprom
for(i=0; i <128; i++)
{
fd1 = wiringPiI2CReadReg8 (xio,i);
if (address == 0x50)
{
A50[i] = fd1;
}
else
{
A51[i] = fd1;
}
if (fd1 <0)
{
fprintf (stderr, "xio: Can't read i2c address 0x%x: %sn",
address, strerror (errno));
return 1;
}
}
//close fd1 to prevent segfault and "too many files open" errors
close(fd1);
return 0;
}
用于识别FD泄漏的@Mat信用