Need help with controlling stepper motor in a diy water pump

Hi there,
I built a syringe pump using a NEMA 17 stepper motor and DRV8825, to use in some neuroscience experiment as a reward pump. I'd like to deliver a certain amount of water in regular intervals, and whenever a pushbutton is pressed. For this I've already troubleshot and ditched a couple scripts, due to some fried devices. Now I'm trying to use the accelstepper library and bounce2 to make things right.
I pasted the whole -non working- code below, but basically what I'd like to have it do is:

  • run ~10 steps (that's about what it takes to deliver a drop of water) as fast as possible so I can deliver the reward without much delay
  • give these rewards every 20 seconds regularly
  • also check for a pushbutton, and deliver a reward whenever it's pressed, without affecting the regular interval rewards above (so I can't use delay() )
  • whenever a reward's delivered, output a square pulse to be sent to a DAQ as a reward timestamp
  • ideally I'd also like to have the enable pin, as my circuit makes an audible noise (I know, it's probably not a good sign, but I don't have time to troubleshoot it right now) and I want to minimize that by cutting the power whenever the motor is not stepping

I'm a biologist who's self-taught in all these electrical stuff and arduino, and at this point I'm very much above my pay grade, so any help is highly appreciated. Thanks!

#include <AccelStepper.h>
#include <Bounce2.h>


// set the constants for experiment
int REWARDSIZE = 10; // in number of steps
int MAXSPEED = 1000; // in pins/sec
int ACCEL = 200;
int SPEED = 200;
int REWINTERVAL = 20000; // reward interval in ms
int buttonInterval = 500;
const int stepsPerRevolution = 200;
bool buttonState = false;

const int stepPin = 8; // low: no steps, high: steps
const int directionPin = 9; // low: cw, high: ccw
const int enablePin = 4;  // low: no power to motor, high: motor on

const int ledPin = 2; // indicator light, turns ON in caseof reward
const int rewardTimeStamp = 3; // TTL to Intan
const byte buttonCWpin = 6; // triggers cw (reward)
const byte buttonCCWpin = 7; // triggers ccw (cleaning/adjusting pump)

// define variables
unsigned long curMillis;
unsigned long lastRewardMillis = 0;
unsigned long previousButtonMillis = 0;

// Define motor interface type as driver (used with step and dir pins)
#define motorInterfaceType 1

// Create a stepper object
AccelStepper rewardPump(motorInterfaceType, stepPin, directionPin);

// set enable pin to keep the motor from powering on unnecessarily
// setEnablePin(enablePin); // requires enable/disable outputs before/after using them

// initiate debouncing for buttons
Bounce fwdButton = Bounce();
Bounce revButton = Bounce();

//====================================================SETUP
void setup()
{

  Serial.begin(115200);
  Serial.println("Starting reward pump:");
  Serial.println("Motor is at "); 
  Serial.println(rewardPump.currentPosition());
  pinMode(ledPin, OUTPUT);
  pinMode(rewardTimeStamp, OUTPUT);

  fwdButton.attach(buttonCWpin, INPUT_PULLUP); fwdButton.interval(5);
  revButton.attach(buttonCCWpin, INPUT_PULLUP); revButton.interval(5);

  digitalWrite(rewardTimeStamp, LOW);

  rewardPump.setMaxSpeed(MAXSPEED);
  rewardPump.setAcceleration(ACCEL);
  rewardPump.setSpeed(SPEED);
  rewardPump.move(-REWARDSIZE);
}

//===================================================LOOP

void loop()
{
//  revButton.update();
  readButton();
  curMillis = millis();
  // enableOutputs();
  if (rewardPump.distanceToGo() == 0)
  {
//    rewardPump.setAcceleration(ACCEL);
    rewardPump.setSpeed(SPEED);
    rewardPump.move(-REWARDSIZE);
    Serial.println("reward");
    Serial.println(rewardPump.currentPosition());
    lastRewardMillis += REWINTERVAL;
  }
  rewardPump.run();  

  if (curMillis - lastRewardMillis >= REWINTERVAL)
  {

    

  }
  
  else if (buttonState)
  {
    digitalWrite(ledPin, HIGH);
    rewardPump.run();
    Serial.println("button reward");
    Serial.println(rewardPump.currentPosition());
    digitalWrite(ledPin, LOW); // TODO: do this with attach interrupt + for rewardTimeStamp
  }
//  else if (revButton.fell())
//  {
//    rewardPump.move(150);
//    Serial.println("turning back for cleaning");
//  }
}

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

void readButton()
{

  if (millis() - previousButtonMillis >= buttonInterval)
  {
    fwdButton.update();
    if (fwdButton.fell())
    {
      buttonState = true; 
      previousButtonMillis == millis();
    }
    else
    {
      buttonState = false;
    }
  }
}

I did expect to see a description of what that current code does and where it fails. Does it move the motor at all?

Why do you check for the button state only every 500ms?

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.