cgnuino
General introduction of cgnuino library

Table of Contents

Author
Kei Mochizuki (http://researchmap.jp/keimochizuki)

Copyright (c) 2020 Kei Mochizuki. All right reserved.

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 as published by the Free Software Foundation.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this library; if not, see http://www.gnu.org/licenses/.

Before getting started

cgnuino is a library to help cognitive psychologists and neuroscientists to create behavioral tasks using Arduino boards. It provides several (what I hope are) useful functions when you create behavioral tasks with electrical inputs (e.g., button press, lever move, etc) and outputs (e.g., LED light, beep sound, etc). Now, before getting started, you might be even uncertain whether Arduino is the best option to implement your task. Thus I'd like to start with a brief discussion about pros and cons of using Arduino in controlling behavioral tasks for cognitive psychology and neuroscience. If you are already determined to use Arduino, you can skip to the next section.

Pro: Easy programming

First of all, writing programs with Arduino system is definitely easy for beginners compared with other programming languages such as Python, Ruby, C# and so on. Arduino uses classical C and C++ languages in writing program files, which are called sketches in this platform. Drivers for Arduino boards are distributed with Arduino IDE, which is a useful and easy-to-handle software you can use to write your own sketch. If you have any experience in writing computer programs with other languages, it should be fairly easy to learn writing Arduino sketches. And if you are not familiar with programming languages, Arduino can be still a good starting point due to its simplicity.

Pro: Convenient signal in/out (I/O)

Standard Arduino boards have general purpose in/out (GPIO) pins, with which you can read or put out high (5V) or low (0V) voltage signal. (Be careful that some Arduino boards use 3.3V for high digital signal instead of 5V.) Using these GPIO pins as digital outputs, you are able to directly turn on and off electrical parts using DC 5V power source (e.g., lighting an LED), as well as to control instruments that have DC 5V triggering mechanism (e.g., applying predetermined set of electrical stimulation train at the rising edge of 5V input by external stimulator and isolator). Using GPIO pins as digital inputs, you can easily monitor the participant's button press or lever manipulation. Arduino boards often have analog input pins, and some also have analog output pins, with which you can read or put out arbitrary voltage ranging from 0V to 5V, instead of binary low or high voltage.

Since these pins are physically implemented on Arduino boards as either pin sockets or soldering holes, using them is quite straightforward; you can simply connect electrical devices to Arduino. On the contrary, if you use other programming languages running on a standard PC to execute your behavioral task, using such digital and analog I/Os is not so easy, and you will normally need additional A/D or D/A converter to allow your computer to communicate with external instruments.

Pro: Low cost

In general, Arduino boards are inexpensive. In addition, since Arduino is an open-source project, there are even cheaper Arduino-compatible boards from third parties (although I personally recommend official products). On writing programs with Arduino, you (of course) need a PC. However, it does not require any high performance like high-end CPU, massive RAM memory or gorgeous video card. Just a common PC with ordinary performance will do, with any of Linux, Mac or Windows operating system.

If you have research grants with moderate size, this "low cost" feature will not move your mind so much. You can anyway accommodate any equipments you need for your experiment. However, the problem of the cost is actually not a sole issue on the amount of money you pay. It is in fact a problem of your mental bothersomeness in prototyping. Imagine that you have a set of expensive task control instruments in your experiment room. To modify the existing behavioral task or create a new one, you need to go to that room, to your experimental set. But you may have no Internet connection in that room, or may be forbidden to eat and drink. The chair in the experiment room may be not soft enough. The room can stink (in case you are engaged in animal experiments). These small negatives make you feel the prototyping something bothersome. However, because Arduino is quite cheap, it should be nothing for you to purchase multiple Arduino boards. No paid license is needed to use Arduino IDE. No signing in. No activation. You can thus prepare multiple sets of experimental apparatus everywhere you are, both in the experimental room and lab's study room, in your laptop PC, and even in your home (if you by any chance wish to). This reduces the psychological barrier for your prototyping, accelerating your academic productiveness. This is what I think is the real effect of using low cost and open source Arduino in your experiment.

Con: No graphical display

The biggest disadvantage of Arduino must be the absence of graphical display. ... Well yes, you can find several liquid crystal "displays" and OLED "displays" that can be used with Arduino. But none of them will satisfy the use of graphical display to present visual stimuli in psychological experiments. (i.e., They are not something you, as a normal psychologist or neuroscientist, expect to be by the words of "graphical display".) If you want to use visual stimuli just for the purpose of, for example, instructing timing of actions and telling trial conditions to the participant, then normal LEDs with different colors may be enough to do the job. However, if you wish to present visual stimuli in a normal sense for psychological experiments, then Arduino is not a suitable option for your task. In this case, you should choose other programming language working on a standard computer with graphical display. One of the popular options for such usage would be Expyriment library working on Python (which I prefer), and Psychophysics Toolbox working on Matlab (which I @#$%!).

Con: Data saving

After compiling your code (i.e., sketch) and sending it to the on-board chip, Arduino runs in a "stand alone" way. USB connection is commonly used to power running Arduino, but is not necessary and can be thrown away if external DC supply is provided. When the power supply is out, Arduino stops running and all the temporal values of variables are flushed (except for a few exceptions I don't mention here). Therefore, to record the participant's behavioral performance, you need certain external mechanics to save it on a non-volatile storage in some way.

One of the ways is to use USB serial connection to write task information from Arduino to a PC as a text file. Arduino can easily emit text to a serial port (by Serial.println function) to show it on a serial monitor application running on the connected PC. You may be familiar with this feature through Serial Monitor utility in Arduino IDE. This is useful when you check the behavior of the program, especially during prototyping. However, if you use other serial monitors with automatical saving utility, the same serial interaction mechanism can be used as a "write to a text file" function. Run this kind of application in parallel with a connected Arduino board, and all the text from Arduino's serial connection is automatically saved to a text file. I personally use this method for my own experiments and it is working quite well.

Another alternative for data saving is the usage of an SD (or nowadays more common micro-SD) card. Standard Arduino boards do not have SD card slot. But there are several breakout boards (small external boards that can be connected to Arduino) for SD card facility. Also, Arduino has a library named SD that provides a simple I/O interfaces to SD cards. Using these materials, you can save the task performance to a text file on an SD card, which is later transported into your PC and analyzed.

There is also another possibility for you to use WiFi connection and save your data to remote server computer. For example, there are some Arduino-compatible boards with a built-in WiFi interface such as ESP-WROOM-02 and ESP-WROOM-32. These will allow you to emit texts from your board to remote computer, enabling non-volatile saving of your data. However, the hardware of these boards is a bit complicated compared with standard genuine Arduino, and working on WiFi network in addition to building a web server should be a bother for beginners. Also, not many people will wish their unpublished data (including confidential information and task performance from the participants) be recorded through the Internet. So I personally do not think that this option is much feasible. Saving data to a local server in a private Local Area Network through WiFi can be a bit conceivable, although it does not seem to have a distinct advantage over just recording data through wired USB serial connection.

Con?: Modifying variables and realtime control

In human psychological experiments, variables in the program normally do not require any "manpowered" monitoring during task performance. Constants should remain constant, variables should vary in a way you described in the code. However, especially in animal experiments, there are times one want to change the value of certain variables on-line (i.e., without stopping the task progression). For example, you may want to increase the time length of opening a solenoid that delivers water reward to the animal, when her motivation suddenly starts to collapse during an experiment. In another case, you may want to gradually lengthen the temporal delay until reward delivery in your task during a training session. This is why many commercial specialized systems for behavioral task control in animals have certain on-line mechanism which allow researchers to modify variables during an experiment.

Because Arduino sketches are essentially "compiled language", this kind of flexible variable modification is more or less difficult within a standard usage. However, the same is in fact true for Arduino's other counterparts such as Expyriment on Python or Psychophysics Toolbox on Matlab. Therefore, this is not a unique con for Arduino. Normally, you may need some uncouth hacks to send commands to running task program from secondary PC or something. In cgnuino, you can get rid of this problem by CgnControl class and embedded conditional branching, but you still need a moderate knowledge on serial communication anyway.

Getting started

In the previous section, I briefly explained pros and cons in using Arduino for the implementation of behavioral tasks in cognitive psychology and neuroscience. Because you are still continuing reading, it is likely that you decided to use (or at least are interested in using) Arduino for your experiment. Therefore, I now introduce how to create a behavioral task on Arduino, and how this library will help your job.

How Arduino works

While some of the readers might already have experiences on Arduino programming, others may be completely new to computer programming itself. Since there are many comprehensive tutorials and reviews for Arduino beginners on the Internet, here I focus only a brief introduction to Arduino sketch.

An Arduino sketch is a text file with .ino extention, that is stored in a directory with the same name to the basename of the sketch itself. A sketch is always composed of two functions: setup and loop. The contents of setup function are executed only once after Arduino is terned on. Afterward, the contents of loop function are repeatedly executed. In other words, when the execution of loop function is finished, next loop function is automatically called and starts to be executed. This means that you should carry out necessary preparation of variables, pin modes and/or Serial connections in setup function. The progress of behavioral task itself (within a trial as well as transitions among trials) will then be controlled by repeating loop function. The execution of one loop function can be seen as a time resolution of events that can be detected or determined by Arduino sketch, which is also called as a "tick", "cycle" or "process cycle" in other occasion (the last one is a terminology in legacy TEMPO system). However, according to Arduino's naming basics shown above, I'm going to call it a "loop" from now on.

The other important thing you need to remember is that, the values of local variables in loop function are NOT maintained through different loops. Therefore, if you want the values of some variables to be taken over through loops, all of these variables must be defined as global variables. In other words, define these variables outside of any functions, conventionally at the very beginning of your sketch. This surely sounds very silly for users with prior programming experiences, but it is anyway how things work on Arduino system.

Working on cgnuino library

Now I finally explain how cgnuino library will help you implement your task on Arduino. Here I just briefly overview how you can create behavioral tasks in Arduino, and which cgnuino class may help each stage of task implementation. Detailed explanation of the classes and methods of the library is available in the linked pages. The list of all classes and files of the library is accessed from Classes and Examples tabs on the top menu of this page. Also I prepared a few example sketches that show the usage of cgnuino classes. These are available in examples directory of the library or from the menu bar of Arduino IDE after cgnuino is correctly installed, in a way something like File > Examples > cgnuino.

Usually a trial in a behavioral task is composed of several task periods (also called as epochs in some cases). For example, a pre-trial period is followed by a cue period, in which a visual cue is presented. The participant needs to release the button press in a succeeding response period, after which a post-trial period follows. As in this example, a trial is divided into numbers of task periods in which different events occur or different actions are required. Some of them can have temporal limit (e.g., response is required within 800 ms), while others can last unlimitedly (e.g., next trial starts after the participant's voluntary button press). This kind of progression of task periods can be easily managed by CgnPeriod class.

Using Arduino's digitalRead function, you can read voltage input as high (5V [or 3.3V]) or low (0V) state. This, in addition to pull-up or pull-down mechanism, allows you to record participant's button press and release as a boolean (HIGH/LOW or true/false) value. However, in order to detect the timing of button press and release, you need to monitor the change of the acquired value instead of the current state of the button alone. Therefore, in most cases you need to buffer the previous value of digital input and compare it with the current one. Also, because of the mechanical noise, the value of digital input can be unstable at the time of button manipulation (a phenomenun known as chattering or ripple). Thus you will sometimes want to ignore changes of digital input, during a short period (a few milliseconds should be enough) right after a change has occured. Using CgnDI class, you can perform a set of these stereotypical processing for digital inputs, for multiple digital-in pins simultaneously. The same kind of change monitoring for an arbitrary boolean value instead of digital-in signals can be performed via CgnLogger class.

On acquiring participant's actions, you often want to record response times (or reaction times). For this purpose, CgnStopwatch class provides an easy way to calculate temporal discrepancy between two events in millisecond order. You can even create multiple CgnStopwatch instances (have multiple stopwatches simultaneously) to calculate two or more response times in parallel.

In some tasks, outputs from Arduino is required to announce task-related information to the participant. This is normally done by a light stimulus using an LED and digitalWrite function, or an auditory tone using a piezo buzzer and tone function. However, these emitted outputs need to be later turned off manually using digitalWrite or noTone functions. CgnDO and CgnTone classes provide an easy way to perform such output with fixed time length, allowing you an asynchronous task control along with output signals.

These are the basic utilities that will be often used in various behavioral tasks. There are also some more classes that may help you in somewhat limited situations. By using these functionalities of cgnuino library, I hope your burden in task construction will become a bit lighter.

Example sketches

The cgnuino library provides a few example sketches that help you understand how to utilize cgnuino classes. Some of them require specific circuit with electrical parts such as LEDs and switches, while others don't. Below is basic tips in prototyping Arduino electronics. After that, brief instruction on each example sketch follows. Examples are in alphabetical order, so do not stick to the order of the list and start from wherever you need to learn.

General tips

First of all, be sure to disconnect your Arduino board from the PC when you create a new circuit. If you connect wrong pins with wires and parts on powered Arduino, it can instantly kill your precious board. Also, when you compile and upload a new sketch to your board while moving from an example to another one, nothing should be (ideally) connected to your board. If you create a new circuit (on unpowered Arduino) first and then connect it to the PC to upload a new sketch, the previous sketch that automatically starts to run on your board may apply inappropriate currents to the newly created circuit. In reverse, if you upload a new sketch first and then create a new circuit for the next example, the newly uploaded sketch may apply inappropriate currents to the existing circuit which was only agreeable to the previous sketch (before you unpower Arduino). Taken together, officially ideal way to rewire your board is like follows:

  1. Disconnect Arduino from the PC
  2. Disconnect all the electrical parts from the board
  3. Connect Arduino to the PC and upload a new sketch
  4. Disconnect Arduino from the PC
  5. Create a new circuit on the board
  6. Connect Arduino to the PC to power it and see serial text lines

As you must definitely feel, this is a kind of bothersome procedure. Therefore, when you want to make small changes on your sketch and/or circuit, it might be enough to ensure unpowering the board upon rewiring. But remember that it is recommended to follow the protocol above when you need a large modification to your sketch and circuit.

Another general caution on prototyping with Arduino board is not to use Pin 0 and 1. These are the first two GPIO pins on Arduino. Therefore, you may possibly think that you should start with these pins orderly for the I/Os in your sketch (especially if you are a clean-freak like me). However, Pin 0 and 1 have a special role in serial interaction between Arduino and the PC. Serial connection is also used in uploading procedure of the compiled sketch to the on-board chip with Arduino IDE. Thus if you use these pins for your own purpose in the sketch (changing their function with pinMode etc.), you will lose not only the way for serial text communication with your board but also the way to upload a new sketch again.

In most of popular Arduino and Arduino-compatible boards, Pin 13 is connected to an on-board LED from the beginning. Therefore, in case you need only one digital output during prototyping, set Pin 13 as OUTPUT by pinMode, and you can see the high/low state of the pin without an external electrical circuit.

The baudrate for USB serial interaction is fixed to 115200 in my examples below. So if serial interaction is needed, open Serial Monitor in Arduino IDE and set the baudrate to 115200.

Control.ino

This example shows the basic usage of CgnControl class. Please learn how you can control conditional branching on the working Arduino board from a serial connection.

When executed, the LED starts to blink shortly every second (100 ms light and 900 ms dark alternation). Open up Serial Monitor on Arduino IDE. Then go to the text sending line. You can set the length of light period by sending 1:XXXX and dark period by 2:XXXX where XXXX is an arbitrary integer. Also if you send p (hit only one character p and then Enter), the blinking stops until you send p again.

Control_fzz.png

DI.ino

This example shows the basic usage of CgnDI class. Please learn how can monitor the on/off state of an external button, not only checking its current state but also detecting its changes from the previous loop.

When executed, nothing happens. Open up Serial Monitor on Arduino IDE. When you push the switch, it should read "Pushed". When you release the button press, it should read "Released".

DI_fzz.png

Lchika.ino

This example shows the basic usage of CgnDO class. Please learn how you can achieve so called "L-chika", i.e., an LED blink-blink starter example (which is a "Hello World!" in electronic crafting) with cgnuino library. This is actually not a good example for the usage of CgnDO class because of its oversimplicity, though.

When executed, the LED start to turn on and off every 500 ms.

Lchika_fzz.png

LchikaWave.ino

This example shows the basic usage of CgnDO class. Please learn how you can asynchronously control multiple digital outputs.

When executed, the four LEDs start to blink in each respective pace. Once in every two seconds, all the LEDs turn on, and then turn off at different timings.

LchikaWave_fzz.png

Logger.ino

This example shows the basic usage of CgnLogger class. Please learn how you can monitor changes of arbitrary boolean variable like CgnDI class does on digital-in pins.

When executed, an integer value starts randomwalking, i.e., randomly increase or decrease every 500 ms. Open up Serial Monitor on Arduino IDE. Transition of the value is displayed. The sign of the value is internally monitored by CgnLogger class. When the value crosses zero, CgnLogger class detects it and inserts a new line.

Pause.ino

This example shows the basic usage of CgnPause class. Please learn how you can temporally pause the progression of the task with an external alternating switch.

When executed, nothing happens. Open up Serial Monitor on Arduino IDE. You will see waving dot going right and left on the text lines. When you push the switch, progression of the program is halted by CgnPause class so that the movement of the dot stops.

Pause_fzz.png

Period.ino

This example shows the basic usage of CgnPeriod class. Please learn how you can control the progression of the task through multiple task periods.

When executed, nothing happens. Open up Serial Monitor on Arduino IDE. You will see three task periods are alternatingly repeating: pre-trial, trial, and inter-trial interval. Since nothing is actually required in this example for simplicity, each period just expires its respective time limit and moves to the next period.

SeqResp.ino

This example shows the basic usage of CgnStopwatch and CgnDI classes. Please learn how you can measure temporal intervals between task events. You can also see how open/close state of external switch is monitored by a digital-in pin and further relaid to another digital-out pin.

When executed, Arduino starts to wait for a bottun press. Open up Serial Monitor on Arduino IDE. Every time you press the switch, temporal interval between previous and current button press is displayed. Also you will see the LED to be turned on while you are pressing the button. This relaid output of button's state is automatically performed by CgnDI class.

SeqResp_fzz.png

Strobe.ino

This example shows the basic usage of CgnStrobe class. Please learn how you can see that arbitrary text can be represented by 8 digital-out pins (Pin 4–11) and strobed by another one pin (Pin 12).

When executed, a text line of multiple characters is emitted once in every five seconds. This can be seen through short flash of LEDs, which is actually composed of turning on a combination of the first eight bits and then lighting of the last bit for strobing. Since this occurs in steps of 50000 us (i.e., 50 ms) flashes, lighting would be visible only shortly. For each emission, you can see the time taken to finish strobing on Serial Monitor.

Needless to say, this lighting of LEDs is just for the presentation purpose. Actual usage of CgnStrobe class is to send characters in a quick and temporally accurate way to external receiving devices. Therefore, these nine digital-out pins should be connected to digital-in pins of such external receiver with appropriate current-limiting resistors if needed. How quickly you can send characters depends on both Arduino's digital-out and external device's digital-in. Arduino is temporally accurate at minimum of 3 us. Power1401 data acquisition device from CED, for example, requires strobes longer than 1 us (longer is recommended though). So it should be fine to set strobe length as 10 us to send only one word really quickly. However, whether transmission of a longer text line in this fairly high frequency is secure or not depends on devices and environments. Thus, if you plan to send long texts, I think setting strobe length as, say, 500 or 1000 us will still be OK in a normal situation.

Strobe_fzz.png

Valtiel.ino

This example shows the basic usage of CgnValtiel class. Please learn how you can monitor whether loop function in your sketch is called frequently enough for your experiment.

When executed, loop function starts to run repeatedly with random delay of 1–100 ms. Therefore, a loop typically lasts for about 50 ms on average. The lengths of loops are monitored by CgnValtiel class and printed on Serial Monitor every 20 loops (about 1 Hz).