timing marks, buffering delays, etc.

edited November 2014 in Software
Dear all,

I modified OpenBCI_GUI. I tried to recorded trigger data from another Processing sketch. 
I send data from my program to OpenBCI_GUI over UDP library in processing (oscP5).
I measured running time after starting OpenBCI_GUI and then saved together with EEG raw data.

I measured running time using Processing function  >>> millis().
You can see running time in the first column below.

My question is about yellow lable in saved data. In that time, trigger data was sent from my program to OpenBCI_GUI.
Are there any lost of EEG data during that delayed period ?

Could you give me any suggestion, please ?




20198, 67, -6180.75, -6262.56, -6203.23, -6260.03, -134016.05, -91871.30, -134522.69, -107017.73, 0.00, 0.00, 0.00
20198, 68, -6188.73, -6274.20, -6210.52, -6271.94, -134024.41, -91883.91, -134531.25, -107026.16, 0.00, 0.00, 0.00
20198, 69, -6192.86, -6280.91, -6214.16, -6278.83, -134028.08, -91890.34, -134534.77, -107029.49, 0.00, 0.00, 0.00
20198, 70, -6188.68, -6274.96, -6210.32, -6272.66, -134023.09, -91883.30, -134529.61, -107024.22, 0.00, 0.00, 0.00
20199, 71, -6181.40, -6264.52, -6203.70, -6262.00, -134016.00, -91872.69, -134522.42, -107017.31, 0.00, 0.00, 0.00
20199, 72, -6177.82, -6259.70, -6200.28, -6257.24, -134013.39, -91868.70, -134520.03, -107015.05, 0.00, 0.00, 0.00
20641, 73, -6185.08, -6270.65, -6206.95, -6268.41, -134021.14, -91880.64, -134527.92, -107022.92, 0.00, 0.00, 0.00
20642, 74, -6189.33, -6277.44, -6210.72, -6275.21, -134024.97, -91887.26, -134531.61, -107026.43, 0.00, 0.00, 0.00
20642, 75, -6187.50, -6273.93, -6209.23, -6271.43, -134022.33, -91882.54, -134528.81, -107023.59, 0.00, 0.00, 0.00
20642, 76, -6180.95, -6264.30, -6203.28, -6261.66, -134015.98, -91872.57, -134522.38, -107017.35, 0.00, 0.00, 0.00

«1

Comments

  • wjcroftwjcroft Mount Shasta, CA
    edited November 2014
    P300, hello.

    It's unclear to me at the moment if your delay issues are because of the UDP you mention, or because of the latency adjustment explained below.

    From your other screen snapshots it looks like you are running Windows (Windows 7?)  The VCP, Virtual COM Port driver from FTDI has a Latency Timer that can be manually adjusted.  Using the default settings supplied with the driver may result in larger buffering delays.  Try adjusting it as follows:

    In Control Panel / Device Manager / Ports / USB Serial Port (your COM port for the dongle) / Port Settings / Advanced -- (whew), is a setting called "Latency Timer" in milliseconds.  This is an FTDI specific item that controls how responsive the link is.  At the default of 16ms, you may see longer buffering pauses.  After changing this to 1ms, the buffering pauses should improve.  We don't believe there is any noticeable CPU penalty for this change, since the amount of data is small.

    Can you try that and post some similar debug output as you did before?  I'd like to see how the millisecond values are advancing.

    William

    PS the approximately half second delay shown between your yellow lines above -- I don't believe could be the Latency Timer issue.  So perhaps you are right, you may be doing some kind of blocking IO operation with UDP that occasionally locks things up for longer periods.  Still the Latency Timer adjustment should improve things.
  • edited November 2014
    It appears that the second column of your table is the packet counter created by the OpenBCI board.  You'll note that it increments smoothly...70, 71, 72, 73, 74, 75...through your highlighted region.  So, no data was lost, which is good.

    That won't help you with the half-second delay, however.
  • wjcroftwjcroft Mount Shasta, CA
    Chip, yeah, I had the same guess.  But wasnt sure if that second column was the packet counter or some internal counter of P300's program.  Does look like he is printing all the other sample values.  I'm wondering why the accelerometer values are all zero.  Does that have to be turned on with a command to the firmware?  Or maybe there is even now a button for it on the latest GUI.  I remember you saying that you were going to be using the accelerometer values for some simulated timing marks yourself on an earlier EEGHacker post.

  • edited November 2014
    Discussing the accelerometer is kinda straying from the OP, but I'm OK with that...

    Depending upon when P300 grabbed his version of the Processing_GUI (or depending upon when P300's OpenBCI board was flashed) the accelerometer data stream might not have been enabled.  The hardware certainly works, it's a matter of whether its data is being loaded into the outgoing data stream on his OpenBCI board and whether the data is being interpretted when the stream comes into Processing.

    At this point, I do think that the accelerometer has been all worked out.  I actually think that it was all worked out 3 weeks ago.  I know the Processing code was modified (by me) to handle the Accelerometer data as of Nov 4.  Joel took care of it on the OpenBCI hardware side.  I personally have yet to do an end-to-end test with the real hardware.  That would indeed be a good EEG Hacker post...i'd forgotten about it!

    Chip
  • Dear all,


    Thank you for discussion!

    Here, I used the latest version of GUI from openbci website. I added this in to your program. Highlight only.

      public void writeRawData_dataPacket(DataPacket_ADS1299 data, float scale_to_uV, float scale_for_aux) {
        if (output != null) {
                output.print(millis());
          output.print(", ");
          output.print(Integer.toString(data.sampleIndex));
          writeValues(data.values,scale_to_uV);
          writeValues(data.auxValues,scale_for_aux);
          output.println(); rowsWritten++;
          //output.flush();
        }
      }

    1. Now, I can see accelerometer values. Actually, I did not measure brain right now. Board was quite stable on the table. But I moved it in this time.
    2. Even if I did not run my program . I still see same delay about 440-460 ms. Delayed twice in one packet counter (0-255). So, UDP did not cause of the delay, right?
    3. Program on board I used the original one from shipping. I never flash new program into openbci.

    I have one more question.

    As you mentioned about packet counter . So, It mean that delay was not lost ???? right ??
    BTW, I will lean more about you packet counter

    Thank you for comments

    17592, 110, -102314.15, -90801.26, -148638.89, -89433.88, -187500.02, -87092.98, -184187.23, -166529.70, 0.00, 0.00, 0.00
    17592, 111, -102400.96, -90944.20, -148716.41, -89582.91, -187500.02, -87242.14, -184272.22, -166607.53, 0.00, 0.00, 0.00
    17593, 112, -102310.68, -90786.66, -148631.36, -89419.91, -187500.02, -87083.02, -184187.02, -166516.95, 0.00, 0.00, 0.00
    17593, 113, -102166.60, -90543.77, -148499.48, -89167.41, -187500.02, -86832.61, -184047.55, -166381.19, 0.00, 0.00, 0.00
    17593, 114, -102167.25, -90551.23, -148501.97, -89174.36, -187500.02, -86836.32, -184045.38, -166386.42, 0.00, 0.00, 0.00
    17593, 115, -102312.78, -90799.65, -148636.13, -89431.92, -187500.02, -87089.34, -184184.16, -166526.09, 0.00, 0.00, 0.00
    17593, 116, -102400.63, -90944.59, -148714.73, -89583.17, -187500.02, -87240.71, -184270.25, -166605.03, 0.00, 0.00, 0.00
    17594, 117, -102313.14, -90790.86, -148632.41, -89424.09, -187500.02, -87085.50, -184187.80, -166517.36, 416.00, -224.00, 8304.00
    17594, 118, -102166.84, -90545.48, -148498.33, -89169.02, -187500.02, -86832.61, -184046.11, -166379.31, 0.00, 0.00, 0.00
    17594, 119, -102166.98, -90551.05, -148500.33, -89173.96, -187500.02, -86834.42, -184043.39, -166383.98, 0.00, 0.00, 0.00
    18042, 120, -102313.19, -90799.69, -148635.31, -89431.83, -187500.02, -87087.69, -184182.92, -166524.45, 0.00, 0.00, 0.00
    18043, 121, -102406.13, -90950.81, -148718.84, -89589.21, -187500.02, -87245.16, -184274.02, -166608.31, 0.00, 0.00, 0.00
    18043, 122, -102319.29, -90798.66, -148637.00, -89431.77, -187500.02, -87091.71, -184192.31, -166521.30, 0.00, 0.00, 0.00
    18043, 123, -102172.15, -90551.85, -148502.22, -89175.39, -187500.02, -86837.51, -184049.75, -166382.30, 0.00, 0.00, 0.00
    18043, 124, -102168.01, -90551.90, -148500.09, -89174.74, -187500.02, -86833.66, -184042.72, -166382.72, 0.00, 0.00, 0.00
    18043, 125, -102311.09, -90797.23, -148631.97, -89429.17, -187500.02, -87083.58, -184179.17, -166520.22, 0.00, 0.00, 0.00
    18043, 126, -102403.71, -90948.98, -148715.00, -89587.33, -187500.02, -87241.60, -184269.77, -166603.86, 0.00, 0.00, 0.00
    18043, 127, -102319.69, -90800.63, -148635.88, -89433.77, -187500.02, -87091.78, -184190.75, -166519.31, 352.00, -320.00, 8368.00
    18044, 128, -102174.42, -90555.38, -148502.80, -89178.92, -187500.02, -86839.20, -184050.22, -166382.16, 0.00, 0.00, 0.00
    18044, 129, -102169.30, -90553.38, -148499.86, -89176.04, -187500.02, -86833.24, -184042.33, -166381.95, 0.00, 0.00, 0.00
    18044, 130, -102312.00, -90797.63, -148631.36, -89429.46, -187500.02, -87082.15, -184178.23, -166519.02, 0.00, 0.00, 0.00
    18044, 131, -102407.91, -90953.65, -148717.61, -89591.91, -187500.02, -87244.55, -184272.09, -166605.73, 0.00, 0.00, 0.00



  • wjcroftwjcroft Mount Shasta, CA
    Sorry to side track you with the accelerometer values.

    Did you adjust the Latency Timer in the Control Panel as mentioned previously?  Was hoping this would make the increments in your millisecond values less bunched up.  That is 4 to 7 of the same value of milliseconds each line.  (Longest group in printout above is a run of 7 at 18043.

    So yes, it appears no sample values are being lost.  However the buffering delays are still there.  

    When you take out your UDP code, does the half second delay go away?  How often are you getting half second pauses?


  • Hi, I attached results in one round counter packet at different latecy timer. For 16 ms, you can see twice pauses in every 0-255 counter packet.

    Here, no UDP code anymore. This was original program from openBCI website.

    Thank you

    image
  • Dear all,

    Where can I find the latest Arduino program (.ino) which was flashed on my openBCI board ?

    I found only .cpp and .h inside OpenBCI_8bit-master folder which dowloaded from openbci website (latest version).

    Thank you
  • wjcroftwjcroft Mount Shasta, CA
    P300, thanks for those graphs, very helpful.  So we see that with the 1 ms latency timer, packets come in about every 4 ms.  Which is what we would expect from the sample rate of 250 sps.  (1 / 250 = 4 ms per packet.)

    I'll let Chip or Joel answer the answer the question about the download flash, should be on one of our repos.

    So the half second delays we were seeing earlier, have now gone away with your UDP code added back in?

    William
  • Dear William,

    Those graphs in my last comments were plotted without any UDP code.

    I used the original program from openBCI website.


    Here, I attached graph when my program was running together with OpenBCIGUI (including UDP code). Maximum delay was about 45 ms. It's getting shorter.


    image

  • wjcroftwjcroft Mount Shasta, CA
    OK, I think we can now assume that the 30 to 40 ms pauses are some kind of interaction with the buffering in your UDP call.  Is that a synchronous type call?  Is there anyway you can do async IO or interrupt IO in Processing?  (You can in Java).

    ----

    On the topic of timing marks;  Chip has suggested on other posts that if you want to do some simple timing marks in your data, to just tap on the OpenBCI board.  Which should generate big spikes in the accel. data.  In fact you might even be able to detect which of the 3 axes you tapped on (!)  It looks like you may not have the latest firmware that enables the X, Y, Z data channels.  

    Another approach (as I think you are considering), is to just mod the firmware in the board to put your own values in the X, Y, Z positions, derived from digital input pins on the Arduino.  Joel fully suggested this approach for those not needing all channels of the accel. data;  and for those wanting to pass out of band info back up the pipeline.  Each axis is 16 bits, so you could have multiple bits in just one slot.

    William
  • edited November 2014
    Dear William,

    Thank you for suggestions.

    Actually, my research is quite similar to P300 speller system:


    But, one electrode channel is enough for my research.

    The only way that I can do is solving delay of UDP. Now, it might be not synchronized with the recording program. I has just sent message any time that UDP event happen, and then start new thread for recording trigger data on another .txt file.

    I will try to fix it. 

    Thank you
  • I added the code below into openbciGUI program. 

    I think that oscEvent from oscP5 library might interrupt serial event.

    void oscEvent(OscMessage theOscMessage) {  
      incomingMouseX = theOscMessage.get(idxtrigger).intValue();
      // print out the message
    thread("test");
    }

    void test(){
      print("OSC Message Received: ");
      println(incomingMouseX);
      trigger.print(millis());
      trigger.print(",");
      trigger.println(incomingMouseX);
      trigger.flush();
      idxtrigger++;
    }

    Could you have any suggestion, please? Actually, I have poor programming skills T_T.

    Thank you
  • Dear William,

    The red line show examples of time stamps of trigger data based on UDP events. 

    It seems that delay was not from UDP event. Is  it from serial comm ????? 


    image
  • wjcroftwjcroft Mount Shasta, CA
    Umm.  I think we've isolated the ~ 30 - 40 ms delays as being related to your UDP calls, correct? When you take those calls out (and use Chip's original code), everything runs smoothly on the graph you showed me earlier.

    There might be some profiling you can turn on, not sure. Some IDE environments let you see profiles of where delays and CPU usage pile up.

    I was also curious about your statement that you were only using 1 channel of EEG.  Is that really enough to do a P300 speller?  :-)  What is the trigger that sends your UDP message?  Can't you just use the firmware modification approach I mentioned earlier and wire your trigger to an Arduino digital input port?

    Regards,  William

  • These plotted from sam data. I extended period of plotting. Even though no UDP code, you can see delay on Chip's original code.

    image

    This make me think that delay came from Serial event.

    Thank you
  • edited November 2014
    Dear William,

    Yes, modified arduino code is another way. That why I asked for the latest firmware version (.ino) in the previous post.
    However, it's better to send the trigger signal from visual stimulation itself without any additional wire or sensor. (As Chip's blog, he used photo sensor for recording flickering frequency of his visual stimulation)

    Regard to my research, I developed high cognitive visual stimulation which induced high P300 amplitude. 
    Peak detection was quite enough for my applications. I do not need large datasets for trainning. 

    If I have a chance, I will post more information about my research in near future.

    Thank you
  • wjcroftwjcroft Mount Shasta, CA
    The original delays we were discussing were large and close to 1/2 second.  Those now appear to be gone with the 1 ms Latency Timer.

    The current delays are an order of magnitude less.  .04 seconds.  I don't understand what the problem is at this point. There may be some buffering delays in Processing itself the way it does it's IO, etc.  If you wanted a really fast and realtime / time constraint type environment -- you may want to consider other languages than Processing.  Such as bare Java or C++, even C#.  C# is pretty friendly. 

    You didnt answer my question earlier. What is the trigger info coming in on UDP?  Does it HAVE to be UDP.  Heck ethernet or wireless delays could impact you if you are that time constrained.
  • Dear William,

    Trigger is just only time stamp that let me know where is the starting point of each stimulation onset.

    To find P300 response, we need to do ensemble averaging. That's why trigger point is important.

    Example, You would like to select one target on the computer screen, you need to see it for 3-5 time flashing. Trigger will indicate onset time of each flashing
    Thank you
  • Dear William

    BTW, Your suggestion about latency setting was quite useful.

    I will continue working . You are right. I may not have problem with .04 seconds

    Thank you very much
  • wjcroftwjcroft Mount Shasta, CA
    P300, thanks.  The discussion here was very helpful, and your graphs especially illustrative of what was going on. Very cool.

    William

  • wjcroftwjcroft Mount Shasta, CA
    If you want to see if you can make those 40 ms spikes disappear in the Processing GUI, I'd first try commenting out the part of the code that is writing the data stream file.  It's entirely possible that these pauses are from that periodic output operation.  If the spikes in the graph disappear, then you know what code may benefit from your optimizations.

    The spikes look like they are happening at 2.5 second intervals.  Sounds like a file buffering operation to me.
  • If you want the best time-alignment between your EEG data and any markers, you could use the Analog Input pins on the OpenBCI board.  You'd have to modify the OpenBCI software, but if you have the OpenBCI board look at the Analog Input pin with every EEG sample, you will get the best time alignment possible.

    On the older OpenBCI design, I did this same thing when I attached a light sensor:


    The problem with this approach, however, is that you are now attaching electrical items to the OpenBCI board, which is also connected to your head.  If you are going to plug anything into the OpenBCI board, be sure that it is either completely unpowered (like a button or switch) or that it is battery powered.  Electrically attaching things to the OpenBCI board could pose an extreme electrical hazard to your brain.  Think what could happen if there were a power surge or lightning or something and it got into your board and then into your brain...it could shock you dead!

    But, if you're just attaching a button between the Analog Pin and the OpenBCI Ground, this is a great way to get excellent time alignment.

    Chip
  • wjcroftwjcroft Mount Shasta, CA
    Here's the cool tutorial Joel put together on external triggers,

    http://docs.openbci.com/tutorials/04-External_Trigger_32bit_Example

  • nekrodezynfekatornekrodezynfekator Poznan, Poland
    edited February 2015
    I have question about that tutorial ("EXTERNAL TRIGGERING THE HARDER WAY" part). Where can I find "18 pin"? I understand that this tutorial was written for old version of OpenBCI. Am I wrong?
  • wjcroftwjcroft Mount Shasta, CA
    Nek, hi.

    Joel @biomurph may have further comments, but the D18
    pin you refer to is on the chipKIT 32 bit boards. I think you can
    translate this to the 8 bit boards with some minor changes to use the A
    pins.

    William
  • biomurphbiomurph Brooklyn, NY
    If you are using the 32bit Board, you will find a pin on the lower right labeled D18, and it should be addressed as 18 in your code. You can make an alias:

    int trigger = 18;

    then initialize it and use it:

    pinMode(trigger,INPUT);
    someVar = digitalRead(trigger);

    If you are using an 8bit Board, the available pins are labeled A0 to A7.
    Pins A0 to A5 can be either Analog inputs, or digital GPIOs. pins A6 and A7 are Analog input only.
    Tutorial coming soon with code example for inputting triggers on the 8bit Board!

  • Tutorial for 8bit Board will be very helpful. I tried:

    LIS3DH AccP;
    ...
    int triggerPin = A0;        
    int triggerValue;        
    int lastTriggerValue;   

    void setup(void) {
    ...
      pinMode(triggerPin, INPUT);     
      triggerValue = lastTriggerValue = digitalRead(triggerPin); 
    ...
    }

    void loop() {    
    ...
          triggerValue = digitalRead(triggerPin);    
          if (triggerValue != lastTriggerValue){  
          AccP.axisData[0] = 0xFFFF;     
          auxAvailable = true;            
          lastTriggerValue = triggerValue; 
          }
    ...
    }

    but it doesn't work.
  • I have done it successfully. Maybe the code doesn't look elegant, but i think this is the simplest way. I didn't want to change a lot of the code.

    OpenBCI_8bit_SD.ino:

    int triggerPin = A0;
    byte triggerValue;
    void setup(){
    ...
    pinMode(triggerPin, INPUT);
    ...
    }
    void setup(){
    ...
    pinMode(triggerPin, INPUT);
    ...
    }
    void loop(){
    ...
    triggerValue = digitalRead(triggerPin);
    OBCI.sendChannelData(sampleCounter,triggerValue);
    ...
    }

    OpenBCI_8.h:

    void sendChannelData(byte, byte);

    OpenBCI_8.cpp:

    void OpenBCI::sendChannelData(byte sampleNumber, byte x){
    Serial.write(sampleNumber); // 1 byte
    ads.writeADSchannelData(); // 24 bytes
    //accel.writeLIS3DHdata(x); // 6 bytes
    Serial.write(x);
    Serial.write(x);
    Serial.write(x);
    Serial.write(x);
    Serial.write(x);
    Serial.write(x);
    }
  • biomurphbiomurph Brooklyn, NY
    nekrodezynfekator

    I published a tutorial on including external triggers with our 8bit Board here
    There is a branch of the OpenBCI_8bit Arduino code and library that adds Aux writing functionality linked in the tutorial.

    In the example I made, when the Arduino reads a button press it sets all of the AUX channels to 0x6220. That value gets converted to pi (3.14) by our Processing GUI. The GUI is expecting to see accelerometer data on those channels, and 0x6220 gets converted to pi by the math. 

    Hope that helps!
Sign In or Register to comment.