update Code
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the usual convention is to give header files names that end with `.h'.
|
||||
It is most portable to use only letters, digits, dashes, and underscores in
|
||||
header file names, and at most one dot.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
@@ -0,0 +1,46 @@
|
||||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into executable file.
|
||||
|
||||
The source code of each library should be placed in a an own separate directory
|
||||
("lib/your_library_name/[here are source files]").
|
||||
|
||||
For example, see a structure of the following two libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
and a contents of `src/main.c`:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
@@ -0,0 +1,30 @@
|
||||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:PCB-v01a]
|
||||
platform = espressif32
|
||||
board = featheresp32
|
||||
; change microcontroller to ESP32M4
|
||||
board_build.mcu = esp32
|
||||
; change MCU frequency
|
||||
board_build.f_cpu = 240000000L
|
||||
framework = arduino
|
||||
;upload_protocol = esp-prog
|
||||
|
||||
monitor_speed = 115200
|
||||
monitor_filters = esp32_exception_decoder
|
||||
; debug_tool = esp-prog
|
||||
; debug_init_break = tbreak setup
|
||||
; build_type=debug
|
||||
lib_deps =
|
||||
https://github.com/someweisguy/esp_dmx
|
||||
https://github.com/madhephaestus/ESP32Encoder
|
||||
pkerspe/ESP-FlexyStepper @ ^1.4.3
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/// ********************** PIN ASSIGNEMENTS **********************
|
||||
// DMX
|
||||
const int tx_pin = 16; // define the IO pin the DMX TX pin is connected to
|
||||
const int rx_pin = 17; // define the IO pin the DMX RX pin is connected to
|
||||
const int rts_pin = 4; // define the IO pin the DMX RTS pin is connected to
|
||||
|
||||
// capteur BCD pour adressage DMX
|
||||
#define q1 21 // define the IO pin for the thumbwheel '1' is connected to
|
||||
#define q2 19 // define the IO pin for the thumbwheel '2' is connected to
|
||||
#define q4 18 // define the IO pin for the thumbwheel '4' is connected to
|
||||
#define q8 5 // define the IO pin for the thumbwheel '8' is connected to
|
||||
|
||||
// driver moteur
|
||||
const int MOTOR_ENABLE_PIN = 27; // define the IO pin the motor enable pin is connected to
|
||||
const int MOTOR_STEP_PIN = 26; // define the IO pin the motor step pin is connected to
|
||||
const int MOTOR_DIRECTION_PIN = 25; // define the IO pin the motor direction pin is connected to
|
||||
#ifndef dev_mode
|
||||
const int EMERGENCY_STOP_PIN = 13; // define the IO pin the emergency stop switch is connected to
|
||||
#endif
|
||||
const int HOME_SWITCH_PIN = 35; // define the IO pin where the home switches are connected to (switches in series in normally closed setup against ground)
|
||||
const int LIMIT_SWITCH_PIN = 34; // define the IO pin where the limit switches are connected to (switches in series in normally closed setup against ground)
|
||||
|
||||
// encoder moteur pas à pas
|
||||
#define EB_plus 22 // define the IO pin for the encoder B is connected to
|
||||
#define EA_plus 23 // define the IO pin for the encoder A is connected to
|
||||
|
||||
// potentiomètre pour le réglage des fins de course
|
||||
#define home_set_pot 36 // define the IO pin for the home set potentiometer is connected to
|
||||
#define limit_set_pot 39 // define the IO pin for the limit set potentiometer is connected to
|
||||
#define divider_pot 1 // define the divider potentiometer value
|
||||
|
||||
|
||||
@@ -0,0 +1,143 @@
|
||||
#define nb_dmx_channel 2 // nombre de canaux DMX utilisés
|
||||
#define pos_array 0 // position de la position dans le tableau DMX_data
|
||||
#define speed_array 1 // position de la vitesse dans le tableau DMX_data
|
||||
|
||||
int DMX_start_channel; // numéro de la première adresse DMX
|
||||
int pos_channel; // numéro de l'adresse DMX de la position
|
||||
int speed_channel; // numéro de l'adresse DMX de la vitesse
|
||||
const dmx_port_t dmx_num = DMX_NUM_2; // numéro du port DMX
|
||||
byte data[DMX_PACKET_SIZE]; // tableau de données DMX
|
||||
|
||||
bool dmxIsConnected = false; // état de la connexion DMX
|
||||
unsigned long lastUpdate = millis(); // temps de la dernière mise à jour des données DMX
|
||||
uint8_t DMX_data[nb_dmx_channel + 1]; // tableau de données DMX
|
||||
uint8_t DMX_data_old[nb_dmx_channel + 1]; // tableau de données DMX précédentes
|
||||
bool dataChanged[nb_dmx_channel + 1]; // tableau de drapeau pour donnée DMX ayant changées
|
||||
unsigned long last_connected_Time = 0; // temps de la dernière connexion DMX
|
||||
unsigned long last_disconnected_Time = 0; // temps de la dernière déconnexion DMX
|
||||
|
||||
#define DMX_Connected_Time 1000 // temps en ms entre chaque vérification de la connexion DMX
|
||||
#define DMX_Read_Time 200 // temps en ms entre chaque mise à jour des données DMX
|
||||
#define dmx_debounce_try 0 // nombre de boucle pour le debounce DMX afin d'éviter les valeurs de 0 ou 255 erronées
|
||||
int dmx_count[nb_dmx_channel + 1]; // compteur de boucle pour le debounce DMX afin d'éviter les valeurs de 0 ou 255 erronées
|
||||
|
||||
// fonction
|
||||
int readSwitch(); // fonction pour lire le codeur d'adresse DMX
|
||||
void reset_dmx_counter(); // fonction pour réinitialiser le compteur de boucle pour le debounce DMX afin d'éviter les valeurs de 0 ou 255 erronées
|
||||
void receiveDMX(); // fonction pour recevoir les données DMX
|
||||
|
||||
int readSwitch() // fonction pour lire le codeur d'adresse DMX
|
||||
{
|
||||
int total = 0;
|
||||
if (digitalRead(q1) == HIGH)
|
||||
{
|
||||
total += 1;
|
||||
}
|
||||
if (digitalRead(q2) == HIGH)
|
||||
{
|
||||
total += 2;
|
||||
}
|
||||
if (digitalRead(q4) == HIGH)
|
||||
{
|
||||
total += 4;
|
||||
}
|
||||
if (digitalRead(q8) == HIGH)
|
||||
{
|
||||
total += 8;
|
||||
}
|
||||
total = ((total + 1) * 2) - 1; // correction battarde de l'adresse DMX
|
||||
|
||||
return total;
|
||||
}
|
||||
|
||||
void reset_dmx_counter() // fonction pour réinitialiser le compteur de boucle pour le debounce DMX afin d'éviter les valeurs de 0 ou 255 erronées
|
||||
{
|
||||
for (int i = 0; i < nb_dmx_channel + 1; i++)
|
||||
{
|
||||
dmx_count[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void receiveDMX() // fonction pour recevoir les données DMX
|
||||
{
|
||||
dmx_packet_t packet;
|
||||
if (dmx_receive(dmx_num, &packet, DMX_TIMEOUT_TICK))
|
||||
{
|
||||
|
||||
if (!packet.err)
|
||||
{
|
||||
if (!dmxIsConnected)
|
||||
{
|
||||
Serial.println("DMX is connected!");
|
||||
last_connected_Time = millis();
|
||||
dmxIsConnected = true;
|
||||
}
|
||||
dmx_read(dmx_num, data, packet.size);
|
||||
// mise à jour des données DMX si elles ont changé et si le temps écoulé depuis la dernière mise à jour est supérieur à DMX_Read_Time
|
||||
if (millis() - lastUpdate > DMX_Read_Time)
|
||||
{
|
||||
lastUpdate = millis(); // réinitialisation du temps de la dernière mise à jour des données DMX
|
||||
last_connected_Time = millis(); // réinitialisation du temps de la dernière connexion DMX
|
||||
// mise à jour de la position
|
||||
if (DMX_data[pos_array] != data[pos_channel])
|
||||
{
|
||||
if (DMX_data[pos_array] == 0 || DMX_data[pos_array] == 255)
|
||||
{
|
||||
dmx_count[pos_array]++;
|
||||
if (dmx_count[pos_array] > dmx_debounce_try)
|
||||
{
|
||||
DMX_data[pos_array] = data[pos_channel];
|
||||
reset_dmx_counter();
|
||||
(dataChanged[pos_array]) = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMX_data[pos_array] = data[pos_channel];
|
||||
reset_dmx_counter();
|
||||
(dataChanged[pos_array]) = true;
|
||||
}
|
||||
}
|
||||
|
||||
// mise à jour de la vitesse
|
||||
if (DMX_data[speed_array] != data[speed_channel])
|
||||
{
|
||||
if (DMX_data[speed_array] == 0 || DMX_data[speed_array] == 255)
|
||||
{
|
||||
dmx_count[speed_array]++;
|
||||
if (dmx_count[speed_array] > dmx_debounce_try)
|
||||
{
|
||||
DMX_data[speed_array] = data[speed_channel];
|
||||
reset_dmx_counter();
|
||||
(dataChanged[speed_array]) = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
DMX_data[speed_array] = data[speed_channel];
|
||||
reset_dmx_counter();
|
||||
(dataChanged[speed_array]) = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
reset_dmx_counter();
|
||||
Serial.println("A DMX error occurred.");
|
||||
}
|
||||
}
|
||||
else if (dmxIsConnected)
|
||||
{
|
||||
reset_dmx_counter();
|
||||
// Serial.println("DMX was disconnected."); // affichage de la déconnexion DMX
|
||||
if (millis() - last_connected_Time > DMX_Connected_Time)
|
||||
{
|
||||
dmxIsConnected = false;
|
||||
last_disconnected_Time = millis(); // réinitialisation du temps de la dernière déconnexion DMX
|
||||
Serial.println("DMX was halted."); // affichage de la déconnexion DMX
|
||||
// emergencyStop = true; // arrêt du moteur en cas de déconnexion DMX
|
||||
// emercency_stop_timer = millis(); // réinitialisation du timer d'arrêt d'urgence
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
|
||||
// ********************** variables for software debouncing of the limit switches **********************
|
||||
#define switch_active 1 // active low switch configuration (NO connection with internal pull up) or HIGH for active high switch configuration (NC connection with internal pull up)
|
||||
|
||||
volatile unsigned long lastDebounceTime = 0; // the last time the limit switch input pin was toggled
|
||||
volatile unsigned long debounceDelay = 100; // the minimum delay in milliseconds to check for bouncing of the switch. Increase this slighlty if you switches tend to bounce a lot
|
||||
bool buttonStateChangeDetected = false; // flag to indicate that the button state has changed
|
||||
volatile byte limitSwitchState = !switch_active; // the current reading from the limit switch input pin
|
||||
byte ConfirmedLimitSwitchState = !switch_active; // the last confirmed reading from the limit switch input pin
|
||||
volatile byte homeSwitchState = !switch_active; // the current reading from the home switch input pin
|
||||
byte ConfirmedHomeSwitchState = !switch_active; // the last confirmed reading from the home switch input pin
|
||||
|
||||
volatile int home_steps; // nombre de pas pour bien positionner le moteur à la position de départ
|
||||
volatile int limit_steps; // nombre de pas pour bien positionner le moteur à la position de fin
|
||||
|
||||
void homeReachedCallback(); // callback function that will be called when the home position is reached
|
||||
void limitReachedCallback(); // callback function that will be called when the limit position is reached
|
||||
void IRAM_ATTR limitSwitchHandler(); // interrupt handler for the limit switch
|
||||
void IRAM_ATTR homeSwitchHandler(); // interrupt handler for the home switch
|
||||
void limit_sw_check(); // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
void home_sw_check(); // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
|
||||
void homeReachedCallback() // callback function that will be called when the home position is reached
|
||||
{
|
||||
Serial.println("Home reached");
|
||||
}
|
||||
|
||||
void limitReachedCallback() // callback function that will be called when the limit position is reached
|
||||
{
|
||||
Serial.println("Limit reached");
|
||||
}
|
||||
|
||||
void IRAM_ATTR limitSwitchHandler() // interrupt handler for the limit switch
|
||||
{
|
||||
lastDebounceTime = millis();
|
||||
limitSwitchState = digitalRead(LIMIT_SWITCH_PIN);
|
||||
}
|
||||
|
||||
void IRAM_ATTR homeSwitchHandler() // interrupt handler for the home switch
|
||||
{
|
||||
lastDebounceTime = millis();
|
||||
homeSwitchState = digitalRead(HOME_SWITCH_PIN);
|
||||
}
|
||||
|
||||
void limit_sw_check() // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
{
|
||||
|
||||
if (limitSwitchState != ConfirmedLimitSwitchState && (millis() - lastDebounceTime) > debounceDelay)
|
||||
{
|
||||
ConfirmedLimitSwitchState = limitSwitchState;
|
||||
Serial.printf("Limit switch change detected. New state is %i\n", limitSwitchState);
|
||||
Serial.printf("Limit setting is %i\n", limit_steps);
|
||||
buttonStateChangeDetected = true;
|
||||
}
|
||||
}
|
||||
|
||||
void home_sw_check() // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
{
|
||||
if (homeSwitchState != ConfirmedHomeSwitchState && (millis() - lastDebounceTime) > debounceDelay)
|
||||
{
|
||||
|
||||
ConfirmedHomeSwitchState = homeSwitchState;
|
||||
Serial.printf("Home switch change detected. New state is %i\n", homeSwitchState);
|
||||
Serial.printf("Home setting is %i\n", home_steps);
|
||||
buttonStateChangeDetected = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,169 @@
|
||||
|
||||
/*
|
||||
controle de moteur pas à pas selon commande DMX
|
||||
|
||||
code par Clément SAILLANT pour Hémisphère - 2023
|
||||
[email protected]
|
||||
0625334420
|
||||
|
||||
Un canal DMX est utilisé pour la commande de la position du moteur
|
||||
Un autre canal DMX est utilisé pour la commande de la vitesse du moteur
|
||||
Une fonction affine est utilisée pour convertir la valeur DMX en position ou vitesse
|
||||
La position et la vitesse sont stockées dans des variables globales
|
||||
Une fonction est utilisée pour la sécurité si un obstacle est détecté par la perte de pas du moteur
|
||||
|
||||
moteur : 34HS59-6004D-E1000
|
||||
Angle de pas: 1.8 deg
|
||||
Résolution de l'encodeur: 1000PPR(4000CPR)
|
||||
https://www.omc-stepperonline.com/download/34HS59-6004D-E1000_Torque_Curve.pdf
|
||||
https://www.omc-stepperonline.com/download/34HS59-6004D-E1000.pdf
|
||||
|
||||
Controleur CL86T V4.0
|
||||
https://www.omc-stepperonline.com/index.php?route=product/product/get_file&file=389/CL86T%20(V4.0).pdf
|
||||
*/
|
||||
|
||||
#include "PIN_mapping.h" // fichier contenant les variables globales et le mapping des pins
|
||||
bool emergencyStop = false; // variable pour stocker l'état de l'arrêt d'urgence
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <esp_dmx.h>
|
||||
#include <ESP_FlexyStepper.h> // librairie pour le controle des moteurs pas à pas
|
||||
#include <ESP32Encoder.h> // librairie pour le controle des encodeurs
|
||||
|
||||
ESP_FlexyStepper stepper; // création de l'ojet motor
|
||||
ESP32Encoder encoder; // création de l'objet encoder
|
||||
|
||||
#include "limit.h" // fichier contenant les fonctions de limites
|
||||
#include "dmx_data.h" // fichier contenant les fonctions dmx
|
||||
#include "moving.h" // fichier contenant les fonctions de mouvement
|
||||
#include "security.h" // fichier contenant les fonctions de sécurité type emergency stop
|
||||
|
||||
void setup()
|
||||
{
|
||||
// delay(1000);
|
||||
Serial.begin(115200);
|
||||
Serial.println("started");
|
||||
|
||||
dmx_set_pin(dmx_num, tx_pin, rx_pin, rts_pin);
|
||||
dmx_driver_install(dmx_num, DMX_DEFAULT_INTR_FLAGS);
|
||||
|
||||
// configuration encoder pour suivre la position du moteur et la perte de pas
|
||||
encoder.attachHalfQuad(EB_plus, EA_plus);
|
||||
encoder.setCount(0);
|
||||
|
||||
// configuration ENABLE motor
|
||||
pinMode(MOTOR_ENABLE_PIN, OUTPUT);
|
||||
|
||||
// configuration BCD Coder
|
||||
pinMode(q1, INPUT); // thumbwheel '1'
|
||||
pinMode(q2, INPUT); // thumbwheel '2'
|
||||
pinMode(q4, INPUT); // thumbwheel '4'
|
||||
pinMode(q8, INPUT); // thumbwheel '8'
|
||||
|
||||
/*
|
||||
// attach an interrupt to the IO pin of the ermegency stop switch and specify the handler function
|
||||
pinMode(EMERGENCY_STOP_PIN, INPUT_PULLUP);
|
||||
attachInterrupt(digitalPinToInterrupt(EMERGENCY_STOP_PIN), emergencySwitchHandler, RISING);
|
||||
*/
|
||||
|
||||
// lecture des potentiomètres pour définir les offset de pas a ajouter aux positions home et limit
|
||||
limit_steps = map((analogRead(limit_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
home_steps = map((analogRead(home_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
|
||||
// attach an interrupt to the IO pin of the home switch and specify the handler function
|
||||
attachInterrupt(digitalPinToInterrupt(HOME_SWITCH_PIN), homeSwitchHandler, CHANGE);
|
||||
stepper.registerHomeReachedCallback(homeReachedCallback);
|
||||
|
||||
// attach an interrupt to the IO pin of the limit switch and specify the handler function
|
||||
attachInterrupt(digitalPinToInterrupt(LIMIT_SWITCH_PIN), limitSwitchHandler, CHANGE);
|
||||
stepper.registerLimitReachedCallback(limitReachedCallback);
|
||||
|
||||
// connect and configure the stepper motor to its IO pins
|
||||
stepper.connectToPins(MOTOR_STEP_PIN, MOTOR_DIRECTION_PIN);
|
||||
// set the speed and acceleration rates for the stepper motor
|
||||
stepper.setSpeedInStepsPerSecond(SPEED_IN_STEPS_PER_SECOND);
|
||||
stepper.setAccelerationInStepsPerSecondPerSecond(ACCELERATION_IN_STEPS_PER_SECOND);
|
||||
stepper.setDecelerationInStepsPerSecondPerSecond(DECELERATION_IN_STEPS_PER_SECOND);
|
||||
stepper.setStepsPerRevolution(STEP_PER_REV);
|
||||
stepper.registerTargetPositionReachedCallback(targetPositionReachedCallback);
|
||||
|
||||
// start the stepper instance as a service in the "background" as a separate task
|
||||
stepper.startAsService(1); // core 1 sinon bug avec le dmx et déplacement aléatoire du moteur
|
||||
|
||||
init_range(); // set home and limit position of the motor
|
||||
|
||||
DMX_start_channel = readSwitch(); // lecture de la position du codeurs BCD pour définir le canal DMX de départ
|
||||
// DMX_start_channel = 2; // pour test avec adresse fixe
|
||||
pos_channel = DMX_start_channel;
|
||||
speed_channel = DMX_start_channel + 1;
|
||||
|
||||
Serial.println("----------------------------------------");
|
||||
Serial.printf("number of tasks is %i\n", uxTaskGetNumberOfTasks());
|
||||
Serial.printf("home position is %i\n", min_steps);
|
||||
Serial.printf("limit position is %i\n", max_steps);
|
||||
Serial.printf("Limit setting is %i\n", limit_steps);
|
||||
Serial.printf("Home setting is %i\n", home_steps);
|
||||
Serial.printf("DMX start channel is %i\n", DMX_start_channel);
|
||||
Serial.printf("DMX position channel is %i\n", pos_channel);
|
||||
Serial.printf("DMX speed channel is %i\n", speed_channel);
|
||||
Serial.println("----------------------------------------");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
receiveDMX(); // reception des données DMX
|
||||
|
||||
// mise à jour de la vitesse du moteur si la valeur DMX a changée
|
||||
if (dataChanged[speed_array] == true)
|
||||
{
|
||||
dataChanged[speed_array] = false;
|
||||
speed_map(); // fonction pour convertir la valeur DMX en vitesse/acceleration/deceleration
|
||||
}
|
||||
|
||||
// mise à jour de la position du moteur si la valeur DMX a changée
|
||||
// if (dataChanged[pos_array] == true && emergencyStop == false && digitalRead(MOTOR_ENABLE_PIN) == LOW)
|
||||
if (dataChanged[pos_array] == true)
|
||||
{
|
||||
// stepper.setTargetPositionToStop();
|
||||
dataChanged[pos_array] = false;
|
||||
pos_in_step = map(DMX_data[pos_array], 255, 0, min_steps, max_steps);
|
||||
// pos_map(); // fonction pour convertir la valeur DMX en position
|
||||
stepper.setTargetPositionInSteps(pos_in_step);
|
||||
DMX_data_old[pos_array] = DMX_data[pos_array];
|
||||
last_dmx_change_pos = millis();
|
||||
Serial.printf("dmx pos to step => %ld\n", pos_in_step);
|
||||
}
|
||||
// gestion de la position du moteur si la valeur DMX n'a pas changée mais que le moteur n'est pas à la position demandée
|
||||
if (millis() - last_dmx_change_pos > 1000)
|
||||
{
|
||||
int codeur_pos = map(encoder.getCount(), min_count, max_count, min_steps, max_steps);
|
||||
if (pos_in_step <= min_steps && ConfirmedHomeSwitchState != switch_active && stepper.getDirectionOfMotion() == 0)
|
||||
{
|
||||
Serial.println("!!!!!!!!!!!!! home not reached");
|
||||
Serial.printf("codeur pos => %i\n", codeur_pos);
|
||||
// stepper.setTargetPositionInSteps(min_steps - codeur_pos); // home_steps
|
||||
int step_add = nb_microstep * 2;
|
||||
stepper.setTargetPositionRelativeInSteps(-step_add);
|
||||
delay(100);
|
||||
}
|
||||
else if (pos_in_step >= max_steps && ConfirmedLimitSwitchState != switch_active && stepper.getDirectionOfMotion() == 0)
|
||||
{
|
||||
Serial.println("!!!!!!!!!!!!! limit not reached");
|
||||
Serial.printf("codeur pos => %i\n", codeur_pos);
|
||||
// stepper.setTargetPositionInSteps(max_steps + (max_steps - codeur_pos)); // limit_steps
|
||||
int step_add = nb_microstep * 2;
|
||||
stepper.setTargetPositionRelativeInSteps(step_add);
|
||||
delay(100);
|
||||
}
|
||||
else if (abs(codeur_pos - pos_in_step) > 100 && stepper.getDirectionOfMotion() == 0)
|
||||
{
|
||||
Serial.println("!!!!!!!!!!!!! Not in position");
|
||||
Serial.printf("codeur pos => %i\n", codeur_pos);
|
||||
Serial.printf("pos in step => %i\n", pos_in_step);
|
||||
stepper.setTargetPositionInSteps(pos_in_step);
|
||||
}
|
||||
}
|
||||
// motor_follower(emergency_stop_loss_step); // fonction pour suivre la position du moteur et la perte de pas
|
||||
emergency_check(); // fonction pour la sécurité si un obstacle est détecté par la perte de pas du moteur
|
||||
limit_check(); // fonction pour la sécurité si un obstacle est détecté par le bouton poussoir
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
|
||||
#define nb_microstep 8 // nombre de microstep configuré sur le driver moteur
|
||||
#define STEP_PER_REV_MOTOR 200 // nombre de pas par tour du moteur
|
||||
#define CPR_ENCODER 4000 // nombre de pas par tour du codeur optique
|
||||
/*
|
||||
Nb SW1 SW2 SW3 SW4
|
||||
1 200 on on on on
|
||||
4 800 off on on on
|
||||
8 1600 on off on on
|
||||
16 3200 off off on on
|
||||
32 6400 on on off on
|
||||
64 12800 off on off on
|
||||
128 25600 on off off on
|
||||
256 51200 off off off on
|
||||
5 1000 on on on off
|
||||
10 2000 off on on off
|
||||
20 4000 on off on off
|
||||
25 5000 off off on off
|
||||
40 8000 on on off off
|
||||
50 10000 off on off off
|
||||
100 20000 on off off off
|
||||
200 40000 off off off off
|
||||
*/
|
||||
#define SECOND_PER_REV 2 // nombre de seconde pour faire un tour
|
||||
const int STEP_PER_REV = nb_microstep * STEP_PER_REV_MOTOR; // nombre de pas par tour du moteur
|
||||
const int MIN_SPEED = 1; // vitesse minimum du moteur
|
||||
const int MAX_SPEED = ((STEP_PER_REV / 2) / SECOND_PER_REV) * nb_microstep; // vitesse maximum du moteur (1/2 révolution par SECOND_PER_REV seconde)
|
||||
//const int MAX_SPEED = ((STEP_PER_REV / 2) / SECOND_PER_REV) * nb_microstep; // vitesse maximum du moteur (1/2 révolution par SECOND_PER_REV seconde)
|
||||
|
||||
const int SPEED_IN_STEPS_PER_SECOND = STEP_PER_REV; // vitesse initiale de déplacement du moteur = 1/2 de la vitesse maximum
|
||||
const int ACCELERATION_IN_STEPS_PER_SECOND = nb_microstep * 2; // accélération initiale du moteur
|
||||
const int DECELERATION_IN_STEPS_PER_SECOND = nb_microstep; // décélération initiale du moteur
|
||||
int ACC_DEC_REMOVE_STEP = ACCELERATION_IN_STEPS_PER_SECOND + DECELERATION_IN_STEPS_PER_SECOND; // nombre de pas à enlever à la position pour l'accélération et la décélération ?
|
||||
int min_steps = 0; // position de départ du moteur
|
||||
int max_steps = STEP_PER_REV / 2; // position de fin du moteur (1600 en 16 microstep) (400 en 1 microstep)
|
||||
int pos_in_step = max_steps / 2; // position du moteur en pas pour le mappage de la position
|
||||
|
||||
int min_count = 0; // valeur minimum du compteur du codeur optique
|
||||
int max_count = CPR_ENCODER / 4; // valeur maximum du compteur du codeur optique avec uniquement les fronts montants du codeur
|
||||
const int min_offset = 0; // min offset pour le potentiomètre de réglage de la position min/max
|
||||
const int max_offset = nb_microstep * 5; // max offset pour le potentiomètre de réglage de la position min/max
|
||||
|
||||
volatile unsigned long last_dmx_change_pos;
|
||||
|
||||
volatile int speed_in_accel = MAX_SPEED / 10; // variable pour la vitesse d'acceleration
|
||||
volatile int speed_in_decel = DECELERATION_IN_STEPS_PER_SECOND; // variable pour la vitesse de deceleration
|
||||
|
||||
// fonction
|
||||
void targetPositionReachedCallback(long position); // callback function as the target position is reached
|
||||
void speed_map(); // fonction de mapping de la vitesse du moteur avec accélération et décélération
|
||||
void pos_map(); // fonction de mapping de la position du moteur
|
||||
void set_min(); // fonction pour position minimum de la plage de déplacement du moteur
|
||||
void set_max(); // fonction pour position maximum de la plage de déplacement du moteurF
|
||||
void init_range(); // fonction d'initialisation de la plage de déplacement du moteur
|
||||
|
||||
void targetPositionReachedCallback(long position) // callback function as the target position is reached
|
||||
{
|
||||
Serial.printf("Stepper reached target position %ld\n", position);
|
||||
Serial.printf("Encoder map count is %ld\n", map(encoder.getCount(), min_count, max_count, min_steps, max_steps));
|
||||
Serial.printf("Encoder count is %ld\n", encoder.getCount());
|
||||
}
|
||||
|
||||
void speed_map() // fonction de mapping de la vitesse du moteur avec accélération et décélération
|
||||
{
|
||||
int speed_in_step = map(DMX_data[speed_array], 0, 255, MIN_SPEED, MAX_SPEED);
|
||||
stepper.setSpeedInStepsPerSecond(speed_in_step);
|
||||
Serial.printf("dmx speed receive => %ld\n", DMX_data[speed_array]);
|
||||
Serial.printf("speed in step => %ld\n", speed_in_step);
|
||||
}
|
||||
|
||||
void pos_map() // fonction de mapping de la position du moteur
|
||||
{
|
||||
//int pos_in_step = map(DMX_data[pos_array], 255, 0, min_steps, max_steps);
|
||||
//int pos_in_step = map(DMX_data[pos_array], 0, 255, min_steps - home_steps, max_steps + limit_steps); // fait dans la fonction limit_check
|
||||
//stepper.setTargetPositionInSteps(pos_in_step);
|
||||
Serial.printf("dmx pos to step => %ld\n", pos_in_step);
|
||||
}
|
||||
|
||||
void set_min() // fonction pour position minimum de la plage de déplacement du moteur
|
||||
{
|
||||
home_steps = map((analogRead(home_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
stepper.setCurrentPositionAsHomeAndStop(); // set the current position as the home position and stop the stepper
|
||||
// min_steps = stepper.getCurrentPositionInSteps() - home_steps; // position min du moteur en pas
|
||||
min_steps = stepper.getCurrentPositionInSteps();
|
||||
encoder.setCount(0); // remise à zéro de l'encodeur
|
||||
min_count = encoder.getCount(); // valeur minimum du compteur du codeur en position min
|
||||
}
|
||||
|
||||
void set_max() // fonction pour position maximum de la plage de déplacement du moteur
|
||||
{
|
||||
limit_steps = map((analogRead(limit_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
// max_steps = stepper.getCurrentPositionInSteps() + limit_steps; // position max du moteur en pas
|
||||
max_steps = stepper.getCurrentPositionInSteps();
|
||||
max_count = encoder.getCount(); // valeur maximum du compteur du codeur en position max
|
||||
}
|
||||
|
||||
void init_range() // fonction d'initialisation de la plage de déplacement du moteur
|
||||
{
|
||||
int direction = -1;
|
||||
bool limit_OK = false;
|
||||
int position_init = max_steps / 2;
|
||||
Serial.println("starting homing");
|
||||
digitalWrite(MOTOR_ENABLE_PIN, LOW); // enable motor
|
||||
stepper.setDirectionToHome(direction);
|
||||
if (digitalRead(HOME_SWITCH_PIN) == switch_active) // si position est déjà à home
|
||||
{
|
||||
Serial.println("already in home position");
|
||||
stepper.setCurrentPositionAsHomeAndStop(); // set the current position as the home position and stop the stepper
|
||||
stepper.setTargetPositionInSteps(position_init);
|
||||
delay(2000);
|
||||
}
|
||||
stepper.goToLimitAndSetAsHome(); // go to the limit switch and set the current position as the home position
|
||||
|
||||
while (!limit_OK)
|
||||
{
|
||||
home_sw_check();
|
||||
if (ConfirmedHomeSwitchState == switch_active)
|
||||
{
|
||||
stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_BEGIN); // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is active
|
||||
stepper.setTargetPositionToStop();
|
||||
limit_OK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
|
||||
}
|
||||
}
|
||||
set_min();
|
||||
Serial.println("home OK");
|
||||
stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
|
||||
limit_OK = false;
|
||||
Serial.println("waiting for limit switch");
|
||||
stepper.setTargetPositionInSteps(position_init); // set the target position to the middle of the range
|
||||
while (!limit_OK)
|
||||
{
|
||||
limit_sw_check();
|
||||
if (ConfirmedLimitSwitchState == switch_active)
|
||||
{
|
||||
stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_END); // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is active
|
||||
stepper.setTargetPositionToStop();
|
||||
limit_OK = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
|
||||
if (stepper.getCurrentPositionInSteps() < (max_steps - (max_steps / 4)))
|
||||
{
|
||||
position_init = stepper.getCurrentPositionInSteps() + (max_steps / 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
position_init = stepper.getCurrentPositionInSteps() + nb_microstep;
|
||||
}
|
||||
stepper.setTargetPositionInSteps(position_init);
|
||||
}
|
||||
}
|
||||
Serial.println("limit init OK");
|
||||
stepper.setTargetPositionToStop();
|
||||
position_init = max_steps / 2;
|
||||
stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
|
||||
set_max();
|
||||
stepper.setTargetPositionInSteps(position_init); // set the target position to the middle of the range
|
||||
delay(500);
|
||||
buttonStateChangeDetected = false; // remise à zéro du flag de changement d'état des switchs
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
https://github.com/arttupii/CLSMB Closed loop step motor controller
|
||||
|
||||
https://www.switchdoc.com/2018/04/esp32-tutorial-debouncing-a-button-press-using-interrupts/
|
||||
avec vtask pour plus d'efficacité
|
||||
|
||||
voir pour mieur gérer le homming avec les fonctions explicité dans la lib felxystepper
|
||||
|
||||
rajouter plus de délai à la lecture dmx pour mieux éviter les problème de chanement de valeurs trop rapide
|
||||
@@ -0,0 +1,167 @@
|
||||
|
||||
#define emergency_stop_bounce_time 1000 // time in ms to wait before disabling the motor in emergency when step as been lost
|
||||
#define emergency_release_time 2000 // time in ms to wait before releasing the emergency stop
|
||||
#define emergency_stop_loss_step 5 // number of step to wait before disabling the motor in emergency when step as been lost
|
||||
unsigned long emercency_stop_timer; // temps en ms depuis lequel le moteur est en arrêt d'urgence
|
||||
unsigned long lastStepTime; // variable pour stocker le temps de la dernière mise à jour des données encoder
|
||||
long old_count; // variable des précedentes données de l'encoder
|
||||
long newPosition; // variable des données de l'encoder
|
||||
|
||||
// fonction :
|
||||
void motor_follower(int loss_step); // fonction pour suivre la position du moteur et la perte de pas
|
||||
void emergency_check(); // fonction pour la sécurité si un obstacle est détecté par la perte de pas du moteur
|
||||
void limit_check(); // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
|
||||
/*
|
||||
void IRAM_ATTR emergencySwitchHandler() // interrupt handler for the emergency stop switch
|
||||
{
|
||||
|
||||
// we do not realy need to debounce here, since we only want to trigger a stop, no matter what.
|
||||
// So even triggering mutliple times does not realy matter at the end
|
||||
if (digitalRead(EMERGENCY_STOP_PIN) == LOW) // Switch is configured in active low configuration
|
||||
{
|
||||
// the boolean true in the following command tells the stepper to hold the emergency stop until reaseEmergencyStop() is called explicitly.
|
||||
// If ommitted or "false" is given, the function call would only stop the current motion and then instanlty would allow for new motion commands to be accepted
|
||||
stepper.emergencyStop(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// release a previously enganed emergency stop when the emergency stop button is released
|
||||
stepper.releaseEmergencyStop();
|
||||
}
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
void motor_follower(int loss_step) // fonction pour suivre la position du moteur et la perte de pas
|
||||
{
|
||||
// Quand le moteur est en mouvement, on vérifie si la position a changé de plus de 5 pas
|
||||
// mise à jour de la position de l'encodeur
|
||||
newPosition = encoder.getCount();
|
||||
if (stepper.getDirectionOfMotion() != 0)
|
||||
{
|
||||
if (newPosition > old_count || newPosition < old_count)
|
||||
{
|
||||
lastStepTime = millis();
|
||||
emergencyStop = false;
|
||||
}
|
||||
if (newPosition >= old_count + loss_step || newPosition <= old_count - loss_step)
|
||||
{
|
||||
old_count = newPosition;
|
||||
}
|
||||
else if (millis() - lastStepTime > emergency_stop_bounce_time / (DMX_data[speed_array] + 1) && emergencyStop == false)
|
||||
{
|
||||
Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!! emergency stop");
|
||||
stepper.setTargetPositionToStop();
|
||||
emercency_stop_timer = millis();
|
||||
emergencyStop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void emergency_check() // fonction pour la sécurité si un obstacle est détecté par la perte de pas du moteur
|
||||
{
|
||||
if (emergencyStop)
|
||||
{
|
||||
Serial.printf("emergency stop timer : %i\n", millis() - emercency_stop_timer);
|
||||
if (millis() - emercency_stop_timer > emergency_release_time && emergencyStop == true)
|
||||
{
|
||||
digitalWrite(MOTOR_ENABLE_PIN, LOW); // enable motor
|
||||
Serial.println("======================> emergency stop released");
|
||||
lastStepTime = millis();
|
||||
emergencyStop = false;
|
||||
last_dmx_change_pos = millis();
|
||||
// stepper.setTargetPositionInSteps(pos_in_step);
|
||||
}
|
||||
else if (digitalRead(MOTOR_ENABLE_PIN) == LOW && emergencyStop == true)
|
||||
{
|
||||
Serial.println("======================> emergency stop engaged");
|
||||
digitalWrite(MOTOR_ENABLE_PIN, HIGH); // disable and free motor
|
||||
}
|
||||
}
|
||||
else if (digitalRead(MOTOR_ENABLE_PIN) == HIGH && emergencyStop == false)
|
||||
{
|
||||
digitalWrite(MOTOR_ENABLE_PIN, LOW); // enable motor
|
||||
Serial.println("======================> emergency HARD stop released");
|
||||
lastStepTime = millis();
|
||||
// last_dmx_change_pos = millis();
|
||||
// stepper.setTargetPositionInSteps(pos_in_step);
|
||||
}
|
||||
}
|
||||
|
||||
void limit_check() // fonction pour la sécurité si une limite est détectée par le bouton poussoir
|
||||
{
|
||||
const int limit_step_lost = nb_microstep; // nombre de pas à perdre avant de déclencher l'arrêt d'urgence en cas de détection de limite
|
||||
limit_sw_check(); // check limit switch
|
||||
home_sw_check(); // check home switch
|
||||
|
||||
// si aucun bouton n'est appuyé
|
||||
if (ConfirmedHomeSwitchState != switch_active && ConfirmedLimitSwitchState != switch_active && buttonStateChangeDetected == true)
|
||||
{
|
||||
buttonStateChangeDetected = false;
|
||||
stepper.clearLimitSwitchActive(); // clear the limit switch flag to allow movement in both directions again
|
||||
return;
|
||||
}
|
||||
|
||||
// si les deux boutons sont appuyés il y a un problème
|
||||
if (ConfirmedHomeSwitchState == switch_active && ConfirmedLimitSwitchState == switch_active)
|
||||
{
|
||||
Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ERROOOOORRRRRREEE !!!!!!!!");
|
||||
stepper.emergencyStop(true);
|
||||
emergencyStop = true;
|
||||
}
|
||||
|
||||
// si le bouton de début de course est appuyé
|
||||
if (ConfirmedHomeSwitchState == switch_active)
|
||||
{
|
||||
home_steps = map((analogRead(home_set_pot)), 4095, 0, min_offset, max_offset); // mise à jour de la valeur de l'offset de la position de départ
|
||||
// motor_follower(limit_step_lost);
|
||||
if (emergencyStop)
|
||||
{
|
||||
stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_BEGIN); // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is agtive
|
||||
stepper.setCurrentPositionAsHomeAndStop();
|
||||
}
|
||||
// si le bouton vient d'être appuyé on va à la position de départ selon la config d'offset par le potentiomètre
|
||||
else if (buttonStateChangeDetected == true)
|
||||
{
|
||||
Serial.printf("===========> Home <===========\n");
|
||||
buttonStateChangeDetected = false;
|
||||
home_steps = map((analogRead(home_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
// set_min(); // on enregistre la position actuelle comme position de départ
|
||||
min_count = encoder.getCount(); // valeur minimum du compteur du codeur en position min
|
||||
stepper.setCurrentPositionAsHomeAndStop(); // set the current position as the home position and stop the stepper
|
||||
stepper.setCurrentPositionInSteps(min_steps); // mise à jour de la position pour compenser un décalage éventuel
|
||||
stepper.setTargetPositionInSteps(min_steps - home_steps); // on va à la position de départ selon la config d'offset par le potentiomètre
|
||||
Serial.printf("go to Home set : %i\n", min_steps - home_steps);
|
||||
Serial.printf("min_steps : %i\n", min_steps);
|
||||
Serial.printf("add config step : %i\n", home_steps);
|
||||
Serial.printf("pos_in_step : %i\n", pos_in_step);
|
||||
}
|
||||
}
|
||||
|
||||
// si le bouton de fin de course est appuyé
|
||||
if (ConfirmedLimitSwitchState == switch_active)
|
||||
{
|
||||
limit_steps = map((analogRead(limit_set_pot)), 4095, 0, min_offset, max_offset); // mise à jour de la valeur de l'offset de la position de fin
|
||||
// motor_follower(limit_step_lost);
|
||||
if (emergencyStop)
|
||||
{
|
||||
stepper.setLimitSwitchActive(stepper.LIMIT_SWITCH_END); // this will cause to stop any motion that is currently going on and block further movement in the same direction as long as the switch is agtive
|
||||
}
|
||||
// si le bouton vient d'être appuyé on va à la position de fin selon la config d'offset par le potentiomètre
|
||||
else if (buttonStateChangeDetected == true)
|
||||
{
|
||||
Serial.printf("===========> Limit <===========\n");
|
||||
buttonStateChangeDetected = false;
|
||||
limit_steps = map((analogRead(limit_set_pot)), 4095, 0, min_offset, max_offset);
|
||||
// set_max(); // on enregistre la position actuelle comme position de fin
|
||||
max_count = encoder.getCount(); // valeur maximum du compteur du codeur en position max
|
||||
stepper.setCurrentPositionInSteps(max_steps); // mise à jour de la position pour compenser un décalage éventuel
|
||||
stepper.setTargetPositionInSteps(max_steps); // mise à jour de la position pour compenser un décalage éventuel
|
||||
stepper.setTargetPositionInSteps(max_steps + limit_steps); // on va à la position de fin selon la config d'offset par le potentiomètre
|
||||
Serial.printf("go to Limit set : %i\n", max_steps + limit_steps);
|
||||
Serial.printf("max_steps : %i\n", max_steps);
|
||||
Serial.printf("add config step : %i\n", limit_steps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
Reference in New Issue
Block a user