Timing of a closed circuit

We are trying to conduct a medical experiment with rats.

The rat walks on a rotating metal cylinder.
Every time the rat's feet (fitted with electrodes in its pad) touches a rotating metal cylinder,
a circuit gets closed. We want to time this event.

i;e we want to record the time of contact between the electrode in the rat's paw and the metal cylinder.

Without getting into the gory details, we want to time, for how long the circuit remains closed -
micros or even millis resolution would be fine.

Here's my naive attempt. It reads values on analog pin and converts it to voltage reading.
If voltage exceed the threshold, it records the timings.

boolean feetTouching;
boolean recordedThisFeetTouching;

void setup() {
  Serial.begin(2000000);   
  feetTouching = false;
  recordedThisFeetTouching = false;
}


void loop() {
  int sensorValue = analogRead(A0);
  float voltage = sensorValue * (5.0 / 1023.0); //map (0 - 1023) to (0 - 5V):
  if(voltage > 3.5) {
    feetTouching = true;
    if(recordedThisFeetTouching == false){
       String t =  String(millis(), DEC); 
       String v =  String(voltage, 3);
       String toprint = String(t + "," + v);
       Serial.println(toprint);
       recordedThisFeetTouching = true;
    }   
   }
   else{
    Serial.println("not touching"); // this fires even when touching 
    feetTouching = false;
    recordedThisFeetTouching = false;
    }
}

However there is one major problem with this code.
The else clause triggers even when the analogue pin is touching the cylinder.

What would be a good approach to record the time of contact between the
rat's paws and the cylinder floor.

else clause
else claws
Sorry :wink:

I suggest you use digital inputs for this instead of analog inputs.
Note you will have a lot of bouncing to contend with.

.

Here is a sketch you might be able to build on.
Library is attached.

/*Timing a switch closer
  LarryD
  Date      Version   
  17/05/12  1.00       Running code
  
  This is sketch is to introduce new people to the SwitchManager library written by Nick Gammon

  The library handles switch de-bouncing and provides timing and state change information in your sketch.
  The SwitchManagerWithFilter.h file should be placed in your libraries folder, i.e.
  C:\Users\YouName\Documents\Arduino\libraries\SwitchManagerWithFilter\SwitchManagerWithFilter.h

  In this example, we have 1 normally open (N.O.) switch connected to the Arduino.
  The switch is connected between GND (0 volts) and an Arduino input pin.
  The library enables pull-up resistors for your switch inputs.
  Pushing a switch makes its pin LOW. Releasing a switch makes its pin HIGH.

  The SwitchManager library provides 10ms de-bounce for switches.
  i.e. enum { debounceTime = 10, noSwitch = -1 };
  If you need more time, edit the SwitchManager.h file
  i.e. enum { debounceTime = 50, noSwitch = -1 }; //here it is changed to 50ms

  When SwitchManagerWithFilter.h is used as the library, input signals > 20ms are guaranteed to be captured.
  Signals 10-20ms might be captured, with signals < 10ms are ignored.
*/

//**********************************************************************
//+5V----InternalPullupResitor----InputPin----[SwitchPin1/SwitchPin2]----GND
#define Pressed  LOW
#define Released HIGH

//+5V----[LEDanode/LEDcathode]----[220ohmResistor]----OutputPin
#define LEDon    LOW
#define LEDoff   HIGH
//***************************

/*
  //**********************************************************************
  //+5V----[SwitchPin1/SwitchPin2]----InputPin----[10K resistor]----GND
  #define Pressed  HIGH
  #define Released LOW

  //OutputPin----[LEDanode/LEDcathode]----[220ohmResistor]----GND
  #define LEDon    HIGH
  #define LEDoff   LOW
  //***************************
*/

//#include <SwitchManager.h>
#include <SwitchManagerWithFilter.h>

//object instantiations
SwitchManager mytouchSwitch;

unsigned long currentMillis;
unsigned long heartBeatMillis;
unsigned long touchMillis;
unsigned long heartFlashRate  = 500UL;  // time the led will change state

const byte heartBeatLED       = 13;
const byte touchLED           = 12; //toggles on switch release
const byte touchSwitch        =  8; //touch switch

int myCounter;

//======================================================================

void setup()
{
  Serial.begin(9600);

  //gives a visual indication if the sketch is blocking
  pinMode(heartBeatLED, OUTPUT);

  //a LED which toggles when the touch switch is released
  pinMode(touchLED, OUTPUT);

  mytouchSwitch.begin (touchSwitch, handleSwitchPresses);
  //the handleSwitchPresses() function is called when a switch changes state

} //                   E N D  O F  s e t u p ( )

//======================================================================

void loop()
{
  //leave this line of code at the top of loop()
  currentMillis = millis();

  //***************************
  //some code to see if the sketch is blocking
  if (CheckTime(heartBeatMillis, heartFlashRate, true))
  {
    //toggle the heartBeatLED
    digitalWrite(heartBeatLED, !digitalRead(heartBeatLED));
  }

  //***************************
  //check to see what's happening with the switches
  //"Do not use delay()s" in your sketch as it will make switch changes unresponsive
  //Use BlinkWithoutDelay (BWD) techniques instead
  mytouchSwitch.check ();

  //***************************
  //Other non-blocking stuff here
  //***************************

} //                      E N D  O F  l o o p ( )


//======================================================================
//                          F U N C T I O N S
//======================================================================


//                        C h e c k T i m e ( )
//**********************************************************************
//Delay time expired function
//parameters:
//lastMillis = time we started
//wait = delay in ms
//restart = do we start again

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart)
{
  //has time expired for this task?
  if (currentMillis - lastMillis >= wait)
  {
    //should this start again?
    if (restart)
    {
      //yes, get ready for the next iteration
      lastMillis = millis();
    }
    return true;
  }
  return false;

} //                 E N D   o f   C h e c k T i m e ( )


//                h a n d l e S w i t c h P r e s s e s( )
//**********************************************************************

void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  // You get here "ONLY" if there has been a change in a switches state.

  //When a switch has changed state, SwitchManager passes this function 3 arguments:
  //"newState" this will be HIGH or LOW. This is the state the switch is in now.
  //"interval" the number of milliseconds the switch stayed in the previous state
  //"whichPin" is the switch pin that we are examining

  switch (whichPin)
  {
    //***************************
    //are we dealing with this switch?
    case touchSwitch:
      //has this switch gone from Released to Pressed
      //this happens with normally open switches wired as mentioned at the top of this sketch
      if (newState == Pressed)
      {
        touchMillis = millis();
      }

      else
      {
        Serial.print("Switch was closed for ");
        Serial.print( millis() - touchMillis);
        Serial.println(" milli seconds.");
        //toggle the LED
        digitalWrite(touchLED, !digitalRead(touchLED));
      }

      break; //End of case touchSwitch
      //***************************

  } //End switch (whichPin)

} //      E n d   o f   h a n d l e S w i t c h P r e s s e s ( )


//======================================================================
//                      E N D  O F  C O D E
//======================================================================

.

SwitchManagerWithFilter.h (4.14 KB)

In the microsecond resolutions you will probably find many different taps for a single step - that's the rat's feet bouncing off the metal tube. That's probably also what triggers both events - in different cycles of your loop().

So you can basically do two things.

  1. debounce in software (a short delay) or hardware (a small cap),
  2. no debounce but log all the touches, later "debounce" when you analyse your data: if two touches are less than a certain time apart, consider them part of the same touch. Should give more accurate overall timing as method 1) by nature introduces delays (of milliseconds).

However there is one major problem with this code.
The else clause triggers even when the analogue pin is touching the cylinder.

I don't see a logic error in your code. If you declare

float voltage = 3.7

you only get one printout of the time and the data. With your sketch, if you move a jumper between 5v and ground, the printout stops with the 5v applied.

As larryd suggests, there may be an unsteady/noisy reading from the foot on the cylinder. The input may also be floating.

Where is the 5v source, and how are the electrode and the metal cylinder wired. What goes to 5v, what goes to ground and what goes to the Arduino.

As larryd suggests, you may be better with digital rather than analog methods but I think that more explanation of the experiment and the expected signal would help us give advice.

The debounce routine may be similar in both cases(analog/digital), as I think this measurement may lend itself to the debounce routines which require a stable input state for a consecutive number of readings.

Where is this project headed? What are you actually trying to measure? Do you need to record the time the foot touches and the length of time it remains on the cylinder? Are you wanting to measure all 4 feet?

@larryd
I will switch to the digital pins instead of Analog pins. Though I am not sure why this is better. Is it because the sampling will happen at fixed intervals ? Thanks :slight_smile:

@wvmarle
Thanks. Your second advice to keep all data and do a post processing to get the actual contact time, seems to be a great approach - without loosing any of the accuracy.

@cattledog

Where is this project headed? What are you actually trying to measure? Do you need to record the time the foot touches and the length of time it remains on the cylinder? Are you wanting to measure all 4 feet?

Yes we need to record the time the foot touches and the length of time it remains on the cylinder.
We are measuring only on the two hind feet. One of the feet would be injected with a medicine, while the other would serve as a control feet.

I have attached a PDF with a similar experiment setup (see page 3-4 for the instrumentation detail). However, while this experiment uses 6 rats at a time, we do it on one rat at a time.

Where is the 5v source, and how are the electrode and the metal cylinder wired. What goes to 5v, what goes to ground and what goes to the Arduino.

The attached PDF gives a schematic for 6 rats but we will simplify it to work only for a single rat.

04DDR28(NewM)93.pdf (285 KB)

Analog inputs take time to be converted by the A/D.
It is easier to debounce digital inputs.

Suggest you try the example posted in #2.
You should be able to easily modify it to your final needs.
The library the sketch needs is attached at the bottom of the same post.

@larryd

Yes I will definitely try the code and should I need any clarification, will bother you again :slight_smile:

@larryd

Thanks your code and the library seem to be working great for my needs.

I modified it to add another pin as I need two switches - one for the left leg and another for the right leg of the rat.

While this seems to be working well, can you please look at this code and validate if I am going in the right direction ?

#include <SwitchManagerWithFilter.h>

#define Pressed  LOW
#define Released HIGH
SwitchManager myleftLegSwitch;
SwitchManager myrightLegSwitch;

unsigned long currentMillis;
unsigned long touchMillis;

const byte leftLegSwitch        =  8;
const byte rightLegSwitch        =  12;

void setup()
{
  Serial.begin(9600);
  myleftLegSwitch.begin (leftLegSwitch, handleSwitchPresses);
  myrightLegSwitch.begin (rightLegSwitch, handleSwitchPresses);
 
} 

void loop()
{
  currentMillis = millis();
  myleftLegSwitch.check ();
  myrightLegSwitch.check ();
} 

boolean CheckTime(unsigned long  & lastMillis, unsigned long wait, boolean restart)
{
  if (currentMillis - lastMillis >= wait)
  {
    if (restart)
    {
      lastMillis = millis();
    }
    return true;
  }
  return false;

} 


void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
    if (newState == Pressed)
      {
        touchMillis = millis();
      }

      else
      {
        Serial.print("Switch ");
        Serial.print(whichPin);
        Serial.print(" was closed for ");
        Serial.print( millis() - touchMillis);
        Serial.println(" milli seconds.");
        
      }
   
}

One more related question:

Since I am logging this data through the serial port, does it help to increase the baud rate from current 9600 to higher baud rate ?

Thanks Sir, you have done me a great help.

It is easy to check sketch functionality, all you need is two switches connected as mentioned in the original sketch in post #2.

While this seems to be working well,

I don’t think so. :wink:

Here is what you will need to do for two ‘independent’ switch monitoring:

#include <SwitchManagerWithFilter.h>

#define Pressed  LOW
#define Released HIGH
SwitchManager myleftLegSwitch;
SwitchManager myrightLegSwitch;

unsigned long touchLeftMillis;  //for left  leg timing
unsigned long touchRightMillis; //for right leg timing

const byte leftLegSwitch  =  8;
const byte rightLegSwitch =  12;

int myCounter;

//                            s e t u p ( )
//**********************************************************************
void setup()
{
  Serial.begin(9600);
  myleftLegSwitch.begin  (leftLegSwitch, handleSwitchPresses);
  myrightLegSwitch.begin (rightLegSwitch, handleSwitchPresses);

} //  >>>>>>>>>>>>>>>>>> E N D  O F  s e t u p ( ) <<<<<<<<<<<<<<<<<<<<<


//                             l o o p ( )
//**********************************************************************
void loop()
{
  myleftLegSwitch.check ();
  myrightLegSwitch.check ();

} //  >>>>>>>>>>>>>>>>>>> E N D  O F  l o o p ( ) <<<<<<<<<<<<<<<<<<<<<<



//======================================================================
//                          F U N C T I O N S
//======================================================================


//              h a n d l e S w i t c h P r e s s e s ( )
//**********************************************************************
void handleSwitchPresses(const byte newState, const unsigned long interval, const byte whichPin)
{
  switch (whichPin)
  {
    //************************
    case leftLegSwitch:
      {
        if (newState == Pressed)
        {
          touchLeftMillis = millis();
        }

        else
        {
          Serial.print("Left switch ");
          Serial.print(whichPin);
          Serial.print(" was closed for ");
          Serial.print( millis() - touchLeftMillis);
          Serial.println(" milli seconds.");
        }
        break;
      }

    //************************
    case rightLegSwitch:
      {
        if (newState == Pressed)
        {
          touchRightMillis = millis();
        }

        else
        {
          Serial.print("Right switch ");
          Serial.print(whichPin);
          Serial.print(" was closed for ");
          Serial.print( millis() - touchRightMillis);
          Serial.println(" milli seconds.");
        }
        break;
      }

  } //END of switch/case

} //END of     h a n d l e S w i t c h P r e s s e s ( )

//**********************************************************************




//======================================================================
//                        E N D  O F  C O D E
//======================================================================

I would suggest you have two LEDs that toggle when the feet move, this gives the researcher some visual feed back.
I also suggest a heartBeatLED to let you know the sketch is working properly.

.

See post #9
I would set up the I/O as follows:

const byte leftLegSwitch  =  8;
const byte rightLegSwitch =  9;
const byte leftLegLED     = 11; //toggles on switch release
const byte rightLegLED    = 12; //toggles on switch release
const byte heartBeatLED   = 13;

You can easily change your baud rate to 115200 if need arises.

.

@larryd

Thanks a lot.

We would like to give you the due credit in our research paper.
How do we mention it in the papers ?

thanks again.

"Thanks to the Arduino forum volunteers"

.