Таймер на arduino

DeVeLoPer_HiKiTa

✩✩✩✩✩✩✩
20 Фев 2019
3
5
Добрый день. Меня зовут Никита Сергеевич, мне 14 лет и в этом посте я имею желание рассказать вам о мною сделанном устройстве(и приложении). Хотя возможно такое устройство вы уже видели не раз, но мне это не мешает.

Создавалось все это для автоматического включения и выключения света в курятнике, но применимо и для других целей.
20190222_204805.jpg 20190222_205851.jpg
Готовое и собранное устройство может подать на указанный цифровой пин arduino 1 или 0 в период от и до указанного времени в точности до минут(вне периода подается значение противоположное указанному в приложении при добавлении таймера ).
Все параметры указываются в приложении. А вот отсюда поподробнее...

Есть приложение для android в котором необходимо подключиться к блютус модулю и добавить таймер.Приложение интуитивно понятное и думаю проблем с ним не возникнет.
Screenshot_2019-02-21-20-47-29.png Screenshot_2019-02-21-20-48-13.png
.apk файл будет в папке этого проекта.

Необходимые элементы:
1.arduino;
2.rtc module ds1307;
3.bluetooth module HC-05;
4.соединительные элементы(например провода);
5.прошивка для arduino; скетч на мой взгляд сложный и лучше в подробности не вдаваться.
6.приложение для android;

Разбираемся с arduino и подключаемыми модулями.
Ага, пункты 1-4:

prototyping_boardjpg.jpg
arduino - hc-05
5v - vcc
gnd - gnd
TX1 - RXD
RX0 - TXD

arduino - ds1307
5v - 5v
gnd - gnd
A5 - scl
A4 - sda

Не забываем при загрузке скетча отключать пин RX0 на arduino.Вы сказали "скетч"?

5.Скетч в студию:

C++:
#include <Wire.h>                                            //библиотека для работы с шиной i2c
#include <iarduino_RTC.h>                                    //библиотека для rtc модуля(если cчто, лежит в папке проекта(Timer->firmware_for_timer->iarduino_RTC))     
#include <EEPROM.h>                                          //библиотека для работы с энергонезависимой памятью

iarduino_RTC time(RTC_DS1307);                               //создание объекта для работы с модулем реального времени

int values;                                                  //переменная для получения данных

unsigned int to_minutes(unsigned int hours, unsigned int minutes)//функция для перевода часов и минут в минуты
{
  return (60*hours)+minutes;
}

void setup()
{
  time.begin();                                             //начало работы часов
  Serial.begin(9600);                                       //открытие сериал порта
 
}

void loop()
{
  if(Serial.available() > 0)                                //если что-то пришло
  {
    values = Serial.read();
    time.settime(0,-1, values);                             //считывание и установка часов
    delay(50);
    values = Serial.read();
    time.settime(0, values);                                //считывание и установка минут
    delay(50);

    //очищаем энергонезависимую память
    for (int i = 0 ; i < EEPROM.length() ; i++)
    {
      EEPROM.write(i, 0);
    }
    //////////////////////////////////
    
    values = Serial.read();                                 
    delay(50);
    
    //запись данных в энергонезависимую память, полученых с телефона
    while (values > 0)                                        //пока есть что получать
    {
      for(int i = 0; i < 7; ++i)
      {
        EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());
        delay(50);
      }

      EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);

      values = Serial.read();
      delay(50);
    }
    /////////////////////////////////////////
  }

  //проход по каждому таймеру
  for(int i = 0; i < EEPROM.read(EEPROM.length() - 1); ++i)
  {
    if(EEPROM.read(i * 7 + 0) == 1)                                                                               //если таймер нужно проверять
    {
      bool find = 0;                                                                                              //флаг
      time.gettime();
      if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
         (to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))
      {
        pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                  //настраиваем пин таймера как выход
        digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));                                             //посылаем на пин нужное значение
      }                           
      else                                                                                                        //иначе если время не пришло
      {
        //ищем таймер с таким же пином
        for (int j = 0; j < EEPROM.read(EEPROM.length() - 1); ++j)
        {
          if(EEPROM.read(i * 7 + 5) == EEPROM.read(j * 7 + 5) && (i != j) && (EEPROM.read(j * 7 + 0) == 1))
          {
            //и если нашли таймер с таким же пином и если для него время пришло
            if((to_minutes(EEPROM.read(j * 7 + 1), EEPROM.read(j * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) &&
               (to_minutes(EEPROM.read(j * 7 + 3), EEPROM.read(j * 7 + 4)) > to_minutes(time.Hours, time.minutes))) //если пришло время для работы
            {
              pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                             //настраиваем пин таймера как выход
              digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(j * 7 + 6));                                        //посылаем на пин нужное значение
              find = 1;                                                                                            //поднимаем флаг
            }
          }
        }

        if(find == 0)                                                                                              //если таймер с таким же пином не найден
        {
          pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                 //настраиваем пин таймера как выход
          digitalWrite(EEPROM.read(i * 7 + 5), !EEPROM.read(i * 7 + 6));                                           //посылаем на пин значение протиаоположное нужному
        }
      }
    }
  }
}
Но все это без приложения будет холодным и неподвижным как камень, поэтому идем дальше.

6.

Приложение интуитивно понятное и думаю проблем с ним не возникнет.
Но лучше разобраться сразу.При первом входе в приложение необходимо будет подключиться к блютус модулю, для этого нажимаем "синхронизировать устройство"
и выбираем наш модуль. При галочке "подключаться автоматически" телефон сам будет пытаться подключиться к блютус модулю, при открытии приложения(эту фишку взял у alex gyver)."таймеры" здесь список всех таймеров и их поиск по имени. При нажатии на имя таймера открывается экран изменения этого таймера. Здесь же(где список таймеров) в правом нижнем углу расположен "+" нажав на который открывается экран добавления таймера, где указывается:
-его имя,
- от какого времени(часы минуты),
- до какого времени(часы минуты),
- управляемый пин,
-значение для него
-и состояние(будет arduino включать его или не будет в нужное время).

На этом хочу поблагодарить за внимание и сказать что, если нашли какие-то косяки или баги - смело пишите об этом, будем исправлять.

скачать весь проект;
скачать приложение;
 

AstreyRize

★✩✩✩✩✩✩
31 Июл 2018
7
18
Никита, привет! Здорово, что ты делаешь такие штуки, это очень круто! Продолжай в том же духе.
Хочу внести свои замечания по проекту:
1) Как профессиональный программист не советую тебе составлять конструкции такого вида:
C:
EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());
EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);
for(int i = 0; i < EEPROM.read(EEPROM.length() - 1); ++i)
if(EEPROM.read(i * 7 + 0) == 1)
  
if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
(to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))

pinMode(EEPROM.read(i * 7 + 5), OUTPUT);
digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));

if(EEPROM.read(i * 7 + 5) == EEPROM.read(j * 7 + 5) && (i != j) && (EEPROM.read(j * 7 + 0) == 1))
  
if((to_minutes(EEPROM.read(j * 7 + 1), EEPROM.read(j * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) &&
(to_minutes(EEPROM.read(j * 7 + 3), EEPROM.read(j * 7 + 4)) > to_minutes(time.Hours, time.minutes)))
  
pinMode(EEPROM.read(i * 7 + 5), OUTPUT);
digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(j * 7 + 6));
Пока в твоей программе всего 100 строк понять что здесь происходит не так сложно, как только твои программы начнут расти, понять что происходит, будет сложно. Я бы сделал так:

C:
// Так было
EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());

// Так стало
byte val = EEPROM.read(EEPROM.length() - 1);
val = val * 7 + i;

int ncomingByte = Serial.read();

EEPROM.write(val, ncomingByte);
C:
// Так было
EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);

// Так стало
int length = EEPROM.length() - 1;
byte val2 = EEPROM.read(length);

EEPROM.write(length, val2 + 1);
C:
// Так было
if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
   (to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))
{
  pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                  //настраиваем пин таймера как выход
  digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));                                             //посылаем на пин нужное значение
}

// Так стало
byte val1 = EEPROM.read(i * 7 + 1);
byte val2 = EEPROM.read(i * 7 + 2);
int minutes1 = to_minutes(val1, val2);
int minutes2 = to_minutes(time.Hours, time.minutes);
byte val3 = EEPROM.read(i * 7 + 3);
byte val4 = EEPROM.read(i * 7 + 4);
int minutes3 = to_minutes(val3, val4);
int minutes4 = to_minutes(time.Hours, time.minutes);

if (minutes1 <= minutes2 && minutes3 > minutes4)
{
    byte val5 = EEPROM.read(i * 7 + 5);
    byte val6 = EEPROM.read(i * 7 + 6);

    // Настраиваем пин таймера как выход
    pinMode(val5, OUTPUT);

    // Посылаем на пин нужное значение
    digitalWrite(val5, val6);
}
 

AstreyRize

★✩✩✩✩✩✩
31 Июл 2018
7
18
Теперь условия, которые проверяются в if стали понятны.

2) Обрати внимание, что теперь нам нужно меньше вызывать функции, такие как эта: EEPROM.length() - 1, т.к. вызвав ее один раз и записав ее значение в переменную, мы можем несколько раз использовать эту переменную.
3) Еще хочу обратить внимание, что есть такая штука как самоописание кода, это значит, что переменные в коде сами должны говорить, что они хранят в себе. Т.к. я не знаю что делает твой код, все переменные в примерах я назвал просто: val1, val2 и т.д. но названия должны нести в себе информацию о том, что хранит переменная, напирмер: timeInMinutes, endTime, startTime.
4) Ну и напоследок, если тебе когда-нибудь придется дебажить код, понять, какие значения передают функции будет очень сложно, т.к. эти значения не записываются в переменные, а передаются чразу в другии функции.
 

DeVeLoPer_HiKiTa

✩✩✩✩✩✩✩
20 Фев 2019
3
5
2) Обрати внимание, что теперь нам нужно меньше вызывать функции, такие как эта: EEPROM.length() - 1, т.к. вызвав ее один раз и записав ее значение в переменную, мы можем несколько раз использовать эту переменную.
3) Еще хочу обратить внимание, что есть такая штука как самоописание кода, это значит, что переменные в коде сами должны говорить, что они хранят в себе. Т.к. я не знаю что делает твой код, все переменные в примерах я назвал просто: val1, val2 и т.д. но названия должны нести в себе информацию о том, что хранит переменная, например: timeInMinutes, endTime, startTime.
4) Ну и напоследок, если тебе когда-нибудь придется дебажить код, понять, какие значения передают функции будет очень сложно, т.к. эти значения не записываются в переменные, а передаются сразу в другие функции.[/QUOTE]

Спасибо за помощь в правильном и читабельном написании кода. Буду стараться
 

qbaddev

✩✩✩✩✩✩✩
23 Апр 2020
54
8
22
[email protected]
t.me
Избыточное цитирование ни к чему
Никита, привет! Здорово, что ты делаешь такие штуки, это очень круто! Продолжай в том же духе.
Хочу внести свои замечания по проекту:
1) Как профессиональный программист не советую тебе составлять конструкции такого вида:
C:
EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());
EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);
for(int i = 0; i < EEPROM.read(EEPROM.length() - 1); ++i)
if(EEPROM.read(i * 7 + 0) == 1)

if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
(to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))

pinMode(EEPROM.read(i * 7 + 5), OUTPUT);
digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));

if(EEPROM.read(i * 7 + 5) == EEPROM.read(j * 7 + 5) && (i != j) && (EEPROM.read(j * 7 + 0) == 1))

if((to_minutes(EEPROM.read(j * 7 + 1), EEPROM.read(j * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) &&
(to_minutes(EEPROM.read(j * 7 + 3), EEPROM.read(j * 7 + 4)) > to_minutes(time.Hours, time.minutes)))

pinMode(EEPROM.read(i * 7 + 5), OUTPUT);
digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(j * 7 + 6));
Пока в твоей программе всего 100 строк понять что здесь происходит не так сложно, как только твои программы начнут расти, понять что происходит, будет сложно. Я бы сделал так:

C:
// Так было
EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());

// Так стало
byte val = EEPROM.read(EEPROM.length() - 1);
val = val * 7 + i;

int ncomingByte = Serial.read();

EEPROM.write(val, ncomingByte);
C:
// Так было
EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);

// Так стало
int length = EEPROM.length() - 1;
byte val2 = EEPROM.read(length);

EEPROM.write(length, val2 + 1);
C:
// Так было
if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
   (to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))
{
  pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                  //настраиваем пин таймера как выход
  digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));                                             //посылаем на пин нужное значение
}

// Так стало
byte val1 = EEPROM.read(i * 7 + 1);
byte val2 = EEPROM.read(i * 7 + 2);
int minutes1 = to_minutes(val1, val2);
int minutes2 = to_minutes(time.Hours, time.minutes);
byte val3 = EEPROM.read(i * 7 + 3);
byte val4 = EEPROM.read(i * 7 + 4);
int minutes3 = to_minutes(val3, val4);
int minutes4 = to_minutes(time.Hours, time.minutes);

if (minutes1 <= minutes2 && minutes3 > minutes4)
{
    byte val5 = EEPROM.read(i * 7 + 5);
    byte val6 = EEPROM.read(i * 7 + 6);

    // Настраиваем пин таймера как выход
    pinMode(val5, OUTPUT);

    // Посылаем на пин нужное значение
    digitalWrite(val5, val6);
}
Ага, не забываем про оптимизацию. Сборщика мусора то нет...

Добрый день. Меня зовут Никита Сергеевич, мне 14 лет и в этом посте я имею желание рассказать вам о мною сделанном устройстве(и приложении). Хотя возможно такое устройство вы уже видели не раз, но мне это не мешает.

Создавалось все это для автоматического включения и выключения света в курятнике, но применимо и для других целей.
Готовое и собранное устройство может подать на указанный цифровой пин arduino 1 или 0 в период от и до указанного времени в точности до минут(вне периода подается значение противоположное указанному в приложении при добавлении таймера ).
Все параметры указываются в приложении. А вот отсюда поподробнее...

Есть приложение для android в котором необходимо подключиться к блютус модулю и добавить таймер.Приложение интуитивно понятное и думаю проблем с ним не возникнет.
.apk файл будет в папке этого проекта.

Необходимые элементы:
1.arduino;
2.rtc module ds1307;
3.bluetooth module HC-05;
4.соединительные элементы(например провода);
5.прошивка для arduino; скетч на мой взгляд сложный и лучше в подробности не вдаваться.
6.приложение для android;

Разбираемся с arduino и подключаемыми модулями.
Ага, пункты 1-4:

arduino - hc-05
5v - vcc
gnd - gnd
TX1 - RXD
RX0 - TXD

arduino - ds1307
5v - 5v
gnd - gnd
A5 - scl
A4 - sda

Не забываем при загрузке скетча отключать пин RX0 на arduino.Вы сказали "скетч"?

5.Скетч в студию:

C++:
#include <Wire.h>                                            //библиотека для работы с шиной i2c
#include <iarduino_RTC.h>                                    //библиотека для rtc модуля(если cчто, лежит в папке проекта(Timer->firmware_for_timer->iarduino_RTC))    
#include <EEPROM.h>                                          //библиотека для работы с энергонезависимой памятью

iarduino_RTC time(RTC_DS1307);                               //создание объекта для работы с модулем реального времени

int values;                                                  //переменная для получения данных

unsigned int to_minutes(unsigned int hours, unsigned int minutes)//функция для перевода часов и минут в минуты
{
  return (60*hours)+minutes;
}

void setup()
{
  time.begin();                                             //начало работы часов
  Serial.begin(9600);                                       //открытие сериал порта

}

void loop()
{
  if(Serial.available() > 0)                                //если что-то пришло
  {
    values = Serial.read();
    time.settime(0,-1, values);                             //считывание и установка часов
    delay(50);
    values = Serial.read();
    time.settime(0, values);                                //считывание и установка минут
    delay(50);

    //очищаем энергонезависимую память
    for (int i = 0 ; i < EEPROM.length() ; i++)
    {
      EEPROM.write(i, 0);
    }
    //////////////////////////////////
   
    values = Serial.read();                                
    delay(50);
   
    //запись данных в энергонезависимую память, полученых с телефона
    while (values > 0)                                        //пока есть что получать
    {
      for(int i = 0; i < 7; ++i)
      {
        EEPROM.write(EEPROM.read(EEPROM.length() - 1) * 7 + i, Serial.read());
        delay(50);
      }

      EEPROM.write(EEPROM.length() - 1, EEPROM.read(EEPROM.length() - 1) + 1);

      values = Serial.read();
      delay(50);
    }
    /////////////////////////////////////////
  }

  //проход по каждому таймеру
  for(int i = 0; i < EEPROM.read(EEPROM.length() - 1); ++i)
  {
    if(EEPROM.read(i * 7 + 0) == 1)                                                                               //если таймер нужно проверять
    {
      bool find = 0;                                                                                              //флаг
      time.gettime();
      if((to_minutes(EEPROM.read(i * 7 + 1), EEPROM.read(i * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) && //если пришло время для работы
         (to_minutes(EEPROM.read(i * 7 + 3), EEPROM.read(i * 7 + 4)) > to_minutes(time.Hours, time.minutes)))
      {
        pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                  //настраиваем пин таймера как выход
        digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(i * 7 + 6));                                             //посылаем на пин нужное значение
      }                          
      else                                                                                                        //иначе если время не пришло
      {
        //ищем таймер с таким же пином
        for (int j = 0; j < EEPROM.read(EEPROM.length() - 1); ++j)
        {
          if(EEPROM.read(i * 7 + 5) == EEPROM.read(j * 7 + 5) && (i != j) && (EEPROM.read(j * 7 + 0) == 1))
          {
            //и если нашли таймер с таким же пином и если для него время пришло
            if((to_minutes(EEPROM.read(j * 7 + 1), EEPROM.read(j * 7 + 2)) <= to_minutes(time.Hours, time.minutes)) &&
               (to_minutes(EEPROM.read(j * 7 + 3), EEPROM.read(j * 7 + 4)) > to_minutes(time.Hours, time.minutes))) //если пришло время для работы
            {
              pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                             //настраиваем пин таймера как выход
              digitalWrite(EEPROM.read(i * 7 + 5), EEPROM.read(j * 7 + 6));                                        //посылаем на пин нужное значение
              find = 1;                                                                                            //поднимаем флаг
            }
          }
        }

        if(find == 0)                                                                                              //если таймер с таким же пином не найден
        {
          pinMode(EEPROM.read(i * 7 + 5), OUTPUT);                                                                 //настраиваем пин таймера как выход
          digitalWrite(EEPROM.read(i * 7 + 5), !EEPROM.read(i * 7 + 6));                                           //посылаем на пин значение протиаоположное нужному
        }
      }
    }
  }
}
Но все это без приложения будет холодным и неподвижным как камень, поэтому идем дальше.

6.



Но лучше разобраться сразу.При первом входе в приложение необходимо будет подключиться к блютус модулю, для этого нажимаем "синхронизировать устройство"
и выбираем наш модуль. При галочке "подключаться автоматически" телефон сам будет пытаться подключиться к блютус модулю, при открытии приложения(эту фишку взял у alex gyver)."таймеры" здесь список всех таймеров и их поиск по имени. При нажатии на имя таймера открывается экран изменения этого таймера. Здесь же(где список таймеров) в правом нижнем углу расположен "+" нажав на который открывается экран добавления таймера, где указывается:
-его имя,
  • от какого времени(часы минуты),
  • до какого времени(часы минуты),
  • управляемый пин,
-значение для него
-и состояние(будет arduino включать его или не будет в нужное время).

На этом хочу поблагодарить за внимание и сказать что, если нашли какие-то косяки или баги - смело пишите об этом, будем исправлять.

скачать весь проект;
скачать приложение;
Рекомендую создать репозиторий проекта на Github.