// WARNING!!! as per 23 Dec 2024,
// hardware timer on STM32 Bluepill IS NOT IMPLEMENTED YET!
// so use it as a reference idea only
#include <LiquidCrystal.h> // Include the LCD library
#include "HardwareTimer.h"
const int rs = PB11, en = PB10, d4 = PB0, d5 = PB1, d6 = PC13, d7 = PC14; // Pin konfigurasi LCD
LiquidCrystal lcd(rs, en, d4, d5, d6, d7); // Initialize the LCD
unsigned long currentTime = 0;
unsigned long startTime = 0;
#define pinCLK PB6
#define pinDT PB7
#define pinZ PA9
// TIMER9-11 don't support hardware encoder mode
volatile bool ROTARY_ZERO_state = false;
HardwareTimer *MyEncoder ; // encoder connected to ch1/ch2 of TIMx
void RotaryZero() {
ROTARY_ZERO_state = true;
// Serial.println("Rotary Zero");
}
void setup() {
pinMode(pinCLK, INPUT);
pinMode(pinDT, INPUT);
pinMode(pinZ, INPUT);
// attachInterrupt(digitalPinToInterrupt(pinZ), RotaryZero, RISING);
// Instantiate HardwareTimer object. Thanks to 'new' instantiation, HardwareTimer is not destructed when setup() function is finished.
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(pinCLK), PinMap_PWM);
uint32_t channel_1 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pinCLK), PinMap_PWM));
uint32_t channel_2 = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(pinDT ), PinMap_PWM));
TIM_IC_InitTypeDef Encoder;
MyEncoder = new HardwareTimer(Instance);
MyEncoder->pause();
MyEncoder->setPreloadEnable(true);
MyEncoder->setOverflow(65536 , TICK_FORMAT);
MyEncoder->setPrescaleFactor(1);
MyEncoder->setMode(channel_1, TIMER_INPUT_CAPTURE_FALLING, pinCLK);
MyEncoder->setMode(channel_2, TIMER_INPUT_CAPTURE_FALLING, pinDT );
Instance->SMCR |= TIM_ENCODERMODE_TI12; // set encoder moder (counting both rising and falling edges on both channels)
// Encoder.ICPolarity = TIM_ICPOLARITY_RISING;
// // input capture 1 selection
// Encoder.ICSelection = TIM_ICSELECTION_DIRECTTI;
// // input capture 1 prescaler
// Encoder.ICPrescaler = TIM_ICPSC_DIV1; // 0x00
// // input capture 1 filter
// Encoder.ICFilter = 0x0F;
// HAL_TIM_IC_Init(MyEncoder->getHandle());
// HAL_TIM_IC_Start(MyEncoder->getHandle(), TIM_CHANNEL_1);
// HAL_TIM_IC_Start(MyEncoder->getHandle(), TIM_CHANNEL_2);
MyEncoder->setCount(27);
MyEncoder->resume();
// MyEncoder->refresh();
// if (Instance == TIM1) {
// Serial.println("Encoder is on TIM1");
// }
// if (Instance == TIM2) {
// Serial.println("Encoder is on TIM2");
// }
// if (Instance == TIM3) {
// Serial.println("Encoder is on TIM3");
// }
// if (Instance == TIM4) {
// Serial.println("Encoder is on TIM4");
// }
lcd.begin(16, 2); // Inisialisasi LCD 16x2
lcd.setCursor(0, 0); // Baris pertama, kolom pertama
lcd.print("Start :"); // Tampilkan teks pertama
delay(2000); // Tunggu 2 detik
lcd.clear(); // Bersihkan layar
lcd.setCursor(0, 1);
lcd.print("Pos-");
if (Instance == TIM1) {
lcd.print("1");
}
if (Instance == TIM2) {
lcd.print("2");
}
if (Instance == TIM3) {
lcd.print("3");
}
if (Instance == TIM4) {
lcd.print("4");
}
lcd.print(": ");
// startTime = millis(); // Mulai hitungan waktu
}
void loop() {
// Hitung waktu berjalan dalam milidetik
// currentTime = millis();
// Hitung detik berjalan dengan kecepatan 3 kali lipat
// unsigned long fastSeconds = (currentTime - startTime) / (1000 / 3);
// Tampilkan detik berjalan di LCD
// lcd.setCursor(0, 0); // Baris pertama
// lcd.print("Seconds: ");
// lcd.setCursor(9, 0); // Baris pertama kolom ke-10
// lcd.print(fastSeconds); // Tampilkan detik berjalan
lcd.setCursor(0,0);
if(digitalRead(pinCLK) == LOW) {
lcd.print("0");
} else {
lcd.print("1");
}
lcd.setCursor(2,0);
if(digitalRead(pinDT) == LOW) {
lcd.print("0");
} else {
lcd.print("1");
}
lcd.setCursor(4,0);
if(MyEncoder->isRunning()) {
lcd.print("1");
} else {
lcd.print("0");
}
lcd.setCursor(7,1);
lcd.print(int16_t( MyEncoder->getCount() ) );
// if(ROTARY_ZERO_state) {
// MyEncoder->setCount(0);
// ROTARY_ZERO_state = false;
// }
delay(100); // Update tampilan setiap 100 ms untuk menjaga akurasi
}