bonsai as waveform generator to arduino?

2,309 views
Skip to first unread message

Korey Kam

unread,
Oct 1, 2015, 9:56:55 AM10/1/15
to Bonsai Users
Hi all,

I'm attempting to use bonsai to create a waveform and then do the following:
1. write to digital output of an arduino pin to blink an LED
2. timestamp each train of pulses (attached example: 10 Hz, 2 sec duration)
3. timestamp each pulse

I can create the waveform and timestamps just fine, but am unable to define that sequence into an arduino readable format. Is there a way to do this in bonsai without the need for a python transform?

Korey
pulseArd.bonsai

goncaloclopes

unread,
Oct 1, 2015, 7:24:29 PM10/1/15
to Bonsai Users
Hi Korey,

This is a recurrent topic so I guess I'll take a bit of time to explain the available options and their implications.

The first thing to realize is that unfortunately computers are still mostly designed to work in "autistic" mode. Long story short, although their clocks can reach as high as the Ghz range (1 instruction every nanosecond), their communication latencies with the outside world are subject to a variety of constraints that make them less than ideal for precisely timed signal generation. Specifically, as a rule of thumb (i.e. unless otherwise noted), you should expect that for every instruction you send out to an external device there will be a delay no shorter than 10 ms and possibly even longer (e.g. projectors and other displays). The same rule generally applies for the input side (save for exceptions).

Keep in mind that this does not mean that the computer is slow processing data. In fact, once data is in, it will very often indeed be processed in the microsecond range (unless we're talking about expensive image processing). So usually what we're fighting against is latency in the communications and precision in some signal generation or control loop. There is also of course the impact of the operating system task switching behavior, where different processes compete for access to the CPU, but in practice what I have observed is that the first issue tends to dominate dramatically over the second one.

This leads us to the first decision point, which is figuring out what is the minimal acceptable latency for stimulation. Usually, if your target is below 10 ms response time, you should consider running your stimulation protocol in hardware. Otherwise, it may work just doing a loop on the computer and updating a digital output, but you still absolutely need to test it by running benchmarks which will depend on your specific output device.

With this in mind, here are the options:

1) The Arduino support in Bonsai was designed to operate on the range >= 10 ms. This is because the Firmata protocol and indeed, the Arduino serial port communication usually has latencies of that order (e.g. around 16 ms). If your stimulus range is above these restrictions, then you don't actually need the FunctionGenerator at all, and can simply use the built-in timers to flip your signal on and off. For example, here's the Arduino Blink example translated to Bonsai:


This just periodically toggles an Arduino pin on and off with some interval, with the timing between On and Off specified by the intermediate Delay. This will work well if, for example, your Timer is 1 second and the Delay is 0.5 seconds.

2) For tight loops on the order of 1ms, you usually need to have a stimulator pattern coded in the Arduino (see here and here), or a dedicated stimulator circuit like PulsePal (which is also now supported in Bonsai). In these cases, Bonsai will simply trigger the stimulation protocol on or off depending on a condition detected in the video or elsewhere. For this you just usually need a boolean output that sends out a trigger.


This is an example of a mouse-based trigger, which signals HIGH whenever the mouse is beyond the threshold position. Now, to have your command respond in the Arduino, you can actually hijack the Firmata protocol inside the callback functions. For example, to hijack the digitalWrite, you have to modify the function digitalWriteCallback in the StandardFirmata:

void digitalWriteCallback(byte port, int value)
{
 
byte pin, lastPin, mask = 1, pinWriteMask = 0;

 
if (port < TOTAL_PORTS) {
   
// create a mask of the pins on this port that are writable.
    lastPin
= port * 8 + 8;
   
if (lastPin > TOTAL_PINS) lastPin = TOTAL_PINS;
   
for (pin = port * 8; pin < lastPin; pin++) {

      // YOUR MODIFICATION GOES HERE
     
if (pin == MYSPECIALPIN) {
       
// DO MY SPECIAL ACTION
     
}

     
// do not disturb non-digital pins (eg, Rx & Tx)
     
else if (IS_PIN_DIGITAL(pin)) {
       
// only write to OUTPUT and INPUT (enables pullup)
       
// do not touch pins in PWM, ANALOG, SERVO or other modes
       
if (pinConfig[pin] == OUTPUT || pinConfig[pin] == INPUT) {
          pinWriteMask
|= mask;
          pinState
[pin] = ((byte)value & mask) ? 1 : 0;
       
}
     
}

      mask
= mask << 1;
   
}
    writePort
(port, (byte)value, pinWriteMask);
 
}
}

In this way, you can write your own action functions that are associated with digital pins, such that when you write to that pin in Bonsai, the Arduino will actually not just turn on the Pin, but will actually run whatever you want (e.g. a stimulation protocol).

Also bear in mind that Arduino has no real support for analog outputs, so you can't do graded sine waves of voltage. Everything is either 0 or 5V. At best you can do a technique known as PWM that allows you under certain conditions to encode an analog signal using only digital output pins. If you do need graded voltages, check below.

3) If you need below 1 ms response time in your control system (i.e. imaging galvo system), or you need true analog outputs, then most likely you can't use Arduino in the first place (unless you go to Arduino Due, which is a whole different ballpark).

In this case, you're maybe better off with a NI-DAQ or other buffered output stimulators (e.g. PulsePal, SoundCard), that allow you to send in a buffer of samples that specifies a stimulation train that will then be played back all at once with no delay in between samples and with precise timing. This is the case for which FunctionGenerator was originally designed, to generate a waveform buffer that could be transmitted efficiently to such stimulators.

This is an example of the FunctionGenerator for sound generation.


In each of these examples, you could replace the sources and sinks by the particular output device that you have (e.g. Arduino, NI-DAQ, PulsePal, Speaker, HardDrive), but depending on whether your device is buffered or not, you may have to send a Mat (e.g. the output of FunctionGenerator), or a Boolean value, or a number.

It is indeed possible to convert from one to the other, but things will most likely still not work if the principles outlined above are not met.

Conversion from single numbers to buffer:


Conversion from buffer to single numbers:



I hope this will cover most of what you need to know to design stimulation protocols in Bonsai.

If it is still not clear how to proceed, could you detail a bit further the timing constraints you need in your case, and maybe we can build a more concrete example from there.


Best,

Korey Kam

unread,
Oct 5, 2015, 3:53:38 PM10/5/15
to Bonsai Users
Thank you as always for the detailed response.

This is merely a toy example for me to play with so Option #1 (> 10ms) is sufficient. 

In following your workflow from Option #1, I've identified the right COM port to write to (as I can access it in matlab), but for some reason I'm unable to write to it from Bonsai. Any ideas?

goncaloclopes

unread,
Oct 5, 2015, 6:57:00 PM10/5/15
to Bonsai Users
Are you using the AnalogOutput node? Do you have Firmata installed on the Arduino? Firmata is included as one of the examples in the Arduino distribution. You need to make sure that Firmata has been uploaded and configured to use the same baudrate as Bonsai (if you use the default of 57600 it should be fine).

If you do have Firmata installed and configured let me know so we can diagnose it further.

G

Niccolò Bonacchi

unread,
Oct 6, 2015, 5:53:27 AM10/6/15
to goncaloclopes, Bonsai Users
Bonsai can only use Arduino as an I/O board if the Firmata is installed (of all the upload options under firmata pick *Standard Firmata* to begin). To do more funky stuff you will need to play around the Firmata code, or re implement the firmata I/O yourself. For what I can tell using Arduino w/ the Standard Firmata is what you want. 


--
N

--
You received this message because you are subscribed to the Google Groups "Bonsai Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bonsai-users...@googlegroups.com.
Visit this group at http://groups.google.com/group/bonsai-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/bonsai-users/c1bd70c8-3633-4d1e-9703-e9dad819ae91%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Korey Kam

unread,
Oct 6, 2015, 9:35:06 AM10/6/15
to Niccolò Bonacchi, goncaloclopes, Bonsai Users
The waveform generator works. Thank you both!

I foolishly was treating the arduino as plug/play after I had matlab controlling it.

--
You received this message because you are subscribed to a topic in the Google Groups "Bonsai Users" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/bonsai-users/--XCO8AHvo0/unsubscribe.
To unsubscribe from this group and all its topics, send an email to bonsai-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages