forked from bgp/feeder
format and data
This commit is contained in:
parent
6e41e3d1c2
commit
4a5d41c48d
307
microDS3231.h
307
microDS3231.h
|
@ -1,82 +1,247 @@
|
||||||
/*
|
/*
|
||||||
Лёгкая библиотека для работы с RTC DS3231 для Arduino
|
Скетч к проекту "Спутниковая Роботорговля"
|
||||||
Документация:
|
bgp, 2023
|
||||||
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 - исправлены отрицательные температуры
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef microDS3231_h
|
#define EE_RESET 26 // любое число 0-255. Измени, чтобы сбросить настройки и обновить время
|
||||||
#define microDS3231_h
|
#define FEED_SPEED 2500 // задержка между шагами мотора (мкс)
|
||||||
//#include <microWire.h> // выбор между библиотеками Wire и microWire
|
#define DIRPIN 2 // d2 направление
|
||||||
#include <Wire.h>
|
#define STEPPIN 3 // d3 движение
|
||||||
#include "buildTime.h"
|
#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 {
|
EncButton<EB_TICK, BTN_PIN> btn;
|
||||||
uint8_t second;
|
EncButton<EB_TICK, BTN_PIN2> btn_setup;
|
||||||
uint8_t minute;
|
EncButton<EB_TICK, BUNKERPIN> term_inhib;
|
||||||
uint8_t hour;
|
// EncButton<EB_TICK, TERM_COIN> term_coin_put;
|
||||||
uint8_t day;
|
int feedAmount = 1;
|
||||||
uint8_t date;
|
|
||||||
uint8_t month;
|
|
||||||
uint16_t year;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MicroDS3231 {
|
// https://robotchip.ru/podklyuchenie-kupyuropriemnika-cashcode-sm-k-arduino/
|
||||||
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
|
int valuePulse = 10; // Стоимость одного импульса
|
||||||
uint8_t getSeconds(void); // получить секунды
|
int minWidthPulse = 80; // Минимальная ширина одного импульса
|
||||||
uint8_t getMinutes(void); // получить минуты
|
int maxWidthPulse = 120; // Максимальная ширина одного импульса
|
||||||
uint8_t getHours(void); // получить часы
|
int debounce = 4; // Защита от помех
|
||||||
uint8_t getDay(void); // получить день недели
|
int pulseCount = 0; // Сколько импульсов получено
|
||||||
uint8_t getDate(void); // получить число
|
int receivedRUB = 0; // Сумма
|
||||||
uint16_t getYear(void); // получить год
|
unsigned long pulseDuration; // Как давно был последний импульс
|
||||||
uint8_t getMonth(void); // получить месяц
|
unsigned long pulseBegin = 0; // Начало импульса
|
||||||
|
unsigned long pulseEnd = 0; // Конец импульса
|
||||||
|
unsigned long curtime; // Время
|
||||||
|
int postPulsePause = 300; // Время ожидания, для завершения подсчета импульсов
|
||||||
|
int pulseState; // Состояние входа "0" или "1"
|
||||||
|
int lastState = 1; // Последние состояние входа "0" или "1"
|
||||||
|
|
||||||
String getTimeString(); // получить время как строку вида HH:MM:SS
|
int paymentsCount = 0;
|
||||||
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); // проверка на сброс питания
|
int onTime = 6; // время включения
|
||||||
float getTemperatureFloat(void);// получить температуру float
|
int offTime = 20; // время выключения
|
||||||
int getTemperature(void); // получить температуру int
|
|
||||||
|
|
||||||
private:
|
unsigned long sleepTime; // переменная для задания времени сна
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
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