Skip to content

Commit

Permalink
Merge pull request #15 from fchampalimaud/AS_olfactometer_example_2
Browse files Browse the repository at this point in the history
Add new olfactometer example
  • Loading branch information
artursilva0 authored Sep 24, 2024
2 parents 180bbf4 + b1ccc3c commit 2535534
Show file tree
Hide file tree
Showing 4 changed files with 276 additions and 3 deletions.
8 changes: 5 additions & 3 deletions docs/articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
href: install_bonsai.md
- name: Install Harp
href: install_harp.md
- name: Bonsai/Harp Examples (13)
- name: Bonsai/Harp Examples (14)
items:
- name: Behavior Board (11)
items:
Expand All @@ -32,10 +32,12 @@
href: ../workflows/HarpExamples/BehaviorBoard/QuadratureEncoder/QuadratureEncoder.md
- name: Log Selected
href: ../workflows/HarpExamples/BehaviorBoard/LogSelected/LogSelected.md
- name: Olfactometer (1)
- name: Olfactometer (2)
items:
- name: End Valve Toggle
href: ../workflows/HarpExamples/Olfactometer/EndValveToggle/EndValveToggle.md
href: ../workflows/HarpExamples/Olfactometer/EndValveToggle/EndValveToggle.md
- name: Odor Valve Toggle
href: ../workflows/HarpExamples/Olfactometer/OdorValveToggle/OdorValveToggle.md
- name: Syringe Pump (1)
items:
# - name: Toggle Single Steps
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,225 @@
<?xml version="1.0" encoding="utf-8"?>
<WorkflowBuilder Version="2.8.1"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
xmlns:harp="clr-namespace:Bonsai.Harp;assembly=Bonsai.Harp"
xmlns:p1="clr-namespace:Harp.Olfactometer;assembly=Harp.Olfactometer"
xmlns:wie="clr-namespace:Bonsai.Windows.Input;assembly=Bonsai.Windows.Input"
xmlns="https://bonsai-rx.org/2018/workflow">
<Workflow>
<Nodes>
<Expression xsi:type="Annotation">
<Name>1</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="rx:BehaviorSubject" TypeArguments="harp:HarpMessage">
<rx:Name>Device Commands</rx:Name>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="p1:Device">
<harp:OperationMode>Active</harp:OperationMode>
<harp:OperationLed>On</harp:OperationLed>
<harp:DumpRegisters>true</harp:DumpRegisters>
<harp:VisualIndicators>On</harp:VisualIndicators>
<harp:Heartbeat>Disabled</harp:Heartbeat>
<harp:IgnoreErrors>false</harp:IgnoreErrors>
<harp:PortName>COM5</harp:PortName>
</Combinator>
</Expression>
<Expression xsi:type="rx:PublishSubject">
<Name>Device Events</Name>
</Expression>
<Expression xsi:type="Annotation">
<Name>1.1</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:Parse">
<harp:Register xsi:type="p1:Channel0ActualFlow" />
</Expression>
<Expression xsi:type="Annotation">
<Name>1.2</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:Parse">
<harp:Register xsi:type="p1:Channel1ActualFlow" />
</Expression>
<Expression xsi:type="Annotation">
<Name>1.3</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:Parse">
<harp:Register xsi:type="p1:Channel4ActualFlow" />
</Expression>
<Expression xsi:type="Annotation">
<Name>2</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="wie:KeyDown">
<wie:Filter>B</wie:Filter>
<wie:SuppressRepetitions>false</wie:SuppressRepetitions>
</Combinator>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateEnableFlowPayload">
<p1:EnableFlow>Enabled</p1:EnableFlow>
</harp:Payload>
</Expression>
<Expression xsi:type="Annotation">
<Name>3</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="wie:KeyDown">
<wie:Filter>E</wie:Filter>
<wie:SuppressRepetitions>false</wie:SuppressRepetitions>
</Combinator>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateEnableFlowPayload">
<p1:EnableFlow>Disabled</p1:EnableFlow>
</harp:Payload>
</Expression>
<Expression xsi:type="Annotation">
<Name>4</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateEnableValvePulsePayload">
<p1:EnableValvePulse>Valve0 Valve1</p1:EnableValvePulse>
</harp:Payload>
</Expression>
<Expression xsi:type="Annotation">
<Name>5</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateValve0PulseDurationPayload">
<p1:Valve0PulseDuration>500</p1:Valve0PulseDuration>
</harp:Payload>
</Expression>
<Expression xsi:type="Annotation">
<Name>6</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateValve1PulseDurationPayload">
<p1:Valve1PulseDuration>500</p1:Valve1PulseDuration>
</harp:Payload>
</Expression>
<Expression xsi:type="Annotation">
<Name>7</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateChannelsTargetFlowPayload">
<p1:Channel0>80</p1:Channel0>
<p1:Channel1>80</p1:Channel1>
<p1:Channel2>0</p1:Channel2>
<p1:Channel3>0</p1:Channel3>
<p1:Channel4>720</p1:Channel4>
</harp:Payload>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="rx:Merge" />
</Expression>
<Expression xsi:type="MulticastSubject">
<Name>Device Commands</Name>
</Expression>
<Expression xsi:type="Annotation">
<Name>8</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="SubscribeSubject">
<Name>Device Events</Name>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="rx:SubscribeWhen" />
</Expression>
<Expression xsi:type="Annotation">
<Name>9</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="wie:KeyDown">
<wie:Filter>A</wie:Filter>
<wie:SuppressRepetitions>false</wie:SuppressRepetitions>
</Combinator>
</Expression>
<Expression xsi:type="Annotation">
<Name>9.1</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateOdorValveStatePayload">
<p1:OdorValveState>Valve0</p1:OdorValveState>
</harp:Payload>
</Expression>
<Expression xsi:type="MulticastSubject">
<Name>Device Commands</Name>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="rx:Delay">
<rx:DueTime>PT2S</rx:DueTime>
</Combinator>
</Expression>
<Expression xsi:type="Annotation">
<Name>9.2</Name>
<Text><![CDATA[]]></Text>
</Expression>
<Expression xsi:type="p1:CreateMessage">
<harp:MessageType>Write</harp:MessageType>
<harp:Payload xsi:type="p1:CreateOdorValveStatePayload">
<p1:OdorValveState>Valve1</p1:OdorValveState>
</harp:Payload>
</Expression>
<Expression xsi:type="MulticastSubject">
<Name>Device Commands</Name>
</Expression>
</Nodes>
<Edges>
<Edge From="0" To="1" Label="Source1" />
<Edge From="1" To="2" Label="Source1" />
<Edge From="2" To="3" Label="Source1" />
<Edge From="3" To="5" Label="Source1" />
<Edge From="3" To="7" Label="Source1" />
<Edge From="3" To="9" Label="Source1" />
<Edge From="4" To="5" Label="Source2" />
<Edge From="6" To="7" Label="Source2" />
<Edge From="8" To="9" Label="Source2" />
<Edge From="10" To="11" Label="Source1" />
<Edge From="11" To="12" Label="Source1" />
<Edge From="12" To="24" Label="Source1" />
<Edge From="13" To="14" Label="Source1" />
<Edge From="14" To="15" Label="Source1" />
<Edge From="15" To="24" Label="Source2" />
<Edge From="16" To="17" Label="Source1" />
<Edge From="17" To="24" Label="Source3" />
<Edge From="18" To="19" Label="Source1" />
<Edge From="19" To="24" Label="Source4" />
<Edge From="20" To="21" Label="Source1" />
<Edge From="21" To="24" Label="Source5" />
<Edge From="22" To="23" Label="Source1" />
<Edge From="23" To="24" Label="Source6" />
<Edge From="24" To="25" Label="Source1" />
<Edge From="25" To="28" Label="Source1" />
<Edge From="26" To="27" Label="Source1" />
<Edge From="27" To="28" Label="Source2" />
<Edge From="29" To="30" Label="Source1" />
<Edge From="30" To="32" Label="Source1" />
<Edge From="31" To="32" Label="Source2" />
<Edge From="32" To="33" Label="Source1" />
<Edge From="33" To="34" Label="Source1" />
<Edge From="34" To="36" Label="Source1" />
<Edge From="35" To="36" Label="Source2" />
<Edge From="36" To="37" Label="Source1" />
</Edges>
</Workflow>
</WorkflowBuilder>
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# Odor Valve Toggle

## Summary
This example demonstrates how to configure the Harp Olfactometer to toggle the Odor Valves using the [Harp Olfactometer](https://github.com/harp-tech/device.olfactometer) board (see hardware diagram below).

## Workflow

:::workflow
![Example](~/workflows/HarpExamples/Olfactometer/OdorValveToggle/OdorValveToggle.bonsai)
:::

## Details

1. Creates a subject node to send commands to the Olfactometer board and publishes all the events from the device. The PortName property in the Olfactometer node needs to be set to the COM device on the computer. To create the subject node, right-click on the Olfactometer node -> Create Source -> Behavior Subject, and name it accordingly.
1. Filters event messages associated with the Channel 0 flow rate.
2. Filters event messages associated with the Channel 1 flow rate.
3. Filters event messages associated with the Channel 4 flow rate.
2. Enables the Olfactometer flow by pressing the 'B' key.
3. Disables the Olfactometer flow by pressing the 'E' key.
4. Enables the valves to be configured with hardware generated pulse.
5. Configures the value (in milliseconds) of the Odor valve 0 pulse.
6. Configures the value (in milliseconds) of the Odor valve 1 pulse.
7. Sets the target flow rate for all the channels of the olfactometer. If they are not used they are configure with zero value.
8. Ensures that command messages are sent only when the device is ready.
9. Sets the state of the different valves to perform a 500 ms odor delivery after 'A' key press.
1. Odor valve 0 is enabled 2 seconds before the Odor valve 1 toggles.
2. Odor valve 1 is enabled.


## Requirements

This example requires the following Bonsai package:
- Harp.Olfactometer (from nuget.org) - make sure to select 'Include prerelease'


## Schematics

The [Harp Olfactometer](https://github.com/harp-tech/device.olfactometer) supports up to 4 odor channels and 1 carrier line.

In this example, Channel 0 (odor line) is configured with a 80 ml/min flow rate, Channel 1 (odor line) with 80 ml/min and Channel 4 (carrier line) with 720 ml/min.

After 'A' key press the odor channel 0 flow is enabled, goes through the correspondent vial, mixes with the auxiliary carrier line and is delivered to the animal. The duration of the odor pulse is 500 ms. Then, 2 s after the enabling of odor channel 0, odor channel 1 is also enabled during 500 ms, mixed with the auxiliary carrier line and delivered to the animal.

![Schematics](./OdorValveToggle.png){ width=80% }


Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 2535534

Please sign in to comment.