{ "name": "biomaker-grove-tutorial-v2", "patches": { "@/tuto000-introduction": { "comments": { "Sy3bms2Lv": { "content": "**Welcome to No-Code Programming for Biology!**\n*This tutorial is designed to accompany the Open Plant Biomaker No-Code Programming for Biology Beginner's Guide.* \n\nIt will introduce you to the basics of using XOD as well as some simple hardware. Our beginner's guide uses the [Grove All-in-one Beginner Kit for Arduino](https://www.seeedstudio.com/Grove-Beginner-Kit-for-Arduino-p-4549.html?gclid=Cj0KCQjw8fr7BRDSARIsAK0Qqr48EzQQLHNapejVpJZq7i0NiSxg0TG0_Ephxa3OaHbeetzX-EmHb0caAqpqEALw_wcB), but can also be adapted for other Arduino-based microcontrollers.\n\nIf you haven't done so already, we advise dowloading the Beginner's Guide from the [Biomaker website](https://www.biomaker.org/nocode-programming-for-biology-handbook) and reading through 'Lesson 1: Introduction' and the start of 'Lesson 2: Getting Started'. This will provide some useful background information to help you with the tasks in this tutorial.\n\nYou can complete this tutorial by opening and working through each of the patches in turn. These can be found in the Project Browser, at the top left of the screen.\n\n*When you're ready let's start with Task 1: Testing Your Board, by opening 'tuto101-testing-your-board'...*", "id": "Sy3bms2Lv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 4, "width": 10, "units": "slots" } } }, "path": "@/tuto000-introduction" }, "@/tuto101-testing-your-board": { "comments": { "HkRaG32LP": { "content": "**Task 1: Testing Your Board**\n*Adding a Node*", "id": "HkRaG32LP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SJxEwnoT8w": { "content": "*Now that you’ve downloaded the software you’re all set and ready to get stuck in!
*\n\n*This task will walk you through how to how to connect your board to the computer and upload your first programme using XOD.

*\n\nWe’ll be using the LED light in the top left corner of the board to test our connection.

\n\nYou may notice that when you first plug in the board the OLED screen in the middle-left turns on. This is part of the inbuilt demo mode on the board. You can learn more about this in the [Grove User Manual](https://files.seeedstudio.com/wiki/Grove-Beginner-Kit-For-Arduino/res/Grove-Beginner-Kit-For-ArduinoPDF.pdf).", "id": "SJxEwnoT8w", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 13, "units": "slots" } }, "rJVvni6Uw": { "content": "*Let's start by adding a node to this patch.*\n\nTo do this, find the xod/common-hardware library in the Project Browser on the left. Click the dropdown menu and find the node called *“led”*. Click on this node and drag it into the patch.", "id": "rJVvni6Uw", "position": { "x": 14, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "path": "@/tuto101-testing-your-board" }, "@/tuto102": { "comments": { "BJe7rn2Uw": { "content": "*1. Drag from Libraries*
\n\nAs you did in tuto101. If you know the library the node is in, you can find the library in the Project Browser, click the \t\t\tdropdown menu, click on the node, drag it into the patch and release.", "id": "BJe7rn2Uw", "position": { "x": -6, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "Hk0jP22Uw": { "content": "**Task 1: Testing Your Board**\n*Adding a Node*", "id": "Hk0jP22Uw", "position": { "x": -6, "y": 1, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HkCJS3hLD": { "content": "*Great!*\n\nThere are also several other ways of adding a node in XOD. Let's try them out too.", "id": "HkCJS3hLD", "position": { "x": -6, "y": 2, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "rJDuHhh8v": { "content": "*2. Double Click on the Patch*
\n\nIf you know the name of the node you want, or want to search for a node you can use the search bar. Double click anywhere in your patch and the search bar will appear. Start typing the name of the node and options will appear. Click on the correct node and it will insert into your patch.\n\n*Test this out by double clicking on the patch and typing 'led' to insert an led node.*", "id": "rJDuHhh8v", "position": { "x": 1, "y": 3, "units": "slots" }, "size": { "height": 3, "width": 7, "units": "slots" } }, "rJSjU33Uv": { "content": "*4. Menu Bar
*\n\nThis is a third way to bring up the search bar. Select ‘Edit > Insert Node...’ from the menu bar.\n\n*Test this out by selecting 'Edit > Insert Node...'. Then type 'led' to insert an led node.*", "id": "rJSjU33Uv", "position": { "x": 9, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 7, "units": "slots" } }, "rkx4UhhIP": { "content": "*3. Keyboard Shortcut*
\n\nSimilar to double-clicking the patch. Click anywhere on the patch and press ‘i’ on your keyboard. This will bring up the \t\tsame search bar as above.\n\n*Test this out by clicking on the patch and typing 'i'. Then type 'led' to insert an led node.*", "id": "rkx4UhhIP", "position": { "x": 9, "y": 2, "units": "slots" }, "size": { "height": 2, "width": 7, "units": "slots" } } }, "path": "@/tuto102" }, "@/tuto103": { "comments": { "HyWvO2hLw": { "content": "*1. The PORT Pin*\n\nThe LED on the board is connected to port D4, so click on the text box next to PORT and set this to D4 by typing ‘D4’.", "id": "HyWvO2hLw", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "S1wsu23IP": { "content": "*2. The LUM Pin*\n\nLUM stands for luminance, i.e. how bright is the LED is on a scale of 0-1. Set this to 1 (brightest level) by typing ‘1’.", "id": "S1wsu23IP", "position": { "x": 7, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "SJNAv3h8P": { "content": "**Task 1: Testing Your Board**\n*Setting Pins*", "id": "SJNAv3h8P", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SyfZd328v": { "content": "*Now let's change the node's pin parameters*\n\nClick on the led node. The outer edge will turn blue and more information will appear in the Inspector pane on the bottom left.", "id": "SyfZd328v", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "ryTpd2hUD": { "content": "*3. The ACT Pin*\n\nACT is a boolean pin that can only be true or false. Use the dropdown to set this to ‘True’. This makes sure the LED responds.", "id": "ryTpd2hUD", "position": { "x": 14, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "nodes": { "SyLId33UP": { "id": "SyLId33UP", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto103" }, "@/tuto104": { "comments": { "BJQMthnUw": { "content": "**Task 1: Testing Your Board**\n*Uploading*", "id": "BJQMthnUw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HyLw323Iw": { "content": "Click on the small lightening icon in the bottom right, or select ‘Deploy > Upload to Arduino...’ from the menu bar.\n\n**Then watch your board to see what happens!**", "id": "HyLw323Iw", "position": { "x": 17, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 5, "units": "slots" } }, "SydP5hh8D": { "content": "*If you haven't plugged your board in already, do so now.*\n\nWhen you upload the patch a screen will pop up for you to set the board model and serial port.\n\nUse the dropdown menu below *Board Model* to select *‘Arduino Uno’ or ‘Arduino/Genion Uno’*.\n\nUse the dropdown menu below *Serial Port* to select *‘dev/tty.usbserial-0001 (Silicon Labs)’*.", "id": "SydP5hh8D", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 16, "units": "slots" } }, "rJgj7Y3nIw": { "content": "*Time to upload!*\n\nYou should have ended up with an led like the one displayed on the right, with the correct pin settings displayed above the circles.", "id": "rJgj7Y3nIw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "nodes": { "SkomKhn8w": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "SkomKhn8w", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto104" }, "@/tuto105": { "comments": { "HJisJpnLP": { "content": "*Still need help?*\n\nXOD provides watch and tweak nodes which are useful for troubleshooting and debugging your programme. Learn more about them in tuto301, or take a look at [XOD’s guide to debugging](https://xod.io/docs/guide/debugging/). For further help you can always contact the Biomaker team at synbio@hermes.cam.ac.uk.", "id": "HJisJpnLP", "position": { "x": 9, "y": 5, "units": "slots" }, "size": { "height": 2, "width": 8, "units": "slots" } }, "HkLWCnh8D": { "content": "*3. Have you uploaded using the right board model and serial port?*\n\n
After you click the upload button you should make sure that you have the correct board model and serial port selected. Use the dropdown menus to select ‘Arduino Uno’/’Arduino/Genion Uno’ and ‘dev/tty.usbserial-0001 (Silicon Labs)’.", "id": "HkLWCnh8D", "position": { "x": 14, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 7, "units": "slots" } }, "SJ4o03n8P": { "content": "*3. Do you need to install a USB driver?*\n\nTo communicate with the board you will need to have a CP210 USB driver installed. Most operating systems will have this installed already, but if you're having trouble (e.g. XOD is not recognising your board) you can download the driver from the [Silabs website](www.silabs.com/products/development-tools/software/usb-to-uart-bridge-vcp-drivers).", "id": "SJ4o03n8P", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 2, "width": 8, "units": "slots" } }, "SkGd622LD": { "content": "*1. Is the board plugged in correctly?
*\n\nIf your board is plugged in correctly the power light on the right side of the seeeduino module should light up. If not, \t\t\tmake sure that the USB cable is plugged in fully.", "id": "SkGd622LD", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "SyxQpn2Lv": { "content": "**Task 1: Testing Your Board**\n*Troubleshooting*", "id": "SyxQpn2Lv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "r1WjphhLw": { "content": "*2. Have you set your node parameters correctly?*
\n\nSetting the wrong parameters is a common mistake. In this case you should make sure the pins are set as follows:
 PORT = D4, LUM = 1, ACT = True", "id": "r1WjphhLw", "position": { "x": 7, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "ry24phh8D": { "content": "*If you are having trouble uploading your programme, don't worry, there's a few simple things you can try!*\n\nIf everything is working fine, feel free to carry on to tuto106.", "id": "ry24phh8D", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "nodes": { "S1cxC338D": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "S1cxC338D", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto105" }, "@/tuto106": { "comments": { "Skz96SbKD": { "content": "**Task 1: Testing Your Board**\n*Adding Another Node*", "id": "Skz96SbKD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "ryWp6H-Kv": { "content": "*Great! Now let’s expand our patch by adding another node.*\n\nWe will use a button node so that we can switch the led on and off at will.\n\nUsing one of the ways described in tuto102, add a button node from the xod/common-hardware library.", "id": "ryWp6H-Kv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "nodes": { "HJk2TBWKv": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "HJk2TBWKv", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto106" }, "@/tuto107": { "comments": { "BJgsb0SWtP": { "content": "*Now we need to set the pins for this new node.*\n\n*1. PORT*\n\nAs with the LED node, PORT specifies which port the button is connected to. Set this to ‘D6’.\n\n*2. UPD*\n\nThe UPD pin specifies how often the programme updates. This can be set to ‘Never’, ‘On Boot (Boot)’, or ‘Continuously (Loop)’.\n\nAlternatively another node can be connected to this pin and used to determine how often it updates.\n\nMake sure this is set to ‘Continuously (Loop)’, so that whenever we press the button it is read instantly.", "id": "BJgsb0SWtP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 5, "width": 6, "units": "slots" } }, "S1ZiWAHWKv": { "content": "**Task 1: Testing Your Board**\n*Set Button Pins*", "id": "S1ZiWAHWKv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "nodes": { "ByjWRrWtD": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "ByjWRrWtD", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" }, "HJYKASbFw": { "id": "HJYKASbFw", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" } }, "path": "@/tuto107" }, "@/tuto108": { "comments": { "SkMZlJ8-tw": { "content": "**Task 1: Testing Your Board**\n*Connect the Nodes*", "id": "SkMZlJ8-tw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rJZZx1IZYD": { "content": "*Next, we need to connect the two nodes by creating a link between them.*\n\nWe want the led to turn on whenever we press the button, so we need to connect the button output pin PRS (press) to the led input pin LUM.\n\nDo this by clicking on the PRS pin and then on the LUM pin. A line will appear between them.\n\nNote that, now when you click on the led node you will not be able to set the LUM pin, because it’s value is determined by button node. ", "id": "rJZZx1IZYD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } } }, "nodes": { "B1-gJ8btv": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "B1-gJ8btv", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" }, "rye-eyLWtP": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "rye-eyLWtP", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" } }, "path": "@/tuto108" }, "@/tuto109": { "comments": { "ByM53y8WFD": { "content": "**Task 1: Testing Your Board**\n*Upload Your Patch and Test the Button*", "id": "ByM53y8WFD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "S1WcnkUbKP": { "content": "*Now let's test our expanded patch by uploading it to the board again.*\n\nUpload the patch using the little lightening upload button and see what happens.\n\nYou will notice that the programme is backwards. The LED is on and turns off when you press it.\n\nThis is because the board’s buttons are set to be on by default, and turn off when pressed.\n\nWe can fix this programme with a logic node.", "id": "S1WcnkUbKP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } } }, "links": { "H1UkxUbtD": { "id": "H1UkxUbtD", "input": { "nodeId": "B153k8-Fw", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "r1xqh1IZtD", "pinKey": "BJ--G1tI-" } } }, "nodes": { "B153k8-Fw": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "B153k8-Fw", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" }, "r1xqh1IZtD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "r1xqh1IZtD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" } }, "path": "@/tuto109" }, "@/tuto110": { "comments": { "BJXj3mLZYD": { "content": "**Task 1: Testing Your Board**\n*Add a Not Node*", "id": "BJXj3mLZYD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Syfj3XUbKw": { "content": "*To invert the signal from the button we can use a different type of node that represent a logic function, rather than a piece of hardware.*\n\nInsert a not node from the xod/core library. ", "id": "Syfj3XUbKw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } } }, "links": { "rJWoh7LZFP": { "id": "rJWoh7LZFP", "input": { "nodeId": "HJihmLWtD", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "BylihmUWKD", "pinKey": "BJ--G1tI-" } } }, "nodes": { "BylihmUWKD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "BylihmUWKD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "HJihmLWtD": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "HJihmLWtD", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto110" }, "@/tuto111": { "comments": { "BJqoN8WFv": { "content": "*Then we can re-test the patch.*\n\nNow try uploading your programme again. This time it should work as planned.", "id": "BJqoN8WFv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "SJmuSNUZYD": { "content": "**Task 1: Testing Your Board**\n*Rewire and Re-test*", "id": "SJmuSNUZYD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SyMuHE8btv": { "content": "*We need to rewire the patch to incude the not node between the button and led.*\n\nDelete the link between the button and led. Connect PRS to the not input pin, and the not output pin to LUM.\n\nYou can move the nodes around to help visualise the flow of the programme if it helps.", "id": "SyMuHE8btv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "links": { "S1bdSVUbKv": { "id": "S1bdSVUbKv", "input": { "nodeId": "H1drE8WYD", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "SkxdH4LbFD", "pinKey": "BJ--G1tI-" } } }, "nodes": { "H1drE8WYD": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "H1drE8WYD", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/common-hardware/led" }, "HyvbH8bFv": { "id": "HyvbH8bFv", "position": { "x": 12, "y": 2, "units": "slots" }, "type": "xod/core/not" }, "SkxdH4LbFD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "SkxdH4LbFD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" } }, "path": "@/tuto111" }, "@/tuto112": { "comments": { "BkrztrLWYP": { "content": "*You will learn more about using inputs and outputs in the next task, but for now, why not try experimenting with this patch?*\n\nPlay around with some pins. E.g. change the led ACT pin, or link a clock node to the button UPD pin and see what happens. See what you can achieve!", "id": "BkrztrLWYP", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "HkXMYS8btD": { "content": "*Your final patch should look like this.*\n\nCongrats! you've now made a simple programme that uses an input (the button) and an output (the led) to affect change.\n\n", "id": "HkXMYS8btD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "r1EfYr8Ztw": { "content": "**Task 1: Testing Your Board**\n*Experiment!*", "id": "r1EfYr8Ztw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "H1fnSIWYP": { "id": "H1fnSIWYP", "input": { "nodeId": "BJ-MYSUWKv", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "rJxfYB8bFD", "pinKey": "BJ--G1tI-" } }, "Hk42HUZFw": { "id": "Hk42HUZFw", "input": { "nodeId": "rJftBUWKP", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "BJ-MYSUWKv", "pinKey": "r1if8ROSDJ-" } } }, "nodes": { "BJ-MYSUWKv": { "id": "BJ-MYSUWKv", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" }, "rJftBUWKP": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "rJftBUWKP", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "rJxfYB8bFD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "rJxfYB8bFD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" } }, "path": "@/tuto112" }, "@/tuto113": { "comments": { "Bk1J-6nLP": { "content": "*2. Name the patch
*\n\nType a name for your new patch, e.g. ‘clear’ and click confirm or press the Enter key.", "id": "Bk1J-6nLP", "position": { "x": 7, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "Bkpvla2Uw": { "content": "**Task 1: Testing Your Board**\n*Clearing the Board*", "id": "Bkpvla2Uw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Bks3ga3Uw": { "content": "*1. Make a new patch
*\n\nAdd a new patch by clicking the ‘Add patch’ button in the project browser or selecting ‘File > New Patch...’ from the menu.", "id": "Bks3ga3Uw", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "r1Fcx62UP": { "content": "Once a programme is loaded onto your board it will remain there and restart whenever you turn on the board. Each time you upload a new programme it will write over the previous programme.\n\nYou don't need to clear the board before you upload a new programme, but *if you wish to reset your board you can do this manually by uploading a blank patch in XOD*.", "id": "r1Fcx62UP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 10, "units": "slots" } }, "ryWJbT28D": { "content": "*3. Upload
*\n\nUpload the empty patch by clicking the upload button as before. This will turn off the LED and clear the board.", "id": "ryWJbT28D", "position": { "x": 14, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "path": "@/tuto113" }, "@/tuto114": { "comments": { "Bk5A-Th8v": { "content": "*Great work! You've now completed Task 1: Testing Your Board!*\n\nYou can now move on to Task 2: Inputs and Outputs by opening tuto201.", "id": "Bk5A-Th8v", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 10, "units": "slots" } }, "ryhpb6hUP": { "content": "**Task 1: Testing Your Board**\n*The End*", "id": "ryhpb6hUP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto114" }, "@/tuto201-inputs-and-outputs": { "comments": { "H1DHoj6Lw": { "content": "**Task 2: Inputs and Outputs**\n*Adding a New Library*", "id": "H1DHoj6Lw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HkeR0jTLv": { "content": "*3. Locating the Library*\n\nThe library *marcoaita/malibrary* should now appear in the Project Browser.", "id": "HkeR0jTLv", "position": { "x": 14, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "HyfjssaID": { "content": "*Great! You now understand the basic principles of using XOD, and can programme your board to control one of the onboard devices: the LED.*\n\nLike the button and the LED, most devices you will use can be grouped into two general categories: inputs and outputs.

\n\nUnderstanding how to control different inputs and outputs, and how to combine them together is key to making useful devices.

\n\nIn this task we will build on our knowledge to add two new devices to our belt. The buzzer and the rotary potentiometer (also known as a knob sensor).", "id": "HyfjssaID", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 13, "units": "slots" } }, "SJS9AspUP": { "content": "*2. Adding a library*\n\nAdd this library by clicking on the ‘Add library’ button (next to the ‘New patch’ button at the top of the Project Browser) or by navigating to ‘File > Add Library...’. Type the full name of the library, and when it appears, click on it to install. If you get an error message asking to install dependencies, accept this.", "id": "SJS9AspUP", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 13, "units": "slots" } }, "ryNYjspIP": { "content": "*1. Finding a buzzer node*\n\nThere is no preinstalled node to represent the buzzer. However, several have been created by members of the XOD community. We will use one from the library called marcoaita/malibrary.", "id": "ryNYjspIP", "position": { "x": 14, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "path": "@/tuto201-inputs-and-outputs" }, "@/tuto202": { "comments": { "SJgk4Jha8w": { "content": "*We can copy our previous nodes into this patch to save ourselves some work!*\n\n*1.* Select all of the nodes from tuto112 by dragging a box around them.\n\n*2.* Copy them by navigating to 'Edit > Copy' or using Ctrl+C/⌘+C.\n\n*3.* Paste into this patch by navigating to 'Edit > Paste' or using Ctrl+V/⌘+V.", "id": "SJgk4Jha8w", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "Sy1VJ3TIw": { "content": "**Task 2: Inputs and Outputs**\n*Copy Your Patch*", "id": "Sy1VJ3TIw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto202" }, "@/tuto203": { "comments": { "B14DteDWtD": { "content": "*This time we want to use the buzzer as an output instead of the LED.*\n\n*1. Delete the led node*\n\nClick on the led node and delete it by navigating to 'Edit > Cut' or using the delete or backspace keys on your keyboard.\n\n*2. Add a buzzer node*\n\nNow that the library is installed you can search for the marcoaita/malibrary/
buzzer node and add it as usual.", "id": "B14DteDWtD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "H1SwKgvbYv": { "content": "**Task 2: Inputs and Outputs**\n*Edit Your Programme*", "id": "H1SwKgvbYv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "SJMvKxPWYv": { "id": "SJMvKxPWYv", "input": { "nodeId": "Hy-wtlPZFP", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "HyxwKlDZFw", "pinKey": "BJ--G1tI-" } }, "rk7wKxvWtP": { "id": "rk7wKxvWtP", "input": { "nodeId": "SywKgPWtw", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "Hy-wtlPZFP", "pinKey": "r1if8ROSDJ-" } } }, "nodes": { "Hy-wtlPZFP": { "id": "Hy-wtlPZFP", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" }, "HyxwKlDZFw": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "HyxwKlDZFw", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "SywKgPWtw": { "boundLiterals": { "B1oqkTnIb": "D4", "HyYh1a3LZ": "1" }, "id": "SywKgPWtw", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto203" }, "@/tuto204": { "comments": { "SyEDRGP-FP": { "content": "*Now we need to set the pins on this new buzzer node.*\n\n*1. PORT*\n\nThe buzzer is connected to port D5, so make sure the PORT pin is set to ‘D5’\n\n*2. FREQ*\n\nThe FREQ pin sets the frequency and pitch of the buzzer. You can leave this as 440, or change it too see what happens.\n\n*3. Reconnect*\n\nConnect the not output pin to the buzzer EN (enabled) pin. This will ‘enable’ the buzzer when the button is pressed. ", "id": "SyEDRGP-FP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 5, "width": 6, "units": "slots" } }, "SyrDRfP-Yw": { "content": "**Task 2: Inputs and Outputs**\n*Set Buzzer Pins and Reconnect*", "id": "SyrDRfP-Yw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "SyGv0MPbKw": { "id": "SyGv0MPbKw", "input": { "nodeId": "SJbP0GwbtD", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "B1gDAGPWtD", "pinKey": "BJ--G1tI-" } } }, "nodes": { "B1gDAGPWtD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "B1gDAGPWtD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "HyZxQPZFD": { "id": "HyZxQPZFD", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" }, "SJbP0GwbtD": { "id": "SJbP0GwbtD", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" } }, "path": "@/tuto204" }, "@/tuto205": { "comments": { "ByEb3QDZKD": { "content": "**Task 2: Inputs and Outputs**\n*Upload and Test*", "id": "ByEb3QDZKD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SkmZnXDbKD": { "content": "*Now try uploading your programme.*\n\nIt should work similarly to the LED patch, i.e. the buzzer turns on when you press the button.", "id": "SkmZnXDbKD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "links": { "HkM-hXP-tv": { "id": "HkM-hXP-tv", "input": { "nodeId": "SylZnmwWtD", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "SJZ3mD-Kv", "pinKey": "BJ--G1tI-" } }, "SkqbI_WYw": { "id": "SkqbI_WYw", "input": { "nodeId": "BJW-2XwWFD", "pinKey": "Hkb8Ui77-7" }, "output": { "nodeId": "SylZnmwWtD", "pinKey": "r1if8ROSDJ-" } } }, "nodes": { "BJW-2XwWFD": { "id": "BJW-2XwWFD", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" }, "SJZ3mD-Kv": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "SJZ3mD-Kv", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "SylZnmwWtD": { "id": "SylZnmwWtD", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" } }, "path": "@/tuto205" }, "@/tuto206": { "comments": { "B1N5AFuZFD": { "content": "*Great! Now let’s add a second input.*\n\nWe can use the inbuilt rotary potentiometer (knob) to adjust the frequency of the buzzer sound.\n\nTo represent the potentiometer we can use the pot node from the xod/common-hardware library.\n\n*1.* Add a pot node to the patch.\n\n*2.* Set PORT pin to 'A0'.\n\n*3.* Set UPD pin to 'Continuously'.", "id": "B1N5AFuZFD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "BkrqCtuZtD": { "content": "**Task 2: Inputs and Outputs**\n*Add a Pot Node and Set Pins*", "id": "BkrqCtuZtD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "SkM5AY_ZtP": { "id": "SkM5AY_ZtP", "input": { "nodeId": "B1l50FdWYP", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "rkcCtuZYw", "pinKey": "BJ--G1tI-" } }, "rkmc0F_WYv": { "id": "rkmc0F_WYv", "input": { "nodeId": "HJWcAKObKP", "pinKey": "Hkb8Ui77-7" }, "output": { "nodeId": "B1l50FdWYP", "pinKey": "r1if8ROSDJ-" } } }, "nodes": { "B1l50FdWYP": { "id": "B1l50FdWYP", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" }, "HJWcAKObKP": { "id": "HJWcAKObKP", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" }, "rkcCtuZYw": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "rkcCtuZYw", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "ryIdUcZFw": { "id": "ryIdUcZFw", "position": { "x": 27, "y": 2, "units": "slots" }, "type": "xod/common-hardware/pot" } }, "path": "@/tuto206" }, "@/tuto207": { "comments": { "BkE0gtWKw": { "content": "\n\n*1.* Add a map node from xod/math.\n\n*2.* Connect the pot VAL pin to the map X pin.\n\n*3.* Connect the map output pin to the buzzer FREQ pin.", "id": "BkE0gtWKw", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "H14QX9OZtv": { "content": "*So, how do we connect the pot node to the patch?*\n\nWe could connect the pot output VAL (value) pin straight to the FREQ input pin.\n\nHowever, this wouldn’t work well, as the VAL output ranges between 0 and 1, and frequencies emmited by the buzzer are much higher.\n\n*To get around this, we can add a map node.*\n\nThis will ‘map’ your input range to a new output range, so we can change the 0-1 scale of the potentiometer to a larger scale that the buzzer can use.", "id": "H14QX9OZtv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "r1r7Q5_WFD": { "content": "**Task 2: Inputs and Outputs**\n*Mapping Values: Add and Connect a Map Node*", "id": "r1r7Q5_WFD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "BkmQQ9OWKP": { "id": "BkmQQ9OWKP", "input": { "nodeId": "BkZ779dZtP", "pinKey": "Hkb8Ui77-7" }, "output": { "nodeId": "r1g7X9_Ztw", "pinKey": "r1if8ROSDJ-" } }, "rkGmmcOWYv": { "id": "rkGmmcOWYv", "input": { "nodeId": "r1g7X9_Ztw", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "ByQm5dbFw", "pinKey": "BJ--G1tI-" } } }, "nodes": { "BkZ779dZtP": { "id": "BkZ779dZtP", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" }, "ByQm5dbFw": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "ByQm5dbFw", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "HJtE9OWtv": { "id": "HJtE9OWtv", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/common-hardware/pot" }, "r1g7X9_Ztw": { "id": "r1g7X9_Ztw", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" } }, "path": "@/tuto207" }, "@/tuto208": { "comments": { "B1IUDZt-tD": { "content": "**Task 2: Inputs and Outputs**\n*Set Map Pins*", "id": "B1IUDZt-tD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SkSLwZtWKD": { "content": "*Now we need to set the remaining map input nodes to define our source and target ranges.* \n\nSmin and Smax set the source range, whilst Tmin and Tmax set the target range.\n\n*1.* Set Smin to ‘0’ and Smax to ‘1’.\n\n*2.* Set Tmin to ‘200’ and Tmax to ‘1000’.", "id": "SkSLwZtWKD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "rkDIPZKWFP": { "content": "*Now try uploading your programme.*\n\nUse the button to turn the buzzer on and off, and the potentiometer to set the frequency.", "id": "rkDIPZKWFP", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "links": { "By4IvWtbYv": { "id": "By4IvWtbYv", "input": { "nodeId": "SJZIDZFZtP", "pinKey": "Hkb8Ui77-7" }, "output": { "nodeId": "rylIP-tWtv", "pinKey": "r1if8ROSDJ-" } }, "HJX8w-F-Kv": { "id": "HJX8w-F-Kv", "input": { "nodeId": "rylIP-tWtv", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "HkLwWFZKv", "pinKey": "BJ--G1tI-" } }, "S1Av-F-YP": { "id": "S1Av-F-YP", "input": { "nodeId": "BJsPZFWtw", "pinKey": "BJlzICOSv1-" }, "output": { "nodeId": "S1fUPbYZFw", "pinKey": "H1sM2A12-" } }, "rJl_btZFw": { "id": "rJl_btZFw", "input": { "nodeId": "SJZIDZFZtP", "pinKey": "HkULoQXbQ" }, "output": { "nodeId": "BJsPZFWtw", "pinKey": "H12bIR_SPyZ" } } }, "nodes": { "BJsPZFWtw": { "id": "BJsPZFWtw", "position": { "x": 12, "y": 2, "units": "slots" }, "type": "xod/math/map" }, "HkLwWFZKv": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "HkLwWFZKv", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "S1fUPbYZFw": { "id": "S1fUPbYZFw", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/common-hardware/pot" }, "SJZIDZFZtP": { "id": "SJZIDZFZtP", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" }, "rylIP-tWtv": { "id": "rylIP-tWtv", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" } }, "path": "@/tuto208" }, "@/tuto209": { "comments": { "B1tfadtWFv": { "content": "*Now try uploading your programme!*\n\nUse the button to turn the buzzer on and off, and use the potentiometer to set the frequency.", "id": "B1tfadtWFv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "BkuGTuKZKD": { "content": "**Task 2: Inputs and Outputs**\n*Upload and Test!*", "id": "BkuGTuKZKD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "B1SM6_tZKw": { "id": "B1SM6_tZKw", "input": { "nodeId": "rkWGadFbFD", "pinKey": "Hkb8Ui77-7" }, "output": { "nodeId": "SJxza_YWtP", "pinKey": "r1if8ROSDJ-" } }, "BJ4GTOK-Kv": { "id": "BJ4GTOK-Kv", "input": { "nodeId": "SJxza_YWtP", "pinKey": "ry3zLA_Bv1Z" }, "output": { "nodeId": "r1fa_tbYD", "pinKey": "BJ--G1tI-" } }, "BJwzTOKbKD": { "id": "BJwzTOKbKD", "input": { "nodeId": "rkWGadFbFD", "pinKey": "HkULoQXbQ" }, "output": { "nodeId": "Sy7G6utZYD", "pinKey": "H12bIR_SPyZ" } }, "rkLG6OFZKw": { "id": "rkLG6OFZKw", "input": { "nodeId": "Sy7G6utZYD", "pinKey": "BJlzICOSv1-" }, "output": { "nodeId": "SJGzaOt-Yv", "pinKey": "H1sM2A12-" } } }, "nodes": { "SJGzaOt-Yv": { "id": "SJGzaOt-Yv", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/common-hardware/pot" }, "SJxza_YWtP": { "id": "SJxza_YWtP", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/not" }, "Sy7G6utZYD": { "boundLiterals": { "HJCWLAdSwyW": "1", "rJbGU0_Hv1Z": "200", "rkpbU0OrwyZ": "1000" }, "id": "Sy7G6utZYD", "position": { "x": 12, "y": 2, "units": "slots" }, "type": "xod/math/map" }, "r1fa_tbYD": { "boundLiterals": { "ByNiWkt8Z": "D6" }, "id": "r1fa_tbYD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "xod/common-hardware/button" }, "rkWGadFbFD": { "id": "rkWGadFbFD", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "marcoaita/malibrary/buzzer" } }, "path": "@/tuto209" }, "@/tuto210": { "comments": { "S1cXWo-vw": { "content": "**Building Complex Devices**\n\nWhen building biological devices, you will need to combine a variety of inputs and outputs to create a functioning programme and device. You will often receive inputs, e.g. from an on/off button or sensor, and then use these inputs to create the desired output, e.g. displaying a reading, sending data to a computer or moving a motor.

\n\nThe button, buzzer and potentiometer example used here is a very simple example, but the principle applies in more complex systems too. Using XOD allows you to visualise this information flow from input to output, which can be helpful and sometimes more intuitive than traditional text-based coding.

", "id": "S1cXWo-vw", "position": { "x": 0, "y": 2, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "S1jr-o-wP": { "content": "**Before moving on to tuto301, we suggest reading the introduction to Lesson 3: 'XOD Basics' and 'Tweak and Watch Nodes' in the Beginner's Guide (p26-27).**\n*These pages will provide some useful background information to help you with the next tasks.*", "id": "S1jr-o-wP", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "r1cwJoZwv": { "content": "**Task 2: Inputs and Outputs**\n*The End*", "id": "r1cwJoZwv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rJe9vko-vP": { "content": "*Congrats, you've now completed Task 2: Inputs and Outputs!*", "id": "rJe9vko-vP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rkBwbjWPw": { "content": "In the next lesson we’ll be getting a better understanding of what is possible in XOD by exploring a variety of useful nodes and processes using a range of the board’s inbuilt devices.

\n\nWhen you are ready to explore beyond the starter kit’s capabilities, the No-Code Programming for Biology Handbook explores a variety of common input and output devices which are useful for building biological devices, and explains how they can be programmed using XOD.", "id": "rkBwbjWPw", "position": { "x": 11, "y": 2, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } } }, "path": "@/tuto210" }, "@/tuto301-tweak-and-watch-nodes": { "comments": { "H1El4i-Dw": { "content": "*Before we start, lets practice saving and creating a new project.*\n\nFor this run-through tutorial, we don't actually need to do this, as we'll be carrying on in this project - but it's useful to know how. Once you've completed this step you should reopen this XOD file to continue with tuto302.\n\nFirst, save this project (you can’t have two projects open at once) by navigating to 'File > Save'.\n\nThen navigate to ‘File > New Project...’ in the menu bar.\n\nFinally, give your project a name. XOD will then open a new blank project.\n\nIt's good to keep one project file for each device you are working on, so that your project files don't get to big and messy.\n\n", "id": "H1El4i-Dw", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "HyxnvGobDv": { "content": "**Before starting the task, we suggest reading the introduction to Lesson 3: 'XOD Basics' and 'Tweak and Watch Nodes' in the Beginner's Guide (p26-27).**\n\n*In this task we’ll look at how we can use tweak and watch nodes to take readings from another of the unbuilt devices: the temperature and humidity sensor.*\n\n

We’ll be using a tweak-pulse node to act as a button and take a reading whenever we press (or ‘tweak’) it, and watch nodes to display our readings on the computer screen.\n\n
We’ll also be using the ‘Simulate/Debug’ mode in XOD, which lets us to watch and make changes while the code is running.

\n\nThis is a great example of how tweak and watch nodes can be used to quickly and easily test a patch. They are very useful for testing and debugging patches, so you should try to get used to using them as you build.", "id": "HyxnvGobDv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "r1hPMi-ww": { "content": "**Task 3: Tweak and Watch Nodes**\n*Creating a New Project*", "id": "r1hPMi-ww", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto301-tweak-and-watch-nodes" }, "@/tuto302": { "comments": { "B1x2V8j-ww": { "content": "*Let's add a hygrometer node and set it's pins.*\n\nThe onboard temperature and humidity sensor is technically known as a DHT11 hygrometer. There is an preinstalled XOD node for this device called dht11-hygrometer.\n\nAdd this node to your patch from the xod-dev/dht library.\n\nSet the port pin to ‘D3’", "id": "B1x2V8j-ww", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "Bk2ELoWww": { "content": "**Task 3: Tweak and Watch Nodes**\n*Add and Set Hygrometer Node*", "id": "Bk2ELoWww", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto302" }, "@/tuto303": { "comments": { "BJ1A8s-DD": { "content": "**Task 3: Tweak and Watch Nodes**\n*Add and Connect Tweak and Watch Nodes*", "id": "BJ1A8s-DD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HJg1RIibvD": { "content": "*Your node should look like this.*\n\nAdd a tweak-pulse and two watch nodes from the xod/debug library.\n\nConnect the tweak-pulse node to the UPD pin and a watch node to each of the pins Tc (temperature ºC) and RH (relative humidity).", "id": "HJg1RIibvD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "nodes": { "ry5yDj-DD": { "boundLiterals": { "BJj5mmtUH": "D3" }, "id": "ry5yDj-DD", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod-dev/dht/dht11-hygrometer" } }, "path": "@/tuto303" }, "@/tuto304": { "comments": { "H1efrPobDP": { "content": "**Task 3: Tweak and Watch Nodes**\n*Upload and Debug*", "id": "H1efrPobDP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Sy7XOjZwD": { "content": "*Once you've pressed 'Upload and Debug' and the patch has sucessfully uploaded.*\n\n*1. Watch*\nLook at the watch node. It won’t display a reading yet because we have set the UPD pin to only update when we tweak it.\n\n*2. 'Tweak' the Node*\nWhilst it is still running, click on the tweak node. In the Inspector pane is a button next to OUT that says ‘pulse’. Click it.\n\n*3. Watch Again*\nLook at the watch nodes again. This time they should display the current temperature and humidity.", "id": "Sy7XOjZwD", "position": { "x": 14, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "rkZfBPoZvD": { "content": "*Your patch should now look like this.*\n\nThis time, instead of just uploading, we are going to 'upload and debug'. This will allow us to edit and watch the patch in real-time.\n\nClick the ‘Upload and Debug’ button (ladybird) next to the upload button, or use the upload button and tick the box labelled ‘Debug after upload’.", "id": "rkZfBPoZvD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "links": { "BkhLwjWPD": { "id": "BkhLwjWPD", "input": { "nodeId": "r1KIPjWvv", "pinKey": "HkXK-dGob" }, "output": { "nodeId": "rJGrPjWww", "pinKey": "SkeWYtEY8S" } }, "ByBLvjWDP": { "id": "ByBLvjWDP", "input": { "nodeId": "H1XLPobDw", "pinKey": "HkXK-dGob" }, "output": { "nodeId": "rJGrPjWww", "pinKey": "HybttEF8r" } }, "H1xUDoWPv": { "id": "H1xUDoWPv", "input": { "nodeId": "rJGrPjWww", "pinKey": "Bkbs7mtUr" }, "output": { "nodeId": "BkRrvoZDv", "pinKey": "Bkf4BDsmV" } } }, "nodes": { "BkRrvoZDv": { "id": "BkRrvoZDv", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" }, "H1XLPobDw": { "id": "H1XLPobDw", "position": { "x": 8, "y": 3, "units": "slots" }, "type": "xod/debug/watch" }, "r1KIPjWvv": { "id": "r1KIPjWvv", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/debug/watch" }, "rJGrPjWww": { "boundLiterals": { "BJj5mmtUH": "D3" }, "id": "rJGrPjWww", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod-dev/dht/dht11-hygrometer" } }, "path": "@/tuto304" }, "@/tuto305": { "comments": { "HJTZFs-DP": { "content": "*Congrats, you've now completed Task 3: Tweak and Watch Nodes*\n\nHopefully this was a nice simple task to show you how tweak and watch nodes can be useful.\n\nWe will use this nodes often throughout the rest of the tutorial, so its good to understand how they work. You can learn more about tweak and watch nodes on the [XOD website](https://xod.io/docs/guide/debugging/).", "id": "HJTZFs-DP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "rkLKktsWPw": { "content": "**Task 3: Tweak and Watch Nodes**\n*The End*", "id": "rkLKktsWPw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rkckqjbPw": { "content": "**Before moving on to tuto401, we suggest reading 'Flip, Clock and Count Nodes' in the Beginner's Guide (p30).**\n*This will provide some useful background information for the next task.*", "id": "rkckqjbPw", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto305" }, "@/tuto401-flip-clock-and-count-nodes": { "comments": { "BJxVbjiZwP": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Add and Link Nodes*", "id": "BJxVbjiZwP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Hk4boibwD": { "content": "**Before starting the task, we suggest reading 'Flip, Clock and Count Nodes' in the Beginner's Guide (p30).**\n\n*In this task we’ll be experimenting with flip, clock and count nodes to control the behaviour of the inbuilt LED, making it flash.

*\n\nThe flip and clock nodes can be useful for modifying and timing the behaviour of nodes, whilst the count node can be useful for monitoring these behaviours. In the context of biological devices, these nodes are very useful for fine-tuning devices and for building larger programmes.", "id": "Hk4boibwD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "Hy8HjobvP": { "content": "*1. Add the following nodes to this patch:*\n\ntweak-pulse (xod/debug)\nflip-n-times (xod/core)\nled (xod/common-hardware)", "id": "Hy8HjobvP", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "S1w5oo-Pv": { "content": "*2. Link the nodes as follows:*\n\nConnect the tweak-pulse node to the flip-n-times SET pin.\n\nConnect the flip-n-times OUT pin to the led LUM pin.", "id": "S1w5oo-Pv", "position": { "x": 7, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } } }, "path": "@/tuto401-flip-clock-and-count-nodes" }, "@/tuto402": { "comments": { "Bkyt6oWPP": { "content": "**Output Pins**\n\n*OUT* (output) reads the current state of the node (true/false).\n\n*Nc* (cycle number) reads the number of times cycled.\n\n*ACT* (active) reads whether the sequence is currently running or not.\n\n*If you’d like to get a better idea of how these outputs work, you can always add watch nodes, to help see what’s going on.*", "id": "Bkyt6oWPP", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "H15Paobvv": { "content": "**Input Pins**\n\n*N* (number) sets how many times the sequence will run.\n\n*Ton* (time on) defines the duration of each 'on' state.\n\n*Toff* (time off) defines the duration of each 'off' state.\n\nA pulse to *SET* (set) will start the sequence.\n\nA pulse to *RST* (reset) will reset the node.", "id": "H15Paobvv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "HyIP2jbDD": { "content": "*Your patch should now look like this.*\n\n*Let's look at the flip-n-times node and each of its pins, so that we understand what it does.*\n\nThis node defines a sequence that will switch between true and false a set number of times. You can alter this sequence of on/off modes by setting the different input pins. There are also several output pins that allow you to monitor different aspects of the sequence.", "id": "HyIP2jbDD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "SJ81nsZDw": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*The Flip-N-Times Node*", "id": "SJ81nsZDw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "SkSVhobwD": { "id": "SkSVhobwD", "input": { "nodeId": "HkgQ2jZDv", "pinKey": "S1vneCK1z" }, "output": { "nodeId": "HJfV2sWwD", "pinKey": "Bkf4BDsmV" } }, "ry3N3o-PP": { "id": "ry3N3o-PP", "input": { "nodeId": "BkFEniZvv", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "HkgQ2jZDv", "pinKey": "BkE-fCKJG" } } }, "nodes": { "BkFEniZvv": { "id": "BkFEniZvv", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "HJfV2sWwD": { "id": "HJfV2sWwD", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" }, "HkgQ2jZDv": { "id": "HkgQ2jZDv", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/flip-n-times" } }, "path": "@/tuto402" }, "@/tuto403": { "comments": { "S146Ik2bPv": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Setting the Pins*", "id": "S146Ik2bPv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rJMygnWwv": { "content": "*2. led pins*\n\nAs in tuto103, set the PORT pin to ‘D4’ and the ACT pin to ‘True’.", "id": "rJMygnWwv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "rkXs13-Pw": { "content": "*1. flip-n-times pins*\n\nSet N to ‘5’, Ton and Toff to ‘1’, and RST to ‘Never’.\n\nYou can also add a tweak-pulse node to the RST pin to test how it works, if you like.", "id": "rkXs13-Pw", "position": { "x": 0, "y": 2, "units": "slots" }, "size": { "height": 2, "width": 6, "units": "slots" } }, "ryrpLk2ZvD": { "content": "*Now let's determine the sequence parameters by setting the node pins.*", "id": "ryrpLk2ZvD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 1, "width": 6, "units": "slots" } } }, "links": { "BkGTIyhbwD": { "id": "BkGTIyhbwD", "input": { "nodeId": "ByaL12-Pw", "pinKey": "S1vneCK1z" }, "output": { "nodeId": "Skg6Iknbwv", "pinKey": "Bkf4BDsmV" } }, "rymaIk2-DP": { "id": "rymaIk2-DP", "input": { "nodeId": "HJZ6U1h-Dv", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "ByaL12-Pw", "pinKey": "BkE-fCKJG" } } }, "nodes": { "ByaL12-Pw": { "id": "ByaL12-Pw", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/flip-n-times" }, "HJZ6U1h-Dv": { "id": "HJZ6U1h-Dv", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "Skg6Iknbwv": { "id": "Skg6Iknbwv", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" } }, "path": "@/tuto403" }, "@/tuto404": { "comments": { "BJETBenbvP": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Upload and Debug*", "id": "BJETBenbvP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "H1HTren-Dw": { "content": "*Your patch should now look like this*\n\n*Upload and debug this patch using the ladybird button.*\n\nWhilst in debug mode, press the tweak-pulse node and watch what happens to the LED. Each time you press, the light should flash 5 times.", "id": "H1HTren-Dw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } } }, "links": { "SkX6Hl2-vP": { "id": "SkX6Hl2-vP", "input": { "nodeId": "SyZ6rx2WDw", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "ry6Hx2bPD", "pinKey": "BkE-fCKJG" } }, "rJM6rg2Zvw": { "id": "rJM6rg2Zvw", "input": { "nodeId": "ry6Hx2bPD", "pinKey": "S1vneCK1z" }, "output": { "nodeId": "Hyl6BxnZvv", "pinKey": "Bkf4BDsmV" } } }, "nodes": { "Hyl6BxnZvv": { "id": "Hyl6BxnZvv", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" }, "SyZ6rx2WDw": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "SyZ6rx2WDw", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "ry6Hx2bPD": { "boundLiterals": { "rknsx0tyf": "5" }, "id": "ry6Hx2bPD", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/flip-n-times" } }, "path": "@/tuto404" }, "@/tuto405": { "comments": { "B19BM3bPv": { "content": "**Output Pins**\n\n*MEM* (memory) reads out the latest state of the node.\n*Connect this to the LUM pin of the led.*", "id": "B19BM3bPv", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "Hk4EG-2ZPw": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*The Flip-Flop Node*", "id": "Hk4EG-2ZPw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HkBVGZ3ZvP": { "content": "*Now lets try a different flip node.*\n\nDelete the flip-n-times node and add a flip-flop node (xod/core).\n\n*Let's look at the flip-flop node, set each of its pins and reconnect the patch.*\n\nThe flip-flop node switches between true and false (on and off) states each time it is pulsed.", "id": "HkBVGZ3ZvP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "Hk_qWhZvv": { "content": "**Input Pins**\n\n*TGL* (toggle) switches the node between true and false each time it receives a pulse.\n*Connect the tweak-pulse node to TGL.*\n\n*SET* (set) sets current state to true.\n*Set this to ‘On Boot’.*\n\n*RST* (reset) sets current state to false.\n*Set this to to ‘Never’.*", "id": "Hk_qWhZvv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } } }, "links": { "ByQVfZhWPD": { "id": "ByQVfZhWPD", "input": { "nodeId": "H1WVG-nbvD", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "BkNf-3WDv", "pinKey": "BkE-fCKJG" } }, "SJMVGbn-PP": { "id": "SJMVGbn-PP", "input": { "nodeId": "BkNf-3WDv", "pinKey": "S1vneCK1z" }, "output": { "nodeId": "rkxVz-3-Dw", "pinKey": "Bkf4BDsmV" } } }, "nodes": { "BkNf-3WDv": { "boundLiterals": { "rknsx0tyf": "5" }, "id": "BkNf-3WDv", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "xod/core/flip-n-times" }, "H1WVG-nbvD": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "H1WVG-nbvD", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "rkxVz-3-Dw": { "id": "rkxVz-3-Dw", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" } }, "path": "@/tuto405" }, "@/tuto406": { "comments": { "B18U5Xh-vw": { "content": "*Upload and debug the program, and pulse the tweak-pulse node.*\n\nThe LED should switch between on and off each time you press it.", "id": "B18U5Xh-vw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "r1BU57h-vD": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Upload and Debug (round 2)*", "id": "r1BU57h-vD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "HJVoQnbDP": { "id": "HJVoQnbDP", "input": { "nodeId": "rkMI5m2ZvP", "pinKey": "ryTIROHwkW" }, "output": { "nodeId": "BJx8972-wv", "pinKey": "Bkf4BDsmV" } }, "HJoimnZDD": { "id": "HJoimnZDD", "input": { "nodeId": "rJWL972Wvw", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "rkMI5m2ZvP", "pinKey": "HkyxURuSPyW" } } }, "nodes": { "BJx8972-wv": { "id": "BJx8972-wv", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" }, "rJWL972Wvw": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "rJWL972Wvw", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "rkMI5m2ZvP": { "boundLiterals": { "Bkh8A_Sv1-": "On Boot" }, "id": "rkMI5m2ZvP", "position": { "x": 10, "y": 2, "units": "slots" }, "type": "xod/core/flip-flop" } }, "path": "@/tuto406" }, "@/tuto407": { "comments": { "B1Sz5V2bvw": { "content": "*The flip-flop node can also make the LED flash in sequence, when it is combined with a clock node.*\n\nAdd a clock node (xod/core) to the patch.\n\n*Let's look at the clock node, set each of its pins and reconnect the patch.*\n\nThe clock node sends pulses at a specific time interval, creating a regular ‘ticking’ of pulses.", "id": "B1Sz5V2bvw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "By3YrnZvD": { "content": "**Input Pins**\n\n*EN* (enabled) determines whether the 'ticking' is enabled or not.\n*Set this to 'True'.*\n\n*IVAL* (interval) determines how often the clock ticks (in secs).\n*Set this to ‘1’.*\n\n*RST* (reset) resets the clock.\n*Set this to ‘Never’.* ", "id": "By3YrnZvD", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "HJe3KBnWPP": { "content": "**Output Pins**\n\n*TICK* (tick) pulses at the end of each interval (set by the IVAL pin).\n*Delete the tweak-pulse node and connect the clock node in its place by linking the TICK pin to the TGL pin.*", "id": "HJe3KBnWPP", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "SkVf5Nh-vw": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*The Clock Node*", "id": "SkVf5Nh-vw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "HyQf9E2ZvD": { "id": "HyQf9E2ZvD", "input": { "nodeId": "HJgMcNhbPw", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "r1-M94h-Dw", "pinKey": "HkyxURuSPyW" } }, "r1ff9EhbPP": { "id": "r1ff9EhbPP", "input": { "nodeId": "r1-M94h-Dw", "pinKey": "ryTIROHwkW" }, "output": { "nodeId": "rkzq42-vP", "pinKey": "Bkf4BDsmV" } } }, "nodes": { "HJgMcNhbPw": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "HJgMcNhbPw", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "r1-M94h-Dw": { "boundLiterals": { "Bkh8A_Sv1-": "On Boot" }, "id": "r1-M94h-Dw", "position": { "x": 10, "y": 2, "units": "slots" }, "type": "xod/core/flip-flop" }, "rkzq42-vP": { "id": "rkzq42-vP", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/debug/tweak-pulse" } }, "path": "@/tuto407" }, "@/tuto408": { "comments": { "Bkwnd83WPv": { "content": "**Input Pins**\n\n*INC* (increase) increases the count each time it recieves a pulse or True signal.\n*Connect the led DONE pin to the clock INC pin.*\nThe led DONE pin pulses each time the LED turns on or off, so we can count how many times the led switches.\n\n*STEP* (step) determines how much the count increases by with each pulse.\n*Set this to ‘1’.*\n\n*RST* (reset) resets the count to 0.\n*Set this to ‘Never’.*", "id": "Bkwnd83WPv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } }, "ByBnu82ZPD": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*The Count Node*", "id": "ByBnu82ZPD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "ByU2OI2ZPP": { "content": "*We’ll also add a count node to this patch so that we can monitor the number of times the LED flashes.*\n\nAdd a count node (xod/core).\n\n*Let's look at the count node, set each of its pins and connect it to the patch.*\n\nThe count node measures how many times a pulse or boolean ‘True’ signal has been sent, counting up each time it recieves a signal.", "id": "ByU2OI2ZPP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "S1uhuL2WPv": { "content": "**Output Pins**\n\n*Add a watch node and connect it to the clock output pin*\nThis setup will let us see on the screen each time the LED pulses.", "id": "S1uhuL2WPv", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 9, "units": "slots" } } }, "links": { "r13tLhbDw": { "id": "r13tLhbDw", "input": { "nodeId": "BJ-3_I3-vP", "pinKey": "ryTIROHwkW" }, "output": { "nodeId": "HkMhdL2WPD", "pinKey": "HJU8CE2lW" } }, "ryE2dLhWDv": { "id": "ryE2dLhWDv", "input": { "nodeId": "Skgnu82Zww", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "BJ-3_I3-vP", "pinKey": "HkyxURuSPyW" } } }, "nodes": { "BJ-3_I3-vP": { "boundLiterals": { "Bkh8A_Sv1-": "On Boot" }, "id": "BJ-3_I3-vP", "position": { "x": 10, "y": 2, "units": "slots" }, "type": "xod/core/flip-flop" }, "HkMhdL2WPD": { "id": "HkMhdL2WPD", "position": { "x": 11, "y": 1, "units": "slots" }, "type": "xod/core/clock" }, "Skgnu82Zww": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "Skgnu82Zww", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" } }, "path": "@/tuto408" }, "@/tuto409": { "comments": { "B1Bd6dhbPv": { "content": "*Your patch should now look something like this.*\n\nUpload and debug the program. Watch the LED and your watch node.\n\nThe LED should flash and the count will increase with each switch.", "id": "B1Bd6dhbPv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "H1Nd6unZvv": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Upload and Debug (round 3)*", "id": "H1Nd6unZvv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "H1f_6dnbPP": { "id": "H1f_6dnbPP", "input": { "nodeId": "ByupO3-wP", "pinKey": "HyYh1a3LZ" }, "output": { "nodeId": "Bye_pu3ZvD", "pinKey": "HkyxURuSPyW" } }, "HJXOpu3-vv": { "id": "HJXOpu3-vv", "input": { "nodeId": "Bye_pu3ZvD", "pinKey": "ryTIROHwkW" }, "output": { "nodeId": "Hk-Opun-Dw", "pinKey": "HJU8CE2lW" } }, "r1WkK2Wvv": { "id": "r1WkK2Wvv", "input": { "nodeId": "Hk1yKhbvP", "pinKey": "HJAq-A_8-" }, "output": { "nodeId": "ByupO3-wP", "pinKey": "rJxhvs_Lx7" } }, "r1oJtnZwP": { "id": "r1oJtnZwP", "input": { "nodeId": "Syt1th-vP", "pinKey": "HkXK-dGob" }, "output": { "nodeId": "Hk1yKhbvP", "pinKey": "r1yhZRd8W" } } }, "nodes": { "Bye_pu3ZvD": { "boundLiterals": { "Bkh8A_Sv1-": "On Boot" }, "id": "Bye_pu3ZvD", "position": { "x": 10, "y": 2, "units": "slots" }, "type": "xod/core/flip-flop" }, "ByupO3-wP": { "boundLiterals": { "B1oqkTnIb": "D4" }, "id": "ByupO3-wP", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "xod/common-hardware/led" }, "Hk-Opun-Dw": { "id": "Hk-Opun-Dw", "position": { "x": 11, "y": 1, "units": "slots" }, "type": "xod/core/clock" }, "Hk1yKhbvP": { "id": "Hk1yKhbvP", "position": { "x": 8, "y": 4, "units": "slots" }, "type": "xod/core/count" }, "Syt1th-vP": { "id": "Syt1th-vP", "position": { "x": 8, "y": 5, "units": "slots" }, "type": "xod/debug/watch" } }, "path": "@/tuto409" }, "@/tuto410": { "comments": { "Bygdt3Zww": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*Experiment!*", "id": "Bygdt3Zww", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SJxxOF2ZvP": { "content": "As with all programming, there is always more than one way to achieve a similar outcome, and different methods may suit different applications. Here we have tested two different ways of making the LED flash, but there are plenty of other ways you can experiment with.
\n\n*Why not try using a square-wave node to make the LED flash?*\nSee if you can work it out using the help pane and [XOD website](https://xod.io/libs/xod/waves/square-wave/?utm_source=ide&utm_campaign=docs&utm_medium=inspector).\n\n*Or you can just try playing around with the nodes you’ve already tried.*\nTry experimenting with different timings and patterns of flashing.\n\n**If you need to, you can copy nodes from previous patches into this patch by dragging a box around the nodes you want, then copy-and-pasting.**", "id": "SJxxOF2ZvP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } } }, "nodes": { "rJt6z1GPv": { "id": "rJt6z1GPv", "position": { "x": 8, "y": 4, "units": "slots" }, "type": "xod/waves/square-wave" } }, "path": "@/tuto410" }, "@/tuto411": { "comments": { "ByuWHp-PD": { "content": "*Great, you've now completed Task 4: Flip, Clock and Count Nodes*\n\nThese nodes are really useful for controlling and monitoring the sequence of your programmes.\n\nAdditionaly, we have been introduced to a few useful skills:\n\n*1. Combining count and watch nodes*\nCombining these nodes (like we did in tuto409) is a really useful way to visualise the output of a pulse pin. You can learn more about this trick by reading 'Watching Pulse Pins:
 Combining Count and Watch Nodes' in the Beginner's Guide (p35).\n\n*2. Discovering new nodes*\nThe last step of this task (tuto410) encourages you to try out a new node: the square-wave node. We have not provided specific information about this node here, but it is useful to practice discovering new nodes for yourself. You can learn more about the different ways to do this by reading 'Discovering New Nodes' in the Beginner's Guide (p35).", "id": "ByuWHp-PD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "HkxuZHabDw": { "content": "**Before moving on to tuto501, we suggest reading 'Concat, Join and
 Format-Number Nodes' in the Beginner's Guide (p36).**\n*This will provide some useful background information for the next task.*", "id": "HkxuZHabDw", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SJWySaWPD": { "content": "**Task 4: Flip, Clock and Count Nodes**\n*The End*", "id": "SJWySaWPD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto411" }, "@/tuto501-concat-join-and-format-number-nodes": { "comments": { "B1Bnw6Zvv": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Barometer-Thermometer Node*", "id": "B1Bnw6Zvv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "H1O9KaZPw": { "content": "*2. Add node*\n\nAdd a barometer-thermometer node from this library to the patch.", "id": "H1O9KaZPw", "position": { "x": 7, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "H1q9KTbvw": { "content": "*3. Set node*\n\nSet UPD to ‘Continuously’. Leave other inputs as they are.\n\nThe outputs of this node are temperature (TEMP) and pressure (PRESS).\n\nTo learn more about what each of the input and output pins does, click on the node and open the quick help pane (question mark button in the top right corner).", "id": "H1q9KTbvw", "position": { "x": 14, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "HJeHhwa-ww": { "content": "**Before starting the task, we suggest reading 'Concat, Join and
 Format-Number Nodes' in the Beginner's Guide (p36).**\n\n*In this task we’ll look at using concat, join and format-number nodes. These nodes are especially useful when working with data and displays.

*\n\nThe concat and join nodes are both used to combine information in the form of strings (text). The format-number node is used to set the number of decimal points displayed in a number. In combination, these nodes are useful for formatting the outputs of sensor modules, both for data storage, and for display on a screen.", "id": "HJeHhwa-ww", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "SkXYKaWwv": { "content": "*1. Add library*\n\nTo work with the air pressure sensor (also known as a barometer) you will need to install the library wayland/bmp280-barometer (as in tuto201).", "id": "SkXYKaWwv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "SyaIO6bPP": { "content": "*Let's start by adding a barometer-thermometer node, so that we can use the Grove air pressure

 sensor.*", "id": "SyaIO6bPP", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto501-concat-join-and-format-number-nodes" }, "@/tuto502": { "comments": { "B1xrVqabDP": { "content": "*Now let's add and set a concat node.*\n\n*1.* Add a concat node (xod/core).\n\nThis node combines multiple strings from the input pins into a single output.\n\nThis node is ‘variadic’ meaning you can expand the node by pulling on the tab on the right, letting you increase the number of inputs. Give this a try. Then reduce it back to two inputs.\n\n*2.* Connect the first input to the barometer-thermometer TEMP pin.\n\n*3.* Set the second input to ‘oC’ (degrees centigrade) using the inspector pane .", "id": "B1xrVqabDP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "rJrE9pWwv": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Concat Node*", "id": "rJrE9pWwv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "nodes": { "SyHDj6ZPD": { "boundLiterals": { "BJ5ZVjFq8": "Continuously" }, "id": "SyHDj6ZPD", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "wayland/bmp280-barometer/barometer-thermometer" } }, "path": "@/tuto502" }, "@/tuto503": { "comments": { "rkXFssTZwv": { "content": "*Your patch should now look like this.*\n\n*Next, we'll add and set a format-number node.*\n\n*1.* Add a format-number node (xod/core).\n\nThis node lets you format the number of decimal places in a number.\n\n*2.* Link the barometer-thermometer PRESS (pressure) pin to the format-number NUM (number) pin.\n\n*3.* Set DIG (digits) to ‘0’ decimal places.", "id": "rkXFssTZwv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } }, "ryGtjjpbvw": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Format-Number Node*", "id": "ryGtjjpbvw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "BybKjjpWvw": { "id": "BybKjjpWvw", "input": { "nodeId": "ByFojaWwD", "pinKey": "Hkqu9oaWb" }, "output": { "nodeId": "ryetjo6-wv", "pinKey": "S1i8fst98" } } }, "nodes": { "ByFojaWwD": { "boundLiterals": { "BkeKcj6ZZ": "\"oC\"" }, "id": "ByFojaWwD", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/core/concat" }, "ryetjo6-wv": { "boundLiterals": { "BJ5ZVjFq8": "Continuously" }, "id": "ryetjo6-wv", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "wayland/bmp280-barometer/barometer-thermometer" } }, "path": "@/tuto503" }, "@/tuto504": { "comments": { "HJf-dn6-vw": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Join Node*", "id": "HJf-dn6-vw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Sk7bd2pZvw": { "content": "*Now we'll add and set a join node.*\n\n*1.* Add a join node (xod/core).\n\nThis is similar to concat, but has a D (deliminator) pin. D determines how inputs are joined (e.g. via a space or colon).\n\nIt’s automatically set to be a space. Leave it as this.\n\n*2.* Connect the first input (S1) to the format-number STR (string) pin.\n\n*3.* Set the second input to ‘Pa’ (pascals, the unit of air pressure) using the inspector pane.", "id": "Sk7bd2pZvw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } } }, "links": { "Hk0_2aZPD": { "id": "Hk0_2aZPD", "input": { "nodeId": "rJjuha-Pw", "pinKey": "BJlHojaWZ" }, "output": { "nodeId": "rkgZu2pbDP", "pinKey": "S1XUziFqU" } }, "HkbZdhTWPP": { "id": "HkbZdhTWPP", "input": { "nodeId": "rJbdh6Zvw", "pinKey": "Hkqu9oaWb" }, "output": { "nodeId": "rkgZu2pbDP", "pinKey": "S1i8fst98" } } }, "nodes": { "rJbdh6Zvw": { "boundLiterals": { "BkeKcj6ZZ": "\"oC\"" }, "id": "rJbdh6Zvw", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/core/concat" }, "rJjuha-Pw": { "boundLiterals": { "HJTIija-W": "0" }, "id": "rJjuha-Pw", "position": { "x": 11, "y": 2, "units": "slots" }, "type": "xod/core/format-number" }, "rkgZu2pbDP": { "boundLiterals": { "BJ5ZVjFq8": "Continuously" }, "id": "rkgZu2pbDP", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "wayland/bmp280-barometer/barometer-thermometer" } }, "path": "@/tuto504" }, "@/tuto505": { "comments": { "B14tY6pbvD": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Add Watch Nodes, Upload and Debug*", "id": "B14tY6pbvD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SyHKKTTZvw": { "content": "*Your patch should now look like this.*\n\n*Finally, we can add watch nodes, upload and debug the patch.*\n\n*1.* Add two watch nodes (xod/debug).\n\n*2.* Link one to the output of the concat node, and one to the output of the join node.\n\nYou may need to expand the watch nodes by pulling on the bottom right corner.\n\n*3.* Upload and debug using the ladybird button.\n\nLook at the watch nodes and notice how the two values are displayed.", "id": "SyHKKTTZvw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 6, "units": "slots" } } }, "links": { "BJ490TWwP": { "id": "BJ490TWwP", "input": { "nodeId": "r1k9CpWwP", "pinKey": "HynENHNOz" }, "output": { "nodeId": "Bk-YFpTWPP", "pinKey": "r1H_oipZb" } }, "BJzttapbwP": { "id": "BJzttapbwP", "input": { "nodeId": "SkFt66bww", "pinKey": "Hkqu9oaWb" }, "output": { "nodeId": "B1eYK6pbwP", "pinKey": "S1i8fst98" } }, "Hk7FK6a-DD": { "id": "Hk7FK6a-DD", "input": { "nodeId": "Bk-YFpTWPP", "pinKey": "BJlHojaWZ" }, "output": { "nodeId": "B1eYK6pbwP", "pinKey": "S1XUziFqU" } } }, "nodes": { "B1eYK6pbwP": { "boundLiterals": { "BJ5ZVjFq8": "Continuously" }, "id": "B1eYK6pbwP", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "wayland/bmp280-barometer/barometer-thermometer" }, "Bk-YFpTWPP": { "boundLiterals": { "HJTIija-W": "0" }, "id": "Bk-YFpTWPP", "position": { "x": 11, "y": 2, "units": "slots" }, "type": "xod/core/format-number" }, "SkFt66bww": { "boundLiterals": { "BkeKcj6ZZ": "\"oC\"" }, "id": "SkFt66bww", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/core/concat" }, "r1k9CpWwP": { "boundLiterals": { "rJJHNrVuM": "\"Pa\"" }, "id": "r1k9CpWwP", "position": { "x": 11, "y": 3, "units": "slots" }, "type": "xod/core/join" } }, "path": "@/tuto505" }, "@/tuto506": { "comments": { "H1e3ky0WwD": { "content": "*Play around with the nodes in your patch to see how you can format the sensor output in different ways.*\n\n*Try exploring other nodes available for formatting numbers in XOD.*\n\nFor example, number-split-to-digit (from the gst/number-split-to-digit library), dec-to-2digits or dec-to-4digits (both from the cesars/utils library). You may need to install these libraries first.", "id": "H1e3ky0WwD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 6, "units": "slots" } }, "rk3JyCZDD": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*Experiment!*", "id": "rk3JyCZDD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "links": { "B1EROERWPv": { "id": "B1EROERWPv", "input": { "nodeId": "r1ZCdEAZvD", "pinKey": "BJlHojaWZ" }, "output": { "nodeId": "Hyx0uE0ZDv", "pinKey": "S1XUziFqU" } }, "H1Ks40ZPD": { "id": "H1Ks40ZPD", "input": { "nodeId": "SywsNRZwP", "pinKey": "HkXK-dGob" }, "output": { "nodeId": "S1A_4Cbww", "pinKey": "rksccsp-W" } }, "S1SAu4A-vw": { "id": "S1SAu4A-vw", "input": { "nodeId": "SyzC_V0bvP", "pinKey": "HynENHNOz" }, "output": { "nodeId": "r1ZCdEAZvD", "pinKey": "r1H_oipZb" } }, "SyynNC-ww": { "id": "SyynNC-ww", "input": { "nodeId": "BypjVRbvD", "pinKey": "HkXK-dGob" }, "output": { "nodeId": "SyzC_V0bvP", "pinKey": "HJrBNr4dG" } }, "rymCO4RWvD": { "id": "rymCO4RWvD", "input": { "nodeId": "S1A_4Cbww", "pinKey": "Hkqu9oaWb" }, "output": { "nodeId": "Hyx0uE0ZDv", "pinKey": "S1i8fst98" } } }, "nodes": { "BkCGUJzww": { "id": "BkCGUJzww", "position": { "x": 17, "y": 2, "units": "slots" }, "type": "cesars/utils/dec-to-2digits" }, "ByCWIJzvw": { "id": "ByCWIJzvw", "position": { "x": 16, "y": 1, "units": "slots" }, "type": "gst/number-split-to-digit/number-split-to-digit" }, "BypjVRbvD": { "id": "BypjVRbvD", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 1, "width": 2, "units": "slots" }, "type": "xod/debug/watch" }, "Hyx0uE0ZDv": { "id": "Hyx0uE0ZDv", "position": { "x": 8, "y": 1, "units": "slots" }, "type": "wayland/bmp280-barometer/barometer-thermometer" }, "S1A_4Cbww": { "boundLiterals": { "BkeKcj6ZZ": "\"oC\"" }, "id": "S1A_4Cbww", "position": { "x": 8, "y": 2, "units": "slots" }, "type": "xod/core/concat" }, "SkzmUkzPP": { "id": "SkzmUkzPP", "position": { "x": 16, "y": 3, "units": "slots" }, "type": "cesars/utils/dec-to-4digits" }, "SywsNRZwP": { "id": "SywsNRZwP", "position": { "x": 8, "y": 3, "units": "slots" }, "size": { "height": 1, "width": 2, "units": "slots" }, "type": "xod/debug/watch" }, "SyzC_V0bvP": { "boundLiterals": { "rJJHNrVuM": "\"Pa\"" }, "id": "SyzC_V0bvP", "position": { "x": 11, "y": 3, "units": "slots" }, "type": "xod/core/join" }, "r1ZCdEAZvD": { "boundLiterals": { "HJTIija-W": "0" }, "id": "r1ZCdEAZvD", "position": { "x": 11, "y": 2, "units": "slots" }, "type": "xod/core/format-number" } }, "path": "@/tuto506" }, "@/tuto507": { "comments": { "HygJUrRWDv": { "content": "*You've now completed Task 5: Concat, Join and
 Format-Number Nodes, well done!*\n\nThis section has covered a number of basic nodes that we have found useful in building simple biological devices. However, there are plenty of other useful nodes out there, both pre-installed in XOD, and created by XOD users such as yourself.\n\n

In the rest of this tutorial we will continue to explore useful nodes and techniques in XOD, but if you’d like to explore for yourself, here are a few useful resources for getting to grips with XOD:

\n\n*XOD Tutorial
*\nEach time you open XOD it will offer you the option of following its inbuilt tutorial. Working through this is a great way to learn more about what XOD can do. It is also available on the XOD website under [Tutorial](www.xod.io/docs/tutorial).\n\n*

XOD Guide*\nThe XOD user guide provides advice on some more complex concepts, as well as some case studies to work through. It is available on the XOD website under [Guide](www.xod.io/docs/guide).\n\n*

XOD Core Library*\n
Taking a look through the nodes in the XOD core library will help you understand the most basic nodes available and what they do. Find xod/core in the Project Browser.", "id": "HygJUrRWDv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 20, "units": "slots" } }, "SJk4BAWPD": { "content": "**Task 5: Concat, Join and
 Format-Number Nodes**\n*The End*", "id": "SJk4BAWPD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SyvXZZGDD": { "content": "**Before moving on to tuto601, we suggest reading the introduction to Lesson 4: 'Building Programmes' and 'Creating New Nodes' in the Beginner's Guide (p42-43).**\n*These pages will provide some useful background information to help you with the next tasks.*", "id": "SyvXZZGDD", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto507" }, "@/tuto601-creating-new-nodes": { "comments": { "r15pWZGPP": { "content": "**Before starting the task, we suggest reading the introduction to Lesson 4: 'Building Programmes' and 'Creating New Nodes' in the Beginner's Guide (p42-43).**\n\n*In this task we’ll learn how to make a new node that will allow us to write text on our OLED screen.*\n\n

Instructing the OLED screen to display text is a slightly more complex task that we have done so far, and involves several nodes to represent the screen rather than one.\n\nIn this task we’ll be combining these multiple nodes into one, which we will then use to display the readings from our onboard sound sensor.

\n\nCreating your own nodes is much easier than it sounds. It is essentially the same as creating any other patch, but we need to add special nodes called ‘terminals’ to allow our new node to communicate with other nodes.\n\nCreating nodes like this is useful as it helps to simplify the patch, and we can also save new nodes for later use in different programmes.\n\n", "id": "r15pWZGPP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "ry24fWzww": { "content": "*In this task, the tutorials (tuto601-610) will guide you through the steps, but you will build your node in a seperate patch.*\n\nStart by making a new patch (page icon next to Project Browser, or navigate to 'File > New Patch...') and naming it 'write-test-to-oled'.\n\nYou can switch back and forth between the tutorial patches and your 'write-text-to-oled' patch using the tabs at the top of the screen.\n\nIf you have not done so already, now might be a good time to close some of the old tutorial patches so that you have less tabs to keep track of.", "id": "ry24fWzww", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "ry9SdAWvP": { "content": "**Task 6: Creating New Nodes**\n*Making a 'write-text-to-oled' Patch*", "id": "ry9SdAWvP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto601-creating-new-nodes" }, "@/tuto602": { "comments": { "B1g4HSbGwv": { "content": "*To work with the OLED screen you will need to install the library wayland/ssd1306-oled-i2c.*\n\nOnce installed, add the following nodes to your 'write-text-to-oled' patch:\nssd1306-oled-i2c-device\nrotate-display\nclear-display\ndraw-text\nsend-buffer-to-display.", "id": "B1g4HSbGwv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "Hy4Br-zDv": { "content": "**Task 6: Creating New Nodes**\n*Install Library and Add Nodes*", "id": "Hy4Br-zDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto602" }, "@/tuto603": { "comments": { "B1Hs_Zzwv": { "content": "*3. clear-display

*\n\nThis node should be used before displaying anything on the screen.\n\nConnect the *DONE* pin to the *draw-text UPD* pin.", "id": "B1Hs_Zzwv", "position": { "x": 0, "y": 9, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "B1huFbGPw": { "content": "*5. send-buffer-to-display

*\n\nSo far we have written information to the microchip’s memory, but we haven’t actually send it to the screen.\n\nThis node is the final step that sends this data. It needs to be used whenever you want to display something on the screen.", "id": "B1huFbGPw", "position": { "x": 0, "y": 14, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "BygX2UWfDw": { "content": "Setting up the OLED screen requires several connections between these nodes, so let’s take it step by step.\n\nAn annoted version of the patch is available in the Beginner's Guide, on page 45. It may be useful to have this to hand when completing this task.", "id": "BygX2UWfDw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "Hk_ZPZfPP": { "content": "*2. rotate-display

*\n\nYou can change the screen orientation using this node. \n\nSet *ROT* (rotation state) to ‘02h’, which is correct for our screen.\n\nSet *UPD* (update) to ‘On Boot’ so that the screen updates when the programme starts.\n\nThis node starts a sequence that allows us to display items on the screen. *In this sequence, each DONE pin connects to the next UPD pin.*\n\nConnect the *rotate-screen DONE* pin to the *clear-display UPD* pin.", "id": "Hk_ZPZfPP", "position": { "x": 0, "y": 6, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "Hy7bDWfPv": { "content": "*1. ssd1306-oled-i2c-device

*\n\nThis node represents the OLED device.\n\n*WIDTH* and *HEIGHT* set the dimensions of the screen in pixels. Leave these as ‘128’ and ‘64’.\n\n*ADDRESS* identifies the port, leave this as ‘3Ch’. \n\n*RESET* represents the screen’s reset pin. Leave this as ‘-1’, as our board does not have a dedicated screen reset pin.\n\n*The output of this node, DEV (device) needs to be connected to each of the other nodes' DEV input pins.* ", "id": "Hy7bDWfPv", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "S10L9ZzPw": { "content": "*5. Test the

 'write-text-to-oled' patch*\n\nUpload the patch and watch your OLED screen. White text should appear in the top left-hand corner of the screen.\n\nIf you're having trouble, compare your patch to the example in tuto 604 to check that it's set up correctly.", "id": "S10L9ZzPw", "position": { "x": 0, "y": 16, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "SyX2IbMPP": { "content": "**Task 6: Creating New Nodes**\n*Setting up the OLED Screen*", "id": "SyX2IbMPP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rywXtWGDP": { "content": "*4. 
draw-text

*\n\nThis node inputs the text we want displayed.\n\n*X* and *Y* determine the position of the text by coordinates. Leave these as ‘0’, ‘0’.\n\n*TEXT* is where you enter your text. Use ‘Hello!’ as a test.\n\n*SIZE* determines the size of the text. Leave this as ‘02h’.\n\n*COLOUR* determines the colour of the text (black or white). Set this to ‘1’.\n\n*WRAP* determines whether the text is wrapped within the boundaries of the screen. Leave this as ‘True”.\n\nConnect the *DONE* pin to the *send-buffer-to-display UPD* pin.", "id": "rywXtWGDP", "position": { "x": 0, "y": 11, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } } }, "path": "@/tuto603" }, "@/tuto604": { "comments": { "B1YlsZGPD": { "content": "**Task 6: Creating New Nodes**\n*Turning Your Patch into a Node*", "id": "B1YlsZGPD", "position": { "x": -2, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } }, "rJxFxibMPD": { "content": "*Your patch should now look like this*\n\n*Now that your know your patch works correctly, let's turn it into a useful node by making a few quick changes.*\n\n**In your 'write-text-to-oled' patch:**\n\n*1. Add a clock node*\n\nAdd a clock node (xod/core) and link the TICK pin to rotate-display UPD. This will make your screen update once a second.\n\n*2. Add an input terminal*\n\nAdd an input-string node (xod/patch-nodes) and connect it to draw-text TEXT.", "id": "rJxFxibMPD", "position": { "x": -2, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 11, "units": "slots" } } }, "links": { "B1FryjZMww": { "id": "B1FryjZMww", "input": { "nodeId": "S1fryibfPv", "pinKey": "B11QT1qLN" }, "output": { "nodeId": "HkbH1sWfvw", "pinKey": "rylSGPt8E" } }, "BJLBksbGPD": { "id": "BJLBksbGPD", "input": { "nodeId": "S1fryibfPv", "pinKey": "HJIQ6AY8E" }, "output": { "nodeId": "S1Sko-GPP", "pinKey": "ryH6tSt8N" } }, "BkcrJj-GPw": { "id": "BkcrJj-GPw", "input": { "nodeId": "SJmrksbMwv", "pinKey": "SJDbf_YUV" }, "output": { "nodeId": "S1fryibfPv", "pinKey": "r1DL6CFU4" } }, "By_SJjZGvv": { "id": "By_SJjZGvv", "input": { "nodeId": "HkbH1sWfvw", "pinKey": "r1H7MwK8E" }, "output": { "nodeId": "HJlH1j-fPP", "pinKey": "H1MN0Vh85U" } }, "HkDHkoZzPw": { "id": "HkDHkoZzPw", "input": { "nodeId": "SJmrksbMwv", "pinKey": "Sy6LZuYIE" }, "output": { "nodeId": "S1Sko-GPP", "pinKey": "ryH6tSt8N" } }, "S1BSyoZzvP": { "id": "S1BSyoZzvP", "input": { "nodeId": "HkbH1sWfvw", "pinKey": "S1mxGvKUN" }, "output": { "nodeId": "S1Sko-GPP", "pinKey": "ryH6tSt8N" } }, "r1NrkjZfwD": { "id": "r1NrkjZfwD", "input": { "nodeId": "HJlH1j-fPP", "pinKey": "rJV0NhU5U" }, "output": { "nodeId": "S1Sko-GPP", "pinKey": "ryH6tSt8N" } } }, "nodes": { "HJlH1j-fPP": { "boundLiterals": { "BJ7urnUq8": "02h", "rJg4RN3I9I": "On Boot" }, "id": "HJlH1j-fPP", "position": { "x": 11, "y": 0, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/rotate-display" }, "HkbH1sWfvw": { "id": "HkbH1sWfvw", "position": { "x": 11, "y": 2, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/clear-display" }, "S1Sko-GPP": { "id": "S1Sko-GPP", "position": { "x": 16, "y": 0, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/ssd1306-oled-i2c-device" }, "S1fryibfPv": { "boundLiterals": { "S1gH6CKIN": "\"Hello!\"" }, "id": "S1fryibfPv", "position": { "x": 11, "y": 4, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-text" }, "SJmrksbMwv": { "id": "SJmrksbMwv", "position": { "x": 11, "y": 6, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/send-buffer-to-display" } }, "path": "@/tuto604" }, "@/tuto605": { "comments": { "BkgJ8TbzDP": { "content": "*1. Now we’ve made our new node, let’s try adding it to this patch.*\n\nTo add your new node to a patch, simply search for it as usual, or drag the 'write-test-to-oled' patch from the Project Browser into this patch.\n\nYou should see a small node with one input pin.", "id": "BkgJ8TbzDP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } }, "HJSRaZzPv": { "content": "*2. Next, let’s use this node to display a sensor reading.*\n\nFor many common analog sensors (including the inbuilt sound sensor) you can use the simple XOD analog-sensor node (xod/common-hardware).\n\nAdd an analog sensor node to this patch. Set PORT to ‘A2’, and connect VAL to the write-text-to-oled node.", "id": "HJSRaZzPv", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } }, "r1l4S1Pvv": { "content": "*3. Upload the patch, and watch your board.*\n\nYou should see the readings from the sound sensor displayed on your screen.\n\nIf you are having trouble, compare your 'write-text-to-oled' patch to the example in tuto606 to check that it's set up correctly.", "id": "r1l4S1Pvv", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } }, "ryy8TbMDv": { "content": "**Task 6: Creating New Nodes**\n*Connect OLED to Sensor and Test*", "id": "ryy8TbMDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto605" }, "@/tuto606": { "comments": { "BJeO81zzwP": { "content": "**Task 6: Creating New Nodes**\n*Modifying Your Node*", "id": "BJeO81zzwP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } }, "ryuIkMGDv": { "content": "*Your 'write-text-to-oled' patch should now look like this*\n\nWriting a line of text directly to the OLED screen is great, but what if we need a more complicated node? For example, one that takes multiple lines of text, or one that sends a signal once the text has been uploaded?\n\nLets make some more edits to our 'write-text-to-display' node to add in these capabilities.\n\nAn annoted version of the modifed patch is available in the Beginner's Guide, on page 47. It may be useful to have this to hand when completing this task.\n\n**In your 'write-text-to-oled' patch:**\n\n*1. Second draw-text node

*\n\nAdd a second draw-text node below the first. We will use this to draw a second line of text. Set the Y pin of this node to 20. This will move the text down by 20 pixels, creating a new line.\n\n*2. 
Reconnect*\n\n

Delete the link between the first draw-text node and send-buffer-to-display. Link the first draw-text DONE pin to the second draw-text UPD pin. Link the second draw-text DONE pin to the send-buffer-to-display UPD pin. Connect ssd1306-oled-i2c-device DEV to the second draw-text DEV pin.\n\n*3. 

Label input-string nodes*\n\nAdd a second input-string node and connect it to the TEXT pin of the second draw-text node. We will now have more than one input into our node, so we need give them labels, to avoid confusion. Click on each input-string node in turn. Use the Inspector pane to name your nodes by typing in the ‘Label’ text box. Name your nodes ‘LINE 1’ and ‘LINE 2’ respectively.

\n\n*4. Add output-string node*\n\n

Add an output-pulse node to the patch, and connect it to the send-buffer-to-display DONE pin. Use the Inspector to label this node ‘DONE’.\n\nIf you are having trouble, compare your 'write-text-to-oled' patch to the example in tuto607 to check that it's set up correctly.", "id": "ryuIkMGDv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 9, "width": 11, "units": "slots" } } }, "links": { "B1Rxhkffvv": { "id": "B1Rxhkffvv", "input": { "nodeId": "ryMxn1MGPD", "pinKey": "S1gH6CKIN" }, "output": { "nodeId": "SkHg3kMzvP", "pinKey": "__out__" } }, "BJhe2JMzPw": { "id": "BJhe2JMzPw", "input": { "nodeId": "Symg3JfMPv", "pinKey": "SJDbf_YUV" }, "output": { "nodeId": "ryMxn1MGPD", "pinKey": "r1DL6CFU4" } }, "By9l2yMzwv": { "id": "By9l2yMzwv", "input": { "nodeId": "B1Wx2JfzPv", "pinKey": "r1H7MwK8E" }, "output": { "nodeId": "HJgl2JfGvD", "pinKey": "H1MN0Vh85U" } }, "H1OlhJfzPv": { "id": "H1OlhJfzPv", "input": { "nodeId": "ryMxn1MGPD", "pinKey": "HJIQ6AY8E" }, "output": { "nodeId": "S1lnyfzPv", "pinKey": "ryH6tSt8N" } }, "HJ8g3JGGvP": { "id": "HJ8g3JGGvP", "input": { "nodeId": "HJgl2JfGvD", "pinKey": "rJV0NhU5U" }, "output": { "nodeId": "S1lnyfzPv", "pinKey": "ryH6tSt8N" } }, "HkFx2JzfDD": { "id": "HkFx2JzfDD", "input": { "nodeId": "Symg3JfMPv", "pinKey": "Sy6LZuYIE" }, "output": { "nodeId": "S1lnyfzPv", "pinKey": "ryH6tSt8N" } }, "HyDx31MGvw": { "id": "HyDx31MGvw", "input": { "nodeId": "B1Wx2JfzPv", "pinKey": "S1mxGvKUN" }, "output": { "nodeId": "S1lnyfzPv", "pinKey": "ryH6tSt8N" } }, "S1Tlh1Mfwv": { "id": "S1Tlh1Mfwv", "input": { "nodeId": "HJgl2JfGvD", "pinKey": "rJg4RN3I9I" }, "output": { "nodeId": "BkEehyGzPD", "pinKey": "HJU8CE2lW" } }, "rJjl2JfMPv": { "id": "rJjl2JfMPv", "input": { "nodeId": "ryMxn1MGPD", "pinKey": "B11QT1qLN" }, "output": { "nodeId": "B1Wx2JfzPv", "pinKey": "rylSGPt8E" } } }, "nodes": { "B1Wx2JfzPv": { "id": "B1Wx2JfzPv", "position": { "x": 13, "y": 3, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/clear-display" }, "BkEehyGzPD": { "id": "BkEehyGzPD", "position": { "x": 13, "y": 0, "units": "slots" }, "type": "xod/core/clock" }, "HJgl2JfGvD": { "boundLiterals": { "BJ7urnUq8": "02h", "rJg4RN3I9I": "On Boot" }, "id": "HJgl2JfGvD", "position": { "x": 13, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/rotate-display" }, "S1lnyfzPv": { "id": "S1lnyfzPv", "position": { "x": 18, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/ssd1306-oled-i2c-device" }, "SkHg3kMzvP": { "id": "SkHg3kMzvP", "position": { "x": 16, "y": 4, "units": "slots" }, "type": "xod/patch-nodes/input-string" }, "Symg3JfMPv": { "id": "Symg3JfMPv", "position": { "x": 13, "y": 7, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/send-buffer-to-display" }, "ryMxn1MGPD": { "boundLiterals": { "S1gH6CKIN": "\"Hello!\"" }, "id": "ryMxn1MGPD", "position": { "x": 13, "y": 5, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-text" } }, "path": "@/tuto606" }, "@/tuto607": { "comments": { "H1lPvM1PwD": { "content": "*Your write-text-to-oled patch should now look like this*", "id": "H1lPvM1PwD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } }, "HkPvzyPPw": { "content": "**Task 6: Creating New Nodes**\n*Check your write-text-to-oled Node*", "id": "HkPvzyPPw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } } }, "links": { "BJ9xIMyvwv": { "id": "BJ9xIMyvwv", "input": { "nodeId": "BJ4gLMkPPD", "pinKey": "Sy6LZuYIE" }, "output": { "nodeId": "H1xeIMkPvw", "pinKey": "ryH6tSt8N" } }, "BySegIfyDPv": { "id": "BySegIfyDPv", "input": { "nodeId": "S1OxIMyvDw", "pinKey": "__in__" }, "output": { "nodeId": "BJ4gLMkPPD", "pinKey": "BkPGzdFI4" } }, "HJseIfJDww": { "id": "HJseIfJDww", "input": { "nodeId": "ryQxLMJDwD", "pinKey": "S1mxGvKUN" }, "output": { "nodeId": "H1xeIMkPvw", "pinKey": "ryH6tSt8N" } }, "HJzxl8f1DvP": { "id": "HJzxl8f1DvP", "input": { "nodeId": "BJ4gLMkPPD", "pinKey": "SJDbf_YUV" }, "output": { "nodeId": "HkLgLfJPww", "pinKey": "r1DL6CFU4" } }, "Hk0lIGyDvD": { "id": "Hk0lIGyDvD", "input": { "nodeId": "rJzeLfyvDv", "pinKey": "HJIQ6AY8E" }, "output": { "nodeId": "H1xeIMkPvw", "pinKey": "ryH6tSt8N" } }, "HyYgUMkvvv": { "id": "HyYgUMkvvv", "input": { "nodeId": "ryQxLMJDwD", "pinKey": "r1H7MwK8E" }, "output": { "nodeId": "S1xIMyDvD", "pinKey": "H1MN0Vh85U" } }, "SJNll8GJwww": { "id": "SJNll8GJwww", "input": { "nodeId": "HkLgLfJPww", "pinKey": "S1gH6CKIN" }, "output": { "nodeId": "B1DeIf1Pvw", "pinKey": "__out__" } }, "SJQgxUG1PwD": { "id": "SJQgxUG1PwD", "input": { "nodeId": "HkLgLfJPww", "pinKey": "HJIQ6AY8E" }, "output": { "nodeId": "H1xeIMkPvw", "pinKey": "ryH6tSt8N" } }, "SJygeIzJPwD": { "id": "SJygeIzJPwD", "input": { "nodeId": "S1xIMyDvD", "pinKey": "rJV0NhU5U" }, "output": { "nodeId": "H1xeIMkPvw", "pinKey": "ryH6tSt8N" } }, "rJhxIMJPwD": { "id": "rJhxIMJPwD", "input": { "nodeId": "rJzeLfyvDv", "pinKey": "B11QT1qLN" }, "output": { "nodeId": "ryQxLMJDwD", "pinKey": "rylSGPt8E" } }, "rkxee8fyPPw": { "id": "rkxee8fyPPw", "input": { "nodeId": "rJzeLfyvDv", "pinKey": "S1gH6CKIN" }, "output": { "nodeId": "H1bgIMJPwD", "pinKey": "__out__" } }, "ry6lIGkPvD": { "id": "ry6lIGkPvD", "input": { "nodeId": "S1xIMyDvD", "pinKey": "rJg4RN3I9I" }, "output": { "nodeId": "rJre8z1PvD", "pinKey": "HJU8CE2lW" } }, "ryZxgLMywwv": { "id": "ryZxgLMywwv", "input": { "nodeId": "HkLgLfJPww", "pinKey": "B11QT1qLN" }, "output": { "nodeId": "rJzeLfyvDv", "pinKey": "r1DL6CFU4" } } }, "nodes": { "B1DeIf1Pvw": { "id": "B1DeIf1Pvw", "label": "LINE 2", "position": { "x": 16, "y": 5, "units": "slots" }, "type": "xod/patch-nodes/input-string" }, "BJ4gLMkPPD": { "id": "BJ4gLMkPPD", "position": { "x": 13, "y": 7, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/send-buffer-to-display" }, "H1bgIMJPwD": { "id": "H1bgIMJPwD", "label": "LINE 1", "position": { "x": 16, "y": 3, "units": "slots" }, "type": "xod/patch-nodes/input-string" }, "H1xeIMkPvw": { "id": "H1xeIMkPvw", "position": { "x": 18, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/ssd1306-oled-i2c-device" }, "HkLgLfJPww": { "boundLiterals": { "Bkw-6yqI4": "20", "S1gH6CKIN": "\"Hello!\"" }, "id": "HkLgLfJPww", "position": { "x": 13, "y": 6, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-text" }, "S1OxIMyvDw": { "id": "S1OxIMyvDw", "label": "DONE", "position": { "x": 13, "y": 8, "units": "slots" }, "type": "xod/patch-nodes/output-pulse" }, "S1xIMyDvD": { "boundLiterals": { "BJ7urnUq8": "02h", "rJg4RN3I9I": "On Boot" }, "id": "S1xIMyDvD", "position": { "x": 13, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/rotate-display" }, "rJre8z1PvD": { "id": "rJre8z1PvD", "position": { "x": 13, "y": 0, "units": "slots" }, "type": "xod/core/clock" }, "rJzeLfyvDv": { "boundLiterals": { "S1gH6CKIN": "\"Hello!\"" }, "id": "rJzeLfyvDv", "position": { "x": 13, "y": 4, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-text" }, "ryQxLMJDwD": { "id": "ryQxLMJDwD", "position": { "x": 13, "y": 3, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/clear-display" } }, "path": "@/tuto607" }, "@/tuto608": { "comments": { "S1Wo0608PP": { "content": "*Now let's see how our node has changed when we add it to a patch.*\n\n*1. Add a write-text-to-oled node to this patch.*\n\nYou will notice that the write-text-to-oled node has changed. It now has two inputs and an output. This time, link the VAL pin to LINE 2. Use the Inspector to set LINE 1 to ‘Volume:’.\n\n*2. Like we did in tuto409, we're going to watch the output of the DONE pulse pin using a combination of count and watch nodes.*\n\nAdd a count node (xod/core) and watch node (xod/debug). Link the write-text-to-oled DONE pin to the count INC pin, and the watch node to the count output pin.\n\n*3. Upload and Debug.*\n\nUpload and debug the patch. You should see two lines of text on your screen, and the watch node will count when the screen updates.", "id": "S1Wo0608PP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 5, "width": 9, "units": "slots" } }, "rkgsRTAUwv": { "content": "**Task 6: Creating New Nodes**\n*Upload and Test (round 2)*", "id": "rkgsRTAUwv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "nodes": { "BkoATC8DD": { "boundLiterals": { "r1l3XcR17": "A2" }, "id": "BkoATC8DD", "position": { "x": 11, "y": 1, "units": "slots" }, "type": "xod/common-hardware/analog-sensor" } }, "path": "@/tuto608" }, "@/tuto609": { "comments": { "ByCYgkDwv": { "content": "**Task 6: Creating New Nodes**\n*Experiment!*", "id": "ByCYgkDwv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rygCYe1DDD": { "content": "*The OLED screen is a really useful device, and can be used in a multitude of different ways.*\n\nTry playing around with your new node by adding another line, or changing the position and size of the text.\n\nOr you can try using the OLED to display data from a different sensor.\n\n*You can also experiment with some of the other nodes in the wayland/ssd1306-oled-i2c library.*\n\nThis library contains lots of useful nodes for drawing different objects on the screen, as well as several example patches to show you how they work.\n\nYou can see several of these nodes here on the right.", "id": "rygCYe1DDD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 8, "units": "slots" } } }, "nodes": { "B1Pvb1vDD": { "id": "B1Pvb1vDD", "position": { "x": 9, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-triangle" }, "BkbNZkwPw": { "id": "BkbNZkwPw", "position": { "x": 17, "y": 4, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-circle" }, "ByRNWJwvw": { "id": "ByRNWJwvw", "position": { "x": 9, "y": 4, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-line" }, "Sy4I-yPvw": { "id": "Sy4I-yPvw", "position": { "x": 19, "y": 3, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-pixel" }, "rJJvZJPPD": { "id": "rJJvZJPPD", "position": { "x": 9, "y": 3, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-rectangle" }, "rkjPW1wPv": { "id": "rkjPW1wPv", "position": { "x": 21, "y": 2, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/invert-display" }, "ryGDZkPDD": { "id": "ryGDZkPDD", "position": { "x": 9, "y": 2, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-rounded-rectangle" } }, "path": "@/tuto609" }, "@/tuto610": { "comments": { "SJx2X7yDDv": { "content": "**Task 6: Creating New Nodes**\n*The End*", "id": "SJx2X7yDDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "SkhXm1PDw": { "content": "*Great job! You've now completed Task 6: Creating New Nodes!*\n\nOne of the great advantages of XOD is the growing community of contributors, who are generating an ever-expanding range of nodes and libraries for other to use. When you create new nodes that you think might be useful for others, you can easily share these with the XOD community by publishing them as a library.\n\n*Learn more about how to share nodes and publish libraries on page 49 of the Beginner's Guide.*\n\nWhen publishing your work it is good practice to make sure that your nodes are well documented. This helps to remind yourself what you’ve done, and allows others to get an idea of how the node can be used.\n\n*Learn more about how to document your nodes on page 49 of the Beginner's Guide.*", "id": "SkhXm1PDw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "r1-2QmJDPv": { "content": "**Before moving on to tuto701, we suggest reading 'Sharing Nodes and Publishing Libraries' and 'Documenting Nodes' in the Beginner's Guide (p49).**\n*These pages will provide some useful information and context for this task.*", "id": "r1-2QmJDPv", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto610" }, "@/tuto701-using-buses": { "comments": { "B1Cw81Pvw": { "content": "**Task 7: Using Buses**\n*Add Library and Clone Patch*", "id": "B1Cw81Pvw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "BkKswyPvv": { "content": "*2. Clone write-text-oled patch.*\n\nFor this task we’ll be using the OLED display again, but in a slightly different way. So that we don’t have to start again, we can clone the write-text-to-oled patch by right clicking on the patch in the Project Browser and selecting ‘Clone’. Rename the new patch from ‘write-text-to-oled-copy’ to ‘write-dot-to-oled’.", "id": "BkKswyPvv", "position": { "x": 11, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } }, "H1gAPIkDPv": { "content": "**Before starting the task, we suggest reading 'Sharing Nodes and Publishing Libraries' and 'Documenting Nodes' in the Beginner's Guide (p49).**\n\n*In this task we’ll look at another way to simplify our patches: using buses.*\n\n*Buses are a way to link pins ‘invisibly’ so that you don’t have too many link intersections that make the data flow confusing.*\n\n

Buses are a little like input and output nodes. They come in two types, to-bus and from-bus, and they automatically take the data type of the pin they’re connected to.\n\n
The to-bus node is used like an output node and sends information from an output to a bus. The from-bus node acts like an input node and retrieves information from the bus of the same name.

\n\nWe’ll practice using buses by displaying the output of our 3-axis acceleration sensor (also known as an accelerometer or tilt sensor) on our OLED screen.", "id": "H1gAPIkDPv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "ryy8DkPPP": { "content": "*1. Install library.*\n\nTo work with the accelerometer you will need to install the library wayland/lis3dh-accelerometer.\n\nInstall this library now.", "id": "ryy8DkPPP", "position": { "x": 0, "y": 4, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } } }, "path": "@/tuto701-using-buses" }, "@/tuto702": { "comments": { "Bye3YkvDD": { "content": "*5. 

Change clock timing

*\n\nSet the clock IVAL pin to 0.1, so that it updates more frequently.", "id": "Bye3YkvDD", "position": { "x": 0, "y": 9, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Hk6iY1DPw": { "content": "*4. Replace links with buses*\n\n

Although the OLED patch worked, it was very messy, with links criss-crossing, and it would be easy to miss a connection. Let’s improve this by replacing these links with a bus. First, delete all of the orange links between the ssd1306-oled-i2c-device and the other nodes. Add a to-bus node (xod/patch-nodes) and link it to the output of ssd1306-oled-i2c-device. Use the inspector to label this node ‘DEV’. Add a from-bus node (xod/patch-nodes). Make sure this from-bus node is also labelled ‘DEV’ as buses can only communicate if they have the same name. Repeat this process, or copy and paste the DEV from-bus node until you have four in total. Connect these to each of the DEV input pins on the nodes rotate-display, clear-display, draw-circle and send-buffer-to-display.\n", "id": "Hk6iY1DPw", "position": { "x": 11, "y": 5, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } }, "HyAOPkwwD": { "content": "**Task 7: Using Buses**\n*Modifying Your Node*", "id": "HyAOPkwwD", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HyOYu1vPD": { "content": "*This time we would like to draw a small circle on the screen instead of text.*\n\nThe circle will move around the screen as you tilt the board.

Follow the instructions below to modify the write-dot-to-oled patch for this new purpose.\n\nAn annoted version of this patch is available in the Beginner's Guide, on page 51. It may be useful to have this to hand when completing this task.", "id": "HyOYu1vPD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } }, "rJAKK1vww": { "content": "*2. Reconnect*\n\n

Link the clear-display DONE pin to the the draw-circle UPD pin. Link the draw-circle DONE pin to the send-buffer-to-display UPD pin.

", "id": "rJAKK1vww", "position": { "x": 11, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } }, "rkYJFkPwP": { "content": "*3. Add input-number pins

*\n\nAdd two input-number nodes and connect them to the X and Y pins. Use the inspector to label these ‘X’ and ‘Y’.

", "id": "rkYJFkPwP", "position": { "x": 0, "y": 5, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } }, "ryY2ukwvv": { "content": "*1. Add and set draw-circle node

*\n\nDelete both draw-text nodes along with their associated input nodes. Add a draw-circle node. Set R (radius) to ‘3’ to make a circle 3 pixels wide. Leave colour as ‘1’. Set FILL to ‘True’ so that we get a solid circle rather than an outline.

", "id": "ryY2ukwvv", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 2, "width": 9, "units": "slots" } } }, "path": "@/tuto702" }, "@/tuto703": { "comments": { "SyxEP51DDv": { "content": "**Task 7: Using Buses**\n*Checking Your Node*", "id": "SyxEP51DDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } }, "rJVDq1DwD": { "content": "*Your write-dot-to-oled patch should now look like this.*", "id": "rJVDq1DwD", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 1, "width": 11, "units": "slots" } } }, "links": { "B1EenE2JPvw": { "id": "B1EenE2JPvw", "input": { "nodeId": "rJu3V2Jwvw", "pinKey": "__in__" }, "output": { "nodeId": "B1e3Vn1Dvw", "pinKey": "ryH6tSt8N" } }, "B1Ie24nkwDv": { "id": "B1Ie24nkwDv", "input": { "nodeId": "BkZh42kPPw", "pinKey": "S1mxGvKUN" }, "output": { "nodeId": "Sk5343kDwP", "pinKey": "__out__" } }, "B1Xx3N3Jvwv": { "id": "B1Xx3N3Jvwv", "input": { "nodeId": "SyHhN3JvDw", "pinKey": "H1J2v0qL4" }, "output": { "nodeId": "HJw24hkvDP", "pinKey": "__out__" } }, "BJ_gnV21Dvw": { "id": "BJ_gnV21Dvw", "input": { "nodeId": "B1G342kwwD", "pinKey": "Sy6LZuYIE" }, "output": { "nodeId": "H132EhJDPP", "pinKey": "__out__" } }, "Bkye3E3kPwD": { "id": "Bkye3E3kPwD", "input": { "nodeId": "ByV2N2JvPw", "pinKey": "__in__" }, "output": { "nodeId": "B1G342kwwD", "pinKey": "BkPGzdFI4" } }, "H1Hln43JPwP": { "id": "H1Hln43JPwP", "input": { "nodeId": "Bkn4hyDDv", "pinKey": "rJV0NhU5U" }, "output": { "nodeId": "HJY3Eh1vDw", "pinKey": "__out__" } }, "HkphN31wPv": { "id": "HkphN31wPv", "input": { "nodeId": "BkZh42kPPw", "pinKey": "r1H7MwK8E" }, "output": { "nodeId": "Bkn4hyDDv", "pinKey": "H1MN0Vh85U" } }, "HylenNhJwwP": { "id": "HylenNhJwwP", "input": { "nodeId": "SyHhN3JvDw", "pinKey": "B1BSYmjLE" }, "output": { "nodeId": "BkZh42kPPw", "pinKey": "rylSGPt8E" } }, "SJ-ehV21Pvv": { "id": "SJ-ehV21Pvv", "input": { "nodeId": "B1G342kwwD", "pinKey": "SJDbf_YUV" }, "output": { "nodeId": "SyHhN3JvDw", "pinKey": "S1dZKAcU4" } }, "SkDlhVhkDDD": { "id": "SkDlhVhkDDD", "input": { "nodeId": "SyHhN3JvDw", "pinKey": "H1WqD0584" }, "output": { "nodeId": "B1ohNnJPDv", "pinKey": "__out__" } }, "SyR2V2JPDv": { "id": "SyR2V2JPDv", "input": { "nodeId": "Bkn4hyDDv", "pinKey": "rJg4RN3I9I" }, "output": { "nodeId": "BJXnNnywPw", "pinKey": "HJU8CE2lW" } }, "Syzl3N3ywDD": { "id": "Syzl3N3ywDD", "input": { "nodeId": "SyHhN3JvDw", "pinKey": "rJtovR584" }, "output": { "nodeId": "SJLn4n1wDv", "pinKey": "__out__" } } }, "nodes": { "B1G342kwwD": { "id": "B1G342kwwD", "position": { "x": 13, "y": 7, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/send-buffer-to-display" }, "B1e3Vn1Dvw": { "id": "B1e3Vn1Dvw", "position": { "x": 18, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/ssd1306-oled-i2c-device" }, "B1ohNnJPDv": { "id": "B1ohNnJPDv", "label": "DEV", "position": { "x": 12, "y": 5, "units": "slots" }, "type": "xod/patch-nodes/from-bus" }, "BJXnNnywPw": { "boundLiterals": { "B13SCNhl-": "0.1" }, "id": "BJXnNnywPw", "position": { "x": 13, "y": 0, "units": "slots" }, "type": "xod/core/clock" }, "BkZh42kPPw": { "id": "BkZh42kPPw", "position": { "x": 13, "y": 3, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/clear-display" }, "Bkn4hyDDv": { "boundLiterals": { "BJ7urnUq8": "02h", "rJg4RN3I9I": "On Boot" }, "id": "Bkn4hyDDv", "position": { "x": 13, "y": 1, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/rotate-display" }, "ByV2N2JvPw": { "id": "ByV2N2JvPw", "label": "DONE", "position": { "x": 13, "y": 8, "units": "slots" }, "type": "xod/patch-nodes/output-pulse" }, "H132EhJDPP": { "id": "H132EhJDPP", "label": "DEV", "position": { "x": 12, "y": 7, "units": "slots" }, "type": "xod/patch-nodes/from-bus" }, "HJY3Eh1vDw": { "id": "HJY3Eh1vDw", "label": "DEV", "position": { "x": 12, "y": 1, "units": "slots" }, "type": "xod/patch-nodes/from-bus" }, "HJw24hkvDP": { "id": "HJw24hkvDP", "label": "Y", "position": { "x": 15, "y": 4, "units": "slots" }, "type": "xod/patch-nodes/input-number" }, "SJLn4n1wDv": { "id": "SJLn4n1wDv", "label": "X", "position": { "x": 14, "y": 4, "units": "slots" }, "type": "xod/patch-nodes/input-number" }, "Sk5343kDwP": { "id": "Sk5343kDwP", "label": "DEV", "position": { "x": 12, "y": 3, "units": "slots" }, "type": "xod/patch-nodes/from-bus" }, "SyHhN3JvDw": { "boundLiterals": { "B13M_058N": "True", "H1x13wRqIE": "3" }, "id": "SyHhN3JvDw", "position": { "x": 13, "y": 5, "units": "slots" }, "type": "wayland/ssd1306-oled-i2c/draw-circle" }, "rJu3V2Jwvw": { "id": "rJu3V2Jwvw", "label": "DEV", "position": { "x": 18, "y": 2, "units": "slots" }, "type": "xod/patch-nodes/to-bus" } }, "path": "@/tuto703" }, "@/tuto704": { "comments": { "ByxzpkDDv": { "content": "**Task 7: Using Buses**\n*Testing the Node*", "id": "ByxzpkDDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "S1jS61Pvw": { "content": "*Let's test our new node to see how it works*\n\n*1.* Add a write-dot-to-oled node to this patch.\n\n*2.* Add two tweak-number nodes and connect them to the X and Y inputs.\n\n*3.* Upload and debug.\n\nClick on the tweak-number nodes and use the Inspector to change their values. Watch how this shifts the dot around the screen.", "id": "S1jS61Pvw", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } } }, "path": "@/tuto704" }, "@/tuto705": { "comments": { "HJVA01vDv": { "content": "**Task 7: Using Buses**\n*Setting up the Accelerometer*", "id": "HJVA01vDv", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "HknLZlPww": { "content": "*4. Connect map node.*\n\nLink the accelerometer X and map X pins. The node now converts the accelerometer X range to values within the height of the screen.\n\n*5. Repeat map node.*\n\nAdd a second map node add link it to the Y output. Set Smin to ‘-10’, Smax to ‘10’ (the range of the accelerometer), Tmin to ‘128’ (the screen width) and Tmax to ‘0’.\n\n*6. Add round nodes.*\n\nAdd two round nodes (xod/math). Connect them to the outputs of the map nodes. This will round the outputs to whole numbers.", "id": "HknLZlPww", "position": { "x": 11, "y": 3, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } }, "SkyiylPPP": { "content": "*1. Add an accelerometer node.*\n\nAdd an accelerometer node (wayland/lis3dh-accelerometer).\n\n*2. Add a map node.*\n\nAdd a map node (xod/math). This node lets us map the accelerometer output range to the write-dot-to-oled input range.\n\n*3. Set map node.*\n\nSet Smin to ‘-10’ and Smax to ‘10’ (the range of the accelerometer). Set Tmin to ‘64’ (the screen height) and Tmax to ‘0’.", "id": "SkyiylPPP", "position": { "x": 0, "y": 3, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } }, "ryheyxDDP": { "content": "*We want to use this write-dot-to-oled node to display the readout from the accelerometer, so that when we tilt the board, the dot moves around on the screen.*\n\nYou could connect the accelerometer X and Y pins directly to the write-dot-to-oled X and Y pins, but it wouldn’t work as the nodes’ ranges don’t match up. Let's take a look at how to set up the accelerometer correctly, so that the write-dot-to-oled node recieves the right input values.", "id": "ryheyxDDP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 2, "width": 20, "units": "slots" } } }, "path": "@/tuto705" }, "@/tuto706": { "comments": { "SkUvzevvP": { "content": "**Task 7: Using Buses**\n*Connect the OLED Screen and Test*", "id": "SkUvzevvP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "rkbYGgwPP": { "content": "*Your patch should now look like this.*\n\nNow let's link these outputs to the write-dot-to-oled noe.\n\n*1. Connect accelerometer to OLED*\n\nAdd a write-dot-to-oled node. Connect the round output linked to the accelerometer X output to the Y input pin, and the round output linked to the accelerometer Y output to the X pin. *This seems counter-intuitive, but is due to the settings of the different nodes.*\n\n*8. Upload and Test*\n\nUpload the patch. Tilt your board left and right, backwards and forwards, and watch the little dot on the screen move!", "id": "rkbYGgwPP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } } }, "links": { "BJByOfeDDw": { "id": "BJByOfeDDw", "input": { "nodeId": "S1ZyOzevPP", "pinKey": "BJlzICOSv1-" }, "output": { "nodeId": "Hkkufevvv", "pinKey": "HkAplwVmP" } }, "Skvy_zxPDP": { "id": "Skvy_zxPDP", "input": { "nodeId": "S17kuMgvDv", "pinKey": "BkF78AurDJW" }, "output": { "nodeId": "S1ZyOzevPP", "pinKey": "H12bIR_SPyZ" } }, "SyUJdfxwvD": { "id": "SyUJdfxwvD", "input": { "nodeId": "BJzydfxPvD", "pinKey": "BkF78AurDJW" }, "output": { "nodeId": "SyxkOGxPDw", "pinKey": "H12bIR_SPyZ" } }, "rk4kOzgDPD": { "id": "rk4kOzgDPD", "input": { "nodeId": "SyxkOGxPDw", "pinKey": "BJlzICOSv1-" }, "output": { "nodeId": "Hkkufevvv", "pinKey": "HkZ6gPEXD" } } }, "nodes": { "BJzydfxPvD": { "id": "BJzydfxPvD", "position": { "x": 10, "y": 3, "units": "slots" }, "type": "xod/math/round" }, "Hkkufevvv": { "id": "Hkkufevvv", "position": { "x": 10, "y": 1, "units": "slots" }, "type": "wayland/lis3dh-accelerometer/accelerometer" }, "S17kuMgvDv": { "id": "S17kuMgvDv", "position": { "x": 11, "y": 3, "units": "slots" }, "type": "xod/math/round" }, "S1ZyOzevPP": { "boundLiterals": { "HJCWLAdSwyW": "10", "rJbGU0_Hv1Z": "128", "ry1z8CuBDy-": "-10" }, "id": "S1ZyOzevPP", "position": { "x": 15, "y": 2, "units": "slots" }, "type": "xod/math/map" }, "SyxkOGxPDw": { "boundLiterals": { "HJCWLAdSwyW": "10", "rJbGU0_Hv1Z": "64", "ry1z8CuBDy-": "-10" }, "id": "SyxkOGxPDw", "position": { "x": 10, "y": 2, "units": "slots" }, "type": "xod/math/map" } }, "path": "@/tuto706" }, "@/tuto707": { "comments": { "B1Kr7ePvw": { "content": "**Task 7: Using Buses**\n*Experiment!*", "id": "B1Kr7ePvw", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } }, "Hk-uXxwvv": { "content": "*Experiment with the nodes in this patch.*\n\nCan you get some text to appear when the dot lands in the middle?\n\nIt is also worth exploring the wayland/lis3dh-accelerometer library, as it has useful nodes and plenty of demonstrations. For example, the click-detector node, which detects taps of the sensor.\n\nDouble click on the nodes to the right to explore some of these examples.\n\n*See if you can work out what each patch is doing.*\n\nRemember to use the quick help pane to find out more about each node, and if you're unsure what a node is doing, you can always add tweak and watch nodes to test it.", "id": "Hk-uXxwvv", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 4, "width": 9, "units": "slots" } } }, "nodes": { "BkRi7lwvD": { "id": "BkRi7lwvD", "position": { "x": 11, "y": 1, "units": "slots" }, "type": "wayland/lis3dh-accelerometer/example-test-click-detector" }, "HJYaXxvPw": { "id": "HJYaXxvPw", "position": { "x": 13, "y": 1, "units": "slots" }, "type": "wayland/lis3dh-accelerometer/example-motion-detector" }, "HyFCQgwvP": { "id": "HyFCQgwvP", "position": { "x": 15, "y": 1, "units": "slots" }, "type": "wayland/lis3dh-accelerometer/example-tweak-settings" } }, "path": "@/tuto707" }, "@/tuto708": { "comments": { "HJl3kSePDP": { "content": "*You have now completed Task 7: Using Buses.*\n\nIf you compare your write-text-to-oled and write-dot-to-oled patches, hopefully you can now see how using buses has allowed us to tidy up the patch.\n\nThis is especially useful when one node is connected to lots of different inputs and outputs.\n\nWhen you are creating programmes in future, remember that you can use buses, along with creating your own nodes, to simplfy and tidy your patches.\n\n*The next task will explore how we can use logic to instruct our board and build more complex devices.*\n**We are working hard to provide the next task in this tutorial as soon as possible. Please keep an eye on the [Biomaker website](https://www.biomaker.org/nocode-programming-for-biology-handbook) for the latest version of this tutorial file.**", "id": "HJl3kSePDP", "position": { "x": 0, "y": 1, "units": "slots" }, "size": { "height": 3, "width": 20, "units": "slots" } }, "ryhkSgDDP": { "content": "**Task 7: Using Buses**\n*The End*", "id": "ryhkSgDDP", "position": { "x": 0, "y": 0, "units": "slots" }, "size": { "height": 1, "width": 20, "units": "slots" } } }, "path": "@/tuto708" } } }