Imbastire software gestione NR.2 Stepper 28BYJ-48

Ciao,
devo realizzare un software per Arduino-UNO per la gestione di nr. 2 stepper (start-stop) ma sto incontrando alcune difficoltà nello sviluppo.
Il circuito è composto da nr. 2 finecorsa (in2-in3) e nr.2 stepper (in4-5-6-7, in8-9-10-11) comandati da un modulo drive ciascuno (ULN2003A).
La logica è semplice ma per me che sono alle prime armi mi presenta diverse difficoltà: il funzionamento dei due motori deve essere alternato e interrotto dall'intervento del finecorsa associato.
La sequenza da creare sarebbe quindi la seguente:

  • Accensione --> Attivazione M1
  • All'intervento del finecorsa 1 --> Arresto M1 e Attivazione M2
  • All'intervento del finecorsa 2 --> Arresto M2 e Attivazione M1
    ...con loop infinito

Grazie in anticipo a chi mi saprà aiutare
Qoci

Buongiorno e benvenuto, :slight_smile:
essendo il tuo primo post, nel rispetto del regolamento della sezione Italiana del forum (… punto 13, primo capoverso), ti chiedo cortesemente di presentarti IN QUESTO THREAD (spiegando bene quali conoscenze hai di elettronica e di programmazione ... possibilmente evitando di scrivere solo una riga di saluto) e di leggere con molta attenzione tutto il succitato REGOLAMENTO ... Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposito thread, nel rispetto del suddetto regolamento nessuno ti risponderà (eventuali risposte verrebbero cancellate), quindi ti consiglio di farla al più presto. :wink:

Quando tu parli di "Attivazione M1" significa che SAI che comandi dare per far girare quel motore e quindi che SAI come costruire una funzione che potrebbe chiamarsi AttivazioneM1()? E lo stesso per AttivazioneM2()?

O è questo il problema?

Ciao,
P.

Un metodo (e non so se sia il più corretto) è quello di alzare in sequenza le singole uscite di comando del drive.
All'interno del loop principale il motore gira

Facci vedere il programma che hai fatto.

Ciao,
P.

Questo è il codice abbozzato, spero risulti comprensibile, grazie

int Micro1 = 3;         //Micro1 arresto M1 e start M2 (pin 3)
int Micro2 = 2;         //Micro1 arresto M2 e start M1 (pin 2)
int motorPin1 = 8;      //IN1 sul pin 8
int motorPin2 = 9;      //IN2 sul pin 9
int motorPin3 = 10;     //IN3 sul pin 10
int motorPin4 = 11;     //IN4 sul pin 11
int motor2Pin1 = 4;     //Motore 2 IN1 sul pin 4
int motor2Pin2 = 5;     //Motore 2 IN2 sul pin 5
int motor2Pin3 = 6;     //Motore 2 IN3 sul pin 6
int motor2Pin4 = 7;     //Motore 2 IN4 sul pin 7
int val1 = 0;           //Stato Micro 1
int val2 = 0;           //Stato Micro 2
int Precedenteval1 = 0; //Variabile per fronte salita Micro 1
int Precedenteval2 = 0; //Variabile per fronte salita Micro 2
int motor_Speed = 10;
int motor_Step;
bool firstcycle = true; //flag primo ciclo

void setup() {
  pinMode(Micro1, INPUT);
  pinMode(Micro2, INPUT);
  pinMode(motorPin1, OUTPUT);
  pinMode(motorPin2, OUTPUT);
  pinMode(motorPin3, OUTPUT);
  pinMode(motorPin4, OUTPUT);
  pinMode(motor2Pin1, OUTPUT);
  pinMode(motor2Pin2, OUTPUT);
  pinMode(motor2Pin3, OUTPUT);
  pinMode(motor2Pin4, OUTPUT);
}

void loop() {
  val1 = digitalRead(Micro1);
  val2 = digitalRead(Micro2);
  
  if (firstcycle == true) {
    CicloM1();
    firstcycle = false;
  }

  if ((Precedenteval1 == 0) && (val1 == 1) && (firstcycle == false)) {
    CicloM2();
    Precedenteval1 = val1;
  }

  if ((Precedenteval2 == 0) && (val2 == 1) && (firstcycle == false)) {
    CicloM1();
    Precedenteval2 = val2;
  }
}

void CicloM1() {
  do {
      digitalWrite(motorPin1, HIGH);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, LOW);
      delay(motor_Speed);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, HIGH);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, LOW);
      delay(motor_Speed);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, HIGH);
      digitalWrite(motorPin4, LOW);
      delay(motor_Speed);
      digitalWrite(motorPin1, LOW);
      digitalWrite(motorPin2, LOW);
      digitalWrite(motorPin3, LOW);
      digitalWrite(motorPin4, HIGH);
      delay(motor_Speed);
    } while (val1 == 0);
}

void CicloM2() {
  do {
      digitalWrite(motor2Pin1, HIGH);
      digitalWrite(motor2Pin2, LOW);
      digitalWrite(motor2Pin3, LOW);
      digitalWrite(motor2Pin4, LOW);
      delay(motor_Speed);
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, HIGH);
      digitalWrite(motor2Pin3, LOW);
      digitalWrite(motor2Pin4, LOW);
      delay(motor_Speed);
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, LOW);
      digitalWrite(motor2Pin3, HIGH);
      digitalWrite(motor2Pin4, LOW);
      delay(motor_Speed);
      digitalWrite(motor2Pin1, LOW);
      digitalWrite(motor2Pin2, LOW);
      digitalWrite(motor2Pin3, LOW);
      digitalWrite(motor2Pin4, HIGH);
      delay(motor_Speed);
    } while (val2 == 0);
}

Prima di far partire il motore è necessario assicurarsi che non sia già arrivato a un finecorsa.
La condizione per far partire M1 è finecorsa1 = OFF, se finecorsa1 = ON deve partire M2. Questa condizione puoi impostarla già nel setup(). Imposta anche una variabile che ti dice in che direzione è partito il motore, ad es: dir = FWD è partito M1, dir = BCK è partito M2. Se sei SICURO che all'avvio i finecorsa sono ENTRAMBI OFF puoi far partire direttamente M1 e porre dir = FWD.

Nel loop() testi finecorsa1 e finecorsa2.
SE entrambi OFF mantieni direzione corrente (FWD = M1; BCK = M2)
SE finecorsa1 = ON imposti direzione BCK
SE finecorsa2 = ON imposti direzione FWD
SE dir = FWD ALLORA M1
SE dir = BCK ALLORA M2

Mi sembra che possa funzionare.

Ciao,
P.

Un paio di cose che mi sembra doveroso specificare:

  • i motori e i rispettivi finecorsa sono su due "binari" indipendenti (M1 non incontra mai il finecorsa 2 e M2 non incontra mai il finecorsa 1)
  • il percorso è un anello per cui il senso di rotazione dei motori é unico per entrambi
  • entrambi i finecorsa attivi è una condizione che si verifica (arrivo in posizione di un motore e start dell'altro)

Quando entri nel ciclo do while con il tuo codice non esci più la variabile di controllo resta sempre vera, a meno che abbia preso un abbaglio.

Vorrei sapere se ci sono altre "rivelazioni" che ci farai nel seguito sul progetto che stai portando avanti. Sarò mentalmente limitato, ma da quello che descrivi non capisco di cosa stai parlando.

Parli di DUE binari indipendenti, poi di UN anello. Parli di finecorsa, ma finecorsa significa FINE CORSA. Se qualcosa arriva lì poi riparte in senso inverso. Oppure i finecorsa sono semplicemente degli SWITCH o segnalatori di posizione.

Se ci facessi un disegno del tutto e una descrizione un po' più dettagliata si potrebbe rispondere meglio.

Ciao,
P.

Ti chiedo scusa se non sono stato chiarissimo, ma gli switch a leva li conoscevo come "finecorsa". L'applicazione si tratta di 2 catene indipendenti che ruotano: è un po' riconducibile a 2 treni giocattolo (ciascuno nel suo binario ovale) e gli switch rappresentano le rispettive stazioni.
Quando il treno 1 (M1) arriva alla stazione (switch/finecorsa 1) si ferma, parte il treno 2 ed effettua il tratto per arrivare alla stazione 2, poi riparte il treno 1 fino al ritorno in stazione 1 e così in successione alternata.
Al momento non ho modo di disegnarlo ma spero sia un po'più chiaro.
Grazie

Il modo migliore per risolvere il problema può essere un programma a stati. Nel seguito ti propongo uno schema che consiste in DUE passi: 1 per il motore M1 e 2 per il motore M2. I passi si alternano attraverso l'istruzione SWITCH... CASE

int passo

Nel setup()
  passo = 1

Nel loop()
  SWITCH passo
  case 1
    M1step() //il motore M1 avanza di UNO step
    SE sw1 = OFF
      break
    ELSE //sw1 = ON M1 si ferma e parte M2
      passo = 2
      break
  case 2
    M2step() //il motore M2 avanza di UNO step
    SE sw2 = OFF
      break
    ELSE //sw2 = ON M2 si ferma e parte M1
      passo = 1
      break
  //FINE SWITCH
//FINE loop()

M1step() //funzione che fa avanzare M1 di UNO step
  Non le istruzioni che hai scritto che fanno girare M1 in continuazione, come ha detto Arco_500

M2step() //funzione che fa avanzare M2 di UNO step
  Non le istruzioni che hai scritto che fanno girare M2 in continuazione, come ha detto Arco_500

Vedi se può andare.

Ciao,
P.

Ciao, il ciclo rispecchia al 99% quello che avevo in mente.
L'unico aspetto che non coincide con quanto pensato è che all'arrivo del "treno 1" in stazione non avviene il suo arresto finché il "treno 2" non ha lasciato la stazione e viceversa.
Comunque è un grandissimo passo avanti.
Grazie

Perché dici questo? L'arresto del treno1 avviene nella sezione ELSE dela case 1 e solo SUCCESSIVAMENTE il treno2 parte nel case 2.

Potrei aver sbagliato. Ci fai vedere il codice che hai scritto?

Ciao,
P.

Ecco qua, grazie

void loop() {
  val1 = digitalRead(Micro1);
  val2 = digitalRead(Micro2);
  switch (passo) {
  case 1:
    M1step(); //il motore M1 avanza di UNO step 
    if (val1 == 0) {
      break;
      }
    else {    //val1 = ON M1 si ferma e parte M2
      passo = 2;
      break;
      }
  case 2:
    M2step(); //il motore M2 avanza di UNO step SE val2 = OFF
      if (val2 == 0) {
      break;
      }
    else { //val2 = ON M2 si ferma e parte M1
      passo = 1;
      break;
      }
  }
}

void M1step() {
      myStepper1.step(1); //Accende il motore
}
      
void M2step() {
      myStepper2.step(1); //Accende il motore
}

Le funzioni M1step() e M2step() fanno avanzare M1 e M2 di UN SOLO step. Significa che quando una delle funzioni viene chiamata il corrispondente motore, che era FERMO, si muove di uno step e SI FERMA, mentre l'altro è FERMO. All'uscita della funzione il motore corrispondente è FERMO perché ha compiuto il suo step e l'altro è FERMO perché ERA GIÀ FERMO.

Non capisco come sia possibile che un motore avanzi di uno step mentre l'altro sta ancora avanzando. All'uscita delle due funzioni entrambi i motori sono FERMI, perché quello che doveva avanzare è avanzato mentre l'altro era fermo da prima.

Ciao,
P.