forked from bgp/feeder
format and data
This commit is contained in:
parent
6e41e3d1c2
commit
4a5d41c48d
315
microDS3231.h
315
microDS3231.h
|
@ -1,82 +1,247 @@
|
|||
/*
|
||||
Лёгкая библиотека для работы с RTC DS3231 для Arduino
|
||||
Документация:
|
||||
GitHub: https://github.com/GyverLibs/microDS3231
|
||||
Возможности:
|
||||
- Чтение и запись времени
|
||||
- Вывод в char* и String
|
||||
- Чтение температуры датчика
|
||||
|
||||
Egor 'Nich1con' Zakharov & AlexGyver, alex@alexgyver.ru
|
||||
https://alexgyver.ru/
|
||||
MIT License
|
||||
|
||||
Версии:
|
||||
v1.2 - добавлены ограничения на вводимые в setTime числа. Также нельзя ввести 29 февраля увы =)
|
||||
v1.3 - пофикшено зависание, когда модуль отключен но опрашивается
|
||||
v1.4 - незначительный фикс
|
||||
v2.0 - новые возможности, оптимизация и облегчение
|
||||
v2.1 - добавил вывод температуры, вывод в String и char
|
||||
v2.2 - исправлены дни недели (пн-вс 1-7)
|
||||
v2.3 - небольшие исправления, оптимизация, изменён порядок вывода даты
|
||||
v2.4 - исправлена установка времени компиляции
|
||||
v2.5 - добавлен begin для проверки наличия модуля на линии
|
||||
v2.6 - исправлены отрицательные температуры
|
||||
Скетч к проекту "Спутниковая Роботорговля"
|
||||
bgp, 2023
|
||||
*/
|
||||
|
||||
#ifndef microDS3231_h
|
||||
#define microDS3231_h
|
||||
//#include <microWire.h> // выбор между библиотеками Wire и microWire
|
||||
#include <Wire.h>
|
||||
#include "buildTime.h"
|
||||
#define EE_RESET 26 // любое число 0-255. Измени, чтобы сбросить настройки и обновить время
|
||||
#define FEED_SPEED 2500 // задержка между шагами мотора (мкс)
|
||||
#define DIRPIN 2 // d2 направление
|
||||
#define STEPPIN 3 // d3 движение
|
||||
#define BTN_PIN 4 // кнопка выдачи
|
||||
#define BUNKERPIN 5 // d5 датчик наличия корма
|
||||
#define HANDPIN 6 // d6 датчик наличия руки
|
||||
#define TERM_INHIB 8 // d8 посылать "отказ от обслуживания" -upd
|
||||
#define TERM_COIN 7 // d7 считаем монетки - upd
|
||||
#define SLEEP 9 // d9 пока не работаем - двигатель спит
|
||||
#define RELAY 10 // d10 ключ для отключения терминала и двигателя в ночное время
|
||||
#define BTN_PIN2 11 // кнопка настройки
|
||||
// 773 - шаги на один полный круг
|
||||
// 3 - количество выемок в одном круге
|
||||
// 258 = 773/3
|
||||
#define STEPS_FRW 258 // шаги вперёд
|
||||
#define STEPS_BKW 0 // шаги назад
|
||||
|
||||
#include <Arduino.h>
|
||||
#define COMPILE_TIME F(__TIMESTAMP__)
|
||||
// =========================================================
|
||||
#include <EEPROM.h>
|
||||
#include "microDS3231.h"
|
||||
MicroDS3231 rtc;
|
||||
#include "EncButton.h"
|
||||
|
||||
struct DateTime {
|
||||
uint8_t second;
|
||||
uint8_t minute;
|
||||
uint8_t hour;
|
||||
uint8_t day;
|
||||
uint8_t date;
|
||||
uint8_t month;
|
||||
uint16_t year;
|
||||
};
|
||||
EncButton<EB_TICK, BTN_PIN> btn;
|
||||
EncButton<EB_TICK, BTN_PIN2> btn_setup;
|
||||
EncButton<EB_TICK, BUNKERPIN> term_inhib;
|
||||
// EncButton<EB_TICK, TERM_COIN> term_coin_put;
|
||||
int feedAmount = 1;
|
||||
|
||||
class MicroDS3231 {
|
||||
public:
|
||||
MicroDS3231(uint8_t addr = 0x68); // конструктор. Можно передать адрес
|
||||
bool begin(void); // инициализация, вернет true, если RTC найден
|
||||
void setTime(const __FlashStringHelper* stamp); // установка времени == времени компиляции
|
||||
void setTime(DateTime time); // установить из структуры DateTime
|
||||
void setTime(int8_t seconds, int8_t minutes, int8_t hours, int8_t date, int8_t month, int16_t year); // установка времени
|
||||
void setHMSDMY(int8_t hours, int8_t minutes, int8_t seconds, int8_t date, int8_t month, int16_t year); // установка времени тип 2
|
||||
|
||||
DateTime getTime(void); // получить в структуру DateTime
|
||||
uint8_t getSeconds(void); // получить секунды
|
||||
uint8_t getMinutes(void); // получить минуты
|
||||
uint8_t getHours(void); // получить часы
|
||||
uint8_t getDay(void); // получить день недели
|
||||
uint8_t getDate(void); // получить число
|
||||
uint16_t getYear(void); // получить год
|
||||
uint8_t getMonth(void); // получить месяц
|
||||
|
||||
String getTimeString(); // получить время как строку вида HH:MM:SS
|
||||
String getDateString(); // получить дату как строку вида DD.MM.YYYY
|
||||
void getTimeChar(char* array); // получить время как char array [8] вида HH:MM:SS
|
||||
void getDateChar(char* array); // получить дату как char array [10] вида DD.MM.YYYY
|
||||
|
||||
bool lostPower(void); // проверка на сброс питания
|
||||
float getTemperatureFloat(void);// получить температуру float
|
||||
int getTemperature(void); // получить температуру int
|
||||
|
||||
private:
|
||||
uint8_t encodeRegister(int8_t data);
|
||||
int getTemperatureRaw(void);
|
||||
uint8_t readRegister(uint8_t addr);
|
||||
uint8_t unpackRegister(uint8_t data);
|
||||
uint8_t unpackHours(uint8_t data);
|
||||
const uint8_t _addr;
|
||||
};
|
||||
// https://robotchip.ru/podklyuchenie-kupyuropriemnika-cashcode-sm-k-arduino/
|
||||
|
||||
#endif
|
||||
int valuePulse = 10; // Стоимость одного импульса
|
||||
int minWidthPulse = 80; // Минимальная ширина одного импульса
|
||||
int maxWidthPulse = 120; // Максимальная ширина одного импульса
|
||||
int debounce = 4; // Защита от помех
|
||||
int pulseCount = 0; // Сколько импульсов получено
|
||||
int receivedRUB = 0; // Сумма
|
||||
unsigned long pulseDuration; // Как давно был последний импульс
|
||||
unsigned long pulseBegin = 0; // Начало импульса
|
||||
unsigned long pulseEnd = 0; // Конец импульса
|
||||
unsigned long curtime; // Время
|
||||
int postPulsePause = 300; // Время ожидания, для завершения подсчета импульсов
|
||||
int pulseState; // Состояние входа "0" или "1"
|
||||
int lastState = 1; // Последние состояние входа "0" или "1"
|
||||
|
||||
int paymentsCount = 0;
|
||||
|
||||
int onTime = 6; // время включения
|
||||
int offTime = 20; // время выключения
|
||||
|
||||
unsigned long sleepTime; // переменная для задания времени сна
|
||||
|
||||
int monitor_speed = 9600;
|
||||
|
||||
// GND -- [ R2 ] -- A0 -- [ R1 ] -- VIN
|
||||
#define VREF 4.5 // точное напряжение на пине 5V (в данном случае зависит от стабилизатора на плате Arduino)
|
||||
#define DIV_R1 6800 // точное значение 6.80 кОм резистора
|
||||
#define DIV_R2 1100 // точное значение 1.1 кОм резистора
|
||||
|
||||
#define DEBUG true
|
||||
|
||||
void setup()
|
||||
{
|
||||
rtc.begin();
|
||||
if (EEPROM.read(0) != EE_RESET)
|
||||
{ // первый запуск
|
||||
EEPROM.write(0, EE_RESET);
|
||||
EEPROM.put(1, feedAmount);
|
||||
rtc.setTime(BUILD_SEC, BUILD_MIN, BUILD_HOUR, BUILD_DAY, BUILD_MONTH, BUILD_YEAR);
|
||||
}
|
||||
EEPROM.get(1, feedAmount);
|
||||
pinMode(STEPPIN, OUTPUT); // пин движения
|
||||
pinMode(DIRPIN, OUTPUT); // пин направления
|
||||
pinMode(HANDPIN, INPUT); // пин ИК датчик руки
|
||||
pinMode(BUNKERPIN, INPUT); // пин ИК датчик бункер
|
||||
pinMode(LED_BUILTIN, OUTPUT); // встроенный LED
|
||||
pinMode(SLEEP, OUTPUT); // пин для отключения двигателя
|
||||
pinMode(TERM_COIN, INPUT); // прием сигнала от терминала
|
||||
pinMode(RELAY, OUTPUT);
|
||||
|
||||
sleepTime = 60 * 60 * 1000;
|
||||
// Debug
|
||||
if (DEBUG)
|
||||
{
|
||||
Serial.begin(monitor_speed); // debug в serial
|
||||
sleepTime = 10 * 1000;
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
static uint32_t tmr = 0;
|
||||
float voltage = (float)analogRead(0) * VREF * ((DIV_R1 + DIV_R2) / DIV_R2) / 1024;
|
||||
if (millis() - tmr > 500)
|
||||
{ // два раза в секунду
|
||||
static byte prevMin = 0;
|
||||
tmr = millis();
|
||||
DateTime now = rtc.getTime();
|
||||
if (DEBUG)
|
||||
{
|
||||
// получаем время
|
||||
Serial.println(String(voltage) + " V"); // debug
|
||||
Serial.println(String(now.hour) + " h"); // debug
|
||||
String str_time = String(rtc.getHours()) + ":" + String(rtc.getMinutes()) + ":" + String(rtc.getSeconds());
|
||||
String date_time = String(rtc.getDate()) + "-" + String(rtc.getMonth()) + "-" + String(rtc.getYear());
|
||||
Serial.println(str_time + " " + date_time);
|
||||
}
|
||||
if (voltage < 31)
|
||||
{
|
||||
digitalWrite(RELAY, LOW);
|
||||
delay(sleepTime);
|
||||
}
|
||||
if ((now.hour >= onTime && now.hour < offTime && voltage > 31))
|
||||
{ //&& voltage > 10.2
|
||||
digitalWrite(RELAY, HIGH); // работаем если время рабочее И напряжение выше минимума
|
||||
}
|
||||
else
|
||||
{
|
||||
digitalWrite(RELAY, LOW);
|
||||
}
|
||||
}
|
||||
|
||||
digitalWrite(TERM_INHIB, term_inhib.isHold() == 0);
|
||||
|
||||
btn.tick();
|
||||
btn_setup.tick();
|
||||
term_inhib.tick();
|
||||
|
||||
pulseState = digitalRead(TERM_COIN); // Считываем значение с входа TERM_COIN
|
||||
curtime = millis(); // Записываем значение миллисекунд с момента начала выполнения программы
|
||||
|
||||
if ((pulseState == 0) && (lastState == 1)) // Ждем начало импульса, логический "0"
|
||||
{
|
||||
pulseBegin = curtime; // Записываем значение милисикунд
|
||||
lastState = 0; // Записываем значение "0" в переменную lastState
|
||||
}
|
||||
else if ((pulseState == 1) && (lastState == 0)) // Ждем окончания импульса, логический "1"
|
||||
{
|
||||
pulseDuration = curtime - pulseBegin; // Расчет длительности импульса в миллисекунд
|
||||
if (pulseDuration > debounce) // Защита от помех, если импульс был небольшой
|
||||
{
|
||||
lastState = 1; // Записываем значение "1" в переменную lastState
|
||||
}
|
||||
if ((pulseDuration > minWidthPulse) && (pulseDuration < maxWidthPulse)) // Проверяем ширину импульса
|
||||
{
|
||||
pulseEnd = curtime; // Сохранить значение милисикунд, окончания импульса
|
||||
pulseCount++; // Инкремент счетчика импульсов
|
||||
}
|
||||
}
|
||||
if ((pulseEnd > 0) && (curtime - pulseEnd > postPulsePause)) // Проверяем, поступают ли еще импульсы
|
||||
{
|
||||
receivedRUB += pulseCount * valuePulse; // Расчет суммы
|
||||
if (receivedRUB > 0)
|
||||
{
|
||||
paymentsCount++; // Надо описать логику, "принимаем платежи сколько угодно раз и кормим сстолько же, как только в кадре появятся руки"
|
||||
Serial.print("Credit: "); // Вывести текст на последовательный порт //Debug
|
||||
Serial.print(receivedRUB); // Вывести значение переменной на пслеовательный порт //Debug
|
||||
Serial.println(" RUB"); // Вывести текст на последовательный порт //Debug
|
||||
Serial.print("Payed: ");
|
||||
Serial.print(paymentsCount);
|
||||
Serial.println(" times");
|
||||
pulseEnd = 0; // Обнуляем
|
||||
pulseCount = 0; // Обнуляем
|
||||
receivedRUB = 0; // Обнуляем
|
||||
}
|
||||
}
|
||||
|
||||
if (paymentsCount > 0) // Debug подставляем руки, жмем кнопку - получаем внеочередную кормежку
|
||||
{
|
||||
feed();
|
||||
paymentsCount--;
|
||||
Serial.print("Payed: ");
|
||||
Serial.print(paymentsCount);
|
||||
Serial.println(" times");
|
||||
}
|
||||
|
||||
if (btn.click())
|
||||
{
|
||||
feed();
|
||||
}
|
||||
|
||||
if (btn_setup.hold())
|
||||
{
|
||||
feedAmount = 1;
|
||||
EEPROM.put(1, feedAmount);
|
||||
}
|
||||
if (btn_setup.click()) // Задаем размер порции:
|
||||
{
|
||||
feedAmount += 1;
|
||||
EEPROM.put(1, feedAmount); // записываем количество шагов в постоянную память
|
||||
}
|
||||
|
||||
} // конец основного цикла
|
||||
|
||||
// выдача корма
|
||||
void feed()
|
||||
{
|
||||
for (int i = 0; i < feedAmount; i++)
|
||||
oneRev();
|
||||
disableMotor();
|
||||
}
|
||||
|
||||
// кормежка по кнопке
|
||||
void feedByButton()
|
||||
{
|
||||
if (btn.click())
|
||||
{
|
||||
feed();
|
||||
}
|
||||
}
|
||||
|
||||
// выключаем ток на мотор
|
||||
void disableMotor()
|
||||
{
|
||||
digitalWrite(SLEEP, LOW);
|
||||
}
|
||||
|
||||
// вращение
|
||||
void runMotor()
|
||||
{
|
||||
digitalWrite(SLEEP, HIGH); // Включаем мотор
|
||||
digitalWrite(STEPPIN, HIGH); // по часовой
|
||||
delayMicroseconds(FEED_SPEED);
|
||||
digitalWrite(STEPPIN, LOW); // против часовой
|
||||
delayMicroseconds(FEED_SPEED);
|
||||
}
|
||||
|
||||
// вращение двигателя в виброрежиме, для непопущения заклинивания
|
||||
void oneRev()
|
||||
{
|
||||
for (int i = 0; i < STEPS_BKW; i++)
|
||||
{
|
||||
digitalWrite(DIRPIN, HIGH); // low обратное вращение
|
||||
runMotor();
|
||||
}
|
||||
for (int i = 0; i < STEPS_FRW; i++)
|
||||
{
|
||||
digitalWrite(DIRPIN, LOW);
|
||||
runMotor();
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue