#include <Arduino.h>
#include <SPI.h>
/////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// EncButton /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//#include <Arduino.h>
// #define EB_NO_FOR // отключить поддержку pressFor/holdFor/stepFor и счётчик степов (экономит 2 байта оперативки)
// #define EB_NO_CALLBACK // отключить обработчик событий attach (экономит 2 байта оперативки)
// #define EB_NO_COUNTER // отключить счётчик энкодера (экономит 4 байта оперативки)
// #define EB_NO_BUFFER // отключить буферизацию энкодера (экономит 1 байт оперативки)
// #define EB_DEB_TIME 50 // таймаут гашения дребезга кнопки (кнопка)
// #define EB_CLICK_TIME 500 // таймаут ожидания кликов (кнопка)
// #define EB_HOLD_TIME 600 // таймаут удержания (кнопка)
// #define EB_STEP_TIME 200 // таймаут импульсного удержания (кнопка)
// #define EB_FAST_TIME 30 // таймаут быстрого поворота (энкодер)
#include <EncButton.h>
#define EncButton_Pin_CLK 32
#define EncButton_Pin_DT 35
#define EncButton_Pin_SW 33
EncButton eb(EncButton_Pin_CLK, EncButton_Pin_DT, EncButton_Pin_SW); //eb(2, 3, 4); // CLK, DT, SW
// EncButton eb(2, 3, 4, INPUT); // + режим пинов энкодера
// EncButton eb(2, 3, 4, INPUT, INPUT_PULLUP); // + режим пинов кнопки
/////////////////////////////////////////////////////////////////////////////////////////
// управление тремя переменными при помощи энкодера:
// - нащёлкай кнопкой нужную переменную (1, 2 или 3 клика)
// - 1 переменная просто изменяется с постоянным шагом
// - 2 переменная: шаг 1, при зажатой кнопке - шаг 5
// - 3 переменная: шаг 1, при быстром вращении - шаг 5
int var1 = 0;
int var2 = 0;
int var3 = 0;
uint8_t EncButton_select = 1; // выбранная переменная
/////////////////////////////////////////////////////////////////////////////////////////
IRAM_ATTR void isr() { // esp8266/esp32
//void isr() {
eb.tickISR();
}
void EncButton_Read_setup() {
// показаны значения по умолчанию
eb.setBtnLevel(LOW);
eb.setClickTimeout(500);
eb.setDebTimeout(50);
eb.setHoldTimeout(600);
eb.setStepTimeout(200);
eb.setEncReverse(0);
eb.setEncType(EB_STEP4_LOW); //EB_STEP4_LOW - активный низкий сигнал (подтяжка к VCC). Полный период (4 фазы) за один щелчок. Установлен по умолчанию
//EB_STEP4_HIGH - активный высокий сигнал (подтяжка к GND). Полный период (4 фазы) за один щелчок
//EB_STEP2 - половина периода (2 фазы) за один щелчок
//EB_STEP1 - четверть периода (1 фаза) за один щелчок, а также энкодеры без фиксации
eb.setFastTimeout(30);
eb.counter = 0; // сбросить счётчик энкодера
/////////////////////////////////////////////////////////////////////////
//btn.tick();
//if (btn.press()) Serial.println("Кнопка нажата при старте");
//// btn.setBtnLevel(LOW); // можно настроить уровень
//// if (btn.read()) Serial.println("Кнопка нажата при старте");
//eb.tick();
//if (eb.press()) Serial.println("Кнопка нажата при старте");
////////////////////////////////////////////////////////////////////////
attachInterrupt(EncButton_Pin_CLK, isr, CHANGE); //Подкючаем аппаратное прерывание по изменению состояния пина
attachInterrupt(EncButton_Pin_DT, isr, CHANGE); //Подкючаем аппаратное прерывание по изменению состояния пина
eb.setEncISR(true);
}
void EncButton_Read_loop() {
eb.tick(); // Опрос энкодера
//if (eb.action()) {
//Led_Action_Start(Led_Action_Millis_Interval);
//}
//EncButton_Serial_loop();
}
/*
void EncButton_Serial_loop() {
//////////////////////////////////////////////////////////////////////////
// обработка поворота общая
if (eb.turn()) {
Serial.print("turn: dir ");
Serial.print(eb.dir());
Serial.print(", fast ");
Serial.print(eb.fast());
Serial.print(", hold ");
Serial.print(eb.pressing());
Serial.print(", counter ");
Serial.print(eb.counter);
Serial.print(", clicks ");
Serial.println(eb.getClicks());
}
// обработка поворота раздельная
if (eb.left()) Serial.println("left");
if (eb.right()) Serial.println("right");
if (eb.leftH()) Serial.println("leftH");
if (eb.rightH()) Serial.println("rightH");
// кнопка
if (eb.press()) Serial.println("press");
if (eb.click()) Serial.println("click");
if (eb.release()) {
Serial.println("release");
Serial.print("clicks: ");
Serial.print(eb.getClicks());
Serial.print(", steps: ");
Serial.print(eb.getSteps());
Serial.print(", press for: ");
Serial.print(eb.pressFor());
Serial.print(", hold for: ");
Serial.print(eb.holdFor());
Serial.print(", step for: ");
Serial.println(eb.stepFor());
}
// состояния
// Serial.println(eb.pressing());
// Serial.println(eb.holding());
// Serial.println(eb.busy());
// Serial.println(eb.waiting());
// таймаут
if (eb.timeout(1000)) Serial.println("timeout!");
// удержание
if (eb.hold()) Serial.println("hold");
if (eb.hold(3)) Serial.println("hold 3");
// импульсное удержание
if (eb.step()) Serial.println("step");
if (eb.step(3)) Serial.println("step 3");
// отпущена после импульсного удержания
if (eb.releaseStep()) Serial.println("release step");
if (eb.releaseStep(3)) Serial.println("release step 3");
// отпущена после удержания
if (eb.releaseHold()) Serial.println("release hold");
if (eb.releaseHold(2)) Serial.println("release hold 2");
// проверка на количество кликов
if (eb.hasClicks(3)) Serial.println("has 3 clicks");
// вывести количество кликов
if (eb.hasClicks()) {
Serial.print("has clicks: ");
Serial.println(eb.getClicks());
}
/////////////////////////////////////////////////////////////////////////////////////
// выбор переменной для изменения
if (eb.hasClicks()) {
EncButton_select = eb.getClicks();
Serial.println(String("Select: ") + EncButton_select);
}
if (eb.turn()) { // меняем переменную
switch (EncButton_select) {
case 1:
//var1 += 5 * eb.dir(); // изменение с шагом 5
var1 += eb.dir(); // изменение с шагом 1
break;
case 2:
//var2 += (eb.pressing() ? 5 : 1) * eb.dir(); // изменение с шагом 1, при зажатой кнопке шаг 5
var2 += eb.dir(); // изменение с шагом 1
break;
case 3:
//var3 += (eb.fast() ? 5 : 1) * eb.dir(); // изменение с шагом 1, при быстром вращении шаг 5
var3 += (eb.fast() ? 10 : 1) * eb.dir(); // изменение с шагом 1, при быстром вращении шаг 10
//var3 += eb.dir(); // изменение с шагом 1
break;
}
Serial.println(String("vars ") + var1 + ',' + var2 + ',' + var3);
}
///////////////////////////////////////////////////////////////////////////////////
}
*/
/*
// меняем значения переменных
// поворот энкодера
if (enc.turn()) {
// меняем с шагом 5
var += 5 * enc.dir();
// меняем с шагом 1 при обычном повороте, 10 при быстром
var += enc.fast() ? 10 : 1;
// меняем с шагом 1 при обычном повороте, 10 при нажатом
var += enc.pressing() ? 10 : 1;
// меняем одну переменную при повороте, другую - при нажатом повороте
if (enc.pressing()) var0++;
else var1++;
// если кнопка нажата - доступны предварительные клики
// Выбираем переменную для изменения по предв. кликам
if (enc.pressing()) {
switch (enc.getClicks()) {
case 1: var0 += enc.dir();
break;
case 2: var1 += enc.dir();
break;
case 3: var2 += enc.dir();
break;
}
}
}
// импульсное удержание на каждом шаге инкрементирует переменную
if (btn.step()) var++;
// смена направления изменения переменной после отпускания из step
if (btn.step()) var += dir;
if (btn.releaseStep()) dir = -dir;
// изменение выбранной переменной при помощи step
if (btn.step(1)) var1++; // клик-удержание
if (btn.step(2)) var2++; // клик-клик-удержание
if (btn.step(3)) var3++; // клик-клик-клик-удержание
// если держать step больше 2 секунд - инкремент +5, пока меньше - +1
if (btn.step()) {
if (btn.stepFor(2000)) var += 5;
else var += 1;
}
// включение режима по количеству кликов
if (btn.hasClicks()) mode = btn.getClicks();
// включение режима по нескольким кликам и удержанию
if (btn.hold(1)) mode = 1; // клик-удержание
if (btn.hold(2)) mode = 2; // клик-клик-удержание
if (btn.hold(3)) mode = 3; // клик-клик-клик-удержание
// или так
if (btn.hold()) mode = btn.getClicks();
// кнопка отпущена, смотрим сколько её удерживали
if (btn.release()) {
// от 1 до 2 секунд
if (btn.pressFor() > 1000 && btn.pressFor() <= 2000) mode = 1;
// от 2 до 3 секунд
else if (btn.pressFor() > 2000 && btn.pressFor() <= 3000) mode = 2;
}
*/
/////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////// VirtuinoCM /////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
//-------------VirtuinoCM Library and settings --------------
//#include "VirtuinoCM.h"
//VirtuinoCM virtuino;
//#define V_memory_count 32 // the size of V memory. You can change it to a number <=255)
//float V[V_memory_count]; // This array is synchronized with Virtuino V memory. You can change the type to int, long etc.
/////////////////////////////////////////////////////////////
int potentiometer_value = 0;
int value_min = 0;
int value_max = 1000;
//float angle = 0;
int frequency_value = 0;
/////////////////////////////////////////////////////////////
boolean Radio_Power_State; //не включене устройство (режим ожидания) при подключенном источнике питания //don't "power-on" of the unit (stand by mode) when power supply is connected
boolean Radio_Lights_State;
void setup() {
delay(100);
// open the Serial port
Serial.begin(115200);
Serial.println("Serial...");
Serial.println("Hello, ESP32!");
delay(200);
EncButton_Read_setup();
//WiFi_setup();
/////////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////// OLED U8g //////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////
OLED_setup();
/////////////////////////////////////////////////////////////////////////////////////////
//Wire.begin();
//Radio_setup();
//Led_setup();
//Buzzer_setup();
Serial.println(" ================== ");
Serial.println("Setup END");
Serial.println(" ... ");
delay(50);
}
void loop() {
potentiometer_value = constrain(map(analogRead(A0), 0, 1023, value_min, value_max / 10), value_min, value_max / 10);
frequency_value = constrain(map(analogRead(A0), 0, 1023, value_min, value_max), value_min, value_max);
//uiStep(); // проверка нажатия клавиши // check for key press
EncButton_Read_loop(); // RotaryEncoder // проверка нажатия клавиши // check for key press
//Radio_loop();
//WiFi_loop();
OLED_loop(10); // FPS
//Led_loop();
//Buzzer_loop();
}
///////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////// WIFI //////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
/*
#include <Wire.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
/////////////////////////////////////////////////////////////////////////////////////////
//#include "secrets.h" // WiFi Configuration (WiFi name and Password)
#define SSID "Wokwi-GUEST"
#define WIFI_PASSWORD ""
//#define SSID "Router ASUS"
//#define WIFI_PASSWORD "15162030"
const char* ssid = "Wokwi-GUEST";
const char* password = "";
//const char* ssid = "Router ASUS";
//const char* password = "15162030";
// Powered by CoinDesk - https://www.coindesk.com/price/bitcoin
const String url = "http://api.coindesk.com/v1/bpi/currentprice/BTC.json";
const String historyURL = "http://api.coindesk.com/v1/bpi/historical/close.json";
const String cryptoCode = "BTC";
HTTPClient http;
String lastPrice;
*/
/*
void WiFi_setup() {
//Serial.begin(115200);
//Serial.println("Hello, ESP32!");
//if (!display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS)) {
// Serial.println(F("SSD1306 allocation failed"));
// for (;;); // Don't proceed, loop forever
//}
//display.clearDisplay();
//display.setTextSize(1);
//display.setTextColor(SSD1306_WHITE);
//display.setCursor(0,0);
//display.println("Connecting to WiFi...");
//display.display();
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
}
Serial.print("CONNECTED to SSID: ");
Serial.println(ssid);
//display.print("Connected to ");
//display.println(ssid);
//display.display();
delay(5000);
}
void WiFi_loop() {
if (WiFi.status() == WL_CONNECTED) {
Serial.println("Getting current data...");
http.begin(url);
int httpCode = http.GET();
Serial.print("HTTP Code: ");
Serial.println(httpCode);
if (httpCode > 0) {
StaticJsonDocument<768> doc;
DeserializationError error = deserializeJson(doc, http.getString());
if (error) {
Serial.print(F("deserializeJson failed: "));
Serial.println(error.f_str());
delay(2500);
return;
}
Serial.print("HTTP Status Code: ");
Serial.println(httpCode);
String BTCUSDPrice = doc["bpi"]["USD"]["rate_float"].as<String>();
if(BTCUSDPrice == lastPrice) {
Serial.print("Price hasn't changed (Current/Last): ");
Serial.print(BTCUSDPrice);
Serial.print(" : ");
Serial.println(lastPrice);
delay(1250);
return;
} else {
lastPrice = BTCUSDPrice;
}
String lastUpdated = doc["time"]["updated"].as<String>();
http.end();
Serial.println("Getting history...");
StaticJsonDocument<1536> historyDoc;
http.begin(historyURL);
int historyHttpCode = http.GET();
DeserializationError historyError = deserializeJson(historyDoc, http.getString());
if (historyError) {
Serial.print(F("deserializeJson(History) failed: "));
Serial.println(historyError.f_str());
delay(2500);
return;
}
BTCUSD_print();
http.end();
}
//delay(1250);
}
}
*/
/*
void BTCUSD_print() {
{
{
//Display Header
//display.clearDisplay();
//display.setTextSize(1);
//printCenter("BTC/USD", 0, 0);
display.clearDisplay();
display.drawBitmap((128/2) - (24/2), 0, bitcoinIcon, 24, 24, WHITE);
display.display();
//Display BTC Price
display.setTextSize(1);
printCenter("$" + BTCUSDPrice, 0, 32);
//Display 24hr. Percent Change
double yesterdayPrice = historyDoc["bpi"]["2021-03-20"].as<double>();
bool isUp = BTCUSDPrice.toDouble() > yesterdayPrice;
double percentChange;
String dayChangeString = "24hr. Change: ";
if (isUp) {
percentChange = ((BTCUSDPrice.toDouble() - yesterdayPrice) / yesterdayPrice) * 100;
} else {
percentChange = ((yesterdayPrice - BTCUSDPrice.toDouble()) / yesterdayPrice) * 100;
dayChangeString = dayChangeString + "-";
}
display.setTextSize(1);
dayChangeString = dayChangeString + percentChange + "%";
printCenter(dayChangeString, 0, 55);
display.display();
}
}
}
*/
//void printCenter(const String buf, int x, int y) {
// int16_t x1, y1;
// uint16_t w, h;
// display.getTextBounds(buf, x, y, &x1, &y1, &w, &h); //calc width of new string
// display.setCursor((x - w / 2) + (128 / 2), y);
// display.print(buf);
//}
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////
/*
// *************************************************************************
// ****************************** Led **********************************
// *************************************************************************
// ************************* Объявление функций ****************************
#define Led_Power_Pin 9
#define Led_Action_Pin 13
#define Led_Lights_Pin 10
long Led_Action_Millis = 0; // здесь будет храниться время последнего изменения состояния
int Led_Action_Millis_Interval = 100; // интервал мигания в миллисекундах
bool Led_Action_Status = 0; // предыдущее состояние
bool Led_Action_Value = 0; // предыдущее состояние
//boolean Radio_Power_State; //не включене устройство (режим ожидания) при подключенном источнике питания //don't "power-on" of the unit (stand by mode) when power supply is connected
//boolean Radio_Lights_State;
void Led_setup() {
pinMode(Led_Power_Pin, OUTPUT); // переключение вывода в режим «выход»
pinMode(Led_Action_Pin, OUTPUT); // переключение вывода в режим «выход»
pinMode(Led_Lights_Pin, OUTPUT); // переключение вывода в режим «выход»
digitalWrite(Led_Power_Pin, LOW);
digitalWrite(Led_Action_Pin, LOW);
digitalWrite(Led_Lights_Pin, LOW);
//for(int i = 0; i < MAX_Led_RGB_PINS; i++){
//pinMode(Led_RGB_PINS[i], OUTPUT);
// }
Radio_Power_State = 0; //не включене устройство (режим ожидания) при подключенном источнике питания //don't "power-on" of the unit (stand by mode) when power supply is connected
Radio_Lights_State = 0; // Store initial LED state. HIGH when LED is on.
}
void Led_loop() {
Led_Power_loop(0);
Led_Lights_loop(0);
//Led_Action_Start(Led_Action_Millis_Interval);
Led_Action_loop(Led_Action_Millis_Interval);
}
void Led_Power_loop(bool enable) { // turns "power" on or off (stand-by mode)
if (enable == 1) {
digitalWrite(Led_Power_Pin, !digitalRead(Led_Power_Pin));
//power_state = digitalRead(Led_Power_Pin);
//if (power_state == 0) {
// lcd.enableSleep();
// digitalWrite(Led_Power_Pin, LOW);
//} else {
// lcd.disableSleep();
//}
}
return (digitalRead(Led_Power_Pin));
}
void Led_Lights_loop(bool enable) { // LED lights on/off
//if (enable)
{
digitalWrite(Led_Lights_Pin, !digitalRead(Led_Lights_Pin));
//Led_Lights_Pin_state = digitalRead(Led_Lights_Pin); // Remember LED state, lit or unlit.
}
return (digitalRead(Led_Lights_Pin));
}
void Led_Action_Start(int Millis_Interval_Value) { // turns "Action" on or off
if (Millis_Interval_Value >= 10) { // ON
Led_Action_Value = 1;
Led_Action_loop(Millis_Interval_Value);
} else {
Led_Action_Value = 1;
Led_Action_loop(Led_Action_Millis_Interval);
}
}
void Led_Action_loop(int Millis_Interval_Value) { // turns "Action" on or off
if (Led_Action_Status == 0 && Led_Action_Value != 0) { // ON
Led_Action_Status = 1;
digitalWrite(Led_Action_Pin, HIGH);
Led_Action_Millis = millis(); // запоминаем текущее время
} else if (millis() - Led_Action_Millis > Millis_Interval_Value) { // OFF // если светодиод был выключен – включаем и наоборот :)
//Led_Action_Millis = millis(); // запоминаем текущее время
Led_Action_Status = 0;
Led_Action_Value = 0;
digitalWrite(Led_Action_Pin, LOW);
}
//return (digitalRead(Led_Action_Pin));
}
// *************************************************************************
// *********************** Active_Buzzer *****************************
// *************************************************************************
#define Buzzer_Active_PIN 6
boolean Buzzer_ON_Active = 0; // LOW
boolean Buzzer_ON_Status = 0; // LOW
int Buzzer_Active_Value = 0; // предыдущее состояние
long Buzzer_Active_Millis = 0; // здесь будет храниться время последнего изменения состояния
int Buzzer_Active_Interval = 100; // интервал мигания в миллисекундах
void Buzzer_setup() {
pinMode(Buzzer_Active_PIN, OUTPUT);
digitalWrite(Buzzer_Active_PIN, LOW);
Buzzer_ON_Active = 1;
}
void Buzzer_loop() {
//Buzzer_ON_Active = 1;
Buzzer_Active_loop(Buzzer_Active_Interval);
}
void Buzzer_Active_Start(int Millis_Interval_Value) { // turns "Action" on or off
if (Millis_Interval_Value >= 10) { // ON
Buzzer_Active_Value = 1;
Buzzer_Active_loop(Millis_Interval_Value);
} else {
Buzzer_Active_Value = 1;
Buzzer_Active_loop(Buzzer_Active_Interval);
}
}
void Buzzer_Active_loop(int Millis_Interval_Value) {
if (Buzzer_ON_Status == 0 && Buzzer_Active_Value != 0) { // ON
Buzzer_ON_Status = 1;
digitalWrite(Buzzer_Active_PIN, HIGH);
Buzzer_Active_Millis = millis(); // запоминаем текущее время
} else if (millis() - Buzzer_Active_Millis > Millis_Interval_Value) { // OFF // если светодиод был выключен – включаем и наоборот :)
//Buzzer_Active_Millis = millis(); // запоминаем текущее время
Buzzer_ON_Status = 0;
Buzzer_Active_Value = 0;
digitalWrite(Buzzer_Active_PIN, LOW);
}
//Active_Buzzer_ON = 1;
if (Buzzer_ON_Active == 1) {
if (Buzzer_ON_Status == 1) {
digitalWrite(Buzzer_Active_PIN, HIGH); // включаем Buzzer
}
if (Buzzer_ON_Status == 0) {
digitalWrite(Buzzer_Active_PIN, LOW); // выключаем Buzzer
}
}
}
*/