Midibus in a seperate thread - Feedback loop detected

Dear forum members!

I am just writing a patch to sonficate solar wind data i am rexeiving out of a txt file from a server.

I have managed to get the data parsed and send it to an external program via midibus.
Now i got the problem that when i use the function delay(300) it pauses the whole program for 300 milliseconds, which is quite inconvient, because you can’t control anything.
So I tried to move the midibus “sequencer” (this is how i called this bit) to a seperate function and call it with a new thread, so it won’t affect the whole program.
It actually works, i can controll the sliders again - but i get the following error messages:

java.lang.IllegalStateException: Receiver is not open
at com.sun.media.sound.AbstractMidiDevice$AbstractReceiver.send(AbstractMidiDevice.java:492)
at themidibus.MidiBus.sendMessage(Unknown Source)
at themidibus.MidiBus.sendNoteOn(Unknown Source)
at sketch_05_solarwind.sequencer(sketch_05_solarwind.java:246)
at sun.reflect.GeneratedMethodAccessor4.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at processing.core.PApplet.method(PApplet.java:3795)
at processing.core.PApplet$2.run(PApplet.java:3833)

and an error message from loopMidi which says “Feedback Loop detected”.

I am kinda stuck here. Could you maybe give me some thoughts and ideas please?

thanks in advance!

Here is the code:

// SOLAR WIND READER v0.5
// by Fabian Schober


ArrayList<Record> records;
String data;
String[] dataSet;
int recordCount = 0;
int startingEntry = 0; 
int lines;

import themidibus.*;
MidiBus MIDI;

import controlP5.*;


ControlP5 pControl; 
Slider p1Volume; Slider p2Volume; Slider p3Volume; Slider p4Volume; Slider p5Volume; Slider p6Volume; Slider p7Volume; Slider p8Volume; Slider p9Volume; Slider p10Volume;

PrintWriter output;

float v2p1; float v2p2; float v2p3; float v2p4; float v2p5; float v2p6; float v2p7; float v2p8; float v2p9; float v2p10;



void setup() {


 // MIDI.list();  // shows list of available devices
  MIDI = new MidiBus(this, "abletonPort", "abletonPort", "PSYN");

  String[] txt = loadStrings("https://services.swpc.noaa.gov/text/goes-energetic-proton-flux-primary.txt");
  lines = txt.length;
  println("there are " + lines + " lines");
  lines = lines - 26;
  String[] txtTemp = new String[lines];

  output = createWriter("protonFlux/"+""+hour()+""+minute()+""+second()+""+"ProtonFlux.txt");  // create TXT File

  arrayCopy(txt, 26, txtTemp, 0, lines);
  println("there are now " + txtTemp.length + " lines");
  data = join(txtTemp, ' ');
  dataSet = splitTokens(data);

  println("there are " + dataSet.length + " words");

  if (dataSet.length > 0) {
    println("DataSet loaded...");
  } else {
    println("DataSet is empty");
  }

//   for (int i = 0; i < dataSet.length; i++) {
//  output.println(dataSet[i]);
// }

  records = new ArrayList<Record>();
  
  for (int i = 0; i < dataSet.length; i = i+17) {

    records.add( new Record(dataSet[i], 
      dataSet[i+1], 
      dataSet[i+2], 
      dataSet[i+3], 
      dataSet[i+4], 
      dataSet[i+5], 
      dataSet[i+6], 
      dataSet[i+7], 
      dataSet[i+8], 
      dataSet[i+9], 
      dataSet[i+10], 
      dataSet[i+11], 
      dataSet[i+12], 
      dataSet[i+13], 
      dataSet[i+14], 
      dataSet[i+15],
  	 dataSet[i+16]));

  }

    for (int i = 0; i < records.size()-1; i++) {
    	records.get(i).p1 = records.get(i).p1.substring(0,4);
    	records.get(i).p2 = records.get(i).p2.substring(0,4);
    	records.get(i).p3 = records.get(i).p3.substring(0,4);
    	records.get(i).p4 = records.get(i).p4.substring(0,4);
    	records.get(i).p5 = records.get(i).p5.substring(0,4);
    	records.get(i).p6 = records.get(i).p6.substring(0,4);
    	records.get(i).p7 = records.get(i).p7.substring(0,4);
    	records.get(i).p8 = records.get(i).p8.substring(0,4);
    	records.get(i).p9 = records.get(i).p9.substring(0,4);
    	records.get(i).p10 = records.get(i).p10.substring(0,4);
    	records.get(i).p11 = records.get(i).p11.substring(0,4);

    	output.println("Record " + i + " Year:" + records.get(i).year);
    	output.println("Record " + i + " Month:" + records.get(i).month);
    	output.println("Record " + i + " Day:" + records.get(i).day);
    	output.println("Record " + i + " Time:" + records.get(i).time);
    	output.println("Record " + i + " Julian:" + records.get(i).julian);
    	output.println("Record " + i + " Seconds Day:" + records.get(i).secondsDay);
    	output.println("Record " + i + " P1:" + records.get(i).p1);
    	output.println("Record " + i + " P2:" + records.get(i).p2);
    	output.println("Record " + i + " P3:" + records.get(i).p3);
    	output.println("Record " + i + " P4:" + records.get(i).p4);
    	output.println("Record " + i + " P5:" + records.get(i).p5);
    	output.println("Record " + i + " P6:" + records.get(i).p6);
    	output.println("Record " + i + " P7:" + records.get(i).p7);
    	output.println("Record " + i + " P8:" + records.get(i).p8);
    	output.println("Record " + i + " P9:" + records.get(i).p9);
    	output.println("Record " + i + " P10:" + records.get(i).p10);
    	output.println("Record " + i + " P11:" + records.get(i).p11);
      
    }

  output.flush(); 
  output.close();

 
 size(400,400);
  background(255);

  pControl = new ControlP5(this);
		p1Volume = pControl.addSlider("p1Volume").setPosition(20,20).setSize(200,20);
		p2Volume = pControl.addSlider("p2Volume").setPosition(20, 45).setSize(200,20);
		p3Volume = pControl.addSlider("p3Volume").setPosition(20, 70).setSize(200,20);
		p4Volume = pControl.addSlider("p4Volume").setPosition(20, 95).setSize(200,20);
		p5Volume = pControl.addSlider("p5Volume").setPosition(20, 120).setSize(200,20);
		p6Volume = pControl.addSlider("p6Volume").setPosition(20, 145).setSize(200,20);
		p7Volume = pControl.addSlider("p7Volume").setPosition(20, 170).setSize(200,20);
		p8Volume = pControl.addSlider("p8Volume").setPosition(20, 195).setSize(200,20);
		p9Volume = pControl.addSlider("p9Volume").setPosition(20, 220).setSize(200,20);
		p10Volume = pControl.addSlider("p10Volume").setPosition(20, 245).setSize(200,20);


}



void draw() {

	// Volume control
	float v1p1 = p1Volume.getValue();
		  v2p1 = map(v1p1, 0, 100, 0, 1);

	float v1p2 = p2Volume.getValue();
		  v2p2 = map(v1p2, 0, 100, 0, 1);

    float v1p3 = p3Volume.getValue();
		  v2p3 = map(v1p3, 0, 100, 0, 1);

	float v1p4 = p4Volume.getValue();
		  v2p4 = map(v1p4, 0, 100, 0, 1);

	float v1p5 = p5Volume.getValue();
		  v2p5 = map(v1p5, 0, 100, 0, 1);

	float v1p6 = p6Volume.getValue();
		  v2p6 = map(v1p6, 0, 100, 0, 1);

	float v1p7 = p7Volume.getValue();
		  v2p7 = map(v1p7, 0, 100, 0, 1);

	float v1p8 = p8Volume.getValue();
		  v2p8 = map(v1p8, 0, 100, 0, 1);

	float v1p9 = p9Volume.getValue();
		  v2p9 = map(v1p9, 0, 100, 0, 1);

	float v1p10 = p10Volume.getValue();
		  v2p10 = map(v1p10, 0, 100, 0, 1);

	 thread("sequencer");
	

}

class Record {
  String year;
  String month;
  String day;
  String time;
  String julian;
  String secondsDay;
  String p1;
  String p2;
  String p3;
  String p4;
  String p5;
  String p6;
  String p7;
  String p8;
  String p9;
  String p10;
  String p11;


  Record(String yearTemp, String monthTemp, String dayTemp, String timeTemp, String julianTemp,
  				String secondsDayTemp, String p1Temp, String p2Temp, String p3Temp, String p4Temp,
  				String p5Temp, String p6Temp, String p7Temp, String p8Temp, String p9Temp,
  				String p10Temp, String p11Temp) {
    year = yearTemp;
    month = monthTemp;
    day = dayTemp;
    time = timeTemp;
    julian = julianTemp;
    secondsDay = secondsDayTemp;
    p1 = p1Temp;
    p2 = p2Temp;
    p3 = p3Temp;
    p4 = p4Temp;
    p5 = p5Temp;
    p6 = p6Temp;
    p7 = p7Temp;
    p8 = p8Temp;
    p9 = p9Temp;
    p10 = p10Temp;
    p11 = p10Temp;
  }
} 


void sequencer() {

		for (int i = 0; i < records.size(); i++) {

		float ap1 = float(records.get(i).p1);
		float bp1 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(0, int(bp1), int(v2p1));

		float ap2 = float(records.get(i).p2);
		float bp2 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(1, int(bp2), int(v2p2));

		float ap3 = float(records.get(i).p3);
		float bp3 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(2, int(bp3), int(v2p3));

		float ap4 = float(records.get(i).p4);
		float bp4 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(3, int(bp4), int(v2p4));

		float ap5 = float(records.get(i).p5);
		float bp5 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(4, int(bp5), int(v2p5));

		float ap6 = float(records.get(i).p6);
		float bp6 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(5, int(bp6), int(v2p6));

		float ap7 = float(records.get(i).p7);
		float bp7 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(6, int(bp7), int(v2p7));

		float ap8 = float(records.get(i).p8);
		float bp8 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(7, int(bp8), int(v2p8));

		float ap9 = float(records.get(i).p9);
		float bp9 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(8, int(bp9), int(v2p9));

		float ap10 = float(records.get(i).p10);
		float bp10 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(9, int(bp10), int(v2p10));


			 delay(300);

	}
}
1 Like

Not sure if thread is the solution for you here. You see, controlP5 has a handle for the current PApplet so does MIDI. I am not familiar with MIDI and I do not know the implementation of controlP5 internally. However, when you work with objects that manages the PApplet handle, I would keep them in the same thread. In your case, you should stick to the main drawing thread which you have access via draw(). Now, one trick here is that, instead of using delay(300), you can actually execute that code every 300ms which could be done using the timeUtils library or you can create your own definition based on the following demo:

int nextTime=0;  //GLOBAL scope

void draw(){

   if( millis() > nextTime ) {
      ... ALL the code under your sequencer function
      nextTime = millis() + 300;
  }

}

So the block above will execute only every 300ms approximately. Notice that based on your requirement, the way I implemented the code above is not accurate. This code above is just a demonstration and based on your requirements, it could be fine-tuned for functionality.

There is also something else I notice in your code. You are reading the controlP5 elements constantly in your draw() function. You should instead use each function’s callback. Why? Because every time you fire a change, you can use the callback function to update your global variables instead of updating it on every frame. You can check the examples that comes with the controlP5 as they demonstrate the usage of these functions.

Kf

1 Like

Hey there kfrajer,
I implemented the code you suggested and it worked like a charme - thanks a lot! Now the sequencer is a real seperate sequencer module with all its benefits. :slightly_smiling_face:

cheers!

1 Like

Hey, if I could maybe bother you just one more time! I am now trying to do the same with loading this txt-file from the server - it should update every five minutes and write the data in the same array, while deleting the old entries before doing that. Now I am getting this midi-feedback loop again, which is strange, because the midi stuff happens in a different function.
Do you know how i can update this txt-file continually?

UPDATE: I edited the windTime to 300000 - it was originally 5000 for trying purposes.

Here is the code I wrote so far:

// SOLAR WIND READER
// by Fabian Schober

String[] txt;

ArrayList<Record> records;
String data;
String[] dataSet;
int recordCount = 0;
int startingEntry = 0; 
int lines;
int time = 0;
int sequstep;
int windTime = 0;

import themidibus.*;
MidiBus MIDI;

import controlP5.*;


ControlP5 pControl; 
Slider p1Volume; Slider p2Volume; Slider p3Volume; Slider p4Volume; Slider p5Volume; Slider p6Volume; Slider p7Volume; Slider p8Volume; Slider p9Volume; Slider p10Volume;
Knob sequknob;

PrintWriter output;

float v2p1; float v2p2; float v2p3; float v2p4; float v2p5; float v2p6; float v2p7; float v2p8; float v2p9; float v2p10;



void setup() {


 // MIDI.list();  // shows list of available devices
  MIDI = new MidiBus(this, "abletonPort", "abletonPort", "PSYN");

  records = new ArrayList<Record>();

  windReader();

 
 size(400,400);
  background(255);

  pControl = new ControlP5(this);
		p1Volume = pControl.addSlider("p1Volume").setPosition(20,20).setSize(200,20);
		p2Volume = pControl.addSlider("p2Volume").setPosition(20, 45).setSize(200,20);
		p3Volume = pControl.addSlider("p3Volume").setPosition(20, 70).setSize(200,20);
		p4Volume = pControl.addSlider("p4Volume").setPosition(20, 95).setSize(200,20);
		p5Volume = pControl.addSlider("p5Volume").setPosition(20, 120).setSize(200,20);
		p6Volume = pControl.addSlider("p6Volume").setPosition(20, 145).setSize(200,20);
		p7Volume = pControl.addSlider("p7Volume").setPosition(20, 170).setSize(200,20);
		p8Volume = pControl.addSlider("p8Volume").setPosition(20, 195).setSize(200,20);
		p9Volume = pControl.addSlider("p9Volume").setPosition(20, 220).setSize(200,20);
		p10Volume = pControl.addSlider("p10Volume").setPosition(20, 245).setSize(200,20);


    sequknob = pControl.addKnob("sequknob")
               .setRange(0,1000)
               .setValue(300)
               .setPosition(20,300)
               .setRadius(50)
               .setDragDirection(Knob.VERTICAL);

          sequstep = int(sequknob.getValue());

}



void draw() {

	// Volume control
	float v1p1 = p1Volume.getValue();
		  v2p1 = map(v1p1, 0, 100, 0, 127);

	float v1p2 = p2Volume.getValue();
		  v2p2 = map(v1p2, 0, 100, 0, 127);

    float v1p3 = p3Volume.getValue();
		  v2p3 = map(v1p3, 0, 100, 0, 127);

	float v1p4 = p4Volume.getValue();
		  v2p4 = map(v1p4, 0, 100, 0, 127);

	float v1p5 = p5Volume.getValue();
		  v2p5 = map(v1p5, 0, 100, 0, 127);

	float v1p6 = p6Volume.getValue();
		  v2p6 = map(v1p6, 0, 100, 0, 127);

	float v1p7 = p7Volume.getValue();
		  v2p7 = map(v1p7, 0, 100, 0, 127);

	float v1p8 = p8Volume.getValue();
		  v2p8 = map(v1p8, 0, 100, 0, 127);

	float v1p9 = p9Volume.getValue();
		  v2p9 = map(v1p9, 0, 100, 0, 127);

	float v1p10 = p10Volume.getValue();
		  v2p10 = map(v1p10, 0, 100, 0, 127);

	sequencer();
	

}

class Record {
  String year;
  String month;
  String day;
  String time;
  String julian;
  String secondsDay;
  String p1;
  String p2;
  String p3;
  String p4;
  String p5;
  String p6;
  String p7;
  String p8;
  String p9;
  String p10;
  String p11;


  Record(String yearTemp, String monthTemp, String dayTemp, String timeTemp, String julianTemp,
  				String secondsDayTemp, String p1Temp, String p2Temp, String p3Temp, String p4Temp,
  				String p5Temp, String p6Temp, String p7Temp, String p8Temp, String p9Temp,
  				String p10Temp, String p11Temp) {
    year = yearTemp;
    month = monthTemp;
    day = dayTemp;
    time = timeTemp;
    julian = julianTemp;
    secondsDay = secondsDayTemp;
    p1 = p1Temp;
    p2 = p2Temp;
    p3 = p3Temp;
    p4 = p4Temp;
    p5 = p5Temp;
    p6 = p6Temp;
    p7 = p7Temp;
    p8 = p8Temp;
    p9 = p9Temp;
    p10 = p10Temp;
    p11 = p10Temp;
  }
} 


void sequencer() {

  if( millis() > windTime ) {

		for (int i = 0; i < records.size(); i++) {

		float ap1 = float(records.get(i).p1);
		float bp1 = map(ap1, 0, 10, 0, 127);
			MIDI.sendNoteOn(0, int(bp1), int(v2p1));
			// MIDI.sendNoteOn(0, int(bp1), 127);

		float ap2 = float(records.get(i).p2);
		float bp2 = map(ap2, 0, 10, 0, 127);
			MIDI.sendNoteOn(1, int(bp2), int(v2p2));
			// MIDI.sendNoteOn(1, int(bp2), 127);

		float ap3 = float(records.get(i).p3);
		float bp3 = map(ap3, 0, 10, 0, 127);
			MIDI.sendNoteOn(2, int(bp3), int(v2p3));
			// MIDI.sendNoteOn(2, int(bp3), 127);

		float ap4 = float(records.get(i).p4);
		float bp4 = map(ap4, 0, 10, 0, 127);
			MIDI.sendNoteOn(3, int(bp4), int(v2p4));
			// MIDI.sendNoteOn(3, int(bp4), 127);

		float ap5 = float(records.get(i).p5);
		float bp5 = map(ap5, 0, 10, 0, 127);
			MIDI.sendNoteOn(4, int(bp5), int(v2p5));
			// MIDI.sendNoteOn(4, int(bp5), 127);

		float ap6 = float(records.get(i).p6);
		float bp6 = map(ap6, 0, 10, 0, 127);
			MIDI.sendNoteOn(5, int(bp6), int(v2p6));
			// MIDI.sendNoteOn(5, int(bp6), 127);

		float ap7 = float(records.get(i).p7);
		float bp7 = map(ap7, 0, 10, 0, 127);
			MIDI.sendNoteOn(6, int(bp7), int(v2p7));
			// MIDI.sendNoteOn(6, int(bp7), 127);

		float ap8 = float(records.get(i).p8);
		float bp8 = map(ap8, 0, 10, 0, 127);
			MIDI.sendNoteOn(7, int(bp8), int(v2p8));
			// MIDI.sendNoteOn(7, int(bp8), 127);

		float ap9 = float(records.get(i).p9);
		float bp9 = map(ap9, 0, 10, 0, 127);
			MIDI.sendNoteOn(8, int(bp9), int(v2p9));
			// MIDI.sendNoteOn(8, int(bp9), 127);

		float ap10 = float(records.get(i).p10);
		float bp10 = map(ap10, 0, 10, 0, 127);
			MIDI.sendNoteOn(9, int(bp10), int(v2p10));
			// MIDI.sendNoteOn(9, int(bp10), 127);


			 // delay(300);

       time = millis() + sequstep;
     }

	}
}


void windReader() {

  if( millis() > windTime ) {

    String[] txt = loadStrings("https://services.swpc.noaa.gov/text/goes-energetic-proton-flux-primary.txt");
  lines = txt.length;
  println("there are " + lines + " lines");
  lines = lines - 26;
  String[] txtTemp = new String[lines];

  output = createWriter("protonFlux/"+""+hour()+""+minute()+""+second()+""+"ProtonFlux.txt");  // create TXT File

  arrayCopy(txt, 26, txtTemp, 0, lines);
  println("there are now " + txtTemp.length + " lines");
  data = join(txtTemp, ' ');
  dataSet = splitTokens(data);

  println("there are " + dataSet.length + " words");

  if (dataSet.length > 0) {
    println("DataSet loaded...");
  } else {
    println("DataSet is empty");
  }

//   for (int i = 0; i < dataSet.length; i++) {
//  output.println(dataSet[i]);
// }

  if (records.size() == 0) {
  
  for (int i = 0; i < dataSet.length; i = i+17) {

    records.add( new Record(dataSet[i], 
      dataSet[i+1], 
      dataSet[i+2], 
      dataSet[i+3], 
      dataSet[i+4], 
      dataSet[i+5], 
      dataSet[i+6], 
      dataSet[i+7], 
      dataSet[i+8], 
      dataSet[i+9], 
      dataSet[i+10], 
      dataSet[i+11], 
      dataSet[i+12], 
      dataSet[i+13], 
      dataSet[i+14], 
      dataSet[i+15],
     dataSet[i+16]));

  }

    for (int i = 0; i < records.size()-1; i++) {
      records.get(i).p1 = records.get(i).p1.substring(0,4);
      records.get(i).p2 = records.get(i).p2.substring(0,4);
      records.get(i).p3 = records.get(i).p3.substring(0,4);
      records.get(i).p4 = records.get(i).p4.substring(0,4);
      records.get(i).p5 = records.get(i).p5.substring(0,4);
      records.get(i).p6 = records.get(i).p6.substring(0,4);
      records.get(i).p7 = records.get(i).p7.substring(0,4);
      records.get(i).p8 = records.get(i).p8.substring(0,4);
      records.get(i).p9 = records.get(i).p9.substring(0,4);
      records.get(i).p10 = records.get(i).p10.substring(0,4);
      records.get(i).p11 = records.get(i).p11.substring(0,4);

      output.println("Record " + i + " Year:" + records.get(i).year);
      output.println("Record " + i + " Month:" + records.get(i).month);
      output.println("Record " + i + " Day:" + records.get(i).day);
      output.println("Record " + i + " Time:" + records.get(i).time);
      output.println("Record " + i + " Julian:" + records.get(i).julian);
      output.println("Record " + i + " Seconds Day:" + records.get(i).secondsDay);
      output.println("Record " + i + " P1:" + records.get(i).p1);
      output.println("Record " + i + " P2:" + records.get(i).p2);
      output.println("Record " + i + " P3:" + records.get(i).p3);
      output.println("Record " + i + " P4:" + records.get(i).p4);
      output.println("Record " + i + " P5:" + records.get(i).p5);
      output.println("Record " + i + " P6:" + records.get(i).p6);
      output.println("Record " + i + " P7:" + records.get(i).p7);
      output.println("Record " + i + " P8:" + records.get(i).p8);
      output.println("Record " + i + " P9:" + records.get(i).p9);
      output.println("Record " + i + " P10:" + records.get(i).p10);
      output.println("Record " + i + " P11:" + records.get(i).p11);
      
    } } else {

      for (int i = 0; i < records.size()-1; i++) {
      records.remove(i);
    }

       for (int i = 0; i < dataSet.length; i = i+17) {

    records.add( new Record(dataSet[i], 
      dataSet[i+1], 
      dataSet[i+2], 
      dataSet[i+3], 
      dataSet[i+4], 
      dataSet[i+5], 
      dataSet[i+6], 
      dataSet[i+7], 
      dataSet[i+8], 
      dataSet[i+9], 
      dataSet[i+10], 
      dataSet[i+11], 
      dataSet[i+12], 
      dataSet[i+13], 
      dataSet[i+14], 
      dataSet[i+15],
     dataSet[i+16]));

  }

    for (int i = 0; i < records.size()-1; i++) {
      records.get(i).p1 = records.get(i).p1.substring(0,4);
      records.get(i).p2 = records.get(i).p2.substring(0,4);
      records.get(i).p3 = records.get(i).p3.substring(0,4);
      records.get(i).p4 = records.get(i).p4.substring(0,4);
      records.get(i).p5 = records.get(i).p5.substring(0,4);
      records.get(i).p6 = records.get(i).p6.substring(0,4);
      records.get(i).p7 = records.get(i).p7.substring(0,4);
      records.get(i).p8 = records.get(i).p8.substring(0,4);
      records.get(i).p9 = records.get(i).p9.substring(0,4);
      records.get(i).p10 = records.get(i).p10.substring(0,4);
      records.get(i).p11 = records.get(i).p11.substring(0,4);

      output.println("Record " + i + " Year:" + records.get(i).year);
      output.println("Record " + i + " Month:" + records.get(i).month);
      output.println("Record " + i + " Day:" + records.get(i).day);
      output.println("Record " + i + " Time:" + records.get(i).time);
      output.println("Record " + i + " Julian:" + records.get(i).julian);
      output.println("Record " + i + " Seconds Day:" + records.get(i).secondsDay);
      output.println("Record " + i + " P1:" + records.get(i).p1);
      output.println("Record " + i + " P2:" + records.get(i).p2);
      output.println("Record " + i + " P3:" + records.get(i).p3);
      output.println("Record " + i + " P4:" + records.get(i).p4);
      output.println("Record " + i + " P5:" + records.get(i).p5);
      output.println("Record " + i + " P6:" + records.get(i).p6);
      output.println("Record " + i + " P7:" + records.get(i).p7);
      output.println("Record " + i + " P8:" + records.get(i).p8);
      output.println("Record " + i + " P9:" + records.get(i).p9);
      output.println("Record " + i + " P10:" + records.get(i).p10);
      output.println("Record " + i + " P11:" + records.get(i).p11);
      println("Object list written");
    }


    }

  output.flush(); 
  output.close();

  windTime = millis() + 30000;
  }
}

If it should update every 5 minutes you should use 300000 instead of 5000