#include "RTClib.h"
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal_I2C.h>
///////////////////////////////////////////////////////////////////////////
#define I2C_ADDR 0x27
#define LCD_COLUMNS 20
#define LCD_LINES 2
#define DS_PIN 10
#define echoPin 7 // Echo Pin
#define trigPin 8 // Trigger Pin
byte BUTTON_PIN1 = 5;
byte BUTTON_PIN2 = 2;
int maximumRange = 200; // Максимальная высота полки (см)
int minimumRange = 0; // Минимальная высота
long duration, distance; // Длительность и дистанция
unsigned int clickTime = 0;
unsigned int lastClickTime = 0;
const short maxTTC = 500;
const short minTTC = 30;
bool waiting = false;
int combo = 0;
bool wasPressed = false;
struct shlfObject {
float height;
String name;
};
LiquidCrystal_I2C lcd(I2C_ADDR, LCD_COLUMNS, LCD_LINES);
///////////////////////////////////////////////////////////////////////////
bool wasPressed1 = false;
bool wasPressed2 = false;
bool click(byte BUTTON_PIN,bool& wasPressed)
{
if(!digitalRead(BUTTON_PIN))
{
if(wasPressed)
{
return false;
}
else
{
wasPressed= true;
return false;
}
}
else
{
if(wasPressed)
{
wasPressed = false;
return true;
}
else {
return false;
}
}
}
///////////////////////////////////////////////////////////
int countClicks(bool click)
{
if (click)
{ // Если кнопка была нажата
clickTime = millis(); // Текущее время клика
if (waiting) { // Уже ждём следующего клика?
unsigned int tmp = clickTime - lastClickTime; // время между кликами
if (tmp < minTTC) // Если прошло меньше maxTTC
{
return 0;
}
else
{ // Если прошло больше minTTC
combo++;
lastClickTime = clickTime;
return 0; // Возвращаем количество кликов
}
} else
{ // Это первый клик?
combo ++;
waiting = true;
lastClickTime = clickTime; // Фиксируем время первого клика
return 0;
}
}
else
{
if(waiting)
{
clickTime = millis(); // Текущее время
unsigned int tmp = clickTime - lastClickTime; // время между кликами
if(tmp > maxTTC)
{
int res = combo;
combo = 0;
return res;
}
}
else
{
return 0;
}
}
return 0;
// Если кнопка не нажата или продолжаем ждать:
}
///////////////////////////////////////////////////////////////////////////
// Функция измерения стопки
long measureHeight()
{
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
long duration = pulseIn(echoPin, HIGH);
float distance = duration / 58.2; // Конвертация в см
return distance;
}
// Функция ввода
String cin()
{
String smth;
while(Serial.available() <= 0)
{
delay(20);
}
smth = Serial.readString();
return smth;
}
void changeType(String& typeName, float& lenght, float& shelfHeight)
{
//Записываем название
Serial.println("Enter object type");
lcd.setCursor(0, 0);
lcd.print("Enter obj type");
String name = cin();
if(name == "")
{
lcd.setCursor(0, 1);
lcd.print("Wrong name");
Serial.println("Wrong name");
return ;
}
//Измеряем высоту
unsigned int objHeight = 0;
unsigned int tmpHeight = measureHeight();
if(tmpHeight > 0)
{
objHeight = shelfHeight - tmpHeight;
typeName= name;
lenght = objHeight;
lcd.setCursor(0, 1);
lcd.print("Type changed");
Serial.println("Type changed");
}
else
{
lcd.setCursor(0, 1);
lcd.print("Wrong height");
Serial.println("Can`t measure right height");
return ;
}
}
//Колличество предметов на полке
short countObj(shlfObject object, float& shelfHeight)
{
float height = shelfHeight - measureHeight();
return height / object.height;
}
///////////////////////////////////////////////////////////////////////////
OneWire oneWire(DS_PIN);
DallasTemperature sensor(&oneWire);
float temp()
{
sensor.requestTemperatures();
return sensor.getTempCByIndex(0);
}
//////////////////////////////////////////////////////////////////////////
RTC_DS1307 RTC; //Create the DS3231 object
char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
String time()
{
DateTime now = RTC.now();
String date;
if (now.hour()<=9)
{
date += "0";
}
date += String(now.hour()) + "h";
if (now.minute()<=9)
{
date += "0";
}
date += String(now.minute()) + "m";
if (now.second()<=9)
{
date += "0";
}
date += String(now.second()) + "s";
return date;
}
////////////////////////////////////////////////////////////////////////////
#define SENSORPIN 12
bool motion()
{
byte state = digitalRead(SENSORPIN);
if(state == 1){
return true;
}
else if(state == 0)
{
return false;
};
}
//////////////////////////////////////////////////////////////////////////////
struct readings
{
String date = "";
float temp = 0;
bool motion = false;
};
#define HISTORYSIZE 60
short hsIter = 0;
readings history[HISTORYSIZE];
readings prev;
short ecnIter = 0;
shlfObject object;
float shelfHeight = measureHeight();
void setup()
{
Serial.begin(9600); // Устанавливаем скорость обмена
pinMode(trigPin, OUTPUT);
pinMode(echoPin, INPUT);
pinMode(BUTTON_PIN1, INPUT_PULLUP);
pinMode(BUTTON_PIN2, INPUT_PULLUP);
Wire.begin();
RTC.begin();
pinMode(SENSORPIN, INPUT);
sensor.begin();
lcd.init();
lcd.backlight();
Serial.println("Программа запущена");
}
bool mode = true;
void loop()
{
bool button1 = click(BUTTON_PIN1,wasPressed1);
bool button2 = click(BUTTON_PIN2,wasPressed2);
if(button1 && button2)
{
mode = !mode;
button1 = false;
button2 = false;
lcd.clear();
}
if(mode)
{
int doubleClicks = countClicks(button1);
if(doubleClicks==1)
{
lcd.clear();
Serial.println("Click");
if(object.height != 0)
{
int count = countObj(object,shelfHeight);
Serial.println(count);
lcd.setCursor(0, 0);
lcd.print("Obj type:"+ object.name);
lcd.setCursor(0, 1);
lcd.print("Count:"); lcd.print(count);
}
else
{
lcd.setCursor(0, 0);
lcd.print("Wrong obj height");
Serial.println("Wrong object height");
}
}
if(doubleClicks==2){
lcd.clear();
Serial.println("DoubleClick");
lcd.setCursor(0, 0);
shelfHeight = measureHeight();
Serial.println(shelfHeight);
changeType(object.name,object.height,shelfHeight);
Serial.println(object.height);
}
if(doubleClicks > 2){
lcd.clear();
Serial.println("MultiClick");
if(object.height != 0){
lcd.setCursor(0,0);
lcd.print("Obj height:"); lcd.print(object.height);
Serial.println(object.height);
}
else
{
lcd.print("Wrong obj height");
}
}
}
else{
if(button1)
{
Serial.write("<");
ecnIter--;
if(ecnIter<0)
{
ecnIter = HISTORYSIZE-1;
}
Serial.print(history[ecnIter].date); Serial.print(" ");
Serial.print(history[ecnIter].temp); Serial.print(" ");
Serial.println(history[ecnIter].motion);
lcd.setCursor(0, 0);
lcd.print("Time:"+ history[ecnIter].date);
lcd.setCursor(0, 1);
lcd.print(" ");
if((history[ecnIter].temp) >= 0)
{
lcd.print("+");
}
lcd.setCursor(0, 1);
lcd.print(history[ecnIter].temp); lcd.print("c");
lcd.setCursor(9, 1);
lcd.print("Mtn:");
if(history[ecnIter].motion)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
if(button2)
{
Serial.write(">");
ecnIter++;
if(ecnIter==HISTORYSIZE)
{
ecnIter=0;
}
Serial.print(history[ecnIter].date); Serial.print(" ");
Serial.print(history[ecnIter].temp); Serial.print(" ");
Serial.println(history[ecnIter].motion);
lcd.setCursor(0, 0);
lcd.print("Time:"+ history[ecnIter].date);
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(0, 1);
if((history[ecnIter].temp) >= 0)
{
lcd.print("+");
}
lcd.print(history[ecnIter].temp); lcd.print("c");
lcd.setCursor(9, 1);
lcd.print("Mtn:");
if(history[ecnIter].motion)
{
lcd.print("Yes");
}
else
{
lcd.print("No ");
}
}
}
if(temp() != prev.temp || motion() != prev.motion)
{
if(hsIter <HISTORYSIZE)
{
hsIter++;
}
else
{
hsIter = 0;
}
history[hsIter].date = time();
history[hsIter].temp = temp();
history[hsIter].motion = motion();
prev.date = time();
prev.temp = temp();
prev.motion = motion();
}
}