format and data

This commit is contained in:
Kseninia Mikhaylova 2024-08-12 12:31:14 +03:00
parent 6e41e3d1c2
commit 4a5d41c48d
1 changed files with 240 additions and 75 deletions

View File

@ -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();
}
}