Hi I'm having an issue continuously recording data to a .csv file using the following script
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 file\n");
exit(1);
}
fprintf(focat,"Temp, Vcc, Tx_Bias, Tx, Rx, RAWTx, RAWRx\n");
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.4fC\n", temperature);
printf ("Vcc, Internal supply = %4.4fV\n", vcc);
printf ("TX bias current = %4.4fmA\n", tx_bias);
printf ("Tx, Optical Power = %4.4f dBm", optical_tx);
printf (", %6.6f mW\n", RAW_tx);
printf ("Rx, Optical Power = %4.4f dBm", optical_rx);
printf (", %6.6f mW\n", 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,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
//fclose(focat);
}
fclose(focat);
return 0;
}
When I have the code set up to open the .csv file prior to entering the loop I get the following error on the 1020th iteration:
SFP Temperature = 31.9258C
Vcc, Internal supply = 3.1374V
TX bias current = 8.0540mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Unable to open I2C device: Too many open files
When i change the comments towards the bottom of the code so it reads as follows:
//Appends DDM Data into a new row of a csv file
focat=fopen("fcatdata.csv", "a");
fprintf(focat, "%s,%s,%s,%s,%s,%s,%s\n",temp,vccc,txbi,optx,oprx,rwtx,rwrx);
fclose(focat);
and then also comment out the file open prior to the loop, I am subsequently presented with the following fault on the 1021st loop iteration:
SFP Temperature = 31.8906C
Vcc, Internal supply = 3.1372V
TX bias current = 8.0620mA
Tx, Optical Power = -1.8006 dBm, 0.660600 mW
Rx, Optical Power = -40.0000 dBm, 0.000100 mW
Segmentation fault
I think this related somehow to ulimit - n
showing a result of 1024
but i need to be able to run this script continuously for a week and therefore changing ulimit isnt a real solution for the problem.
I tested this theory by making a script which loops endlessly and appends the integer i to a csv file and that reached far beyond 1021 rows of data. This has been bothering me for a week now. Any help is appreciated.
Criticism on formatting etc it welcome, I don't often post here (or anywhere for that matter)
int read_eeprom(unsigned char address)
{
int xio,i,fd1;
xio = wiringPiI2CSetup (address);
if (xio < 0)
{
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
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: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
Edit 1: clarified the two scenarios where the file is opened and closed
Edit 2: added info on what is in read_eeprom
Edit 3: solved by adding close(fp);
at the end of read_eeprom
Edit 4: solved properly by adding close(xio);
at the end of read_eeprom
- Credits to @JohnH
You need to only call wiringPiI2CSetup()
once in the process. One way this can be achieved by using a static variable for xio
so that it will retain the value between calls:
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: %s\n",
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: %s\n",
address, strerror (errno));
return 1;
}
}
return 0;
}
Another way would be to call wiringPiI2CSetup()
each time you enter the routune, but then to close it between each call:
int read_eeprom(unsigned char address)
{
int xio, i, value;
xio = wiringPiI2CSetup (address);
if (xio < 0) {
fprintf (stderr, "xio: Can't initialise I2C: %s\n",
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: %s\n",
address, strerror (errno));
close(xio);
return 1;
}
}
close(xio);
return 0;
}