Skip to content

Commit 684ae2c

Browse files
committed
Fix 4th exercise to only trigger on rising edge
1 parent 1e121ca commit 684ae2c

4 files changed

Lines changed: 128 additions & 58 deletions

tutorials/hobgoblin-reaction.md

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The task begins with an inter-trial interval (`ITI`), followed by stimulus prese
2121

2222
### Exercise 1: Generating a fixed-interval stimulus
2323

24-
In this first exercise, you will assemble the basic hardware and software components required to implement the reaction time task. Connect the LED to digital output channel `0` (`GP15`) on the `Hobgoblin`. Connect the push button to digital input channel `0` (`GP2`) on the `Hobgoblin`.
24+
In this first exercise, you will assemble the basic hardware and software components required to implement the reaction time task. Connect the LED to digital output channel `GP15` on the `Hobgoblin`. Connect the push button to digital input channel `GP2` on the `Hobgoblin`.
2525

2626
>[!TIP]
2727
> You can use other digital input or digital output channels, but make sure to change the appropriate properties.
@@ -39,7 +39,6 @@ Next, we will set up our `Hobgoblin`.
3939
- During this tutorial we will need to have the ability to send/receive commands from distinct places in the workflow. To allow this kind of "many-to-one"/"one-to-many" communication, we will:
4040
- Insert a [`PublishSubject`] operator and name it `Hobgoblin Events`.
4141

42-
4342
- Right-click the [`Device`] operator, select `Create Source (Bonsai.Harp.HarpMessage)` > [`BehaviorSubject`]. Name the generated ``BehaviourSubject`1`` operator `Hobgoblin Commands`. Connect it as input to the [`Device`] operator.
4443

4544
>[!NOTE]
@@ -61,6 +60,7 @@ Lastly, we will set up a fixed-interval blinking LED as our stimulus.
6160
- Insert a [`CreateMessage`] operator, configure the `Payload` property to [`DigitalOutputClearPayload`], and set the [`DigitalOutputClear`] property to the `GP15` pin.
6261
- Insert a [`MulticastSubject`] operator and configure the `Name` property to `Hobgoblin Commands`.
6362
- Insert a [`Repeat`] operator.
63+
- Run the workflow, and verify that the LED is blinking.
6464

6565
### Exercise 2: Measuring reaction time
6666

@@ -72,7 +72,7 @@ Lastly, we will set up a fixed-interval blinking LED as our stimulus.
7272
- Insert a [`Parse`] operator after `Hobgoblin Events`. Configure the `Register` property to [`TimestampedDigitalOutputSet`].
7373
- Insert a [`SubscribeSubject`] operator. Configure the `Name` property to `Hobgoblin Events`.
7474
- Insert a [`Parse`] operator after `Hobgoblin Events`. Configure the `Register` property to [`TimestampedDigitalInputState`].
75-
- Run the workflow, and verify that both the stimulus and the button are correctly recorded.
75+
- Run the workflow, verify that both the stimulus and the button are correctly recorded.
7676

7777
>[!TIP]
7878
> We use separate `Hobgoblin Events` operators to avoid issues with [branching](https://bonsai-rx.org/docs/articles/subjects.html#branching-subjects). See also [workflow guidelines](https://bonsai-rx.org/docs/articles/workflow-guidelines.html)
@@ -138,7 +138,7 @@ In order to translate our simple reaction time task in the previous exercises in
138138
- Right-click, select `Group` > `Sink (Reactive)`. Set the `Name` property to `StimOff`.
139139

140140
> [!Note]
141-
> The `Sink` operator allows you to specify arbitrary processing side-effects without affecting the original flow of events. It is often used to trigger and control stimulus presentation in response to events in the task. Inside the nested specification, `Source1` represents input events arriving at the sink. In the specific case of `Sink` operators, the `WorkflowOutput` node can be safely ignored.
141+
> The [`Sink`] operator allows you to specify arbitrary processing side-effects without affecting the original flow of events. It is often used to trigger and control stimulus presentation in response to events in the task. Inside the nested specification, `Source1` represents input events arriving at the sink. In the specific case of `Sink` operators, the `WorkflowOutput` node can be safely ignored.
142142
143143
- Delete the [`Delay`] operator.
144144
- Insert a [`SelectMany`] operator after `StimOn`, and set its `Name` property to `Response`.
@@ -148,25 +148,34 @@ In order to translate our simple reaction time task in the previous exercises in
148148
![Stimulus presentation](../workflows/hobgoblin-reactiontime-stimulus-response-input.bonsai)
149149
:::
150150

151+
- Delete the `Source1` operator.
151152
- Insert a [`SubscribeSubject`] operator. Configure the `Name` property to `Hobgoblin Events`.
152-
- Insert a [`Parse`] operator after `Hobgoblin Events`. Configure the `Register` property to [`TimestampedDigitalInputState`].
153+
- Insert a [`Parse`] operator after `Hobgoblin Events`. Configure the `Register` property to [`DigitalInputState`].
154+
- Insert a [`Condition`] operator after the [`Parse`] operator.
155+
- Double-click on the [`Condition`] operator and add an [`Equal`] operator after the `Source1` operator. Set the `Value` property to `GP2`.
153156
- Insert a [`Take`] operator and set its `Count` property to 1.
154-
- Delete the `Source1` operator.
155157
- Connect the [`Take`] operator to `WorkflowOutput`.
156158
- Run the workflow a couple of times and validate the state machine is responding to the button press.
157159

160+
> [!Note]
161+
> [`DigitalInputState`] sends a [`HarpMessage`] when it detects a change on any of the digital input pins on the `Hobgoblin`. Using a [`Condition`] with a nested [`Equal`] operator allows us to filter only messages from that pin. It also has the nice effect of only detecting a button press (when the value goes fron `None` > `GP2`) instead of a button release (`GP2`>`None`).
162+
158163
<!--Reference Style Links -->
159164
<!-- [`AnalogData`]: xref:Harp.Hobgoblin.AnalogData -->
160165
<!-- [`AnalogDataPayload`]: xref:Harp.Hobgoblin.AnalogDataPayload -->
161166
[`BehaviorSubject`]: xref:Bonsai.Reactive.BehaviorSubject
167+
[`Condition`]: xref:Bonsai.Reactive.Condition
162168
[`CreateMessage`]: xref:Harp.Hobgoblin.CreateMessage
163169
[`Delay`]: xref:Bonsai.Reactive.Delay
164170
[`Device`]: xref:Harp.Hobgoblin.Device
165171
[`DeviceDataWriter`]: xref:Harp.Hobgoblin.DeviceDataWriter
172+
[`DigitalInputState`]: xref:Harp.Hobgoblin.DigitalInputState
166173
[`DigitalOutputSet`]: xref:Harp.Hobgoblin.DigitalOutputSet
167174
[`DigitalOutputClear`]: xref:Harp.Hobgoblin.DigitalOutputClear
168175
[`DigitalOutputSetPayload`]: xref:Harp.Hobgoblin.CreateDigitalOutputSetPayload
169176
[`DigitalOutputClearPayload`]: xref:Harp.Hobgoblin.CreateDigitalOutputClearPayload
177+
[`Equal`]: xref:Bonsai.Expressions.EqualBuilder
178+
[`HarpMessage`]: xref:Bonsai.Harp.HarpMessage
170179
<!-- [`KeyDown`]: xref:Bonsai.Windows.Input.KeyDown -->
171180
<!-- [`Merge`]: xref:Bonsai.Reactive.Merge -->
172181
[`MulticastSubject`]: xref:Bonsai.Expressions.MulticastSubject

workflows/hobgoblin-reactiontime-stimulus-response-input.bonsai

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,26 @@
1111
<Name>Hobgoblin Events</Name>
1212
</Expression>
1313
<Expression xsi:type="p1:Parse">
14-
<harp:Register xsi:type="p1:TimestampedDigitalInputState" />
14+
<harp:Register xsi:type="p1:DigitalInputState" />
15+
</Expression>
16+
<Expression xsi:type="rx:Condition">
17+
<Workflow>
18+
<Nodes>
19+
<Expression xsi:type="WorkflowInput">
20+
<Name>Source1</Name>
21+
</Expression>
22+
<Expression xsi:type="Equal">
23+
<Operand xsi:type="WorkflowProperty" TypeArguments="p1:DigitalInputs">
24+
<Value>GP2</Value>
25+
</Operand>
26+
</Expression>
27+
<Expression xsi:type="WorkflowOutput" />
28+
</Nodes>
29+
<Edges>
30+
<Edge From="0" To="1" Label="Source1" />
31+
<Edge From="1" To="2" Label="Source1" />
32+
</Edges>
33+
</Workflow>
1534
</Expression>
1635
<Expression xsi:type="Combinator">
1736
<Combinator xsi:type="rx:Take">
@@ -24,6 +43,7 @@
2443
<Edge From="0" To="1" Label="Source1" />
2544
<Edge From="1" To="2" Label="Source1" />
2645
<Edge From="2" To="3" Label="Source1" />
46+
<Edge From="3" To="4" Label="Source1" />
2747
</Edges>
2848
</Workflow>
2949
</WorkflowBuilder>

0 commit comments

Comments
 (0)