05-06-2017, 07:05 PM
(This post was last modified: 05-06-2017, 07:15 PM by cyuan.)
Hi Josh,
I am attempting to program a state machine which should state change to a different state at a fixed timings, depending on the input that it has received during the previous time interval.
I have looked through the example scripts but was unable to find any examples which could solve this issue.
I understand that some form of global timer/counter would be necessary, but I was only able to find examples of a SetGlobalTimer (which has a fixed timeout threshold but cannot respond to events) and SetGlobalCounter (which has a fixed activation threshold and still causes the state change immediately).
Is there a function to read the global counter during a state change process and determine which state to change to?
Hi Cyuan
I'm a bit confused by the wording "change to a different state at fixed timings".
Did you mean that during the first (fixed?) interval, you want to capture a behavior event, and when the interval is over you want to go into one of several different delay states depending on which event you captured?
If so, You can use the following example:
Code: sma = NewStateMachine;
sma = SetGlobalTimer(sma, 'TimerID', 1, 'Duration', 3);
sma = AddState(sma, 'Name', 'PreviousTimeInterval', ...
'Timer', 0,...
'StateChangeConditions', {'Port1In', 'Port1Chosen', 'Port2In', 'Port2Chosen', 'GlobalTimer1_End', 'MassiveDelay'},...
'OutputActions', {'GlobalTimerTrig', 1});
sma = AddState(sma, 'Name', 'Port1Chosen', ...
'Timer', 0,...
'StateChangeConditions', {'GlobalTimer1_End', 'ShortDelay'},...
'OutputActions', {});
sma = AddState(sma, 'Name', 'Port2Chosen', ...
'Timer', 0,...
'StateChangeConditions', {'GlobalTimer1_End', 'LongDelay'},...
'OutputActions', {});
sma = AddState(sma, 'Name', 'ShortDelay', ...
'Timer', 1,...
'StateChangeConditions', {'Tup', 'exit'},...
'OutputActions', {});
sma = AddState(sma, 'Name', 'LongDelay', ...
'Timer', 2,...
'StateChangeConditions', {'Tup', 'exit'},...
'OutputActions', {});
sma = AddState(sma, 'Name', 'MassiveDelay', ...
'Timer', 5,...
'StateChangeConditions', {'Tup', 'exit'},...
'OutputActions', {});
Please let me know if you meant something else and I'll try to help.
-Josh
Hi Josh,
Thanks for the response, that would indeed solve a significant portion of the problem at hand (synchronising if there is one event or zero events). In fact, I managed to arrive at the same result yesterday for solving that issue but did not get about to posting it.
However, I was thinking more along the lines of:
State 1 (start, 0s)
State 2 (input collection, 5s). During this phase, collect input. The number of inputs is logged.
State 3 (input analysis, 0s). If 0 inputs, goto state 4, if 1 input, goto state 5, if 2 inputs, goto state 6, and so on. This is what I meant by "reading the global counter". It is theoretically possible to implement this using the above system but gets messy very quickly.
Also, I have noticed that the position of the 'GlobalTimerTrig' output action doesn't seem to change the time at which the timer starts, and the timer always seems to start at the beginning of the trial, where I had declared it (at least for Bpod 0.5 firmware). Is this intentional behaviour for the timer?
05-11-2017, 01:53 AM
(This post was last modified: 05-11-2017, 01:53 AM by Josh.)
Hi Cyuan
Unfortunately, in the current system there isn't an easy way to use the number of instances of an event counted in an interval preceding a state, to choose among a discrete set of destination states.
I was able to reproduce the issue with the timers. Thank you for reporting it! New firmware is posted on Github (beta branch) that fixes the problem; for Bpod 0.5 you'll want firmware v0.5.7
Much appreciated,
-Josh
Hi Josh,
I'm trying to use a Global Counter with either BNC1High or Wire1High, but unsuccessfully. The signal is available, because I can see it in an oscilloscope and in a port input (for instance Port2In) and I made sure it is 5V. I was successful at using a Global Timer, but nothing is happening with the Global Counter. It doesn't show up in my data file either; I guess it should be saving the timestamps of the events being counted in the BNC input?
Here's what I'm doing, please let me know if there's something wrong. Thanks!
Code: sma = NewStateMachine();
sma = SetGlobalTimer(sma, 'TimerID', 1, 'Duration', S.GUI.TraceDuration);
sma = SetGlobalCounter(sma, 1, 'BNC1High', 20);
sma = AddState(sma, 'Name', 'Go', ...
'Timer', 0,...
'StateChangeConditions', {'GlobalTimer1_End', 'Miss','GlobalCounter1_End','Hit'},...
'OutputActions', {'GlobalTimerTrig', 1,'GlobalCounterReset',1});
Hi Sara
Strange - I hope that isn't true!
I'll test this over the weekend and post my results.
-J
Hi Sara
I tried with this code, and it works on my side:
Code: sma = NewStateMachine();
sma = SetGlobalTimer(sma, 'TimerID', 1, 'Duration', 30);
sma = SetGlobalCounter(sma, 1, 'BNC1High', 5);
sma = AddState(sma, 'Name', 'Go', ...
'Timer', 0,...
'StateChangeConditions', {'GlobalTimer1_End', 'Miss','GlobalCounter1_End','Hit'},...
'OutputActions', {'GlobalTimerTrig', 1,'GlobalCounterReset',1});
sma = AddState(sma, 'Name', 'Hit', ...
'Timer', 0,...
'StateChangeConditions', {'Tup', 'exit'},...
'OutputActions', {});
sma = AddState(sma, 'Name', 'Miss', ...
'Timer', 0,...
'StateChangeConditions', {'Tup', 'exit'},...
'OutputActions', {});
One thing I noticed is the "GlobalCounterReset' in the first state. That's actually not necessary - the counters always reset to 0 when you run a new trial.
If you run this snippet with the latest MATLAB code and firmware from the Gen2 repo, do you still see the problem?
Hi Josh,
This thread is very informative to use global counter.
I succeed to use SetGlobalCounter within a single trial, but it didn't work smoothly when I tried to proceed next trial after running RunStateMachine.
I think it because every millisecond time data is stored in the Events data of GlobalCounter1_End.
Could you give me some advice on how to reduce these data?
Thank you,
Aki
09-22-2017, 03:35 PM
(This post was last modified: 09-22-2017, 03:35 PM by Josh.)
Hi Aki
Sure! If you paste a copy of the code you're using to set up and handle the counter (i.e. the lines calling SetGlobalCounter() and AddState()), I can test here and figure out what's going wrong.
Thanks!
(05-11-2017, 01:53 AM)Josh Wrote: Quote:Unfortunately, in the current system there isn't an easy way to use the number of instances of an event counted in an interval preceding a state, to choose among a discrete set of destination states.
It would be a really nice feature!
|