Long Nose Poke & Tones

108 views
Skip to first unread message

Lydia Bailey

unread,
Nov 18, 2021, 6:37:44 PM11/18/21
to FEDforum

Hello,

I am new to working on the FED machines and was hoping you could help. We are ultimately trying to get to the go/no-go task, but right now I am trying to write a code to make the animals do the following as one of our steps to getting there:

The animal pokes the left hole, a low pitch sound plays, and if the animal keeps their nose in the hole for 0.6 seconds (our goal time), a high pitch sound plays to release them for their treat. If they release before the 0.6 seconds they receive the click, no second tone, and no reward.  

I have the following code:


void loop() {

  fed3.run();                                           //Call fed.run at least once per loop

  if (fed3.Left) {                                      //If left poke is triggered

    fed3.Tone(50, 500);                        //Play low pitch sound

    fed3.logLeftPoke();                         //Log left poke

    if (millis() >= fed3.minPokeTime) {   //if # msec is >= min poke time (0.6 seconds)

      fed3.Tone(2500, 500);                   //play high pitch tone (release)

      fed3.Feed();

    }

    else {

    fed3.Click();                                         //Otherwise, no reward or second sound

  }

  if (fed3.Right) {                                     //If right poke is triggered

    fed3.logRightPoke();                                //Log right poke

  }

}

}

 

This waits for the animal to remove their nose before the second tone plays. Do you know if there is a way to have the time initiate the second tone as soon as the nose poke gets to 0.6 seconds? I know the millis() function is our problem, but we can't find a way to make the poke time register before the animal removes their nose.


Thanks in advance!


Lydia

Lex Kravitz

unread,
Nov 19, 2021, 5:23:42 PM11/19/21
to FEDforum
Hi Lydia!  Sounds like you're doing something cool! 

The issue you're having is because you're asking if millis() itself is >= fed3.minPokeTime.  millis() is an Arduino function that returns the time in milliseconds since the device was started up.  So this will be a very large number, nearly always > 600. 

Instead of asking if millis() >= fed3.minPokeTime, you can set a new variable equal to millis() when he pokes, which is a way to store the time of the poke (how many milliseconds elapsed since the device was started up).  And then ask if (millis() - the_new_variable) >= fed3.minPokeTime.  In your code I've added a new variable "leftpoketime" and set it equal to millis() when a left poke is detected, and then changed your if statement to "if (millis() - leftpoketime) >= fed4.minPokeTime".  Code pasted below and Arduino sketch attached. Is this doing what you want?   Best, -Lex


void loop() {
  fed3.run();                                           //Call fed.run at least once per loop
  if (fed3.Left) {                                      //If left poke is triggered
    int leftpoketime = millis();                        // ******** Note the time of the left poke ******

    fed3.Tone(50, 500);                                 //Play low pitch sound
    fed3.logLeftPoke();                                 //Log left poke

    if ((millis()-leftpoketime) >= fed3.minPokeTime) {  //if # msec is >= min poke time (0.6 seconds)
Long_Nose_Poke_Example.ino

Lydia Bailey

unread,
Nov 22, 2021, 2:34:15 PM11/22/21
to FEDforum

Hi! Thanks for the response.

 

I had this originally, in the FED3.h it defines fed3.leftinterval as what you wrote above. The issue when I do this is that it waits for the animal to remove their nose before it can register the leftpoketime. I was hoping to get it to work as a counter so as soon as the poke reached a certain time, it would cause the sound, instead of waiting for them to remove their nose. Ideally, we want the high-pitched sound to be used as a trigger that indicates they have reached the required time and can now go get their food.


Thanks!

Lydia

Lex Kravitz

unread,
Nov 22, 2021, 11:23:59 PM11/22/21
to FEDforum
Oh that's trickier for sure!  As you found out, the built in "logLeftPoke" function waits for the mouse to leave the poke before determining how long it was activated.  But this approach won't work for your task.  To get around this we have to write the functionality you want in the high level script, including a new "logLeftPoke" function that does not wait for him to leave the poke.

I've done this by setting a new flag variable called "longpoke" in the main script, and setting it equal to true when the poke breaks 600ms, and otherwise setting it equal to false.  This allows the FED3 to deliver the behavior you want, ie: if longpoke == true there is a high pitched tone and a pellet, if it is false there is a click.  I also wrote a new logLeftPoke_mod function, which logs to the SD card but doesn't have the delay where it waits to see how long the poke lasted. 

Anyway take a look at the attached code, I think it's doing what you want.  Please post back if it is!  -Lex
Long_Nose_Poke_Example_v2.ino

Lydia Bailey

unread,
Nov 23, 2021, 6:36:01 PM11/23/21
to FEDforum
Hi again!

Thanks for the response. I tried implementing this, and now I'm having a different issue. Whenever I poke in the hole, it delivers both tones and a pellet, no matter how long I leave my finger there. Either the poke time is too low, and it registers the low value as the poke time but still delivers a pellet, or it is over the desired time, but only registers the poke as exactly 600 ms (instead of the real duration of the poke), and delivers the pellet.

I tried looking through the code, but I can't tell why it is doing this - it seems like the code says only to deliver food if the min time is met, but it isn't doing that.

I have attached my code here (hopefully you can open it). It is basically what you just sent with a few small adjustments to make it run with what I have.

Any thoughts? Thanks!
Trial.ino

Lex Kravitz

unread,
Nov 23, 2021, 8:55:41 PM11/23/21
to FEDforum
Hi again,
Looking at it quickly I think the issue may be that the longpoke variable is getting stuck true.  It looks like the only time you're setting this false is in the else statement in line 36, but I'm not sure if the code will ever enter that if statement how it is written.  

I would try adding longpoke = false; after fed3.Feed(); in line 44 to make sure it sets longpoke to false on each trial and see if that fixes it.

As a general troubleshooting tip, to see where you are in the code you can use Serial.print functions.  I'm attaching a version of your code with Serial.print statements added that might be helpful for decoding what's happening.  You can open the Serial Monitor in the Arduino IDE (under the Tools menu) and see these statements appear when the code reaches them, which can help you figure out what your code is doing.

Lastly, did you move the logLeftPoke_mod() function to your local copy of the FED3 library?  I would advise you not to do that, if you update the library at a later date you'll lose it.  So I would just keep this function with your high level sketch.

Let me know if the print statements help!
Trial_with_Serial_print_statements.ino
Reply all
Reply to author
Forward
0 new messages