Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
problems with Timer and Serial port
#1
Hi,

I am currently using Bpod 0.5 firmware. Instead of communicating Bpod with a PC (running Matlab), I am running the Bpod connected with another Arduino board (controller) which has the same functionality with the Matlab (i.e., Handshake, Send and run state matrix, receiving Events, etc). In this way, I have to change the Bpod firmware from 'SerialUSB' to 'Serial1' to communicate with the controller (actually, that's the only change for the Bpod firmware). The controller can successfully handshake with Bpod, however, the Bpod was stuck when receiving state matrix; it can receive the 'P', but not the following matrix.

when I change the code from timer interrupt way (which is how Bpod is running)

Code:
Timer3.attachInterrupt(handler);
Timer3.start(100); // Runs every 100us
to loop with delay to run the handler

Code:
void loop() {
handler();  // ~30 us?
delayMicroseconds(70);
}
It runs well. The controller can Send, run and receive events successfully and Bpod runs the state matrix well. That's also the reason why I said the controller has the same functionality with the Matlab code. But the timing of this way is not that precious due to the variable handler() running time. So I still want to use the timer one...

It seems that the Timer is incompatible with Serial1 (or 2, 3)? Anyone has this problem before? Thanks a lot.

Best,
Yao
Reply
#2
Hi Yao

This is a known issue with how Arduino Due handles UART serial ports (as opposed to the USB serial port) during timer callbacks. My impression is that you can only load 1 buffer worth of data before the timer callback ends. The 3-byte messages sent by the state machine during trials work fine, but  beyond some limit bytes get dropped.

I haven't managed to find a solution. We do know that UART is handled more like USB on Teensy 3.X, so our new state machine can do what you're describing. We made this work for the new Ethernet module (to be released next week). Its controller (Teensy 3.2) acts as a relay for all state machine communication with the PC. It transfers messages (even long ones!) between Serial5 on one end and a Wiznet embedded Ethernet server on the other. For now, it will only be compatible with State Machine v2.

-Josh
Reply
#3
(12-01-2017, 06:12 PM)Josh Wrote: This is a known issue with how Arduino Due handles UART serial ports (as opposed to the USB serial port) during timer callbacks. ...

Hi Josh,

Thank you very much for your reply; it really helps a lot. I have tried this for several days. Since you have confirmed this issue, I will try other solutions.

I think why the UART is not compatible with Timer callback is that the UART usually takes long time to send some data (at least this is true in our case). In our application, the Serial1 takes ~100 ms (IS THIS NORMAL?) to send the state matrix, which is ~1 KB, to Bpod. Thinking that the Bpod is running in 0.1 ms (100 us), it can not receive all the data in one callback (which is the case with Matlab, due to more powerful of PC???). I think if we can manage to send the matrix within 100 us, the Bpod should work. How do you think?

Thanks,
Yao
Reply
#4
Hi Yao

Depending on the size of your state matrix, via USB it should take between 0-25ms, typically 5-8ms. We saw slightly longer transfer times using the Ethernet module, but well under 100ms.

You don't need to send the entire state matrix in a single HW timer callback cycle. Bpod r0.7-0.9 and r2.0 can accept the next trial's state matrix while the current trial is running (i.e. during reward or time-out), by reading data in each interval between timer callbacks.  Data transfer is delegated to a call from Arduino's loop() function, which runs at lower priority, and gets interrupted appropriately by timer callbacks. The Light2AFC_TrialManager example protocol demonstrates this ability, using the TrialManager to run the transmission in parallel. In this configuration, the "dead-time" between trials should be ~100 microseconds.

I hope this helps
-Josh
Reply
#5
Hi Josh,

Thanks for your reply. Now I realize that the 'SerialUSB' has very different characters from other 'Serial's. While the Matlab can send the big matrix (~ 1KB) to Bpod via USB, the controller (the other Arduino board) just can not send it via UART serial. As Bpod v0.5 is being used in current project, we have to consider other solutions. Thanks again.

Best,
Yao
Reply
#6
Hi Josh and all,
The problem has been finally solved by modifying the Bpod firmware in another way. The main problem before was that the UART serial port is too slow to transfer data, while the Bpod is running fast in 0.1 ms resolution, which results in incompatibility. I adapted the Bpod firmware into following mode: 1. Receiving data from serial port in loop(), once received the running command 'R', START Timer3, which attached the handler() function; 2. in handler(), do the same thing as before. The only difference is that once the running state matrix finished, STOP Timer3. 3. in loop(), if state matrix finished is detected, send timestamp data to Controller. In this way, the Timer only runs during running state matrix (not during receiving or send back timestamp, etc.). Here is the pseudo-code.

Code:
void setup() {
 ...
 Timer3.attachInterrupt(handler);
 //Timer3.start(100); // comment this line
}

void loop() {
 if (connectionState == 0) {
   updateStatusLED(1);
 }
 if (Serial1.available() > 0) {
   CommandByte = Serial1.read();
   switch (CommandByte) {
      ...
     case 'R':  // Run State Matrix
       ...
       Timer3.start(100); // Runs every 100us
       break;
   }
 }

 if (MatrixFinished) {
   MatrixFinished = 0;
   ...// send
 }
}

void handler() {
 if (RunningStateMatrix) {
   ...
   if (NewState != CurrentState) {
     if (NewState == nStates) {
    ...
       Timer3.stop();
     }
   }
 }
 return;
}

Currently, it works well, but still needs more testing. Hope that can help anyone who also has this problem.

Best,
Yao
Reply
#7
Hi Yao

Wow, thanks for sharing!
I'll consider the mod, towards adding Ethernet support for Due-based state machines. Of course, any mods have to be validated across all state machine functions for jitter, clock drift, etc.

Much appreciated!
-Josh
Reply


Forum Jump: