SD-only version for increased sample rate and interrupts

yjyj France , Bordeaux
edited May 2016 in Cyton
Hi everybody!

The question  of "increase the sample rate"  is repeatedly raised on the forum.
The answer is both "Simple" and "Complex"... (But not that much...)

A version who allows it can be found at:

https://github.com/yj-xxxiii/OpenBCI_2kHz

You can use it "as it is" or examine the source code.

This said Joel Murphy (Biomurph) and PushTheWorld are preparing a much improved upgrade release which will rely on interrupts, see there under:

https://github.com/biomurph/OpenBCI_32_Interrupt

Joel also wrote:


Awaiting for this future version you can use and look at this one. Some new added commands are commented in the readme of GitHub.

At 250Hz , it can be used with the "Processing's OBCI_ GUI"    but to record at higher sample rates on a SD you should use the Arduino "Serial Monitor". (Reset the card  before...)

On the following picture   (that I coloured)  you can see :

- in green the message sent by the card when you power it.

- in blue some commands (chars have to be sent one by one and each char is sent back)

- in red the card answers to the commands... (Dont wory, there was no SD Card in it...)

It is not clean, some "CRLF" could be added... But it works more or less...


image

"Taille max des fichiers" means  : maximum size of the files.

  Have fun and give me your impressions or ideas ,    if you try it,

  y.j.

Comments

  • Hi @yj,

    Thanks so much for posting your code.  I started playing around with it today.  I noticed that my channels 9-16 of my daisy board are flat lines when I stream data with your code.  It's definitely not my hardware, because I get data from them with the standard firmware.  Did you successfully test with a 16 channel board?  Do you have any guess what the issue might be?

    Thanks,
    Winslow
  • yjyj France , Bordeaux
    edited June 2016
    @Winslow_Strong,

    Yes, sorry I do not have and use the daisy board.
    The code does nearly nothing  in case of a present Daisy.
    It's already a chance that it does not completly crashes...

    Your hardware is OK, that's sure...

    Do you obtain flat lines by air (blue tooth) or from SD ? (or both?)

    I can have a look to the code, there is probably not a lot to modify... 
    But currently we use all our cards (6 stations) to record mice 23h/24h
    and as a consequence I could not take one of them to debug my attempt to
    correct the code. (I am a very bad programmer, it never works on the
    first try...).

    From memory I think that I read the Daisy_1299 but
    I do not push in the circular buffer these data and of coarse I dont
    retreive (pop) them . I steadfastly ignores the daisy board (joke)
    I dont remember..., I will have a look if you wish to record 16 channels on the SD . 

    2kHz sampling rate works with 8 channels but with 16 no more than 1kHz.
    I tried 4kHz/8channels, it does not crashes but  it is full of overruns...

      Tell me if...
       Y.J.
  • yjyj France , Bordeaux
    @Winslow_Strong,

    I had a glance to the code,
    my memory is bad ,
     the code does more than I wrote in the previous post...

    I need a time for calm reflection...

    y.j.
  • @yj, thanks for having a look.  Yes, even recording to SD, channels 9-16 are all 0 for all frequencies 250-2k.  

    I succeeded in creating a USB serial link from OBCI pins D11 and D12 and the UART "Serial1" capability of the board.  It works at 460800 baud at least (haven't tested higher yet).  So I'm actually attempting to get higher frequencies streaming over that, and don't really need to write to the SD card.  

    So I was looking for a template .ino to modify to accomplish that.  Yours seemed like the best option, since you had already implemented higher sample rates in some fashion.  As we discussed earlier in the other thread, there's the issue that the reported samples on channels 1-8 and 9-16 are not actually synchronous, due to the every-other-sample reporting done. That will need to be modified too, so Im about to start hunting for that snippet of code.  
  • yjyj France , Bordeaux
    @Winslow_Strong,   if you have time...

    I am not sure but try (Sorry , currently I have no available card to test these suggestion modifs)  :

    1)  To not to ignore the Daisy_Board  (at least this should be done )
         In the function       void OpenBCI_32_Daisy::startADS(void)       

      replace     WREG(CONFIG1,0x90                                               + Sample_Rate,BOARD_ADS);
      by            WREG(CONFIG1,0x90 + (daisyPresent? 0xB0-0x90:0) + Sample_Rate,BOARD_ADS); 

      It might be not enough... a bug hides another bug

    2)  To synchronize  the ADS1299 means,  in the two update functions  

         - OpenBCI_32_Daisy::updateBoardData()
            replace twice     daisyPresent    by      ! firstDataPacket
            comment or delete the last line :   if(firstDataPacket == true)  firstDataPacket = false;     

         - Do the same modifs in OpenBCI_32_Daisy::updateDaisyData()  
            Add the test of     ! firstDataPacket     ( I supresssed it )
           To toggle  firstDataPacket replace the commented line by :
           firstDataPacket  = ! firstDataPacket  ;

        It might be something like that,  be careful I am ofen "absent-minded"...

    @biomurph,

    // if daisyPresent tell on-board ADS to output its clk, set the data rate to Sample_Rate

       I do not understand what determines the sample rate of the Daisy_1299.
       Is it the clock it receives from the Board_1299 ?
       if not ,  what should we do/write ?

      y.j.
  • biomurphbiomurph Brooklyn, NY
    Writing to the CONFIG register sets the sample rate.
    making the board ADS output it's CLK will sync both of the ADS chips to the same system clock so that they have as tight timing as possible.
  • yjyj France , Bordeaux
    edited June 2016
    Thank's @biomurph,

    I imagined/(wondered if) ,   that this "clock" signal could be "sample rate" dependent and could have forced the Daisy_ADS to follow the rate and sync...

    So we must write as I already wrote and asked  to Winslow_Strong :
    WREG(CONFIG1  , 0x90 + SampleRate ,      DAISY_ADS )
    WREG(CONFIG1  , 0xB0 + SampleRate ,      BOARD_ADS )

    isn't ?   (I can't test since I do not have a daisy )

    y.j.
  • I downloaded files from https://github.com/yj-xxxiii/OpenBCI_2kHz. 
    I
    used Ardunio 1.6.5 on MacOS 10.11.5. I've copied the folder libraries
    from https://github.com/yj-xxxiii/OpenBCI_2kHz to the folder Ardunio. I
    Upload OpenBCI_32bit_SD_Only.ino on my OpenBCI Board. I do not use the
    Daisy board (I only use 8 channels). I can not send any commands to the
    board OpenBCI from Serial Monitor.
    Please help. I just want to see the EEG signal in the frequency 2KHz, just 2 channels is good enough.
    image
  • yjyj France , Bordeaux
    edited July 2016
    Hello @nhatminh84,

    You must send the chars one by one.

    '.'  send
    "2"  send


    I see that you wrote ".2" in the input window.

    If you want to send the string ".2" then write +.++2+  and send.

    (I use windows XP...)


    What do you mean by "see the 2kHz"?
    You will not "see" the 2kHz it has to be recorded on the SD card...
    the 250 Hz can be seen... with the processing GUI.

    Sincerely,
    y.j.
  • Thank's yj
    Do not fret because of my stupidity. I first used the Arduino. I want to record 1-minute to SD card with Sample Rate 500Hz, I need to write these commands? Please help me. Thanks a lot.
    image
  • yjyj France , Bordeaux
    @nhatminh84,

    Yes ,  you have to write that
    and   to send an "N" command to start recording.

    The file FI_7204.bin   will be a binary file...

    To get a *.txt  file, more readable  ,   send a single 'B'  ,   it toggles     .bin / .txt

    y.j.
  • edited July 2016
    @yj

    I finally got around to testing your suggestion of explicitly changing the sample rate on the daisy in addition to mainboard. 

    Yes! It does seem necessary to also change the sample rate on the Daisy.  Otherwise channels 9-16 sample at the default 250Hz, not at the increased rates I've been testing.

    In OpenBCI_32_Daisy.cpp, I changed the code by adding the line in bold:

     if(!daisyPresent){
          WREG(CONFIG1,0x90+Rate_Adj,BOARD_ADS); //turn off clk output if no daisy present
          numChannels = 8;    // expect up to 8 ADS channels
        }else{
          WREG(CONFIG1,0x90 + Rate_Adj,DAISY_ADS); //WS via YJ - Change sample rate of Daisy to match main.
          numChannels = 16;   // expect up to 16 ADS channels
        } 

    Where Rate_Adj is the sample rate adjustment parameter in the .ino file. 

    // Sample Rate   16KHz  8kHz  4kHz  2kHz  1kHz  500Hz   250Hz     Do not use
    // Rate_adj: 0b    000     001    010     011    100    101     110          111

    //uint8_t Rate_Adj = 0b100 ;  // 1000Hz
    uint8_t Rate_Adj = 0b101 ;  // 500Hz
    //uint8_t Rate_Adj = 0b110 ;  // 250Hz

  • This is great! I really wanted to have a higher than 250Hz sampling frequency with my V3 - 32bit board.
    Is it already "officially/stable" ? Should I use the "biomurph" or "yj-xxiii" ?

    So, how can I do this to record 7 channels at 500Hz? (windows 7)
    Is there any way to sync the start of the recording with a trigger from the PC?

    Thanks in advance.
  • yjyj France , Bordeaux
    @ PedroMen,

    If you need 500Hz and accept to record on the SD only using the command 'N' then upload the yj-xxxiii.
    Else use Winslow_Strong version but you will have to build a hardware link.


    Can you describe a bit what you want to do?
    (If your program can send the 'N' on the serial line, then you will trigger the start of the recording...)

    y.j.
  • Thank you @yj

    A person is looking to a PC monitor as it will show some stimulus (images or video) and I would like to sync the presentation of the stimulus with the recording.
    I mean, I want to be able to know in the OpenBCI file when the stimulus was presented, so that I can analyze what happens right after and compare the before/after state of mind.

    I think 500Hz would be enough, but what is the highest sampling rate you can get without problems (overruns?) ?
  • yjyj France , Bordeaux
    edited November 2016
    @PedroMen,

    1)
         2kHz is the highest sampling rate one can get without problems.

    2)
         If the sound track of the video is not already used, if you can associate some sounds to the images then you could use the sound card output of the  P.C. to "trigger , mark , tag" a signal in the auxiliary field.
    It can be wired through an optical isolator, see in the learning section of the OBCI web site.
    It can be through an Infra Red burst sent by 940nm diodes plug in the sound card, to an IR receptor plugged in the OBCI Card. (like your TV remote control)
    I am using this second way to do.
    I'll give all details and code when it will be clean...

    But in brief the principle:

    - make a 40kHz wav sound (at least 20 periods burst ) synchronized with the video frame / image, to excite  a  940 nm diode.
    - Plug in the OBCI Card, an Infra Red burst receptor  such as the 3 pins component  TSOP34840 (ref Farnell: 1469638). 

    A little modification in the yj-xxxiii code will provide you a tag in the auxiliary data of the SD recording... (keeping 8 channels)

    The output level of the sound card as to be around 2 volts rms in order to exite the 1.3 volts 940nm - IR diodes...
    A few mA from this sound card are enough to transmit a signal at the distance of a few tenth of centimeters.
    If the frequency output of the sound card cannot reach 40kHz , make an arround  20kHz sound (or 44.1/2 it is nicer and works)  and use two "head to tail mounted" diodes to double the freq.
    Note that the IR burst length must be longer than the sample period... (0.5 .. 4 mS, it can be shorter if you use the PIC32 interrupt  to record IR receptor signal change)

    y.j.

    P.S. : Ask @PushTheWorld to know if the new "Sync Command" can do the job  (I did not understood what this command does, but it "sounds nice").
  • I have uploaded yj-xxxiii code to oBCI and it worked. Then I reuploaded the default v1 firmware, but SD card functionality is gone. The createContiguous function under SD library returns a false apparently. I reuploaded yj-xxxiii code and it started to work again. What might be the issue here? Could it be because yj-xxxiii code writes to EEPROM? I'm lost, please help.
  • yjyj France , Bordeaux
    @yttuncel,

    Its a fact that I never went back from my code to the previous initial version...
    Your hypothesis is good, it could be because I used differently the EEPROM...

    The basic code (there under in blue) supposes that 
    variables fileOnes and fileTens  are inside 0..9 or A..F,   or equal to 0xff.
    It is probably not the case if you played with my code.

    Rewrite the following line  in order to check if it is inside 0..9 or A..F,   or equal to 0xff, (I agree that it is much more longer...)
         // if it's the first time writing to EEPROM, seed the file number to '00'
           if(  fileTens == 0xFF | fileOnes == 0xFF )   {     fileTens = fileOnes = '0';  }
    and see if  the createContiguous function  is OK.

    I am nearly sure that you already tried it...
     
       y.j.

    void incrementFileCounter(){
      fileTens = EEPROM.read(0);
      fileOnes = EEPROM.read(1);
      // if it's the first time writing to EEPROM, seed the file number to '00'
      if(fileTens == 0xFF | fileOnes == 0xFF){
        fileTens = fileOnes = '0';
      }
      fileOnes++;   // increment the file name
      if (fileOnes == ':'){fileOnes = 'A';}
      if (fileOnes > 'F'){
        fileOnes = '0';         // hexify
        fileTens++;
        if(fileTens == ':'){fileTens = 'A';}
        if(fileTens > 'F'){fileTens = '0';fileOnes = '1';}
    }

Sign In or Register to comment.