Skip to content

Commit f1fe316

Browse files
authored
Merge pull request #4 from KravitzLabDevices/dev
Dev
2 parents d6e28e4 + fc99313 commit f1fe316

5 files changed

Lines changed: 311 additions & 141 deletions

File tree

README.md

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,12 @@
11
# FORCE2
2-
This is a force sensing device for training mice
2+
FORCE2 is an arduino-based, open-source device for home-cage operant training. This repository includes all the code and documentation needed to run the device. For all information regarding the printing, and assembly of the device click here (add link). FORCE2 source code is written in C++ and all the examples are written in Arduino (itself a superset of C++).
3+
4+
## About this repository
5+
This repository contains all the source code and examples for different behavioral paradigms. The wiki is the main resource for both instructions on how to flash the code in your device once assembled and code documentation.
6+
If you find any bugs in the code or have any enhancement requests, please open an Issue on this repository.
7+
8+
## Flexibility of FORCE2
9+
One of the main goals of FORCE2 is to be highly flexible. The FORCE2 library has been develop to be able to control many variables in the device, home-cage training of many behavioral paradigms. The following are some examples of behavioral paradigms that can be implemented on FORCE2:
10+
11+
## Future goals
12+
In future versions, we hope to include a sleep function that increases the battery efficiency of the device.
Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,144 @@
1+
/*
2+
FORCE example code
3+
by Lex Kravitz and Bridget Matikainen-Ankney
4+
5+
alexxai@wustl.edu
6+
May, 2021
7+
8+
KravitzLabDevices/FORCE_library is licensed under the GNU General Public License v3.0
9+
10+
Permissions of this strong copyleft license are conditioned on making available complete source code of licensed works
11+
and modifications, which include larger works using a licensed work, under the same license. Copyright and license
12+
notices must be preserved. Contributors provide an express grant of patent rights.
13+
14+
*/
15+
16+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
17+
// DON'T EDIT THESE LINES
18+
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
19+
#include <Force.h> //Include FORCE library
20+
String ver = "Force"; //unique identifier text
21+
Force force(ver); //start FORCE object
22+
23+
int prob_left = 70; // Probability of pellet on the high-reward poke
24+
int prob_right = 30; // Probability of pellet on the low-reward poke
25+
int trialsToSwitch = 20; // # of trials before probabilities on the pokes switch
26+
int trial_counter = 0; // Tracks how many pellets have been obtained in this set of probabilities
27+
int highp_counter = 0; // Tracks how many pokes in a row in high probability poke
28+
int trialTimeout = 5; //timeout duration after each poke, set to 0 to remove the timeout
29+
int probs[5] = {10, 30, 50, 70, 90};
30+
unsigned long trial_start = 0;
31+
unsigned long trial_length = 5000;
32+
bool trial_available = false;
33+
bool press = false;
34+
35+
void setup() {
36+
force.begin(); //setup FORCE
37+
force.trial_window = 60000;
38+
}
39+
40+
void loop() {
41+
42+
///////////////////////////////////////////////////////////////////////
43+
// This is the non-stationary part of the task ///
44+
// meaning that probabilities change every trialsToSwitch trials ///
45+
///////////////////////////////////////////////////////////////////////
46+
force.run(false);
47+
if(trial_counter == trialsToSwitch) {
48+
highp_counter = 0;
49+
trial_counter = 0;
50+
prob_left = probs[random(0,5)];
51+
prob_right = 100-prob_left;
52+
}
53+
54+
else if (highp_counter == 8) {
55+
highp_counter = 0;
56+
trial_counter = 0;
57+
prob_left = probs[random(0,5)];
58+
prob_right = 100-prob_left;
59+
}
60+
61+
/////////////////////////////////////////////////////////////////
62+
/// Here we start the task. Mouse has to poke on the left ////
63+
/// to start a trial, and then the bandit task starts ////
64+
/// within 5 seconds of the start of the tone ///
65+
////////////////////////////////////////////////////////////////
66+
force.readPoke();
67+
if (force.poke) {
68+
trial_start = millis();
69+
force.Tone();
70+
trial_available = true;
71+
}
72+
73+
while (((millis()-trial_start) < force.trial_window) && trial_available == true) {
74+
force.ratioLeft = prob_left;
75+
force.ratioRight = prob_right;
76+
force.trials_per_block = trial_counter;
77+
force.FRC = highp_counter;
78+
force.library_version = trialsToSwitch;
79+
force.run(true);
80+
81+
/////////////////////////////////////////////////////////////
82+
//// If mouse presses the left lever ///
83+
/////////////////////////////////////////////////////////////
84+
if ((force.pressLengthLeft > force.hold_timeLeft) && force.LeftActive) {
85+
if (prob_left > 50) {
86+
highp_counter ++;
87+
}
88+
else {
89+
highp_counter = 0;
90+
}
91+
delay(500);
92+
if (random(100) < prob_left) {
93+
force.Tone();
94+
force.DispenseLeft();
95+
trial_counter ++;
96+
}
97+
else {
98+
force.Tone(300,600);
99+
}
100+
press = true;
101+
trial_available = false;
102+
}
103+
104+
//////////////////////////////////////////////////////////////
105+
//// If mouse presses the right lever ////
106+
/////////////////////////////////////////////////////////////
107+
if ((force.pressLengthRight > force.hold_timeRight) && force.RightActive) {
108+
if (prob_right > 50) {
109+
highp_counter ++;
110+
}
111+
else {
112+
highp_counter = 0;
113+
}
114+
delay(500);
115+
if (random(100) < prob_right) {
116+
force.Tone();
117+
force.DispenseRight();
118+
trial_counter ++;
119+
}
120+
else {
121+
force.Tone(300,600);
122+
}
123+
press = true;
124+
trial_available = false;
125+
}
126+
}
127+
128+
//////////////////////////////////////////////////////////////
129+
//// If there was no press during the time window ////
130+
/////////////////////////////////////////////////////////////
131+
if (trial_available && press == false) {
132+
force.Tone(300,600);
133+
}
134+
135+
//////////////////////////////////////////////////////////////
136+
//// Finish trial and start inter-trial timeout ////
137+
/////////////////////////////////////////////////////////////
138+
if (trial_available) {
139+
press = false;
140+
trial_available = false;
141+
force.Timeout(trialTimeout);
142+
force.Tone();
143+
}
144+
}
Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -23,42 +23,30 @@ Force force(ver); //start FORCE object
2323

2424
void setup() {
2525
force.begin(); //setup FORCE
26-
force.trial_available = false;
27-
Serial.begin(9600);
2826
}
2927

3028
void loop() {
31-
force.run(); //call force.run() at least once per loop
32-
if (digitalRead(POKE) == LOW) {
33-
force.logdata();
29+
force.trial_window = 60000;
30+
force.run(false); //call force.run() at least once per loop
31+
force.readPoke();
32+
if (force.poke) {
33+
force.run(true);
3434
force.Tone();
35-
force.trial_available = true;
3635
force.trial_start = millis();
3736
force.trial_length = millis() - force.trial_start;
38-
force.Tare();
3937
while (force.trial_length < force.trial_window) {
40-
force.logdata();
38+
force.run(true);
4139
force.trial_length = millis() - force.trial_start;
42-
//Serial.println(force.trial_length);
43-
force.run();
44-
force.SenseLeft();
45-
if (force.pressLengthLeft > force.hold_timeLeft) {
46-
//force.Tone(2000, 200);
47-
force.DispenseLeft();
48-
force.pressesLeft = 0;
49-
force.logdata();
40+
if ((force.pressLengthLeft > force.hold_timeLeft) && (force.LeftActive)) {
41+
force.run(true);
42+
force.DispenseLeft();
5043
force.Timeout(force.timeout_length);
5144
}
52-
force.SenseRight();
53-
if (force.pressLengthRight > force.hold_timeRight) {
54-
//force.Tone(500, 200);
45+
if ((force.pressLengthRight > force.hold_timeRight) && (force.RightActive)) {
46+
force.run(true);
5547
force.DispenseRight();
56-
force.pressesRight = 0;
57-
force.logdata();
5848
force.Timeout(force.timeout_length);
5949
}
60-
force.trial_available = false;
61-
6250
}
6351
}
6452
}

0 commit comments

Comments
 (0)