nema17+A4988 per apertura e chiusura sportello presepe+dot matrix 4 moduli 8x8

Ciao a tutti,
avrei un'esigenza che è la seguente.
Sto costruendo un presepe in una scatola di legno (quelle delle bottiglie di vino) ho già montato un motore nema17 e creato delle leve per aprire e chiudere la porta.
Avrei bisogno di poter controllare il motore con un pulsante per fare una cosa di questo tipo:

Premo il pulsante --> il motore compie n-gradi di rotazione in senso orario
Premo di nuovo il pulsante --> il motore compie n-gradi di rotazione in senso antiorario.

Leggendo sul forum, decine di ricerche, sono riuscito con le mie scarse competenze a scrivere questo codice:

#define dirPin 4
#define stepPin 5
#define EnablePin 6
#define Pulsante 11


bool rotazione = false; // variabile per senso rotazione
bool pressione; // variabile per leggere lo stato del pulsante
bool ultimapressione = false; // variabile per salvare lo stato della pressione pulsante


const int numStepMotore = 200;
const long velocita = 2000;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(EnablePin, OUTPUT);
  pinMode(Pulsante, INPUT_PULLUP);

  digitalWrite(EnablePin, LOW); // Enable è attivo se LOW
}

void loop() {

  pressione = digitalRead(Pulsante);

  if (pressione == LOW && ultimapressione == HIGH) {
    rotazione = !rotazione; // Inverte lo stato del motore
  }
  ultimapressione = pressione;
  if (rotazione == true) { // se true allora il motore gira in Avanti
    digitalWrite(dirPin, HIGH);
  }
  if (rotazione == false) { // se true allora il motore gira in Indietro
    digitalWrite(dirPin, LOW);
  }

  for (int x = 0; x < numStepMotore; x++);
  digitalWrite(stepPin, HIGH);
  delayMicroseconds(velocita);
  digitalWrite(stepPin, LOW);
  delayMicroseconds(velocita);

}

Il problema è che riesco a invertire il senso di rotazione ma il motore, in un verso o nell'altro gira all'infinito rendendo impossibile ciò che devo fare.

Credo che il problema sia nel ciclo for ma non saprei come uscirmene, qualcuno può darmi una mano?

Grazie in anticipo.

EDIT:
sono riuscito nell'intento con questo codice:

#define dirPin 4
#define stepPin 5
#define EnablePin 6
#define Pulsante 11

bool rotazione = false; // variabile per senso rotazione
bool pressione; // variabile per leggere lo stato del pulsante
bool ultimapressione = false; // variabile per salvare lo stato della pressione pulsante
const int numStepMotore = 200;
const long velocita = 2000;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(EnablePin, OUTPUT);
  pinMode(Pulsante, INPUT_PULLUP);
  digitalWrite(EnablePin, LOW); // Enable è attivo se LOW
}

void loop() {

  pressione = digitalRead(Pulsante);

  if (pressione == LOW && ultimapressione == HIGH) {

    for (int x = 0; x < 70; x++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(velocita);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(velocita);
    }

    rotazione = !rotazione; // Inverte lo stato del motore
  }
  ultimapressione = pressione;
  if (rotazione == true) { // se true allora il motore gira in Avanti
    digitalWrite(dirPin, HIGH);

  }
  if (rotazione == false) { // se true allora il motore gira in Indietro
    digitalWrite(dirPin, LOW);
  }
}

Però adesso vorrei un pò di coppia in più. Come posso fare?

Grazie!

La coppia dipende strettamente dal modello del motore e dalla corrente di fase che vai ad impostare adeguando il Vref del driver.

Tipicamente si consiglia di stare sull'80% del valore di corrente massima
Per la tua applicazione potresti pensare di usare il tuo motore in modo intermittente e quindi disattivare il driver una volta raggiunta la posizione.
In questo modo riduci la temperatura del motore e puoi valutare di usare il 100% della corrente massima.

1 Like

velocita piu bassa significa forza di piu ... pero anche se sei principiante se cerchi conoscere il principio di base di come un stepper gira e come un driver fa girare un motore sara molto utile per te e ti aiuta capire meglio quello che fai , perche facendo preseppe sono siguro che vorrei usare anche altri tipi di motori e sensori , e se parti dalle base , cioe conoscere il principio dopo quale funziona le cose sarai in grado di fare molte cose!
Se tu hai in loop il step , e normale che pin low e high si ripete e il motore gira continuo cambiando direzione solo con pulsante. devi inserire stepPin low e high in un loop che puo essere un if,while,for che fa solo un numero limitato di step. Non so se e permesso pero ho fatto una pagina che none una cosa professionale , pero puoi provare anche scrivere diretto in linguaggio assembly. certo il ide arduino e molto utile avendo un linguaggio avansato e delle librerie , pero asm ti aiuta conoscere come lavora in realta il micocontrollere e cosi avrai di piu legerezza quando creei una linea di codice in arduino ide perche sai che succede in background! Con assembly conosci come lavora registry che succede in realta a un interrupt o timer o come si scrive i registry per poter lavorare con timer,seriale,ecc ... ho messo anche un pochino di essempi . pagina e qui https://www.costycnc.it/avr1/ e da stessa pagina web puoi scrivere codice asm , compilare e scrivere in arduino diretto ... senza arduino ide!
per essempio questo e codice per girare un motore stepper :
'''
.org 0x60
;arduino nano cnc shield v4.0
sbi 4,0 ;pin DIR as output D8 PORTB,PB0
sbi 0xa,5 ;pin STEP as output D5 PORTD,PD5
cbi 5,0 ;enable DIR pin D8 -put high
init:
sbi 0xb,5 ;put pin STEP high
rcall pause ;pause
cbi 0xb,5 ;put pin STEP low
rcall pause ;pause
rjmp init ;repeat

pause:
dec R16
brne pause
ret
'''
e qui video https://www.youtube.com/shorts/3M-RNsV8gwE

@costycnc:

Buongiorno e benvenuto nella sezione Italiana del forum,

cortesemente, come prima cosa, leggi attentamente il REGOLAMENTO di detta sezione, (... e, per evitare future possibili discussioni/incomprensioni, prestando molta attenzione al punto 15), dopo di che, come da suddetto regolamento (punto 16.7), fai la tua presentazione NELL'APPOSITA DISCUSSIONE (... quello che vedi in blu è un link, fai click su di esso per raggiungere la discussione) spiegando bene quali esperienze hai in elettronica e programmazione, affinché noi possiamo conoscere la tua esperienza ed esprimerci con termini adeguati.

Grazie,

Guglielmo

*P.S.: Ti ricordo che, purtroppo, fino a quando non sarà fatta la presentazione nell’apposita discussione, nel rispetto del succitato regolamento nessuno ti risponderà (eventuali risposte o tuoi ulteriori post, verrebbero temporaneamente nascosti), quindi ti consiglio di farla al più presto.

Ti ringrazio per la risposta.
Infatti aumentando la Vref ottengo maggiore coppia. Per quanto riguarda la temperatura non credo sia un problema in quanto il motore viene azionato 3-4 volte al giorno non di più.
Credo che il problema sia anche nel sistema di leveraggio poiché scompongo la forza, in quanto le leve non lavorano in maniera ortogonale.

Provo a fare due calcoli e vi aggiorno.
Grazie.

fatto ... pensavo che gia lo ho fatto dato che sono da tanto tempo iscritto!

1 Like

I motori passo-passo sono sempre in coppia, anche quando sono fermi.
Per evitarlo devi togliere il segnale di enable al driver, ma devi tenere conto che dopo aver disabilitato il driver il motore sarà libero di muoversi.

Se la cosa può andar bene oppure no, dipende dall'applicazione specifica e dal "cinematismo" che il motore è chiamato ad azionare.

Alcuni driver più evoluti (come ad esempio quelli Trinamic) hanno la possibilità di impostare dinamicamente una "corrente di riposo" ad una frazione di quella di lavoro in modo che sia sufficiente a mantenere il motore in posizione.

grazie, è esattamente ciò che sto facendo.
Ho aggiunto dei magneti deboli ma che fanno il loro lavoro per mantener chiusa/aperta la scatola in caso di Enable in stato HIGH.

Per la coppia ho anche provato ad aumentare la tensione portandola a 24V e regolando l'assorbimento all'80% ma cambia poco probabilmente devo giocare con i passi del motore.
Per ora va bene così.

Sarebbe interessante utilizzare la libreria Accelstepper per gestire un movimento più graduale ma non mi sono ancora cimentato in tal senso...

Grazie.

Rieccomi qua.

Il codice per movere motore ha funzionato correttamente seguendo i vostri consigli.
Ho anche aggiunto un altro pulsante con un buzzer che mi suona una piccola melodia: tutto ok!

Vengo al dunque, ho una matrice di 4 moduli 8x8.
Son riuscito a farla funzionare col codice base e le librerie MD_MAX72xx + MD_PAROLA.
Vorrei però che alla pressione del pulsante per la melodia compaia anche il testo in modalità scrolling.

Allego il codice che ho usato per la matrice dei led, è ok:

#include <MD_Parola.h>
#include <MD_MAX72xx.h>
#include <SPI.h>

#define HARDWARE_TYPE MD_MAX72XX::FC16_HW
//#define HARDWARE_TYPE MD_MAX72XX::GENERIC_HW

#define MAX_DEVICES 4
#define CS_PIN 10

MD_Parola myDisplay = MD_Parola(HARDWARE_TYPE, CS_PIN, MAX_DEVICES);

void setup() {

  myDisplay.begin();
  myDisplay.setIntensity(4);
  myDisplay.displayClear();
  myDisplay.displayScroll("testo personalizzato", PA_CENTER, PA_SCROLL_LEFT, 100);
}

void loop() {

  if (myDisplay.displayAnimate()) {
    myDisplay.displayReset();
  }
}

Questo è il codice con motore e melodia:

#define dirPin 4
#define stepPin 5
#define EnablePin 6
#define Pulsante 2
#define MS1 9
#define MS2 8
#define MS3 7
#define pulsante_melodia 3



bool rotazione = false; // variabile per senso rotazione
bool pressione; // variabile per leggere lo stato del pulsante
bool ultimapressione = false; // variabile per salvare lo stato della pressione pulsante
const int numStepMotore = 200;
const long velocita = 1000;
bool melodia = false;

void setup() {
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
  pinMode(EnablePin, OUTPUT);
  pinMode(Pulsante, INPUT_PULLUP);
  pinMode(pulsante_melodia, INPUT);
  digitalWrite(EnablePin, LOW); // Enable è attivo se LOW
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(MS3, OUTPUT);
}

void loop() {
  digitalWrite(EnablePin, HIGH);
  digitalWrite(MS1, HIGH);
  digitalWrite(MS2, HIGH);
  digitalWrite(MS3, HIGH);

  pressione = digitalRead(Pulsante);

  if (pressione == LOW && ultimapressione == HIGH) {
    digitalWrite(EnablePin, LOW);
    for (int x = 0; x < 1120; x++) {
      digitalWrite(stepPin, HIGH);
      delayMicroseconds(velocita);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(velocita);
    }

    rotazione = !rotazione; // Inverte lo stato del motore
  }
  ultimapressione = pressione;
  if (rotazione == true) { // se true allora il motore gira in Avanti
    digitalWrite(dirPin, LOW);
  }
  if (rotazione == false) { // se true allora il motore gira in Indietro
    digitalWrite(dirPin, HIGH);
  }

  melodia = digitalRead(pulsante_melodia);
  delay(20);
  if (melodia == HIGH)
    song(12); //richiama il codice della tab song e lo suona sul buzzer
}

c'è un modo per unire i due codici o solo ciò che serve? così quando premo il pulsante_melodia compare anche il testo personalizzato?
Sto impazzendo, grazie.