Pulsante start stop

Ciao, scusate probabilmente il doppione, ma pur trovando parecchi thread non riesco a capire cosa non funziona.
Il problema è che non riesco a far funzionare correttamente il comando di stop. Il loop parte correttamente la prima volta ma poi alla seconda pressione continua e nel Monitor seriale vedo che allo stesso istante è come se il tasto ricevesse due comandi.
Potete aiutarmi?

Grazie

class MillisAlarm {
  private:
    unsigned long interval;
    unsigned long startTime;

    public:
      void start(unsigned long timerLength) {
        interval = timerLength;
        startTime = millis();
      }

      bool done() {
        return (millis()-startTime >= interval);
      }
      
};

class MillisStopWatch {
  private:
    unsigned long startTime;

  public:
    void start() {
      startTime = millis();
    }

    unsigned long check() { return millis()-startTime; }
};

MillisAlarm alarm;
MillisStopWatch stopWatch;


#include <ezButton.h>
#define LOOP_STATE_STOPPED 0
#define LOOP_STATE_STARTED 1
#include <AccelStepper.h>
#define HALFSTEP 4
int stepRev=200;
ezButton button(0);  // create ezButton object that attach to pin 7;
int loopState = LOOP_STATE_STOPPED;
// ========================SCREW
// Define stepper motor connections and motor interface type.
// Motor interface type must be set to 1 when using a driver:
#define dirPin 19
#define stepPin 18
#define motorInterfaceType 1
#define home_screw 2  // Pin D2 connected to Home Switch (MicroSwitch)


long initial_homing = 1;  // Used to Home Stepper at startup

// Create a new instance of the AccelStepper class:
AccelStepper ScrewStepper(motorInterfaceType, stepPin, dirPin);


long pos0 =-stepRev*1.75*(10/1.5);
long pos1 =-stepRev*1.75*(25/1.5);
long pos2 =-stepRev*1.75*(65/1.5);

// ========================GUIDE
// define number of step per revolution
int stepsPerRevolution = 2048;
// Create stepper istance

#define home_guide 1  // Pin D1 connected to Home Switch (MicroSwitch)

#define motorPin1 3  // IN1 on ULN2003 ==> Blue   on 28BYJ-48
#define motorPin2 4  // IN2 on ULN2004 ==> Pink   on 28BYJ-48
#define motorPin3 5  // IN3 on ULN2003 ==> Yellow on 28BYJ-48
#define motorPin4 6  // IN4 on ULN2003 ==> Orange on 28BYJ-48
AccelStepper GuideStepper(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);


long GuideHoming= stepsPerRevolution;
long StepPermm=stepsPerRevolution/(1.5*15*3.1415);
long posGuiON=-StepPermm*5;
long posGuiOFF=-StepPermm*35;


// ========================LEVER
// Create stepper istance

#define motorPin5 14  // IN1 on ULN2003 ==> Blue   on 28BYJ-48
#define motorPin6 15  // IN2 on ULN2004 ==> Pink   on 28BYJ-48
#define motorPin7 16  // IN3 on ULN2003 ==> Yellow on 28BYJ-48
#define motorPin8 17  // IN4 on ULN2003 ==> Orange on 28BYJ-48
AccelStepper LeverStepper(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);

long LeverHoming= stepsPerRevolution*0.5;
long StepPerdeg=stepsPerRevolution/360;
long LeverON=-StepPerdeg*45;
long LeverOFF=StepPerdeg*10;


void setup() {

  //start an alarm that will end in 1 second
alarm.start(1000);

//start a stopWatch, timer starting @ current millis();
stopWatch.start();

Serial.begin(9600);
while (!Serial);

button.setDebounceTime(100); // set debounce time to 50 milliseconds

GuideStepper.setMaxSpeed(1000);
GuideStepper.setAcceleration(100);
GuideStepper.setSpeed(1000);

LeverStepper.setMaxSpeed(1000);
LeverStepper.setAcceleration(100);
LeverStepper.setSpeed(1000);

// // Homing screw
// // Start Homing procedure of Stepper Motor at startup
// pinMode(home_screw, INPUT_PULLUP);
// ScrewStepper.setMaxSpeed(50);
// ScrewStepper.setAcceleration(50);


// while (digitalRead(home_screw)) {       // Make the Stepper move CW until the switch is activated
//     ScrewStepper.moveTo(initial_homing);  // Set the position to move to
//     initial_homing++;
//     ScrewStepper.run();
// }


// ScrewStepper.setMaxSpeed(5000);       // Set Max Speed of Stepper (Slower to get better accuracy)
// ScrewStepper.setAcceleration(500);    // Set Acceleration of Stepper
// initial_homing = -1;

// while (!digitalRead(home_screw)) {  // Make the Stepper move CCW until the switch is deactivated
//     ScrewStepper.moveTo(initial_homing);
//     initial_homing--;                 
//     ScrewStepper.run();  
// }
// ScrewStepper.setCurrentPosition(0);
// ScrewStepper.moveTo(pos0);
// ScrewStepper.runToPosition();

Serial.println("Homing estrusore eseguito");


// // Homing Lever
// // Start Homing procedure of Stepper Motor at startup
LeverStepper.moveTo(LeverHoming);
LeverStepper.runToPosition();
if (LeverStepper.distanceToGo() == 0) {
LeverStepper.setCurrentPosition(0);
}
LeverStepper.moveTo(LeverON);
LeverStepper.runToPosition();
Serial.println("Homing leva eseguita");

// // Homing Guide
// // Start Homing procedure of Stepper Motor at startup
GuideStepper.moveTo(GuideHoming);
GuideStepper.runToPosition();
GuideStepper.setCurrentPosition(0);
GuideStepper.moveTo(posGuiON);
GuideStepper.runToPosition();
Serial.println("Homing guida eseguita");
}

void loop() {

  

  button.loop(); // MUST call the loop() function first

  if (button.isPressed()) {

    if (loopState == LOOP_STATE_STOPPED) {
      loopState = LOOP_STATE_STARTED;
      String struno = "Button pressed: ";
      String strbot =struno + loopState;
      Serial.println(strbot);
     
    }
    else //if (loopState == LOOP_STATE_STARTED) {
      {loopState = LOOP_STATE_STOPPED;
      String struno = "Button pressed: ";
      String strbot =struno + loopState;
      Serial.println(strbot);
      
    }
  }

  if (loopState == LOOP_STATE_STARTED) {
    Serial.println("Inizio ciclo");

    LeverStepper.moveTo(LeverHoming);
    LeverStepper.runToPosition();
    if (LeverStepper.distanceToGo() == 0) {
    LeverStepper.setCurrentPosition(0);
    }
   
    alarm.start(500);  

    LeverStepper.moveTo(LeverON);
    LeverStepper.runToPosition();

    // // Set the maximum speed and acceleration in working:
    // ScrewStepper.setMaxSpeed(5000);
    // ScrewStepper.setAcceleration(500);

    // ScrewStepper.moveTo(pos1);
    // ScrewStepper.runToPosition();

    // ScrewStepper.setMaxSpeed(500);
    // ScrewStepper.setAcceleration(200);

    // ScrewStepper.moveTo(pos2);
    // ScrewStepper.runToPosition();
    // alarm.start(1500);  



    GuideStepper.moveTo(posGuiOFF);
    GuideStepper.runToPosition();
    Serial.println("Guide off");

    // ScrewStepper.setMaxSpeed(2000);
    // ScrewStepper.setAcceleration(200);

    // ScrewStepper.moveTo(-500);
    // ScrewStepper.runToPosition();

    // Serial.println("screw pre-homing");

    // ScrewStepper.setMaxSpeed(50);
    // ScrewStepper.setAcceleration(50);

    // initial_homing = 1;
    // while (digitalRead(home_screw)) {      
    //   ScrewStepper.moveTo(initial_homing);  // Set the position to move to
    //   initial_homing++;  
    //   ScrewStepper.run();                 
        
    // }
   
    // initial_homing = -1;
    // while (!digitalRead(home_screw)) {  
    //   ScrewStepper.moveTo(initial_homing);
    //   initial_homing--;
    //   ScrewStepper.run();                  
        
    // }

    // ScrewStepper.setCurrentPosition(0);
    // Serial.println("Homing estrusore");
     
    GuideStepper.moveTo(GuideHoming);
    GuideStepper.runToPosition();
    GuideStepper.setCurrentPosition(0);
    GuideStepper.moveTo(posGuiON);
    GuideStepper.runToPosition();
    Serial.println("Fine ciclo");
  }
}
     





Non hai specificato di che board si tratta, ma se è il classico Arduino non è il caso di usare i pin D0 e D1 perché sono connessi rispettivamente al pin RX e TX del convertitore USB/TTL.

Grazie per il suggerimento, la board è arduino uno r4 wifi.
Pin 0 e 1 non li devo mai usare?
Sono un meccanico e quindi brancolo nel buio nell’elettronica :sweat_smile:

Con riferimento ad Arduino Uno, puoi anche usarli, ma devi tenere presente che, se usi la seriale, su quei pin passeranno i dati trasmessi e ricevuti, che vanno a interferire con i segnali in ingresso e in uscita. Se, per esempio, ci metti due LED, lampeggeranno ogni volta che passa qualcosa sulla seriale.

la UNO R4 è un po' diversa, la classica "Serial" è sulla USB nativa, mentre i pin 0 ed 1 vengono usati se usi una seconda porta seriale, la "Serial1", altrimenti sono normali pin di I/O.

Detto questo, per compatibilità con tante altre schede Arduino (se mai un giorno devi trasportare un programma su un'altra scheda), il consiglio è di lasciare liberi i pin 0 ed 1 che, spesso, sono usati per la porta seriale ed usare altri pin liberi.

Guglielmo

Ok, grazie.
Per quanto riguarda il doppio input…è qualcosa di ovvio che nn vedo?

Prova a ridurre ai minimi termini assoluti il codice che genera l'anomalia. Così a occhio sembra giusta la gestione del pulsante (sotto evento impulsivo isPressed). Il debounce è impostato e quindi anche eventuali disturbi non dovrebbero esserci (sempre ammesso che la libreria ezButton applichi un ritardo sia sul fronte di salita che di discesa dell'ingresso :thinking:).

Non dovrebbe esserci un problema in quel senso perché la prima volta funziona regolarmente…il problema è quando da start devo passare a stop che c’è nello stesso tempo due cambiamenti di stato e quindi ritorna in start e il ciclo continua.
Proverò stasera a cambiare pin vedere se il problema persiste. :disappointed:

Trattandosi di Uno R4, come ti ha ben spiegato @gpb01 non dovresti avere alcun problema con quei due pin, quindi con tutta probabilità il problema persiste.

Un consiglio, prova a replicare il tuo progetto sul simulatore online wokwi.
Diventerebbe molto più semplice individuare cosa c'è che non va.

Ad esempio cosi (dal punto di vista elettrico il circuito è completamente sbagliato, ma al momento questo non ha importanza).

questa mi mancava…ha proprio lo stesso output. Però la velocità di debug sarà più veloce, ma non saprei dove mettere le mani

Come già detto:

Togliendo qualcosa l'anomalia sparisce? In che modo questo qualcosa influisce. Ecc.

Fatto, tutto ok se nel loop non metto niente tranne una msg su serial, appena inserisco moveto dello stepper non funziona più. Devo trovare metodo alternativo ad accelstepper?….era na battuta :sweat:

#include <ezButton.h>
#define LOOP_STATE_STOPPED 0
#define LOOP_STATE_STARTED 1
#include <AccelStepper.h>
#define HALFSTEP 4
int stepRev = 200;
ezButton button(12);  // create ezButton object that attach to pin D12;
int loopState = LOOP_STATE_STOPPED;
// ========================SCREW
// Define stepper motor connections and motor interface type.
// Motor interface type must be set to 1 when using a driver:
#define dirPin 19
#define stepPin 18
#define motorInterfaceType 1
#define home_screw 2  // Pin D2 connected to Home Switch (MicroSwitch)


long initial_homing = 1;  // Used to Home Stepper at startup

// Create a new instance of the AccelStepper class:
AccelStepper ScrewStepper(motorInterfaceType, stepPin, dirPin);


long pos0 = -stepRev * 1.75 * (10 / 1.5);
long pos1 = -stepRev * 1.75 * (25 / 1.5);
long pos2 = -stepRev * 1.75 * (65 / 1.5);

// ========================GUIDE
// define number of step per revolution
int stepsPerRevolution = 2048;
// Create stepper istance

#define home_guide 1  // Pin D1 connected to Home Switch (MicroSwitch)

#define motorPin1 3  // IN1 on ULN2003 ==> Blue   on 28BYJ-48
#define motorPin2 4  // IN2 on ULN2004 ==> Pink   on 28BYJ-48
#define motorPin3 5  // IN3 on ULN2003 ==> Yellow on 28BYJ-48
#define motorPin4 6  // IN4 on ULN2003 ==> Orange on 28BYJ-48
AccelStepper GuideStepper(HALFSTEP, motorPin1, motorPin3, motorPin2, motorPin4);


long GuideHoming = stepsPerRevolution;
long StepPermm = stepsPerRevolution / (1.5 * 15 * 3.1415);
long posGuiON = -StepPermm * 5;
long posGuiOFF = -StepPermm * 35;


// ========================LEVER
// Create stepper istance

#define motorPin5 14  // IN1 on ULN2003 ==> Blue   on 28BYJ-48
#define motorPin6 15  // IN2 on ULN2004 ==> Pink   on 28BYJ-48
#define motorPin7 16  // IN3 on ULN2003 ==> Yellow on 28BYJ-48
#define motorPin8 17  // IN4 on ULN2003 ==> Orange on 28BYJ-48
AccelStepper LeverStepper(HALFSTEP, motorPin5, motorPin7, motorPin6, motorPin8);

long LeverHoming = stepsPerRevolution * 0.5;
long StepPerdeg = stepsPerRevolution / 360;
long LeverON = -StepPerdeg * 45;
long LeverOFF = StepPerdeg * 10;


void setup() {

  Serial.begin(9600);
  while (!Serial);

  button.setDebounceTime(50); // set debounce time to 50 milliseconds

  GuideStepper.setMaxSpeed(1000);
  GuideStepper.setAcceleration(100);
  GuideStepper.setSpeed(1000);


}

void loop() {

  button.loop(); // MUST call the loop() function first

  if (button.isPressed()) {

    if (loopState == LOOP_STATE_STOPPED) {
      loopState = LOOP_STATE_STARTED;
      String struno = "Button pressed: ";
      String strbot = struno + loopState;
      Serial.println(strbot);

    }
    else //if (loopState == LOOP_STATE_STARTED) {
    { loopState = LOOP_STATE_STOPPED;
      String struno = "Button pressed: ";
      String strbot = struno + loopState;
      Serial.println(strbot);

    }
  }

  if (loopState == LOOP_STATE_STARTED) {
    Serial.println("Inizio ciclo");
   GuideStepper.moveTo(GuideHoming);
    GuideStepper.runToPosition();
    GuideStepper.setCurrentPosition(0);
    GuideStepper.moveTo(posGuiON);
    GuideStepper.runToPosition();
    Serial.println("Guide off");
    Serial.println("Fine ciclo");
  }
}

se tolgo i movimento dello stepper la routine si comporta come atteso...avete suggerimenti??

quindi giusto per riassumere tu sul monitor seriale leggi:

Button pressed: 1
Inizio ciclo
Guide off
Fine ciclo
Button pressed 0
Button pressed 1
Inizio ciclo
Guide off
Fine ciclo
Button pressed 0
Button pressed 1

e via così?
in particolare fai attenzione alle scritte button pressed

Probabilmente quello che succede è questo (ho sostituito l'elaborazione con un delay):
https://wokwi.com/projects/383253672190368769

Codice
#include <ezButton.h>

#define LOOP_STATE_STOPPED 0
#define LOOP_STATE_STARTED 1
int loopState = LOOP_STATE_STOPPED;

ezButton button(2);  // create ezButton object that attach to pin D12;

void setup() {
  Serial.begin(9600);
  while (!Serial);
  button.setDebounceTime(50);
}

void loop() {
  button.loop();
  if (button.isPressed()) {
    if (loopState == LOOP_STATE_STOPPED)
      loopState = LOOP_STATE_STARTED;
    else
      loopState = LOOP_STATE_STOPPED;
    Serial.print("Button pressed: ");
    Serial.println(loopState);
  }
  
  if (loopState == LOOP_STATE_STARTED) {
    Serial.println("Inizio ciclo");
    delay(3000);
    Serial.println("Fine ciclo");
  }
}

Il metodo runToPosition è bloccante, e probabilmente manda in crisi le temporizzazioni di ezButton.

Anche secondo me dipende da questo.

@fabiod82 dovrebbe usare il metodo moveTo(position) per impostare il target e poi chiamare il metodo non bloccante run() per muovere lo stepper.

Per controllare se il motore è arrivato prima di cambiare target può chiamare il metodo distanceToGo() == 0

Esatto,
se sostituisco con un run() invece non ha problemi.
Ho provato a sostituire con un ciclo while distanceToGo(0), ma il ciclo risulta comunque bloccato, funziona se mantengo premuto il tasto stop per tutto il movimento, ma nel mio loop è improponibile.

Se metti il codice il un while, è comunque bloccante. Non è l'approccio giusto.
La funzione loop() è già un "grande" while

occhio che al termine del ciclo nulla rimette a zero lo stato loop
alla loop() successiva il ciclo si ripete comunque automaticamente

se si vuole fare una cosa non bloccante serve rivoluzionare il programma

e per farlo serveno domande

cosa succede se si preme il pulsante a ciclo iniziato?
cosa succede se il ciclo termina senza che venga premuto il pulsante?
e magari ancora, serve dedicarvisi

però a questo non ha rsiposto