polisseur/code_polisseur/code_polisseur.ino

290 lines
7.4 KiB
C++

/*
Polisseur
Copyright (C) 2019 Arofarn
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#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 ROT_ENC_DIR -1
#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 days = 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_DHMS();
//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 dd:HH if there is more than 1day left, HH:MM if less or MM:SS if there is less than 1h left
if (days) {
char dispBuf[] = "0d00";
dispBuf[0] = days + 48;
dispBuf[2] = (hours / 10) + 48;
dispBuf[3] = (hours % 10) + 48;
sevseg.setChars(dispBuf);
}
else 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
multiplier = 10;
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 * ROT_ENC_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 = +/- 10min (600s)
// if countdown > 1d : encoder step = +/- 1h (3600s)
if (countdown >= 86400) {
multiplier = 3600;
}
else if (countdown >= 3600) {
multiplier = 600;
}
countdown += multiplier * dir * ROT_ENC_DIR;
//Min: 0 = no negative timer value
if (countdown < 0) {
countdown = 0;
}
// Max: 864000s = 10 days
if (countdown >= 864000) {
countdown = 863999;
}
recalculate_DHMS();
}
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_DHMS() {
//Calculate days, hours, minutes and seconds to be display
if (countdown >= 86400) {
days = countdown / 86400;
hours = (countdown % 86400) / 3600;
}
else {
days = 0;
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();
}