Hi Josh,

We would like to to stream the rotary encoder position to Bonsai.

We are using Bpod Gen2 23 together with the latest Bonsai 2.8, and we successfully connected Bonsai to Bpod using the APP_SoftCode_Example on the develop branch, this was nice and easy, thanks for implementing this! I understand that we can use startUSBstream() in Matlab to start streaming the position of the encoder to the PC, but is there a way to directly stream it to the app serial port? Or is there a way to trigger USB streaming of the rotary encoder module directly from Bonsai?

Many thanks & best wishes,
Katharina

Hello Katharina,

Good news - the Bonsai soft code example is now on the main branch, here.

Is the idea to have Bonsai receive and process the rotary position data? Or is the idea to have Bonsai trigger position data streaming to MATLAB?

To have Bonsai receive the streaming data, you'd have Bonsai (instead of MATLAB) open the rotary encoder module's USB serial port. Bonsai would then send byte messages using the encoder module's serial interface. In Python syntax, you'd send:
(ord('S'), 1)
to start position streaming, and
(ord('S'), 0)
to stop streaming.
During streaming, data arriving at the port would be formatted as described in the interface docs.

If the goal is to have Bonsai trigger streaming to MATLAB (with the module controlled via the RotaryEncoderModule class), you'd set the state machine to react to an incoming APP soft code by sending a standard soft code back to the PC (e.g. here). The soft code handler would then call R.startUSBStream().

Please let me know if you run into any issues setting this up, I'd be glad to assist.

Josh

Hi Josh,

thank you so much, that's a great start! I realised that what we want is to use the Rotary Encoder directly in Bonsai.

However, I am new to Bonsai and not sure I understand their Serial Interface. We have a Bonsai Workflow where we use CreateSerialPort with the COM port of the rotary encoder. My understanding is that we can use SerialWrite to write the bytes you mention (ord(S) 1) to start USB streaming, however I can't figure out how to pass these bytes on to SerialWrite. I have a similar issue with SerialRead in Bonsai. When I send an APP_SoftCode from Bpod (e.g. 5), I can get that sent back to Bpod but I am unable to read out the '5' in Bonsai, I can only get the length of the bytes. I realise that this might be more of a Bonsai than a Bpod question, but let me know if you have any leads!

Many thanks,
Katharina

Hello Katharnia,

Admittedly I'm not sure how to read out the data from the SerialWrite and SerialRead nodes into other Bonsai nodes. I tried some intuitive things, but no luck. The byte-level serial interface was recently implemented, while Bonsai's original serial interface required everything to be formatted as text. This would be a good question for the Bonsai forums.

-Josh

21 days later

Hi Josh,

Thank you, we now figured out how to activate USB streaming from Bonsai, thanks to the Bonsai forum https://github.com/orgs/bonsai-rx/discussions/1724.

We are now trying to figure out how to read the position back, but I am confident that with the help of the Bonsai community we'll get there.

Thank you for your support!
Katharina

Hi Josh,

I am now able to retrieve bytes (yeah!) that seem to indicate the position as the message always starts with 80 ('P'). However, the second and third bytes I am getting don't easily translate into a 16-bit integer tick position between 1 and 1024 which is what I understand I should be expecting.

Here are some example messages I get:

[80 203 1 111 151 182 2] -> (16bit: 51969)
[80 131 1 241 24 144 7] -> (16bit: 33537)
[80 131 254 220 148 226 9] -> (16bit: 33790)
[80 101 1 176 214 29 15] -> (16bit: 25857)

Also, one entire turn of the wheel only triggers only around 10 messages. Do you have any ideas on where to start troubleshooting this?

Thank you!
Katharina

Hi Josh,

I am now able to retrieve bytes (yeah!) that seem to indicate the position as the message always starts with 80 ('P'). However, the second and third bytes I am getting don't easily translate into a 16-bit integer tick position between 1 and 1024 which is what I understand I should be expecting.

Here are some example messages I get:

[80 203 1 111 151 182 2] -> (16bit: 51969)
[80 131 1 241 24 144 7] -> (16bit: 33537)
[80 131 254 220 148 226 9] -> (16bit: 33790)
[80 101 1 176 214 29 15] -> (16bit: 25857)

Also, one entire turn of the wheel only triggers only around 10 messages. Do you have any ideas on where to start troubleshooting this?

Thank you!
Katharina

Hi Katharina,

Following the 'P', bytes 2 and 3 encode position as a signed 16-bit integer, and bytes 4-7 encode an unsigned 32-bit timestamp.

Here's what I get in MATLAB for converting the first two bytes:

typecast(uint8([203 1]), 'int16')
ans =
int16
459

typecast(uint8([131 1]), 'int16')
ans =
int16
387

typecast(uint8([131 254]), 'int16')
ans =
int16
-381

typecast(uint8([101 1]), 'int16')
ans =
int16
357

The position range is -512 to 512 by default. This can be set to 0-1024 with commands 'W' and 'M' in the serial interface.

I'm not sure why a full rotation is returning so few messages. Is Bonsai polling the port with some frequency?

-Josh

Thank you, Josh!
I had misunderstood the byte encoding.

I now fixed the Bonsai script and it is returning values -512 and 512!

I was able to figure out the problem of too few messages, I had to set the SerialPort count parameter to 7.

Thank you so much for your support, we are now able to use the RotaryEncoder Module directly in Bonsai!

Katharina

Thanks for sharing, Katharina! That's a great resource!