/*################### File version: 4.0 ##################*/
/*########################################################*/
/* Controllo stepmotor per il nastro trasportatore a */
/* scopo didattico (il docente dovrà spiegarne il */
/* funzionamento). */
/* vengono utilizzati tre pulsanti: */
/* - pulsante rosso P1 per halt e stop del motore; */
/* - pulsante verde P2 per controllare il senso */
/* di rotazione; */
/* - pulsante grigio per controllare il microstepping */
/* (quindi la velocità) del motore. */
/* Il programma utilizza per il tasto P1 tre funzioni */
/* logiche con cui si tenta di simulare il comportamento */
/* di un debounce hardware basato su flip flop; per il */
/* tasto P2 la chiamata a funzione dove con tre funzioni */
/* logiche simili a quelle per il tasto P1; per il tasto */
/* P2 l'interrupt del microcontrollore. */
/* */
/* driver A4988 e DRV8825 */
/* ,-----------, */
/* ENABLE |o o| V_MOTORE */
/* MS1 |o ____ o| GND */
/* MS2 |o| | o| 2B */
/* MS3 |o|____| o| 2A */
/* RESET |o o| 1A */
/* SLEEP |o _ o| 1B */
/* STEP |o |_| o| VDD */
/* DIR |o o| GND */
/* `-----------' */
/* */
/* ========================================== */
/* MS1 | MS2 | MS3 | stepLevel resolution */
/* -----|------|------|---------------------- */
/* Low | Low | Low | Full step */
/* High | Low | Low | 1/2 step */
/* Low | High | Low | 1/4 step */
/* High | High | Low | 1/8 step */
/* High | High | High | 1/16 step */
/* ========================================= */
/*########################################################*/
//##### urutils.h #####
void waitUntilInputLow(int btn, unsigned t)
{
do{
delay(t);
}while(digitalRead(btn)!=LOW);
}
struct DiffTimer
{
volatile unsigned long elapsed, last;
volatile bool timerState=false;
void reset(){
elapsed = 0;
last = millis();
}
void toggle(){
if(timerState){
stop();
}else{
start();
}
}
void stop(){
if(timerState){
timerState = false;
elapsed += millis() - last;
}
}
void start(){
if(!timerState){
timerState = true;
last = millis();
}
}
unsigned long get(){
if(timerState){
return millis() - last + elapsed;
}
return elapsed;
}
void set(unsigned long e){
reset();
elapsed = e;
}
};
//##### urutils.h #####
#include <TimerOne.h> // Libreria per gestire interrupt basati su timer
#define dirPin 6 //2
#define stepPin 3
#define button_ForwardReverse 5
#define button_HaltStart 4
#define button_Microstep 2 //6
#define DEBOUNCETIME 50
volatile bool dirChange = false;
volatile bool directionChange;
volatile bool direction = true;
volatile bool stato = false;
volatile bool stepChange = false;
volatile int count1 = 0;
DiffTimer deb;
uint16_t speed;
uint8_t startStopPin = 0;
uint8_t stepLevel = 0;
uint16_t stepInterval = 1200; // Microsecond (600µs HIGH + 600µs LOW)
int MS[3] = {9, 8, 7}; // pin microstepper MS1=MS[0]->9, MS2=MS[1]->8, MS3=MS[2]->7
boolean microstepArray[5][3] = {
{LOW, LOW, LOW},
{HIGH, LOW, LOW},
{LOW, HIGH, LOW},
{HIGH, HIGH, LOW},
{HIGH, HIGH, HIGH}
};
enum resolution{
FULL,
HALFT,
QUARTER,
EIGHTH,
SIXTEENTH
};
// Definizione per lo stato dei pulsanti
struct Button {
uint8_t pin;
uint8_t val0;
uint8_t val;
//uint8_t count;
//bool state;
bool changed() {
val = digitalRead(pin);
bool changed = (val != val0);
val0 = val; // aggiornamento livello precedente al livello attuale
return changed; // ritorna il valore attuale del pulsante
}
};
Button buttonStart = {button_HaltStart, LOW};
Button buttonDir = {button_ForwardReverse, LOW};
Button buttonStep = {button_Microstep, LOW};
bool setResolution(uint8_t level){
if (level < 0 || level > 4) return false;
Serial.print("Res: ");
for (int i = 0; i < 3; i++) {
digitalWrite(MS[i],microstepArray[level][i]);
Serial.print(microstepArray[level][i]);
}
Serial.println();
return true;
}
// Funzione di interrupt per controllare gli step del motore
void stepMotor() {
static bool stepState = false;
if (directionChange) {
return; // Non generare step durante il cambio di direzione
}
stepState = !stepState;
digitalWrite(stepPin, stepState);
}
void setup() {
Serial.begin(115200);
pinMode(stepPin, OUTPUT);
pinMode(dirPin, OUTPUT);
pinMode(MS[0], OUTPUT);
pinMode(MS[1], OUTPUT);
pinMode(MS[2], OUTPUT);
pinMode(button_ForwardReverse, INPUT);
pinMode(button_HaltStart, INPUT);
pinMode(button_Microstep, INPUT);
setResolution(FULL);
stato = false;
speed = 600;
direction = true;
directionChange = false;
deb.start();
// Configura l'interrupt di timer per gli step del motore
Timer1.initialize(stepInterval/2); // Metà del periodo totale
Timer1.attachInterrupt(stepMotor);
Timer1.stop(); // Ferma il timer finché non è necessario
}
void loop() {
if(deb.get() >= DEBOUNCETIME) {
deb.reset();
if(buttonStep.changed()){
if(buttonStep.val){
stepLevel++;
stepLevel = stepLevel%5;
setResolution(stepLevel);
}
}
if(buttonDir.changed()){
//digitalWrite(stepPin, LOW);
directionChange = true;
Serial.print("Direction: ");Serial.println(buttonDir.val);
delay(1000);
digitalWrite(dirPin, buttonDir.val);
directionChange = false;
//digitalWrite(stepPin, HIGH);
}
if(buttonStart.changed()){
if(buttonStart.val){
Timer1.start();
Serial.println("Timer started");
}else{
Timer1.stop();
Serial.println("Timer stopped");
}
}
}
delay(1);
}
nano:12
nano:11
nano:10
nano:9
nano:8
nano:7
nano:6
nano:5
nano:4
nano:3
nano:2
nano:GND.2
nano:RESET.2
nano:0
nano:1
nano:13
nano:3.3V
nano:AREF
nano:A0
nano:A1
nano:A2
nano:A3
nano:A4
nano:A5
nano:A6
nano:A7
nano:5V
nano:RESET
nano:GND.1
nano:VIN
nano:12.2
nano:5V.2
nano:13.2
nano:11.2
nano:RESET.3
nano:GND.3
stepper1:A-
stepper1:A+
stepper1:B+
stepper1:B-
drv2:ENABLE
drv2:MS1
drv2:MS2
drv2:MS3
drv2:RESET
drv2:SLEEP
drv2:STEP
drv2:DIR
drv2:GND.1
drv2:VDD
drv2:1B
drv2:1A
drv2:2A
drv2:2B
drv2:GND.2
drv2:VMOT
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
btn2:1.l
btn2:2.l
btn2:1.r
btn2:2.r
vcc1:VCC
gnd1:GND
btn3:1.l
btn3:2.l
btn3:1.r
btn3:2.r
r4:1
r4:2
r5:1
r5:2
r6:1
r6:2
led1:A
led1:C
r7:1
r7:2
r3:1
r3:2