Le projet présenté ici est généraliste et a pour but de faire comprendre le principe.
Il est adaptable a plusieurs situation.
Le matériel utilisé :
Le Wemos D1 Mini. C'est lui qui commande. Ce jour, 2,50€ les 10.
.
.
Le TMC2209. Très présent dans les imprimantes 3D, c'est lui qui sert d'interface entre le microprocesseur (ici le Wemos D1 Mini) et le moteur Nema 17. Ce jour, 17,60€ les 5.
.
.
Le moteur avec poulies d'entrainement 1:1. Ce jour 14,90€ pièce, 3,70€ les 2 amortisseurs, Poulies + courroies 5€ environs.
.
#include <AccelStepper.h>
const byte pin_DIR = D3;
const byte pin_STEP = D4;
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 ou 0x3F déclaration adresse du lcd
// LiquidCrystal_I2C lcd(0x3f, 16, 2);
AccelStepper stepper(AccelStepper::DRIVER, pin_STEP, pin_DIR); // création objet Stepper
void setup()
{
stepper.setMaxSpeed(10000.0); // Vitesse max moteur
stepper.setAcceleration(1000.0); // distance accélération / décélération
lcd.init(); // Initialisation de l'afficheur
lcd.backlight(); // Allume l'ecran
lcd.clear();
// Efface l'ecran
lcd.setCursor (0,0); // place le curseur sur la ligne 0 a gauche
lcd.print ("*Initialisation*"); // Affichage sur le lcd
lcd.setCursor (0,1); // passe a la ligne suivante
lcd.print ("* Programme *"); // affichage sur le lcd
}
void loop()
{
delay(1000);
stepper.runToNewPosition(0);
delay(3000) ;
lcd.clear();
lcd.setCursor (0,0); // place le curseur sur la ligne 0 a gauche
lcd.print ("*Direction*"); // Affichage sur le lcd
lcd.setCursor (0,1); // passe a la ligne suivante
lcd.print ("*10 000 points*"); // affichage sur le lcd
delay(1000);
stepper.runToNewPosition(10000);
delay(3000);
lcd.clear();
lcd.setCursor (0,0); // place le curseur sur la ligne 0 a gauche
lcd.print ("*Direction*"); // Affichage sur le lcd
lcd.setCursor (0,1); // passe a la ligne suivante
lcd.print ("*20 000 points*");
delay(1000);
stepper.runToNewPosition(20000);
delay(3000);
lcd.clear();
lcd.setCursor (0,0); // place le curseur sur la ligne 0 a gauche
lcd.print ("*Direction*"); // Affichage sur le lcd
lcd.setCursor (0,1); // passe a la ligne suivante
lcd.print ("*Point zero*");
}
Un déplacement de 10 000 pas représente 5 cm linéaire.
La vidéo :
Etape suivante ajout d'un encodeur rotatif, création de menu interactif.
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 18:25
par patrice_b
likiki a écrit : ↑26 avr. 2025, 17:36
Tu as tout bon Patrice.
Ahhh, je suis content je progresse
Tu maitrise c'est super !
Oui ton système de moteur et entrainement pourrait s'utiliser a l'horizontale pour faire tourner les 2 plateaux du bas ...(pater noster)
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 18:27
par herwat
Ah, ben tu t'y remet ! cool !
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 18:44
par patrice_b
herwat a écrit : ↑26 avr. 2025, 18:27
Ah, ben tu t'y remet ! cool !
Allez Hervé, on t'attend dans le sujet sur mon ascenseur + stockage ;-)
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 20:55
par ramasoft
Et de mon côté j'ai trouvé où placer un ascenseur de 1m50 de long avec une voie d'accès mais qui descendrait à - 10cm sous le plateau actuel comme j'avais fait pour la boucle "un train chasse l'autre" et de là me donnerait accès à 2 (ou 3 ...) niveaux inférieurs pour des garages sous le plan de voie actuel avec une boucle de retournement à chaque niveau pour revenir machine en tête vers l'ascenseur.
Ça ferait au final un peu comme sur les vidéos de DB TR1 sur YouTube: viewtopic.php?p=54472#p54472
Donc on devrait être 3 à se lancer dans l'aventure...
Chez moi, le challenge c'est que je ne peux pas déborder en largeur sur la taille actuelle des plateaux, il faut être strictement en dessous.
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 20:58
par herwat
patrice_b a écrit : ↑26 avr. 2025, 18:44
Allez Hervé, on t'attend dans le sujet sur mon ascenseur + stockage ;-)
J'arrive, j'arrive !
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 21:00
par herwat
ramasoft a écrit : ↑26 avr. 2025, 20:55
Et de mon côté j'ai trouvé où placer un ascenseur de 1m50 de long avec une voie d'accès mais qui descendrait à - 10cm sous le plateau actuel comme j'avais fait pour la boucle "un train chasse l'autre" et de là me donnerait accès à 2 (ou 3 ...) niveaux inférieurs pour des garages sous le plan de voie actuel avec une boucle de retournement à chaque niveau pour revenir machine en tête vers l'ascenseur.
Ça ferait au final un peu comme sur les vidéos de DB TR1 sur YouTube: viewtopic.php?p=54472#p54472
Donc on devrait être 3 à se lancer dans l'aventure...
Chez moi, le challenge c'est que je ne peux pas déborder en largeur sur la taille actuelle des plateaux, il faut être strictement en dessous.
Alors on va faire du travail à la chaine . . . c'est le cas de la dire !
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 21:14
par TrainDoly
likiki a écrit : ↑26 avr. 2025, 17:36
Etape suivante ajout d'un encodeur rotatif, création de menu interactif.
Pour ta culture personnelle,
"encoder" = Anglais
"codeur" = Français
"encodeur" = Barbarisme
Alors mes questions...
Tu veux que le codeur serve à positionner ton ascenseur?
Le programme de comptage des pas ne te semble pas suffisant?
Tu veux utiliser les deux?
Tu penses changer tes NEMA17 simples par des NEMA17 pré-équipés de codeurs?
Il existe des codeurs que tu peux clipser sur les NEMA?
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 21:15
par ramasoft
Moi aussi je dis toujours encodeur...
Sinon j'ai une question aussi: le moteur pas à pas est assez puissant pour lever un plateau d'1,50m avec une rame dessus ?
ramasoft a écrit : ↑26 avr. 2025, 21:15
Moi aussi je dis toujours encodeur...
Sinon j'ai une question aussi: le moteur pas à pas est assez puissant pour lever un plateau d'1,50m avec une rame dessus ?
J'ai fait des essais pour les miens .
J'ai un moteur à chaque extrémité de l'ascenseur . Il fait à peu prés 1.30 m et j'ai soulevais sans problème prés de 5 Kg ! ! !
J'ai donc continué tranquillement !
Re: Comment faire l'automatisme d'un ascenseur
Posté : 26 avr. 2025, 21:45
par herwat
Petite question à Christian :
ton Wemos D1 Mini , il accepte toutes les bibliothèques arduino ?
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 08:46
par likiki
Pour le moment oui.
L'IDE signale un potentiel problème avec la bibliothèque I2C mais cela fonctionne.
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 10:52
par herwat
Oui, on aura surement des surprises, mais bon . . .
Je suppose qu'il fonctionne en 3.3v ?
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 11:32
par patrice_b
ramasoft a écrit : ↑26 avr. 2025, 20:55
Et de mon côté j'ai trouvé où placer un ascenseur de 1m50 de long avec une voie d'accès mais qui descendrait à - 10cm sous le plateau actuel comme j'avais fait pour la boucle "un train chasse l'autre" et de là me donnerait accès à 2 (ou 3 ...) niveaux inférieurs pour des garages sous le plan de voie actuel avec une boucle de retournement à chaque niveau pour revenir machine en tête vers l'ascenseur.
Ça ferait au final un peu comme sur les vidéos de DB TR1 sur YouTube: viewtopic.php?p=54472#p54472
Donc on devrait être 3 à se lancer dans l'aventure...
Chez moi, le challenge c'est que je ne peux pas déborder en largeur sur la taille actuelle des plateaux, il faut être strictement en dessous.
Ahhh bravo Patrick, tu as bien cogité alors !
On va monter une boite de fabrication d'ascenseur HO
(Ce sera moi le moins doué, ça c'est sur )
Sacré réseau DB TR1, je l'avais vu, impressionnant.
ramasoft a écrit : ↑26 avr. 2025, 21:15
Moi aussi je dis toujours encodeur...
Sinon j'ai une question aussi: le moteur pas à pas est assez puissant pour lever un plateau d'1,50m avec une rame dessus ?
J'ai fait des essais pour les miens .
J'ai un moteur à chaque extrémité de l'ascenseur . Il fait à peu prés 1.30 m et j'ai soulevais sans problème prés de 5 Kg ! ! !
J'ai donc continué tranquillement !
Whaou, et avec 2 moteurs, pas trop de complication de décalage ?
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 12:06
par likiki
herwat a écrit : ↑27 avr. 2025, 10:52
Oui, on aura surement des surprises, mais bon . . .
Je suppose qu'il fonctionne en 3.3v ?
Oui, mais il y a une entrée USB C (Un chargeur de téléphone + le câble et op).
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 12:17
par likiki
patrice_b a écrit : ↑27 avr. 2025, 11:32
On va monter une boite de fabrication d'ascenseur HO
(Ce sera moi le moins doué, ça c'est sur )
Je retiens l'idée.
Re: Comment faire l'automatisme d'un ascenseur
Posté : 27 avr. 2025, 12:45
par likiki
Ont continue avec l'ajout d'un encodeur rotatif et la création de menus ...
/*
***************************************************
****** Ascenseur avec un moteur pas à pas *******
****** *******
****** Programme V 3.0 *******
****** Du 22/02/2025 *******
****** Par C.ARFEL *******
****** *******
****** Carte Wemos D1 Mini *******
****** *******
****** Version 1.0 *******
****** Mise a quai manuelle *******
****** Afficheur lcd 16 x 2 I2C *******
****** RC + 5 sous sol *******
****** Menu par encodeur *******
****** *******
****** *******
****** Liste des bornes utilisées *******
****** *******
****** D0 Capteur infrarouge *******
****** D1 I2C écran *******
****** D2 I2C écran *******
****** D3 DIR commande de direction moteur *******
****** D4 STEP commande nb pas moteur *******
****** D5 SW encodeur *******
****** D6 DT encodeur *******
****** D7 Clic encodeur *******
****** D8 Arrêt d'urgence + FC total *******
****** RST (reset carte) *******
****** *******
****** Le croquis utilise ***** octets (**%)*******
****** de l'espace de stockage de *******
****** programmes. Le maximum est de *******
****** ****** octets. *******
****** *******
****** Les variables globales utilisent *******
****** **** octets (**%) de mémoire *******
****** dynamique, ce qui laisse **** *******
****** octets pour les variables locales. *******
****** Le maximum est de **** octets. *******
****** *******
****** *******
***************************************************
. Variables and constants in RAM (global, static), used 29192 / 80192 bytes (36%)
║ SEGMENT BYTES DESCRIPTION
╠══ DATA 1536 initialized variables
╠══ RODATA 1240 constants
╚══ BSS 26416 zeroed variables
. Instruction RAM (IRAM_ATTR, ICACHE_RAM_ATTR), used 60995 / 65536 bytes (93%)
║ SEGMENT BYTES DESCRIPTION
╠══ ICACHE 32768 reserved space for flash instruction cache
╚══ IRAM 28227 code in IRAM
. Code in flash (default, ICACHE_FLASH_ATTR), used 245364 / 1048576 bytes (23%)
║ SEGMENT BYTES DESCRIPTION
╚══ IROM 245364 code in flash
*/
#include <AccelStepper.h> // Bibliothéque moteur pas a pas
const byte pin_DIR = D3; // Borne contrôle pour TMC2209
const byte pin_STEP = D4; // Borne contrôle pour TMC2209
#include <Wire.h>
#include <LiquidCrystal_I2C.h> // Bibliothéque ecran protocole I2C
LiquidCrystal_I2C lcd(0x27, 16, 2); // 0x27 ou 0x3F déclaration adresse du lcd
#include "RotaryEncoder.h" // Appel de la bibliothéque pour encodeur
#define STEPSS 1 // Nombre par pas d'encodeur
#define POSMIN -5 // Position MINI de l'encodeur
#define POSMAX 4 // Position MAX de l'encodeur
#define BPE D5 // Borne SW encodeur (bouton)
RotaryEncoder encoder(D6, D7); // Borne de l'encodeur (DT, CLK)
AccelStepper stepper(AccelStepper::DRIVER, pin_STEP, pin_DIR); // création objet Stepper
int Pos0SS = 0; // Crans moteur pour la position plateau niveau reseau.
int Pos1SS = 10000; // Crans moteur pour la position plateau 1er sous sol
int Pos2SS = 20000; // Crans moteur pour la position plateau 2ème sous sol
int Pos3SS = 30000; // Crans moteur pour la position plateau 3ème sous sol
int Pos4SS = 40000; // Crans moteur pour la position plateau 4ème sous sol
int Pos5SS = 50000; // Crans moteur pour la position plateau 5ème sous sol
int Init = 0; // Variable pour l'initialisation
int Ebpe = 10; // Variable bouton encodeur
int lastPos, newPos; // Variable encodeur
void setup()
{
lcd.init(); // Initialisation de l'afficheur
lcd.backlight(); // Allume l'ecran
lcd.clear(); // Efface l'ecran
lcd.setCursor (0,0); // place le curseur sur la ligne 0 a gauche
lcd.print ("*Initialisation*"); // Affichage sur le lcd
lcd.setCursor (0,1); // passe a la ligne suivante
lcd.print ("* Programme *"); // affichage sur le lcd
stepper.setMaxSpeed(8000.0); // Vitesse max moteur
stepper.setAcceleration(500.0); // distance accélération / décélération
encoder.setPosition(10 / STEPSS); // Position initiale encodeur
pinMode(BPE, INPUT); // Initialisation du clic encodeur rotatif
}
/*
************************
* Fin de la zone SETUP *
************************
*/
/*
****************************
* Séquence initialisation *
****************************
*/
void Initialisation() { // Module initialisation du plateau Recherche du FC
// Il ne se passe rien d'important ici pour le moment a ce stade du programme.
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau reseau. ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (200);
Init = 1; // Informe que l'initialisation a été faite pour ne pas y revenir
}
void loop()
{
if (Init <1) { // Si 1er passage executerligne suivante sinon passer
Initialisation(); // Vas executer le bloc "initialisation"
}
/*
********************************
* Début de la zone des appels *
********************************
*/
/*
****************************************
* Menu selection par encodeur rotatif *
****************************************
*/
// ________________ Zone lecture encodeur rotatif _______________
encoder.tick();
newPos = encoder.getPosition() * STEPSS;
if (newPos < POSMIN) {
encoder.setPosition(POSMIN / STEPSS);
newPos = POSMIN;
}
else if (newPos > POSMAX) {
encoder.setPosition(POSMAX / STEPSS);
newPos = POSMAX;
}
if (lastPos != newPos) {
if (newPos <= 0){ // valable de -5 a 0
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("Choix => ");lcd.print(newPos);lcd.print(" ");
delay (10);
lastPos = newPos;
}
if (newPos >= 1){ // Valable si 1
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("Choix => ");lcd.print("Reglage");
delay (10);
lastPos = newPos;
}
}
if (digitalRead(BPE) == LOW) { // Control si Bouton encodeur actionné
Ebpe = newPos;
delay(500); // Tempo de pause pour éviter la redondance du clic
}
/*
*****************************
* Appel au rez de chaussée *
*****************************
*/
if (Ebpe == 0) { // Action si choix 0 RC
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos0SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau reseau. ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
/*
**************************
* Appel au 1er sous sol *
**************************
*/
if (Ebpe == -1) { // Action si choix -1
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos1SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau -1 ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
/*
***************************
* Appel au 2ème sous sol *
***************************
*/
if (Ebpe == -2 ) {
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos2SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau -2 ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
/*
***************************
* Appel au 3ème sous sol *
***************************
*/
if (Ebpe == -3 ) {
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos3SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau -3 ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
/*
***************************
* Appel au 4ème sous sol *
***************************
*/
if (Ebpe == -4 ) {
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos4SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau -4 ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
/*
***************************
* Appel au 5ème sous sol *
***************************
*/
if (Ebpe == -5 ) {
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print ("** Plateforme **");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("* En mouvement *");
delay (10);
stepper.runToNewPosition(Pos5SS);
delay(1000) ;
Ebpe = 10;
lcd.clear (); // Efface l'ecran
delay (100);
lcd.setCursor (0,0);
lcd.print (" Niveau -5 ");
delay(10);
lcd.setCursor(0,1); // place le curseur ligne suivante
lcd.print ("** En attente **");
delay (1000);
}
}
La vidéo qui vas bien avec :
Etape suivante :
Régler finement les arrêt et enregistrement (volatil dans un 1er temps) des novelles positions.
Modification du programme de sélections qui passera de 170 lignes de codes a .... 40 lignes.