#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET 10 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define NUMFLAKES 10 // Number of snowflakes in the animation example
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 16
static const unsigned char PROGMEM logo_bmp[] =
{ B00000000, B11000000,
B00000001, B11000000,
B00000001, B11000000,
B00000011, B11100000,
B11110011, B11100000,
B11111110, B11111000,
B01111110, B11111111,
B00110011, B10011111,
B00011111, B11111100,
B00001101, B01110000,
B00011011, B10100000,
B00111111, B11100000,
B00111111, B11110000,
B01111100, B11110000,
B01110000, B01110000,
B00000000, B00110000 };
//========================================================
#define BUZZER_PIN 9
#define LASER_PIN 7
#define TRIGGER_PIN 8
#define ENCODER_SW_PIN 4 // кнопка энкодера
#define ENCODER_DT_PIN 5 // пин для считывания направления вращения энкодера
#define ENCODER_CLK_PIN 6 // СL - пин для импульсов для фиксации факта вращения
#define OLED_RESET 10
#define OLED_ADDRESS 0x3C // адрес OLED-дисплея для обращения к нему через I2C
//ОБЪЯВЛЕНИЕ ПЕРЕМЕННЫХ
boolean laser_mode = 0; // состояние лазерного модуля 0 - выкл (по-умолчанию); 1 - вкл
int step1 = 0; // целая часть величины шага измерений (0 по-умолчанию))
int step_dec = 5; // дробная часть величины шага измерений (5 по-умолчанию)
boolean menu_mode = 0; // находимся ли мы в реджиме меню или нет
int select = 5; // счетчик menu
int depth[4] = {0, 0, 0, 0}; // массив для числа расстояния
// переменные для отслеживания состояния кнопки-курка
boolean buttonPressed = false; // Логическая переменная для хранения состояние кнопки button
boolean button_flag = false; // флаг нажатия кнопки-курка
unsigned long button_timer = 0; // переменная хранит время момента последнего нажатия на кнопку lastPress
// переменные для отслеживания состояния энкодера
int CLKCurrent, CLKLast;
int DTCurrent;
int SWCurrent;
boolean encoderPressed = false; // состояние кнопки энкодера
boolean encoder_flag = false; // флаг нажатия энкодера
unsigned long encoder_timer = 0;
void setup() {
Serial.begin(9600);
// SSD1306_SWITCHCAPVCC = generate display voltage from 3.3V internally
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3D)) { // Address 0x3D for 128x64
Serial.println(F("SSD1306 allocation failed"));
for(;;); // Don't proceed, loop forever
}
// НАСТРОЙКА РЕЖИМА РАБОТЫ ПИНОВ ВВОДА/ВЫВОДА
pinMode(BUZZER_PIN, OUTPUT);
pinMode(LASER_PIN, OUTPUT);
pinMode(TRIGGER_PIN, INPUT_PULLUP); // PULLUP подтягивающий резистер, все инвертируется
pinMode(ENCODER_SW_PIN, INPUT_PULLUP); // PULLUP подтягивающий резистер, все инвертируется
pinMode(ENCODER_DT_PIN, INPUT);
pinMode(ENCODER_CLK_PIN, INPUT);
// настройка зуммера, зуммер "молчит" при высоком уровне сигнала на пине
digitalWrite(BUZZER_PIN, HIGH);
display.display();
delay(1000); // вывести команды которые мы дали в буфер обмена на дисплей
display.clearDisplay(); // очистить дисплей
displayUpdate(); // обратится к функции displayUpdate
}
void loop() {
// =========================================================
//БЛОК - РАБОТЫ С ЭНКОДЕРОМ
CLKCurrent = digitalRead(ENCODER_CLK_PIN); // считывание пина факта вращения
DTCurrent = digitalRead(ENCODER_DT_PIN); // переменная для определения вращения энкодера
// ЕСЛИ ПРОИЗОШЛО ВРАЩЕНИЕ
if (CLKCurrent != CLKLast && CLKCurrent == 0) {
// чтобы узнать направления вращения, будем считывать значение DT
digitalWrite(BUZZER_PIN, LOW);
delay(50);
digitalWrite(BUZZER_PIN, HIGH);
if (DTCurrent == CLKCurrent) {
if (menu_mode == 1){
if (select < 4){
depth[select] = (depth[select] + 1) % 10;
displayUpdate();
}
if (select == 4){
step1 = (step1 + (step_dec + 5) / 10) % 11;
step_dec = ((step_dec + 5) % 10);
displayUpdate();
}
}
}
else {
if (menu_mode == 1){
if (select < 4){
depth[select] = (depth[select] - 1) % 10;
if (depth[select] < 0){
depth[select] = 9;
}
displayUpdate();
}
if (select == 4){
step_dec = ((step_dec + 5) % 10);
step1 = (step1 - (step_dec + 5) / 10);
displayUpdate();
}
}
}
}
CLKLast = CLKCurrent;
// ЕСЛИ БЫЛА НАЖАТА КНОПКА ЭНКОДЕРА
encoderPressed = !digitalRead(ENCODER_SW_PIN); // ...
if (encoderPressed && !encoder_flag && millis() - encoder_timer > 100) {
encoder_flag = true;
encoder_timer = millis();
//кнопка энкодера нажата
}
//КОРОТКОЕ НАЖАТИЕ ЭНКОДЕРА
if (!encoderPressed && encoder_flag && (millis() - encoder_timer) > 50 && (millis() - encoder_timer < 1000)) {
encoder_flag = false;
encoder_timer = millis();
// действия после КОРОТКОГО нажатия энкодера
// если режим "МЕНЮ" НЕ АКТИВИРОВАН
if (menu_mode == 0) {
// включение и выключения лазерного модуля
if (laser_mode == 0){
digitalWrite(LASER_PIN, HIGH);
}
else{
digitalWrite(LASER_PIN, LOW);
}
laser_mode = !laser_mode;
Serial.print("laser mode: ");
Serial.println(laser_mode);
displayUpdate();
}
// если режим "МЕНЮ" АКТИВИРОВАН
else{
select = (select + 1) % 5;
displayUpdate();
}
}
//ДЛИННОЕ НАЖАТИЕ ЭНКОДЕРА
if (!encoderPressed && encoder_flag && (millis() - encoder_timer) > 1500) {
encoder_flag = false;
encoder_timer = millis();
//действия после ДЛИННОГО нажатия энкодера
menu_mode = !menu_mode; //переключение в режим "МЕНЮ" и обратно
if (menu_mode) {
select = 0;
}
else {
select = 5;
}
displayUpdate();
Serial.print("menu mode: ");
Serial.println(menu_mode);
}
// ===================================================================
//БЛОК - РАБОТЫ С КНОПКОЙ КУРКОМ
// ЕСЛИ НАЖАТА КНОПКА-КУРОК
buttonPressed = !digitalRead(TRIGGER_PIN); // ...
if (buttonPressed && !button_flag && millis() - button_timer > 100) {
button_flag = true;
button_timer = millis();
//кнопка-курок нажата
}
//КОРОТКОЕ НАЖАТИЕ КУРКА
if (!buttonPressed && button_flag && millis() - button_timer > 100 && millis() - button_timer < 1000) {
button_flag = false;
button_timer = millis();
if (menu_mode == 0) {
Serial.println("TRIGGER - SHORT PRESS");
// подача звукового сигнала короткого нажатия
digitalWrite(BUZZER_PIN, LOW);
delay(50);
digitalWrite(BUZZER_PIN, HIGH);
// эмуляция нажатий клавиш на клавиатуре
/*
Keyboard.press(KEY_RETURN);
Keyboard.release(KEY_RETURN);
*/
// ожидание окончания измерений
delay(1100);
// звуковой сигнал
digitalWrite(BUZZER_PIN, LOW);
delay(500);
digitalWrite(BUZZER_PIN, HIGH);
Serial.println("MEASUREMENT DONE");
depth[0] = (depth[0] + (depth[1] + (depth[2] + step1 + (depth[3] + step_dec) / 10) /10) / 10) % 10; // сотни
depth[1] = (depth[1] + (depth[2] + step1 + (depth[3] + step_dec) / 10) /10) % 10;// десятки
depth[2] = (depth[2] + step1 + (depth[3] + step_dec) / 10) % 10; // единицы
depth[3] = (depth[3] + step_dec) % 10; //доли
displayUpdate();
}
}
// ДЛИННОЕ НАЖАТИЕ КУРКА
if (!buttonPressed && button_flag && millis() - button_timer > 1000) {
button_flag = false;
button_timer = millis();
if (menu_mode == 0) {
Serial.println("TRIGGER - LONG PRESS");
// подача звукового сигнала долгого нажатия
delay(50);
digitalWrite(BUZZER_PIN, HIGH);
digitalWrite(BUZZER_PIN, LOW);
delay(50);
digitalWrite(BUZZER_PIN, HIGH);
// эмуляция нажатий клавиш на клавиатуре
/*
Keyboard.press(KEY_TAB);
Keyboard.release(KEY_TAB);
Keyboard.press(KEY_TAB);
Keyboard.release(KEY_TAB);
Keyboard.write(' ');
Keyboard.press(KEY_TAB);
Keyboard.release(KEY_TAB);
Keyboard.press(KEY_RETURN);
Keyboard.release(KEY_RETURN);
*/
digitalWrite(BUZZER_PIN, LOW);
// ожидание окончания измерений
delay(1100);
// звуковой сигнал
digitalWrite(BUZZER_PIN, LOW);
delay(500);
digitalWrite(BUZZER_PIN, HIGH);
Serial.println("MEASUREMENT REPEATED");
}
}
}
// ====================================================================
// ФУНКЦИИ
// Функция обновления изображения на OLED-дисплее
void displayUpdate(){
display.clearDisplay(); // очистить экран
display.setTextColor(WHITE); // выставить белый цвет текста
display.setTextSize(3); // 3-й размер текста
display.setCursor(20, 20); // утсановить курсор в положение 20 20
for (int i = 0; i < 4; i++){ //для ай пока оно меньше 4 прибавлять нему 1
if (select == i){ // выделить цифру под номером селект
display.setTextColor(BLACK, WHITE); // контрастный цвет
}
else{
display.setTextColor(WHITE);
}
display.print(String(depth[i]));
if (i == 2){
display.setTextColor(WHITE);
display.print(".");
}
display.display();
}
display.setCursor(10, 50);
display.setTextSize(1);
if (laser_mode == 1){
display.setTextColor(BLACK, WHITE);
display.print("ON");
display.setTextColor(WHITE);
display.print(" OFF");
display.display();
}
else{
display.setTextColor(WHITE);
display.print("ON ");
display.setTextColor(BLACK, WHITE);
display.print("OFF");
display.display();
}
display.setTextColor(WHITE);
display.print(" STEP ");
if (select == 4){
display.setTextColor(BLACK, WHITE);
display.print(String(step1) + "." + String(step_dec));
display.display();
}
else {
display.setTextColor(WHITE);
display.print(String(step1) + "." + String(step_dec));
display.display();
}
}