Skip to content

Commit 46e8d52

Browse files
authored
Merge pull request #275 from OpenBCI/177-update-cyton-external-trigger
Update Cyton External Trigger Documentation
2 parents da8b47a + e28aab9 commit 46e8d52

File tree

5 files changed

+30
-128
lines changed

5 files changed

+30
-128
lines changed

website/docs/Cyton/07-External_Trigger_Cyton_Example.md

Lines changed: 30 additions & 128 deletions
Original file line numberDiff line numberDiff line change
@@ -3,98 +3,49 @@ id: CytonExternal
33
title: External Trigger on OpenBCI Cyton Board
44
---
55

6-
Sometimes, when studying EEG or other biopotential signals, you will want to have precise timing between external events or stimulus and the data stream. For example, if you are working with P300 waves it is necessary to know the exact time that the signal was presented to the subject in order to look for the tell-tale brain wave that happens about 300mS after the stimulus.
6+
import D17PushButton from "../assets/CytonImages/D17PushButton.jpg";
77

8-
This tutorial will cover a couple of ways to add an external trigger to the OpenBCI data stream on our 32bit Board. Normally, the Cyton board reads from the Accelerometer at 25 Hz. When we change board mode to `Analog` or `Digital` mode, we read from the external pins at same rate as the signal pins (e.g. 250 Hz)! This is what allows for the precise timing needed for external triggers.
8+
In a lot of EEG experiments, there is a requirement for precise timing between external stimuli and the data stream. For example, with in an experiment collecting P300 data, it is necessary to know the exact time that the signal was presented to the subject in order to look for the recorded EEG signal that occurs about 300ms after the stimulus.
99

10-
**Note:** As of 3.x.x Cyton firmware, the Cyton is able to switch board modes, now you don't have to upload new code to the board just to read from an input!
10+
This tutorial will cover the methods to add an external trigger to the OpenBCI data stream on othe Cyton and Cyton+Daisy boards. Normally, the Cyton reads from the Accelerometer at 25 Hz. When the "Digital Read" or "Analog Read" widgets in the GUI and opened and enabled, signals are read from the GPIO pins at same rate as the NxP input headers. This is what allows for the precise timing required for external triggers.
1111

12-
## External Triggering The Easy Way (Firmware 3.x.x)
12+
## Access the Digital Read Widget
1313

14-
### Using the OpenBCI GUI
14+
Launch the OpenBCI GUI for your operating system following the tutorial for the [OpenBCI GUI](../Software/OpenBCISoftware/01-OpenBCI_GUI.md#running-the-openbci_gui).
1515

16-
Follow the official [OpenBCI GUI guide](Software/OpenBCISoftware/01-OpenBCI_GUI.md) to download version 3.2.0 or later [from our website](http://openbci.com/index.php/downloads).
16+
Once the GUI has launched, follow the guide to [connect to the Cyton board from the OpenBCI GUI](../GettingStarted/Boards/01-Cyton_Getting_Started_Guide.md#iv-connect-to-your-cyton-board-from-the-gui).
1717

18-
Launch the OpenBCI GUI for your operating system following the tutorial for the [OpenBCI GUI](Software/OpenBCISoftware/01-OpenBCI_GUI.md#running-the-openbci_gui) (remember to [run your OpenBCIHub application](Software/OpenBCISoftware/01-OpenBCI_GUI.md#running-on-windows) first windows users!).
18+
After connecting the board to the GUI, open and enable the "Digital Read" for one of your widgets.
1919

20-
Once the GUI has launched, follow the guide to [connect to your Cyton from the OpenBCI GUI](GettingStarted/Boards/01-Cyton_Getting_Started_Guide.md#iv-connect-to-your-cyton-board-from-the-gui).
20+
![Digital Read Widget](../assets/CytonImages/DigitalReadWidget.png)
2121

22-
Once you have connected, you may selected the "Digital Read" for one of your widgets. Then select start digital read mode button in the top left of the newly populated widget. This will activate and send the proper commands to your Cyton. Note that the accelerometer will no long be turned on because the trigger data is now sent instead.
22+
Then select the start digital read mode button in the top left of the newly populated widget. This will activate and send the proper commands to your Cyton. Note that the accelerometer will no longer be turned on because the trigger data is now sent instead.
2323

24-
You can verify the digital read widget is working by pressing the "PROG" button which is hooked up to the D17 pin.
24+
![Turn on Digital Read Widget](../assets/CytonImages/EnableDigitalRead.png)
2525

26-
When you use a Cyton USB dongle, you get up to 5 digital IO pins to read from: D11, D12, D13, D17 and D18! If there appears to be a delay between when you press the button and when the digital read widget in the GUI shows the button pressed, then you may want to lower your serial port latency. Checkout the guides for lowering serial port latency [Windows](Troubleshooting/04-FTDI_Fix_Windows.md) and [macOS](Troubleshooting/05-FTDI_Driver_Fix_Mac.md), and [Linux](Troubleshooting/03-FTDI_Fix_Linux.md)!
26+
When you use a Cyton dongle, you get up to 5 GPIO (General Purpose Input and Output) pins to read from: D11, D12, D13, D17, and D18! If there appears to be a delay between when you press the button and when the digital read widget in the GUI shows the button pressed, then you may want to lower your serial port latency. Check out the guides for lowering serial port latency for [Windows](../Troubleshooting/04-FTDI_Fix_Windows.md), [macOS](../Troubleshooting/05-FTDI_Driver_Fix_Mac.md), and [Linux](../Troubleshooting/03-FTDI_Fix_Linux.md)!
2727

28-
### Programmatically Setting Board Mode
28+
## Trigger Methods on the Cyton Board
2929

30-
Firmware 3.x.x brings a long requested out-of-the-box ability to read from analog or digital inputs with the default firmware. Allowing you to simply read from the analog input (sending `/2`) or digital input (sending `/3`) with the type of two ascii commands. The default board is activated by default, and can always be achieved again by sending a `/0`.
30+
### Utilize the on-device push button
3131

32-
Learn more about board modes in the [Cyton SDK](Cyton/04-OpenBCI_Cyton_SDK.md#board-mode).
32+
The OpenBCI Cyton Board comes with a user-accessible pushbutton already on the board. This is the PROG button and it's attached to pin D17 with a 470K pulldown resistor. When you press the PROG button, D17 goes from LOW to HIGH. The PROG pushbutton is a great way to get user acknowledgment of a stimulus into the data stream.
3333

34-
### External Triggering The Easy Way (Firmware 2.x.x)
34+
<div style={{textAlign: 'center'}}>
35+
<img src={D17PushButton} width="300"/>
36+
</div>
3537

36-
Update to firmware version 3.x.x using the tutorial [**here**](Cyton/05-Cyton_Board_Programming_Tutorial.md)! May all your troubles disappear!
38+
Shown below is an example of what happens when the PROG button is pressed.
3739

38-
### Sample Code Links
40+
![PROG Button Working](../assets/CytonImages/PROGButtonWorking.gif)
3941

40-
The code used in this example is located [**here**](https://github.com/OpenBCI/OpenBCI_Button_Trigger) for those of you who want to play along at home. There's a tutorial for how to program the 32bit Board [**here**](Cyton/05-Cyton_Board_Programming_Tutorial.md)
42+
:::caution
43+
The PROG button, when used along with the RST button, can put the board into programming mode, which will affect its normal operation. The blue LED will start blinking if it is in programming mode. To get the board out of programming mode and back to normal operation, refer to the ["Did you Press the Reset Button?"](../Troubleshooting/Reset_Button_Press.md) guide.
44+
:::
4145

42-
### Utilize the on device push button
46+
We want to get the button press event into the data stream. (Reference the [OpenBCI Data Format Doc](03-Cyton_Data_Format.md) for data packet format.) There are 6 bytes available in each data packet, and the default format is to read them as three 16-bit integers (aka 'words' or 'shorts'). You can decide to add your flags into the auxData array any way you choose. In this example, we are setting each short to the value 0x6620. That's because our [OpenBCI GUI](https://github.com/OpenBCI/OpenBCI_Processing) converts these variables to Gs (the GUI is expecting accelerometer data) and 0x6620 converts to PI (3.14). Our sample rate of 250SPS gives us a 4ms resolution on external trigger events like the rising edge of the PROG button press.
4347

44-
The OpenBCI 32bit Board comes with a user accessible pushbutton switch already on the board, wired right to the PIC32 microcontroller. Brilliant! It is the PROG button, and it is used to put the PIC into bootloader mode when uploading new firmware. When it's not doing that it's attached to pin D17 with a 470K pulldown resistor, so when you press the PROG button, D17 goes from LOW to HIGH. The PROG pushbutton is a great way to get user acknowledgement of a stimulus (for example) into the data stream. You will likely want to note the rising edge (pushed state) of the button press, so that's the example code that we'll work with.
45-
46-
```
47-
48-
int pushButton = 17; // the button is on pin D17
49-
int pushButtonValue; // used to hold the latest button reading
50-
int lastPushButtonValue; // used to remember the last button state
51-
boolean addAuxToSD = false; // use this to write auxiliary data to SD if you like
52-
boolean state = HIGH; // used to toggle the on-board LED
53-
54-
```
55-
56-
First thing is to establish the variables we need to read the pushbutton switch, and a flag to let the rest of the program know we got new data. The OpenBCI library already has a variable array for auxiliary data, called auxData, which we will use for logging. I've also added a flag for writing data to an SD card (if you like that kind of thing) and a boolean to toggle the on-board blue LED for user feedback, which is always nice.
57-
58-
In the setup function, we set the pin direction and prime the button variables. The startFromScratch() function resets the board peripheral devices and does some general housekeeping, along with making initial serial contact with any controlling program. the useAccel and useAux variables are inside the OpenBCI_32_Daisy library (hence the **OBCI.**) and it's important to decide and select which kind of data you want to log. It is possible to do both, but you will need to manually operate the useAux or useAcel variables (tutorial on that coming sooooon).
59-
60-
```
61-
62-
void setup(){
63-
// stuff here...
64-
pinMode(pushButton, INPUT); // set the button pin direction
65-
pushButtonValue = lastPushButtonValue = digitalRead(pushButton); // seed
66-
startFromScratch(); // initialize OpenBCI, read device IDS
67-
68-
```
69-
70-
// you can set EITHER useAccel or useAux to true
71-
// if you want both, you MUST set and clear one of the variables every sample
72-
OBCI.useAccel = false; // option to add/remove accelerometer data to stream
73-
OBCI.useAux = true; // option to add/remove auxiliary data to stream
74-
// more stuff...
75-
{"}"}
76-
77-
Then, in the loop, we want to check for the rising edge of the button press, make note of it in the auxData array, and set the write-to-SD flag (if you like). Finally, we want to get the button press event into the data stream. (Reference the [OpenBCI Data Format Doc](03-Cyton_Data_Format.md) for data packet anatomy) There are 6 bytes available in each data packet, and the default format is to read them as three 16bit integers (aka 'words' or 'shorts'). You can decide to add your flags into the auxData array any way you choose. In this example, we are setting each short to the value 0x6620. That's because our [OpenBCI GUI](https://github.com/OpenBCI/OpenBCI_Processing) converts these variables to Gs (the GUI is expecting accelerometer data) and 0x6620 converts to PI (3.14). Our sample rate of 250SPS gives us a 4mS resolution on external trigger events like the rising edge of the PROG button press.
78-
79-
```
80-
81-
pushButtonValue = digitalRead(pushButton); // feel the PROG button
82-
if (pushButtonValue != lastPushButtonValue){ // if it's changed,
83-
if (pushButtonValue == HIGH){ // if it's gone from LOW to HIGH
84-
// 0x6220 converts to PI in GUI
85-
OBCI.auxData[0] = OBCI.auxData[1] = OBCI.auxData[2] = 0x6220;
86-
addAuxToSD = true; // add Aux Data to the SD card if it's there
87-
state = !state; // toggle the state variable
88-
digitalWrite(LED,state); // toggle the LED for user useability
89-
}
90-
lastPushButtonValue = pushButtonValue; // keep track of the changes!
91-
}
92-
93-
```
94-
95-
You can do the button feeling at any point in the loop() function. In our sample code linked above, I'm putting it outside of the if(is-running) conditional so that I can see the LED toggle even when the board is not streaming data. That's a nice way to know that you've got everything set up and working before starting a data logging session.
96-
97-
Here's an example of what the data looks like after it's been logged by our GUI.
48+
Here's an example of what the data looks like after it's been logged by our GUI:
9849

9950
```
10051
@@ -108,7 +59,7 @@ Here's an example of what the data looks like after it's been logged by our GUI.
10859
10960
```
11061

111-
And here's an example of what the data looks like after it's been logged to the SD card.
62+
And here's an example of what the data looks like after it's been logged to the SD card:
11263

11364
```
11465
@@ -122,65 +73,16 @@ DF,FFFCDE,FFFC00,FFFC49,FFFAC3,FFFBD0,FFFC91,FFFB03,FFFCB0
12273
12374
```
12475

125-
### External Triggering The Harder Way (Firmware 1.x.x)
76+
### Adding Trigger Markers from External Sources
12677

127-
Sometimes a situation may arise where you need to interface OpenBCI with an existing system, for example an audio or visual event-related potential (ERP). In such a case, it is most desirable to have the onset of the signal tightly bound, temporally, with the EEG data. It is possible to interface the OpenBCI 32bit Board with the external signal generating system using a few low-cost components.
128-
Our goal with the OpenBCI board is to make biosensing safe and fun. The biggest part of the safety part is making sure that you can't plug yourself accidentally into the mains electrical supply (yikes!). If you are interfacing an external trigger that is **NOT** operating under a battery supply, we recommend thinking twice about incorporating it into your system/protocol. If you have thought through it twice, here's how we do it when we need to.
78+
Sometimes a situation may arise where you need to interface OpenBCI with an existing system, for example, an audio or visual event-related potential (ERP). In such a case, it is most desirable to have the onset of the signal tightly bound, temporally, with the EEG data. It is possible to interface the Cyton Board with the external signal-generating system using a few low-cost components.
79+
Our goal with OpenBCI is to make biosensing safe and fun. The most important thing is making sure that you can't accidentally plug yourself into the mains electrical supply. If you are interfacing an external trigger that is **NOT** operating under a battery supply, we recommend thinking twice about incorporating it into your system/protocol. If you have thought through it twice, here's how we do it when we need to.
12980

130-
### Optoisolation
81+
#### Isolating the Cyton from an External Voltage
13182

13283
![Optoisolator Schematic](../assets/CytonImages/ExternalTriggerCNY17.jpg)
13384
![Breadboard CNY17](../assets/CytonImages/CNY17_Breadboard.jpg)
13485

135-
The simplest trick is to isolate the OpenBCI circuit from the trigger signal generating circuit. For this purpose, we picked an Optoisolator with 5000 Volts isolation between the input and the output. [CNY17](http://www.mouser.ee/ProductDetail/Vishay-Semiconductors/CNY17F-2X006/?qs=sGAEpiMZZMteimceiIVCB7Uit3aMEvQQFLjPtOr%2f870%3d) family from Vishay is a great example of a low-cost high isolation optoisolator. It's usually available, and costs under a dollar (USD) in singles. In the circuit to the right, when an external trigger of 3.3V to 5V is applied to the Anode of the input (pin 1), the output (pin 5) will go from HIGH to LOW.
136-
137-
```
138-
139-
int triggerPin = 18; // the CNY17 Collector is on pin 18
140-
int triggerValue; // used to hold the latest trigger reading
141-
int lastTriggerValue; // used to remember the latest trigger state
142-
boolean addAuxToSD; // option to add the aux data to the SD card
143-
144-
```
145-
146-
The code to read this trigger input is quite similar to the previous button code. In this case, we need to use a different pin (pin 18) and watch for the **falling** edge of the trigger.
147-
148-
```
149-
150-
void setup(){
151-
// stuff here...
152-
pinMode(triggerPin, INPUT); // set the button pin direction
153-
triggerValue = lastTriggerValue = digitalRead(triggerPin); // seed
154-
startFromScratch(); // initialize OpenBCI, read device IDS
155-
156-
```
157-
158-
// you can set EITHER useAccel or useAux to true
159-
// if you want both, you MUST set and clear one of the variables every sample
160-
OBCI.useAccel = false; // option to add/remove accelerometer data to stream
161-
OBCI.useAux = true; // option to add/remove auxiliary data to stream
162-
// more stuff...
163-
{"}"}
164-
165-
```
166-
167-
void loop(){
168-
// do stuff
169-
triggerValue = digitalRead(triggerPin); // feel the trigger pin
170-
if (triggerValue != lastTriggerValue){ // if it's changed,
171-
if (triggerValue == LOW){ // if it's gone from HIGH to LOW
172-
// 0x6220 converts to PI in GUI
173-
OBCI.auxData[0] = OBCI.auxData[1] = OBCI.auxData[2] = 0x6220;
174-
addAuxToSD = true; // add Aux Data to the SD card if it's there
175-
state = !state; // toggle the state variable
176-
digitalWrite(LED,state); // toggle the LED for user useability
177-
}
178-
lastTriggerValue = triggerValue; // keep track of the changes
179-
}
180-
181-
// do other stuff
182-
}
183-
184-
```
86+
The simplest trick is to isolate the OpenBCI circuit from the trigger signal-generating circuit. For this purpose, we picked an optoisolator with 5000 volts isolation between the input and the output. The [CNY17](http://www.mouser.ee/ProductDetail/Vishay-Semiconductors/CNY17F-2X006/?qs=sGAEpiMZZMteimceiIVCB7Uit3aMEvQQFLjPtOr%2f870%3d) family from Vishay is a great example of a low-cost, high-isolation optoisolator. It's usually available and costs under a dollar (USD) in singles. In the circuit to the right, when an external trigger of 3.3V is applied to the anode of the input (pin 1), the output (pin 5) will go from HIGH to LOW.
18587

18688
As always, help can be found at support@openbci.com and [openbci.com/forum](https://www.openbci.com/forum).
321 KB
Loading
266 KB
Loading
249 KB
Loading
4.77 MB
Loading

0 commit comments

Comments
 (0)