We are working on a project to control the reaction of a system to a lever, whose position is monitored by two IR sensors at the ends of its travel, the Reward sensor and the Trigger sensor.
There are three modes of action:
Mode1: lever has to start at TriggerSensor, and a success is recorded if and when the lever is moved to RewardSensor
Mode2: lever starts at TriggerSensor and has to be held for 4 seconds. At the end of this interval a tone is played for 2 seconds, the reward interval. Within this 2 seconds, if the lever is moved to the RewardSensor, a success is recorded.
Mode3: same as Mode2, but the initial 4 second timeout is of random length.
We also want to use the following lines:
digitalWrite(TriggerSensorOut, digitalRead(TriggerSensorIn)); //This is to record to our computer the states of the trigger sensor
digitalWrite(RewardSensorOut, digitalRead(RewardSensorIn)); //This is to record to our computer the states of the reward sensor
to constantly write the state of both sensors to our computer. However, this doesn't work as planned: there are delays between the execution of the mode functions (as described in full code below).Essentially, we are struggling to come up with a suitable way to time things correctly.
Please see full code below
// -----LIBRARIES
//#include <elapsedMillis.h>
// ----CONSTANTS (won't change)
const int TriggerSensorIn = 2; // Input from trigger sensor, LOW = broken
const int RewardSensorIn = 3; // Input from reward sensor, LOW = broken
const int ModeStateIn1 = 4; // Input 1 from switch to define paradigm mode
const int ModeStateIn2 = 5; // Input 2 from switch to define paradigm mode
const int RewardSignalOut = 12; // Output signal of reward, parallel taken off to counter module
const int ServoResetOut = 6; // Servo reset output signal
const int ToneOut = 10; // Audio stimulus
const int TriggerSensorOut = 7; // Output from trigger sensor for DAC board recording
const int RewardSensorOut = 8; // Output from reward sensor for DAC board recording
//------- VARIABLES (will change)
boolean backPressed = false;
int timeoutWindow = 4000; // 4 second preliminary interval
int rewardWindow = 2000; // 2 second reward interval
unsigned long currentMillis = 0;
//===============
void setup() {
// initialise the digital pins as inputs and outputs
pinMode(TriggerSensorIn, INPUT);
pinMode(RewardSensorIn, INPUT);
pinMode(ModeStateIn1, INPUT);
pinMode(ModeStateIn2, INPUT);
pinMode(RewardSignalOut, OUTPUT);
pinMode(ServoResetOut, OUTPUT);
pinMode(ToneOut, OUTPUT);
pinMode(TriggerSensorOut, OUTPUT);
pinMode(RewardSensorOut, OUTPUT);
}
//===============
void giveReward() {
// This function is the protocol for recording a reward
currentMillis=millis();
digitalWrite(RewardSignalOut, HIGH);
while (millis()>currentMillis+200) {
digitalWrite(RewardSignalOut, LOW);
}
}
//===============
void servoReset() {
// This function is the protocol for resetting servos after a failed action
currentMillis=millis();
digitalWrite(ServoResetOut, HIGH);
while (millis()>currentMillis+200) {
digitalWrite(ServoResetOut, LOW);
}
}
//===============
void mode1() {
// This function is the protocol for controlling the system during mode 1, no time constraint on the action
if (digitalRead(TriggerSensorIn == LOW)) {
backPressed = true;
if (backPressed == true && digitalRead(RewardSensorIn == LOW)) {
giveReward();
backPressed = false;
}
}
}
//===============
void mode2() {
if (digitalRead(TriggerSensorIn == LOW)) {
currentMillis=millis();
while (digitalRead(TriggerSensorIn == LOW)) {
while (millis() > currentMillis + timeoutWindow) {
tone(ToneOut, 3000, 2000);
{
goto rewardSeeking2;
}
}
}
rewardSeeking2:
currentMillis=millis(); // reset timer
if (millis() < (currentMillis + rewardWindow) && digitalRead(RewardSensorIn == LOW)) {
giveReward();
}
else if (millis() > (currentMillis + rewardWindow)) {
servoReset();
}
}
}
//===============
void mode3() {
timeoutWindow=random(1000,5000);
if (digitalRead(TriggerSensorIn == LOW)) {
currentMillis=millis();
while (digitalRead(TriggerSensorIn == LOW)) {
while (millis() > currentMillis + timeoutWindow) {
tone(ToneOut, 3000, 2000);
{
goto rewardSeeking3;
}
}
}
rewardSeeking3:
currentMillis=millis(); // reset timer
if (millis() < (currentMillis + rewardWindow) && digitalRead(RewardSensorIn == LOW)) {
giveReward();
}
else if (millis() > (currentMillis + rewardWindow)) {
servoReset();
}
}
}
//===============
void loop() {
digitalWrite(TriggerSensorOut, digitalRead(TriggerSensorIn)); //This is to record to our computer the states of the trigger sensor
digitalWrite(RewardSensorOut, digitalRead(RewardSensorIn)); //This is to record to our computer the states of the reward sensor
if (digitalRead(ModeStateIn1) == LOW && digitalRead(ModeStateIn2) == LOW) {
// Using the two mode selective switches to define mode1
mode1();
}
else if (digitalRead(ModeStateIn1) == LOW && digitalRead(ModeStateIn2) == HIGH) {
// Using the two mode selective switches to define mode2
mode2();
}
else if (digitalRead(ModeStateIn1) == HIGH && digitalRead(ModeStateIn2) == LOW) {
// Using the two mode selective switches to define mode3
mode3();
}
}
//===============END
while (millis() > currentMillis + timeoutWindow)
looks wrong to me. I'd think the>
should be a<
. – Gerben Jul 14 '15 at 12:47<
it would be wrong because of themillis()
rollover. The right way to write that would bewhile (millis() - currentMillis < timeoutWindow)
. – Edgar Bonet Jul 14 '15 at 15:05