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,