#include <TM1637Display.h>
#include <EEPROM.h>
// Rotary Encoder Inputs
#define CLK 6
#define DT 7
#define SW 8
// Define the connections pins for TM1637
#define TM1637_CLK 4 // Clock pin for TM1637
#define TM1637_DIO 5 // Data pin for TM1637
// Motor control pins
#define MOTOR_PWM 9 // PWM pin for motor control (example)
#define bldc_el_pin 12
// Motor feedback pins (example)
#define MOTOR_ENC_A 2
#define MOTOR_ENC_B 3
// Select motor type: 1 for DC with encoder, 0 for BLDC
static const int select_motor = 0;
int counter = 0;
int currentStateCLK;
int lastStateCLK;
int btnState;
unsigned long lastButtonPress = 0;
int pressCount = 0;
int targetRPM = 0;
volatile int encoderTicks = 0;
unsigned long lastRPMCalcTime = 0;
int currentRPM = 0;
TM1637Display display(TM1637_CLK, TM1637_DIO);
void setup() {
// Set encoder pins as inputs
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
// Set motor control pins as outputs
pinMode(MOTOR_PWM, OUTPUT);
pinMode(bldc_el_pin, OUTPUT);
// Set motor feedback pins as inputs
pinMode(MOTOR_ENC_A, INPUT);
pinMode(MOTOR_ENC_B, INPUT);
// Setup Serial Monitor
Serial.begin(9600);
// Read the initial state of CLK
lastStateCLK = digitalRead(CLK);
// Set the brightness of the display (0 to 7)
display.setBrightness(7);
// Display the initial counter value
display.showNumberDec(counter, true);
// Attach interrupt for motor encoder feedback
attachInterrupt(digitalPinToInterrupt(MOTOR_ENC_A), updateEncoderTicks, CHANGE);
attachInterrupt(digitalPinToInterrupt(MOTOR_ENC_B), updateEncoderTicks, CHANGE);
// Initialize RPM calculation timer
lastRPMCalcTime = millis();
pressCount = 0;
}
void loop() {
// Read the button state
btnState = digitalRead(SW);
// Serial.println(btnState);
// If we detect LOW signal, button is pressed
if (btnState == LOW) {
delay(300);
pressCount++;
handleButtonPress();
}
// Put in a slight delay to help debounce the reading
delay(1);
}
void handleButtonPress() {
switch (pressCount) {
case 1:
// First press: Allow user to set the encoder value between 0 to 9999
Serial.println("Set RPM value (0-9999) using encoder");
setRPM();
break;
case 2:
// Second press: Save the user input RPM in EEPROM and start the motor
EEPROM.put(0, counter);
targetRPM = counter;
Serial.print("Saved RPM: ");
Serial.println(targetRPM);
startMotor();
// Calculate current RPM
if (millis() - lastRPMCalcTime >= 1000) {
updateRPM();
lastRPMCalcTime = millis();
}
// Update motor speed to match the user input RPM
updateMotorSpeed();
break;
case 3:
// Third press: Stop the motor, reset the press count, and allow user to set the encoder value again
stopMotor();
pressCount = 0;
Serial.println("Motor stopped. Set RPM value (0-9999) using encoder");
break;
}
}
void setRPM() {
bool settingRPM = true;
while (settingRPM) {
// Read the current state of CLK
currentStateCLK = digitalRead(CLK);
// If last and current state of CLK are different, then pulse occurred
// React to only 1 state change to avoid double count
if (currentStateCLK != lastStateCLK && currentStateCLK == 1) {
// If the DT state is different than the CLK state then
// the encoder is rotating CCW so decrement
if (digitalRead(DT) != currentStateCLK) {
counter--;
} else {
// Encoder is rotating CW so increment
counter++;
}
// Ensure counter is within the range 0 to 9999
if (counter < 0) counter = 0;
if (counter > 9999) counter = 9999;
// Update the display with the new counter value
display.showNumberDec(counter, true);
}
// Remember last CLK state
lastStateCLK = currentStateCLK;
// Read the button state
btnState = digitalRead(SW);
// If we detect LOW signal, button is pressed
if (btnState == LOW) {
delay(300);
settingRPM = false;
pressCount++;
handleButtonPress();
}
// Put in a slight delay to help debounce the reading
delay(1);
}
}
void startMotor() {
if(select_motor == 1){
// Logic to start the motor
Serial.println("DC Motor started");
// Set initial motor speed (example value)
analogWrite(MOTOR_PWM, 128);
}else{
// Logic to start the motor
Serial.println("BLDC Motor started");
// Set initial motor speed (example value)
digitalWrite(bldc_el_pin, HIGH);
analogWrite(MOTOR_PWM, 128);
}
}
void stopMotor() {
if(select_motor == 1){
// Logic to stop the motor
Serial.println("DC Motor stopped");
analogWrite(MOTOR_PWM, 0);
}else{
// Logic to stop the motor
Serial.println("BLDC Motor stopped");
digitalWrite(bldc_el_pin, LOW);
analogWrite(MOTOR_PWM, 0);
}
}
void updateEncoderTicks() {
// Interrupt service routine to update encoder ticks
encoderTicks++;
}
void updateRPM() {
if(select_motor == 1){
// Calculate RPM based on encoder ticks
// Assuming 20 encoder ticks per revolution (adjust according to your encoder)
const int ticksPerRevolution = 20;
currentRPM = (encoderTicks * 60) / ticksPerRevolution;
encoderTicks = 0;
// Display current RPM
display.showNumberDec(currentRPM, true);
Serial.print("Current RPM: ");
Serial.println(currentRPM);
}else{
int pwmValue = map(targetRPM, 0, 9999, 0, 255);
analogWrite(MOTOR_PWM, pwmValue);
display.showNumberDec(pwmValue, true);
Serial.print("Current RPM: ");
Serial.println(pwmValue);
}
}
void updateMotorSpeed() {
// Adjust motor speed to match target RPM
if(select_motor == 1){
if (targetRPM > 0) {
int pwmValue = map(currentRPM, 0, 9999, 0, 255);
analogWrite(MOTOR_PWM, pwmValue);
}
}
}