#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 32 // OLED display height, in pixels
// Declaration for an SSD1306 display connected to I2C (SDA, SCL pins)
#define OLED_RESET 4 // Reset pin # (or -1 if sharing Arduino reset pin)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
const byte averageFactor = 7; // коэффициент сглаживания показаний (0 = не сглаживать)
// что можно настраивать
const float LineLimit = 5; // предел шкалы, бар
const float WarnLow = 0.1; // нижний предел по давлению, Бар
const float WarnHigh = 9.0; // верхний предел по давлению, Бар
const int WarnZummerCounterLimit = 60; // ограничение по количеству вяков для пищалки
const int pToneDefault = 1300; // начальный тон для пищалки, Гц
// чем выше, тем больше "инерционность"
// точки аппроксимаци
const float U1 = 0.5; // напряжение 1, В
const float P1 = 0; // давление 1, Бар
const float U2 = 4.5; // напряжение 2, В
const float P2 = 10.34; // давление 2, Бар
const int lightPin = 2; // пин, контролирующий подсветку
const int piezoPin = 3; // пин, к которому подключен пьезодинамик
const int sensorPin = A0; // пин, к которому подключен датчик давления
int lightStateCounter = 0;
int lightState = 0;
int lastLightState = LOW;
unsigned long lastDebounceTime = 0;
unsigned long debounceDelay = 50;
int sensorValue = 0;
int i = 0;
int j = 0;
float sValue = 0;
float uValue = 0;
float Vcc = 5.0; // опорное напряжение АЦП, для пересчета в напряжение
float pValue = 0;
int WarnBlinkCounter = 0;
int WarnZummerCounter = 1;
int pTone; // тон для пищалки
float dX = 0;
float x1, y1, x2, y2, k, b;
#define LOGO_HEIGHT 16
#define LOGO_WIDTH 44
const unsigned char logo_bmp [] PROGMEM = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x7f, 0x03, 0xc0, 0x00,
0x00, 0x00, 0x61, 0xc1, 0x80, 0x00, 0x0f, 0x00, 0x60, 0xe1, 0x80, 0x00, 0xf9, 0x80, 0x78, 0x7f,
0xfc, 0x0f, 0xe0, 0xc0, 0x1f, 0xc0, 0x07, 0xfd, 0xc0, 0x00, 0x03, 0xc0, 0x03, 0xc1, 0x80, 0x00,
0x00, 0xc0, 0x00, 0x03, 0x00, 0x00, 0x00, 0x40, 0x00, 0x06, 0x00, 0x40, 0x00, 0x40, 0x00, 0x0e,
0x00, 0x40, 0x00, 0x40, 0x00, 0x1c, 0x00, 0x60, 0x00, 0x40, 0x00, 0x18, 0x00, 0xe0, 0x00, 0x7f,
0xff, 0xf0, 0x00, 0xf0, 0x00, 0xff, 0xff, 0xe0, 0x00, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
void setup()
{
pinMode(lightPin, INPUT); // initialize the light control pin as a input:
digitalWrite(lightPin, 1);
delay(1000); // пауза перед включением
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.clearDisplay();
// определение коэффициентов линейного полинома напряжение-давление
y1 = P1;
y2 = P2;
x1 = U1 / Vcc * 1024;
x2 = U2 / Vcc * 1024;
k = (y1 - y2) / (x1 - x2);
b = y2 - k * x2;
pTone = pToneDefault;
// отрисовка масленки
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
(display.height() - LOGO_HEIGHT) / 2,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
// display.dim(false); // снижение яркости
delay(2000);
// Clear the buffer
display.clearDisplay();
// смещение масленки вниз за пределы экрана
for (i = ((display.height() - LOGO_HEIGHT) / 2);
i < (display.height() + LOGO_HEIGHT / 2);
i += 2 )
{
display.drawBitmap(
(display.width() - LOGO_WIDTH ) / 2,
i,
logo_bmp, LOGO_WIDTH, LOGO_HEIGHT, 1);
display.display();
delay(50);
display.clearDisplay();
}
// display.fadeout();
}
void loop()
{
lightState = digitalRead(lightPin);
if (averageFactor > 0) // усреднение показаний для устранения "скачков" барометра
{
int oldsensorValue = sensorValue;
sensorValue = analogRead(sensorPin);
sensorValue = (oldsensorValue * (averageFactor - 1) + sensorValue) / averageFactor;
}
display.setTextColor(WHITE);
sValue = sensorValue;
pValue = k * sValue + b; // давление в Барах
display.setCursor(5, 0);
// исключение отрицательного давления
if (pValue < 0)
{
pValue = 0;
}
display.setTextSize(3);
display.print(pValue);
display.setTextSize(2);
display.setCursor(85, 0); //80,8
display.print("ba");
if (lightState == HIGH)
{
display.print("1");
}
else
{
display.print("0");
}
// сигнал низкого или высокого давления
if ((pValue <= WarnLow) or (pValue >= WarnHigh))
{
// моргаем дисплеем
if (WarnBlinkCounter <= 10)
{
display.invertDisplay(false);
noTone(piezoPin); // Остановили звучание
++WarnBlinkCounter;
}
else
{
display.invertDisplay(true);
noTone(piezoPin);
pTone = pTone * 1.25;
if (WarnZummerCounter > 0)
{
tone(piezoPin, pTone); // Запустили звучание
++WarnZummerCounter;
if (WarnZummerCounter > WarnZummerCounterLimit * 2)
{
WarnZummerCounter = 0;
}
}
++WarnBlinkCounter;
if (WarnBlinkCounter >= 13)
{
WarnBlinkCounter = 0;
pTone = pToneDefault;
}
}
}
else
{
display.invertDisplay(false);
noTone(piezoPin); // Остановили звучание
WarnBlinkCounter = 0;
pTone = pToneDefault;
WarnZummerCounter = 1;
}
// рисуем полоску
dX = (display.width() - 6) / LineLimit;
for (j = 2; j < 6; j++)
{
display.drawLine (0, display.height() - j , pValue * dX, display.height() - j , 1);
}
for (j = 0; j < (display.width() - 1); j += round(dX))
{
display.setCursor(j, display.height() - 7);
display.setTextColor(1, 0);
// символ размером 5x7 пикселей.
display.setTextSize(1);
display.print(round(j / dX));
}
display.display();
delay(50);
// Clear the buffer
display.clearDisplay();
}