/* Sweep
by BARRAGAN <http://barraganstudio.com>
This example code is in the public domain.
modified 8 Nov 2013
by Scott Fitzgerald
https://www.arduino.cc/en/Tutorial/LibraryExamples/Sweep
*/
#define EEPROM_SIZE 1024 // Ukuran EEPROM yang akan diinisialisasi (0-1023)
#define IR_RECEIVE_PIN 35 // Pin untuk penerima sinyal IR
#define SPEAKER_PIN 27 // Pin untuk speaker
#define SERVO_PIN 23 // Pin untuk servo
#include <ESP32Servo.h>
#include <IRremote.hpp>
#include <EEPROM.h>
Servo myservo; // create Servo object to control a servo
uint16_t pos = 0; // variable to store the servo position
uint16_t posA;
uint16_t posB;
uint16_t speed;
const uint8_t eepromPosA = 0;
const uint8_t eepromPosB = 1;
const uint8_t eepromSpeed = 2;
const uint16_t defaultPosA = 0;
const uint16_t defaultPosB = 180;
const uint16_t defaultSpeed = 6;
const uint16_t speedMax = 11;
bool onSetting = false;
const uint8_t buttonPins[] = {33, 25, 26}; // Pin untuk tombol
const uint8_t numButton = sizeof(buttonPins) / sizeof(buttonPins[0]); // Jumlah tombol
uint8_t oldValue[] = {HIGH, HIGH, HIGH}; // Nilai awal tombol (HIGH karena INPUT_PULLUP)
uint8_t newValue[numButton]; // Buffer untuk nilai baru tombol
unsigned long lastReceiveTime = 0; // Waktu terakhir menerima sinyal
const unsigned long debounceDelay = 500; // Waktu debounce dalam milidetik
const unsigned long holdTime = 2000; // 3 detik
unsigned long buttonPressTimes[numButton] = {0}; // Waktu awal penekanan tombol
bool buttonHeld[numButton] = {false}; // Apakah tombol telah ditahan selama 3 menit
auto moveToPosition = [&](uint8_t target) {
while (pos != target) {
bool isIncreasing = (pos < target);
int increment = isIncreasing ? speed : -speed;
// Cegah melampaui target
if ((isIncreasing && pos + increment > target) ||
(!isIncreasing && pos + increment < target)) {
pos = target;
} else {
pos += increment;
}
myservo.write(pos); // Gerakkan servo ke posisi 'pos'
delay(15); // Tunggu sebentar
}
};
void setup() {
myservo.attach(SERVO_PIN); // attaches the servo on pin 9 to the Servo object
Serial.begin(9600);
IrReceiver.begin(IR_RECEIVE_PIN); // Start the receiver
pinMode(SPEAKER_PIN, OUTPUT); // Set pin speaker sebagai output
// Set pin tombol sebagai input pull-up
for (uint8_t i = 0; i < numButton; i++) {
pinMode(buttonPins[i], INPUT_PULLUP);
}
EEPROM.begin(EEPROM_SIZE); // Inisialisasi EEPROM
posA = EEPROM.read(eepromPosA);
posB = EEPROM.read(eepromPosB);
speed = EEPROM.read(eepromSpeed);
posA = (posA == 255) ? eepromSave(eepromPosA, defaultSpeed) : eepromSave(eepromPosA, posA);
posB = (posB == 255) ? eepromSave(eepromPosB, defaultPosB) : eepromSave(eepromPosB, posB);
speed = (speed == 255 || speed > speedMax) ? eepromSave(eepromSpeed, defaultSpeed) : eepromSave(eepromSpeed, speed);
moveToPosition(posA);
}
// Pointer ke fungsi
void (*action)();
uint16_t eepromSave(uint8_t address, uint16_t value){
EEPROM.write(address, value);
EEPROM.commit();
Serial.println(address == 0?"posA = "+String(value):address == 1?"posB = "+String(value):"speed = "+String(value));
return value;
}
void buzzer(uint8_t bips = 3, uint16_t time = 250){
for(uint8_t i = 0; i < bips; i++){
digitalWrite(SPEAKER_PIN, HIGH);
delay(time);
digitalWrite(SPEAKER_PIN, LOW);
delay(time);
}
}
void setParameter(char param, bool isIncrease = true){
uint16_t *value; // Pointer to the variable to modify
uint16_t minValue; // Minimum allowed value
uint16_t maxValue; // Maximum allowed value
switch (param) {
case 'a': // set pos A
value = &posA;
minValue = 0;
maxValue = posB;
action = &setPosA;
break;
case 'b': // set pos B
value = &posB;
minValue = posA;
maxValue = 180;
action = &setPosB;
break;
case 's': // set speed of servo
value = &speed;
minValue = 1;
maxValue = speedMax;
action = &flip;
break;
default:
return; // Invalid parameter
}
if ((isIncrease && *value < maxValue) || (!isIncrease && *value > minValue)){
*value += isIncrease ? 1 : -1;
eepromSave(eepromAddress(param), *value);
action();
}else{
buzzer(1, 1000);
}
}
int eepromAddress(char param){
switch (param) {
case 'a': return eepromPosA;
case 'b': return eepromPosB;
case 's': return eepromSpeed;
default: return -1; // Error: invalid parameter
}
}
void flip(){
Serial.println("posA = " + String(posA));
Serial.println("posB = " + String(posB));
Serial.println("speed = " + String(speed));
moveToPosition(posA);
moveToPosition(posB);
moveToPosition(posA);
}
void setPosA(){
moveToPosition(posA);
}
void setPosB(){
moveToPosition(posB);
}
void calibrate(char param){
onSetting = !onSetting;
Serial.println(param == 'a'?"posA = " + String(posA):"posB = " + String(posB));
Serial.println("on setting"+ String(param=='a'?"posA = ":"posB = ") + String(onSetting ? "ON" : "OFF"));
while(onSetting){
if (IrReceiver.decode()) {
uint16_t command = IrReceiver.decodedIRData.command;
if (command == 9){
moveToPosition(posA);
onSetting = !onSetting;
}else if(command == 7){
setParameter(param);
}else if(command == 21){
setParameter(param, false);
}else{
buzzer(2, 100);
}
IrReceiver.resume(); // Teruskan penerimaan IR
}
for (uint8_t i = 0; i < numButton; i++) {
newValue[i] = digitalRead(buttonPins[i]);
// Check if the value was changed,
// by comparing it with the previous value.
if(newValue[i] != oldValue[i]){
// Mulai mengukur waktu penekanan
buttonPressTimes[i] = millis();
while (true) {
newValue[i] = digitalRead(buttonPins[i]);
if(millis() - buttonPressTimes[i] > debounceDelay){
switch(buttonPins[i]){
case 25: // button kuning
setParameter(param);
break;
case 26: // button hijau
setParameter(param, false);
break;
default:
buzzer(2, 100);
break;
}
}
if (newValue[i] == HIGH) break;
delay(100);
}
if(newValue[i] == HIGH && millis() - buttonPressTimes[i] <= debounceDelay){
switch(buttonPins[i]){
case 33: // button merah
moveToPosition(posA);
onSetting = !onSetting;
break;
case 25: // button kuning
setParameter(param);
break;
case 26: // button hijau
setParameter(param, false);
break;
default:
buzzer(2, 100);
break;
}
}
buttonPressTimes[i] = 0;
// Remember the value for the next time.
oldValue[i] = newValue[i];
}
}
}
buzzer(3, 100);
Serial.println("on setting posA = " + String(onSetting ? "ON" : "OFF"));
}
void loop() {
if (IrReceiver.decode()) {
unsigned long currentTime = millis();
if (currentTime - lastReceiveTime > debounceDelay) {
uint16_t command = IrReceiver.decodedIRData.command;
Serial.println(command);
lastReceiveTime = currentTime; // Perbarui waktu terakhir menerima sinyal
switch(IrReceiver.decodedIRData.command){
case 7: // tombol "-"
setParameter('s', false); // mengurangi kecepetan gerak servo
break;
case 21: // tombol "+"
setParameter('s'); // menambah kecepetan gerak servo
break;
case 68: // tombol "PREV"
calibrate('b');
break;
case 64: // tombol "NEXT"
calibrate('a');
break;
case 67: // tombol "PLAY"
flip();
break;
case 70: // tombol "CH"
ESP.restart(); // test restart esp
break;
}
}
IrReceiver.resume(); // Enable receiving of the next value
}
for (uint8_t i = 0; i < numButton; i++) {
newValue[i] = digitalRead(buttonPins[i]);
// Check if the value was changed,
// by comparing it with the previous value.
if (newValue[i] != oldValue[i]) {
if (newValue[i] == LOW) {
// Mulai mengukur waktu penekanan
buttonPressTimes[i] = millis();
// Tunggu sampai tombol dilepas atau waktu tahan tercapai
while (true) {
newValue[i] = digitalRead(buttonPins[i]);
if(newValue[i] == HIGH){
switch (buttonPins[i]) {
case 33:
flip();
break;
case 25:
setParameter('s'); // menambah kecepatan gerak servo
break;
case 26:
setParameter('s', false); // mengurangi kecepatan gerak servo
break;
}
break;
}
if (millis() - buttonPressTimes[i] >= holdTime) {
if(buttonPins[i] != 33) buzzer(2, 100);
switch (buttonPins[i]) {
case 25:
calibrate('b');
break;
case 26:
calibrate('a');
break;
}
break;
}
}
}
buttonPressTimes[i] = 0;
// Remember the value for the next time.
oldValue[i] = newValue[i];
}
}
}