d4175e4eef
Fixed display when RPM = 0 or countdown = 0
252 lines
6.1 KiB
C++
252 lines
6.1 KiB
C++
/*
|
|
|
|
*/
|
|
|
|
#include <RotaryEncoder.h>
|
|
#include "SevSeg.h"
|
|
#include <EveryTimer.h>
|
|
#include <AccelStepper.h>
|
|
|
|
// PIN USAGE
|
|
#define SEVSEG_DIGIT_1 16
|
|
#define SEVSEG_DIGIT_2 17
|
|
#define SEVSEG_DIGIT_3 3
|
|
#define SEVSEG_DIGIT_4 4
|
|
#define SEVSEG_COLON 2
|
|
#define SEVSEG_SEGMENT_A 8
|
|
#define SEVSEG_SEGMENT_B 14
|
|
#define SEVSEG_SEGMENT_C 6
|
|
#define SEVSEG_SEGMENT_D A1
|
|
#define SEVSEG_SEGMENT_E 23
|
|
#define SEVSEG_SEGMENT_F 7
|
|
#define SEVSEG_SEGMENT_G 5
|
|
#define SEVSEG_SEGMENT_H 22
|
|
|
|
#define ROT_BUTT 11
|
|
#define ROT_ENC_1 12
|
|
#define ROT_ENC_2 13
|
|
|
|
#define STEPPER_STEP 10
|
|
#define STEPPER_DIRECTION 0
|
|
#define STEPPER_ENABLE A5
|
|
|
|
|
|
//SETTINGS
|
|
#define SEVSEG_REFRESH 250 // Refresh rate in ms
|
|
#define SEVSEG_BRIGHTNESS 100 // 100%, full brightness
|
|
#define STEPPER_MAX_SPEED 5000
|
|
#define STEPPER_MIN_SPEED 0
|
|
#define STEPPER_ACCELERATION 30.0
|
|
#define STEP_MOTOR_STEPS_PER_TURN 200
|
|
#define STEPPER_MICROSTEP 8
|
|
|
|
SevSeg sevseg; //Instantiate a seven segment controller object
|
|
|
|
// Setup a RoraryEncoder for pins 12 and 13:
|
|
RotaryEncoder encoder(ROT_ENC_1, ROT_ENC_2);
|
|
|
|
AccelStepper stepper(1, STEPPER_STEP, STEPPER_DIRECTION);
|
|
|
|
EveryTimer cntdwn;
|
|
EveryTimer calc_dspl;
|
|
|
|
//Global variables
|
|
|
|
byte numDigits = 4;
|
|
byte digitPins[] = {SEVSEG_DIGIT_1, SEVSEG_DIGIT_2,
|
|
SEVSEG_DIGIT_3, SEVSEG_DIGIT_4};
|
|
byte segmentPins[] = {SEVSEG_SEGMENT_A, SEVSEG_SEGMENT_B,
|
|
SEVSEG_SEGMENT_C, SEVSEG_SEGMENT_D,
|
|
SEVSEG_SEGMENT_E, SEVSEG_SEGMENT_F,
|
|
SEVSEG_SEGMENT_G, SEVSEG_SEGMENT_H};
|
|
bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
|
|
byte hardwareConfig = COMMON_ANODE; // See README.md for options
|
|
bool updateWithDelays = false; // Default. Recommended
|
|
bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
|
|
long refresh_timer = 0;
|
|
|
|
long countdown = 0;
|
|
byte hours = 0;
|
|
byte minutes = 0;
|
|
byte seconds = 0;
|
|
int current_rpm = 0;
|
|
int new_rpm = 0;
|
|
static bool currBut = true;
|
|
byte mode = 0;
|
|
|
|
void countdown_callback() {
|
|
if (current_rpm != 0) { // if speed = 0 => pause countdown
|
|
countdown--;
|
|
if (countdown < 0) {
|
|
countdown = 0;
|
|
}
|
|
recalculate_HMS();
|
|
//Serial.println(countdown);
|
|
}
|
|
else {
|
|
Serial.println("Pause");
|
|
}
|
|
}
|
|
|
|
void calculate_display_callback() {
|
|
// Update data to be displayed
|
|
if (mode == 0) { // mode 0 = display speed
|
|
digitalWrite(SEVSEG_COLON, false);
|
|
sevseg.setNumber(current_rpm);
|
|
}
|
|
else if (mode == 1) { // mode 1 = display countdown
|
|
//Blink colon each seconds
|
|
if (countdown % 2) {
|
|
digitalWrite(SEVSEG_COLON, true);
|
|
}
|
|
else {
|
|
digitalWrite(SEVSEG_COLON, false);
|
|
}
|
|
//Display HH:MM or MM:SS if there is less than 1h left
|
|
if (hours) {
|
|
sevseg.setNumber(100*hours+minutes);
|
|
} else {
|
|
sevseg.setNumber(100*minutes+seconds);
|
|
}
|
|
}
|
|
}
|
|
|
|
void update_encoder() {
|
|
static long currVal = 0;
|
|
int multiplier = 10;
|
|
|
|
encoder.tick();
|
|
|
|
long newVal = encoder.getPosition();
|
|
int dir = encoder.getDirection();
|
|
|
|
if (currVal != newVal) {
|
|
currVal = newVal;
|
|
if (mode == 0) { // Mode 0 : speed setting
|
|
if (current_rpm >= 500) {
|
|
multiplier = 100; // default : 1 encoder step = +/- 10 step/min
|
|
// if speed > 500 : encoder step = +/- 100 step/min
|
|
}
|
|
new_rpm += multiplier * dir;
|
|
if (new_rpm < STEPPER_MIN_SPEED) {
|
|
new_rpm = STEPPER_MIN_SPEED;
|
|
}
|
|
if (new_rpm > STEPPER_MAX_SPEED) {
|
|
new_rpm = STEPPER_MAX_SPEED;
|
|
}
|
|
}
|
|
if (mode == 1) { //mode 1 : countdown setting
|
|
multiplier = 60; // default : 1 encoder step = +/- 1min
|
|
// if countdown > 1h : encoder step = +/- 1h
|
|
if (countdown >= 3600) {
|
|
multiplier = 600;
|
|
}
|
|
countdown += multiplier * dir;
|
|
if (countdown < 0) {
|
|
countdown = 0;
|
|
}
|
|
|
|
// Max: 86400s = 1 day
|
|
if (countdown >= 86400) {
|
|
countdown = 86399;
|
|
}
|
|
recalculate_HMS();
|
|
}
|
|
Serial.print("RPM: ");
|
|
Serial.print(new_rpm);
|
|
Serial.print(" | Countdown: ");
|
|
Serial.println(countdown);
|
|
}
|
|
|
|
//Check button for mode change
|
|
bool newBut = digitalRead(ROT_BUTT);
|
|
if (newBut != currBut) {
|
|
currBut = newBut;
|
|
if (currBut) {
|
|
mode++;
|
|
}
|
|
|
|
if (mode == 2) {
|
|
mode = 0;
|
|
}
|
|
else if (mode == 0) {
|
|
encoder.setPosition(current_rpm);
|
|
}
|
|
else if (mode == 1) {
|
|
encoder.setPosition(countdown);
|
|
}
|
|
Serial.print("Mode :");
|
|
Serial.println(mode);
|
|
}
|
|
}
|
|
|
|
void update_stepper() {
|
|
|
|
//Update speend setting and ENABLE pin if new speed value
|
|
if (new_rpm != current_rpm) {
|
|
current_rpm = new_rpm;
|
|
stepper.setSpeed(current_rpm);
|
|
// Enable/Disable motor
|
|
if (current_rpm == 0) {
|
|
stepper.disableOutputs();
|
|
Serial.println("Stepper : Off");
|
|
}
|
|
else {
|
|
stepper.enableOutputs();
|
|
Serial.println("Stepper : On");
|
|
}
|
|
}
|
|
//if Countdown = 0 => pause (no move but keep speed setting)
|
|
if (countdown != 0 and current_rpm != 0) {
|
|
//Serial.println("Run motor !");
|
|
stepper.runSpeed();
|
|
}
|
|
}
|
|
|
|
void recalculate_HMS() {
|
|
minutes = (countdown / 60) % 60;
|
|
if (countdown >= 3600) {
|
|
hours = countdown / 3600;
|
|
}
|
|
else {
|
|
hours = 0;
|
|
seconds = countdown % 60;
|
|
}
|
|
}
|
|
|
|
void setup()
|
|
{
|
|
Serial.begin(115200);
|
|
|
|
pinMode(ROT_BUTT, INPUT_PULLUP);
|
|
pinMode(SEVSEG_COLON, OUTPUT);
|
|
|
|
sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);
|
|
sevseg.setBrightness(SEVSEG_BRIGHTNESS);
|
|
|
|
stepper.setEnablePin(STEPPER_ENABLE);
|
|
stepper.disableOutputs();
|
|
stepper.setMaxSpeed(STEPPER_MAX_SPEED);
|
|
stepper.setAcceleration(STEPPER_ACCELERATION);
|
|
stepper.setSpeed(0);
|
|
|
|
cntdwn.Every(1000, countdown_callback);
|
|
calc_dspl.Every(SEVSEG_REFRESH, calculate_display_callback);
|
|
}
|
|
|
|
void loop() {
|
|
update_encoder();
|
|
|
|
//Make the motor move
|
|
update_stepper();
|
|
|
|
//Update countdown
|
|
cntdwn.Update();
|
|
|
|
//refresh the 7-segment display
|
|
calc_dspl.Update();
|
|
sevseg.refreshDisplay();
|
|
}
|
|
|
|
|