Solder Paste dispenser with Nema Motor - AccelStepper.h library

Hello

I'm having problems programming since I'm sort of in the basics.
I have read the examples and as much as I could I pseudo programmed the code bellow, but need guidance on activating the motor with micro stepping and for as long as each button is pressed.
Must also have variable motor speed and variable retraction speed.

I semi programmed a code from another library that is poorly documented but has to do with drivers

I have already done and designed the mechanical part 3d Printed and I'm willing to share the project with the community when finished.

The idea is to use a nema motor for dispensing the fluid but use as less possible mechanical parts like couplings or threaded rods.

Many projects are based on the hobby 28BYJ-48 motor and the ULN2003A driver

I want to do mine with a display, and a nema and either A4988 or DRV8825 driver with Microstepping since at full steps the motor heats a lot and yes I have calibrated the current of the driver for the motor.

So far I have programmed this:

/*
 * SOLDER PASTE DISPENSER WITH VARIABLE SPEED AND RETRACTIONS
 * MOTOR USED NEMA14
 * DRIVER USED DRV8825 AND MUST BE ABLE TO USE MICROSTEPPING
 * USER CAN BE ABLE TO SELECT THE SPEED OF THE MOTOR AND EXTRUDE PASTE BASED ON THHAT VALUE 
 * ALSO MUST BE ABLE TO READ THE RECTRACTION SPEED AND MOVE THE MOTOR BACKWARDS BASED ON THE RETRACTION SPEED
 * IF THE PROCESS OF EXTRUDE AND RETRACT IS INVERTED MUST BE ABLE TO USE AS A PICK AND PLACE
 * ALL DISPLAY ON AN LCD 16*2
 * FAST SPEED TO LOAD OR UNLOAD THE PLUNGER
 * SLOW SPEEDS TO EXTRUDE PASTE
 * RETRACTION TO AVOID SPILLS
 * 
 */
#include <LiquidCrystal_I2C.h> // Libreria que controla el I2C
#include<Wire.h>
LiquidCrystal_I2C lcd(0x27,16,2); //Direccion del I2c del LCD si no funciona este codigo usar un i2c Scanner
//Conexiones:
//5V I2C al 5V Arduino
//GND I2C al GND Arduino
//SDA I2C al A4 Arduino
//SCL I2C al A5 del Arduino

#include <AccelStepper.h>
AccelStepper stepper (1, 3, 2); // pin 3 = step, pin 2 = direction

byte dirPin = 2;
byte stepPin = 3;
byte CW_Button = 8;
byte CCW_Button = 9;
byte Emergency_Button = 10;
int SPEED_PIN = A3;
int R_SPEED_PIN = A0;
#define  MAX_SPEED 1000
#define  MIN_SPEED 0.1

boolean buttonpressed = false;
unsigned long curMillis;
unsigned long prevStepMillis = 0;


void setup() {
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.clear();
  lcd.setCursor(2,0);
  lcd.print("Starting...."); // Initial msg
  delay(3000);
  pinMode(dirPin, OUTPUT);
  pinMode(stepPin, OUTPUT);
  pinMode(CW_Button, INPUT_PULLUP);
  pinMode(CCW_Button, INPUT_PULLUP);
  pinMode(Emergency_Button, INPUT_PULLUP);
}

void loop() {
 curMillis = millis();
 readButtons();
 readMotorSpeed();
 readRetractSpeed();
 movestepper();

}

void readButtons() {
 if (digitalRead(CW_Button) == 0) {

  // Here need to know the code for the motor to continuosly move FOWARD based if the button is pressed, with a speed
  // read from the read speed function
  // when the motor is released must retract based on the reading of the retract speed function
  // I tryed to understand the library but I do not know how previously I used StepperDriver lib with some degree 
  // of success with microstepping since full steps heats my motor pretty much and yes the current already calibrated
   
  stepper.setSpeed(50);
  int SpeedValue = map(analogRead(SPEED_PIN), 0, 1023, 0, 1000);
  Serial.println(SpeedValue);
  stepper.setSpeed(SpeedValue);
  int a =0;
  a=SpeedValue;
  stepper.setSpeed(a);
  }
  if (digitalRead(CCW_Button) == 0) {  
    
  // Here need to know the code for the motor to continuosly move Backwards based if the button is pressed, with a speed
  // read from the read speed function
  // when the motor is released must retract based on the reading of the retract speed function

  }
 if ((digitalRead(CW_Button) == 0) || (digitalRead(CCW_Button) == 0) && (digitalRead(Emergency_Button) == 0) ){

// Here if either supply or retract button is pressed and the emergency button is pressed, stop the motor

 digitalWrite(stepPin, LOW);
}
}

void readMotorSpeed() {
  int SpeedValue = map(analogRead(SPEED_PIN), 0, 1023, 0, 1000);
  Serial.println(SpeedValue);
  stepper.setSpeed(SpeedValue);
  int a =0;
  a=SpeedValue;
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("Speed ");
  lcd.setCursor(7,0);
  lcd.print(a);
  delay(100);
   }
   
  void readRetractSpeed() {
  int retractValue = map(analogRead(R_SPEED_PIN), 0, 1023, 0, 1);
  Serial.println(retractValue);
  stepper.setSpeed(retractValue);
  float b =0;
  b=retractValue;
  lcd.clear();
  lcd.setCursor(0,1);
  lcd.print("RSpeed ");
  lcd.setCursor(8,1);
  lcd.print(b,3);
  delay(100);
  }

Thank you for your help

bmetasonic:
So far I have programmed this:

Please tell us what the program actually does and what you want it to do that is different.

It would also be a good idea to post a link to the datasheet for your stepper motor as not all Nema 17 motors can be controlled with a DRV8825

...R
Stepper Motor Basics
Simple Stepper Code

Dear Robin thank you for your fast answer

My program must be able to dispense and retract with variable speed on both, both mean motor speed on dispense and motor speed on retract

Depending on what if I select Dispense it will dispense according to the motor speed but also retract a bit to avoid spills

If I select Pick and place then is more or less the same code as dispense but on a different direction to be able to change the siring for an empty one but use it for pick and place components

What is different if that by selecting a nema motor with a driver with microstepping I can be able to have precise control of the system since mostly will be 3dprinted then the used depending on the diameter of the thread or the syringe can graduate the amount of dispense on retract to each particular system.

My nema 14 motor https://www.geeetech.com/nema-14-35-byghw-stepper-motor-p-909.html works with the Pololu drv8825 Pololu DRV8825 as I already semi coded it with the stepperdriver library but is poorly documented and I have problems in but have problems running the motor for as long as the button is pressed (my bad and ignorance only)

I coded this but only rotates one revolution not for as long as the button is pressed.

/*
 * Microstepping demo
 *
 * This requires that microstep control pins be connected in addition to STEP,DIR
 *
 * Copyright (C)2015 Laurentiu Badea
 *
 * This file may be redistributed under the terms of the MIT license.
 * A copy of this license has been included with this distribution in the file LICENSE.
 */
#include <Arduino.h>

// Motor steps per revolution. Most steppers are 200 steps or 1.8 degrees/step
#define MOTOR_STEPS 200
#define RPM 120

#define DIR 2 
#define STEP 3
#define SLEEP 13 // optional (just delete SLEEP from everywhere if not used)

/*
 * Choose one of the sections below that match your board
 */
 #include "DRV8825.h"
 #define MODE0 10
 #define MODE1 11
 #define MODE2 12
 DRV8825 stepper(MOTOR_STEPS, DIR, STEP, SLEEP, MODE0, MODE1, MODE2);

void setup() {
    /*
     * Set target motor RPM.
     */
    stepper.begin(RPM);
    // if using enable/disable on ENABLE pin (active LOW) instead of SLEEP uncomment next line
    // stepper.setEnableActiveState(LOW);
    stepper.enable();
    
    // set current level (for DRV8880 only). 
    // Valid percent values are 25, 50, 75 or 100.
    // stepper.setCurrent(100);
}

void loop() {
    delay(1000);

    /*
     * Moving motor in full step mode is simple:
     */
//    stepper.setMicrostep(1);  // Set microstep mode to 1:1
//
//    // One complete revolution is 360°
//    stepper.rotate(360);     // forward revolution
//    stepper.rotate(-360);    // reverse revolution
//
//    // One complete revolution is also MOTOR_STEPS steps in full step mode
//    stepper.move(MOTOR_STEPS);    // forward revolution
//    stepper.move(-MOTOR_STEPS);   // reverse revolution
//
//    /*
//     * Microstepping mode: 1, 2, 4, 8, 16 or 32 (where supported by driver)
//     * Mode 1 is full speed.
//     * Mode 32 is 32 microsteps per step.
//     * The motor should rotate just as fast (at the set RPM),
//     * but movement precision is increased, which may become visually apparent at lower RPMs.
//     */
    stepper.setMicrostep(32);   // Set microstep mode to 1:8

    // In 1:8 microstepping mode, one revolution takes 8 times as many microsteps
    stepper.move(36*MOTOR_STEPS);    // forward revolution
    delay(5000);
    stepper.move(-36*MOTOR_STEPS);   // reverse revolution
    delay(2000);
    // One complete revolution is still 360° regardless of microstepping mode
    // rotate() is easier to use than move() when no need to land on precise microstep position
    stepper.rotate(360);
    stepper.rotate(-360);

    delay(5000);
}

That is why I changed to AcccelStepper Library

Thanks again

I have to clear the first code doesn't include the button or the conditions but that library doesn't allow me to select speed but it supports microstepping, and works but for a specific steps or position I do not know hot to use it to move for as long as the button is pressed.
Again my bad

I'm afarid I find your descriptions confusing. For example you say

I coded this but only rotates one revolution not for as long as the button is pressed

followed by

That is why I changed to AcccelStepper Library

which seems to suggest the code that rotates one revolution is irrelevant.

Then you say

the first code doesn't include the button or the conditions but that library doesn't allow me to select speed but it supports microstepping, and works but for a specific steps or position I do not know hot to use it to move for as long as the button is pressed.

but I don't know which code is "the first code"

I suggest you pick one program that represents your best attempt and post it along with a very detailed description of what happens when you run it and what you want it to do that is different.

...R

Dear Robin
Again thank you for taking the time

I have reworked your code adding a retraction function

But when I press the CW button the motor doesn't' retract, it just move forward is like the retraction is not present and I need it to retract really fast for a tiny amount of time.

// testing a stepper motor with a Pololu A4988 driver board or equivalent

// this version uses millis() to manage timing rather than delay()
// and the movement is determined by a pair of momentary push switches
// press one and it turns CW, press the other and it turns CCW

byte directionPin = 2;
byte stepPin = 3;

byte buttonCWpin = 8;
byte buttonCCWpin = 9;

boolean buttonCWpressed = false;
boolean buttonCCWpressed = false;

byte ledPin = 13;

unsigned long curMillis;
unsigned long prevStepMillis = 0;
unsigned long millisBetweenSteps = 1; // milliseconds // Speed of the motor
unsigned long RET_millisBetweenSteps = 1; // milliseconds // Speed of retraction

void setup() {

     Serial.begin(9600);
     Serial.println("Starting Stepper Demo with millis()");

     pinMode(directionPin, OUTPUT);
     pinMode(stepPin, OUTPUT);
     pinMode(ledPin, OUTPUT);
     
     pinMode(buttonCWpin, INPUT_PULLUP);
     pinMode(buttonCCWpin, INPUT_PULLUP);
     
}

void loop() {
   
    curMillis = millis();
    readButtons();
    actOnButtons();
   
}

void readButtons() {
   
    buttonCCWpressed = false;
    buttonCWpressed = false;
   
    if (digitalRead(buttonCWpin) == LOW) {
        buttonCWpressed = true;
    }
    if (digitalRead(buttonCCWpin) == LOW) {
        buttonCCWpressed = true;
    }
}

void actOnButtons() {
    if (buttonCWpressed == true) {
        digitalWrite(directionPin, LOW);
        singleStep();
        digitalWrite(directionPin, HIGH);
        retraction();
        
    }
    if (buttonCCWpressed == true) {
        digitalWrite(directionPin, HIGH);
        singleStep();
    }
}

void singleStep() {
    if (curMillis - prevStepMillis >= millisBetweenSteps) {
            // next 2 lines changed 28 Nov 2018
        //prevStepMillis += millisBetweenSteps;
        prevStepMillis = curMillis;
        digitalWrite(stepPin, HIGH);
        digitalWrite(stepPin, LOW);
    }
}
void retraction() {
    if (curMillis - prevStepMillis >= millisBetweenSteps) {
            // next 2 lines changed 28 Nov 2018
        //prevStepMillis += RET_millisBetweenSteps;
        //prevStepMillis = RET_curMillis;
       byte i ;
       for (i = 0; i < 1000; i++){
        digitalWrite(stepPin, HIGH);
        digitalWrite(stepPin, LOW);
        }
        
    }
}

The retraction code checks that a millisecond has passed since the last step and only acts if it has.

retraction is called here:

void actOnButtons() {
    if (buttonCWpressed == true) {
        digitalWrite(directionPin, LOW);
        singleStep();
        digitalWrite(directionPin, HIGH);
        retraction();
        
    }

prevStepMillis was set in singleStep and all we've done since then is three digitalWrites. So it is highly likely that a millisecond hasn't passed yet and that means no retraction.

If by chance the clock was just right and you did get the retraction code to run, you are stepping as fast as the Arduino can manage it, but I rather doubt that the stepper can keep up.

Don't bother checking the time since the last step in retraction and put a delay in the loop that does the stepping. Just use plain old delay to prove it out - you can replace it with millis later if need be.

I wish you luck in your mechanical solder paste dispensing machine. You have not addressed the fine tuning of solder paste dispensing. The amount dispensed is based on the temperature of the paste, the flux type in the paste and the age of the paste.

Paul

bmetasonic:
I have reworked your code adding a retraction function

Based on what you have said you want to happen it seems to me you are making things far too complicated.

Surely a retraction is just a move backwards so that all you need is

void actOnButtons() {
    if (buttonCWpressed == true) {
        digitalWrite(directionPin, HIGH);
        singleStep();

(assuming direction = HIGH is backwards)

So press one button to extrude and the other button to retract,

...R

Robin2:
Based on what you have said you want to happen it seems to me you are making things far too complicated.

Surely a retraction is just a move backwards so that all you need is

void actOnButtons() {

if (buttonCWpressed == true) {
        digitalWrite(directionPin, HIGH);
        singleStep();



(assuming direction = HIGH is backwards)

So press one button to extrude and the other button to retract,

...R

Experience says the retract needs to be immediately after the end of dispense. We are dealing with a heavy, thick liquid that begs to continue flowing, once it has been accelerated.

Paul

Paul_KD7HB:
Experience says the retract needs to be immediately after the end of dispense.

I was hoping to spur the OP into describing his requirement more clearly.

...R

I doubt the OP has ever seen or used a commercial pneumatic unit.

Paul

Paul_KD7HB:
I doubt the OP has ever seen or used a commercial pneumatic unit.

Probably not, but I assume since he mentions retraction, he has some concept of what needs to happen - even if (as you suggest) the practicalities may turn out to be very intractable.

...R

Dear Guys
Thank you for your interest

I'm sorry I could not work on this since I was doing errands the whole day

To wildbill yes the motor keeps up very well

The whole point is since this will be as much as possible printed parts (already working) the user must be able to select in a menu the amount of paste dispensed as well as the retraction since too many factors are involved, paste density, paste amount in the syringe, type of syringe, plunger....

That is why I was this to be customized

Maybe I did not explain myself

When I press the dispense button it has to dispense a tiny amount and also at the same time RETRACT really fast to avoid dripping that must be configured into the dispense button dispense and as soon as I press, it will need to dispense, retract and stop all that in a matter of a second.

You would be well advised to plan on a foot switch to trigger the dispense/retract cycle, just like the commercial air driven units.

Paul

bmetasonic:
Maybe I did not explain myself

When I press the dispense button it has to dispense a tiny amount and also at the same time RETRACT really fast to avoid dripping

That seems very different from the impression I had from your earlier posts.

I think (but please confirm or clarify) that what you need is the ability for the user to press a button and then the motor moves X steps in the forward direction followed by Y steps backwards. This is a common feature of the extrusion activity in a 3D printer.

If the Arduino is not required to do anything else during this process code something like this pseudo code should work (assume this function is called when the button is pressed)

void extrudePaste() {
   digitalWrite(directionPin, LOW);
   for byte (n = 0; n < extrudeSteps; n++) {
      singleStep();
   }
   digitalWrite(directionPin, HIGH);
   for byte (n = 0; n < retractSteps; n++) {
      singleStep();
   }
}

...R