ARDUINO для автоматизации аквариума

<< 12 45678910 >>

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
ARDUINO для автоматизации аквариума
Создал отдельную тему по вопросам использования простых и не дорогих плат ARDUINO для целей автоматизации аквариума.
Идея такая - довести это устройство до полнофункционального контроллера для аквариума, в итоге - с WEB сервером для управления по сети в т.ч. Интернет, и GSM модулем с отправкой SMS.
Начало обсуждения в теме про дозатор :
дозатор

Информация будет, в основном, в виде конкретных примеров.

Пример 1. Использоание плат Arduino UNO и Arduino NANO для управления по времени суток устройствами в 2-х каналах посредством релейного модуля.
Предполагается использование для создания 2-х канального дозатора, но и для включения света, например подойдет, и для многих других целей также.

Используется модуль часов реального времени, для точного планирования по времени суток, и релейный модуль. В данном примере используется 4-канальный, но 2 канала не используются...

Схема коммутации в случае использования платы UNO R3:


Схема коммутации в случае использования платы NANO:


Программа для среды программирования Arduino:
//***************************************************
// Скетч для управления релейным модулем, в котором *
// использовано два канала. Используется также RTC *
// Релейный модуль - с инверсной логикой на входе *
// Автор: ZORS *
// Версия 1. Дата 21.12.2013 02:40 *
//***************************************************
//----------ИМПОРТ БИБЛИОТЕК-------------------------
#include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC
#include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC

RTC_DS1307 RTC; //Создаем переменную класса - для использования RTC

//----------Объявляем разные переменные------------
const int RelayChn1 = 6; //Используем цифровой ПОРТ 6 для ПЕРВОГО канала релейного модуля
const int RelayChn2 = 7; //Используем цифровой ПОРТ 7 для ВТОРОГО канала релейного модуля
//----------Настройки времени и продолжительности включения реле

//----------ПЕРВЫЙ канал----------------------------
const long StartRelCn_1 = 25200; //Время срабатывания в ПЕРВОМ канале релейного модуля (в секундах от начала суток)
//в данном случае 25200 - это 7 часов 00 минут = ( 60секунд *60 минут *7 = 25200)
const long DurationCh_1 = 10; //ДЛИТЕЛЬНОСТЬ срабатывания реле в ПЕРВОМ канале (в секундах)

//----------ВТОРОЙ канал----------------------------
const long StartRelCn_2 = 37800; //Время срабатывания во ВТОРОМ канале релейного модуля (в секундах от начала суток)
//В данном случае 10 часов 30 минут = (60 секунд * 60 минут * 10 часов + 60сек*30мин = 37800)
const long DurationCh_2 = 15; //ДЛИТЕЛЬНОСТЬ срабатывания реле во ВТОРОМ канале (в секундах)

//----------Модуль инициализации setup() - выполняется один раз при инициализации платы при подаче напряжение (и аналогичных событиях)
void setup(){

pinMode(RelayChn1,OUTPUT); //Инициализируем порт для ПЕРВОГО канала как ВЫХОД
pinMode(RelayChn2,OUTPUT); //Инициализируем порт для ВТОРОГО канала как ВЫХОД

digitalWrite(RelayChn1,HIGH); //Устанавливаем на входах релейного модуля ВЫСОКИЙ уровень
digitalWrite(RelayChn2,HIGH); //Т.к. используемый релейный модуль с опторазвязкой - управляется инверсной логикой



Wire.begin(); //Инициируем I2C интерфейс
RTC.begin(); //Инициирум RTC модуль

// RTC.adjust(DateTime(__DATE__, __TIME__)); //С этой строки необходимо убрать комментарии один раз в начале,
//для того, чтобы загрузить в RTC дату и время на момент компиляции программы
//Иногда необходимо заливать СКЕТЧ на плату со снятым комментарием - для поправки
//времени в RTC, НО оставлять такой СКЕТЧ в работе НЕЛЬЗЯ !!!!!!!!!!!!!

} // КОНЕЦ ИНИЦИАЛИЗАЦИИ

//--------------------------------------------------
void loop() // ПРОГРАММЫй безусловный ЦИКЛ
{
DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла

//----------Раздел обработки реле по времени ----
long utime = myTime.unixtime(); //сохраняем в переменную - время в формате UNIX
utime %= 86400; //Сохраняем в этой же переменной остаток деления на кол-во секнд в сутках,
//Это дает количество секунд с начала текущих суток

//------------КАНАЛ 1------------------------------
if ((utime >= StartRelCn_1) &&
(utime < (StartRelCn_1+DurationCh_1)))
//Если секунд с начала суток больше, чем задано для включения
//Но, одновременно и меньше, чем задано для включения + длительность
{
digitalWrite(RelayChn1,LOW); //Устанавливаем на ПЕРВОМ входе релейного модуля НИЗКИЙ уровень - реле срабатывает
}
else //во всех остальных случаях
{
digitalWrite(RelayChn1,HIGH); //Устанавливаем на ПЕРВОМ входе релейного модуля ВЫСОКИЙ уровень - реле выключается
}

//------------КАНАЛ 2 - все аналогично -----------
if ((utime >= StartRelCn_2) &&
(utime < (StartRelCn_2+DurationCh_2)))
{
digitalWrite(RelayChn2,LOW); //Устанавливаем на ВТОРОМ входе релейного модуля НИЗКИЙ уровень - реле срабатывает
}
else
{
digitalWrite(RelayChn2,HIGH); //Устанавливаем на ВТОРОМ входе релейного модуля ВЫСОКИЙ уровень - реле выключается
}

}//------------Конец ЦИКЛА-----------------------------


(Редактор текста на данном сайте - к сожалению, "ломает" красивое форматирование.

PS: Выложил этот скетч на файлообменник :
http://my-files.ru/h...

В данной программе реализован, довольно-таки простой подход, а простота - основа надежности.

Каждое из 2-х реле срабатывают один раз в сутки в указанное время, причем время указывается в количестве секунд от начала суток, и удерживается указанное количество времени в секундах.
Такой способ задания времени - несколько сложен для понимания, но за это - не нагружает программу и процессор лишним функционалом, который понадобится всего один раз.
Для определения времени наступления события начала включения и выключения реле - используется время в формате UNIX.

Такой подход хорош тем, что даже если включение или перезагрузка платы произойдет в промежутке времени включения, то реле включится в оставшееся время.
В случае с дозированием, это не много что дает, но в случае, если по аналогии будет сделано управление светом, то при подаче напряжения на плату, например, после пропадания напряжения питания, или после посадки напряжения, или др. аналогичных событий, включение и выключение реле произойдет корректно.

У комплектных минутных и секундных таймеров "с розеткой" - об этом можно только мечтать....не реализован такой функционал, и еще у них есть один минус. Реле в таких таймерах - не удерживаемое, а переключаемое, со всеми вытекающими последствиями....

Для программирования нескольких включений каждого реле в течение суток - естественно, потребуется несколько другой подход....спрашивайте когда кому-то потребуется, пока не хочу все усложнять...
В принципе, можно добавить константных переменных, содержащих время и длительность срабатывания, и соответственно добавить проверку на условия.
Если количество необходимых срабатываний каждого реле в сутках больше чем 2 - лучше оформить проверку условий в отдельной функции. Как, говорил человек, учивший меня программированию - "все, что ты делаешь в программе больше двух раз - оформляй отдельной процедурой, или функцией".

Главное ограничение этого подхода - включение и выключение реле - должно произойти в одних сутках. Если необходимо чтобы, реле включилось в одних сутках, а выключилось в других - необходимо разбить это задание на 2 задания, или применить другой метод проверки условий наступления событий включения и выключения.

Весь этот пример тестировался на "живом" железе :

Для наглядности отладки был еще подключен LCD дисплей 16 сим в 2 строках.
Схема итоговая была такая:

Обратите внимание, что при использовании I2C последовательного интерфейса - соединения значительно упрощаются. И LCD дисплей подключен транзитом через модуль RTC (часов реального времени). Никаких паяных соединений нет вообще....все скоммутировано - проводами с разъемами.
Скетч - естественно, несколько другой использовался с добавлением строк инициализации и использования LCD 16x2.

Плата использовалась типа такой:
http://www.ebay.com/...
цена примерно 350 руб.

Релейный модуль
http://www.ebay.com/...
цена примерно 150 руб.

Модуль часов реального времени:
http://www.ebay.com/...
Цена примерно 55 руб.

Для сокращения бюджета можно использовать плату проще:
http://www.ebay.com/...
Цена примерно 200 руб.

Если есть потребность подключить ЖК дисплейчик, то лучше брать ЖК дисплей (LCD) c I2C интерфейсом - это сильно упрощает коммутацию, и сокращает количество использованных портов на микроконтроллере.
Например такой можно использовать :
http://www.ebay.com/...
цена около 180 руб.

На ЖК можно выводить статусную информацию, информацию об ошибках, диагностическую информацию. Все это, конечно, можно и в последовательный порт компьютера выводить, но это не всегда удобно (скорее наоборот), поэтому я всегда использую какой-нибудь девайс для вывода информации.

Для использования I2C интерфейса - необходима библиотека Wire. Она есть в стандартном дистрибутиве среды программирования Arduino.
Для использования модуля RTC на микросхеме DS1307 нужна библиотека RTClib.
Если ее не будет в стандартном дистрибутиве, то ее можно взять в интернет. Например здесь :
http://arduino-info....

Необходимо, скачать, и разархивировать zip-файл в папку с понятным названием, например RTCLib. Затем эту папку поместить в папку, где среда Arduino хранит свои библиотеки. Если ставили среду программирования с настройками по умолчанию, то этой папкой будет :
C:\Program Files\Arduino\libraries
Сюда и помещайте папки с подключаемыми библиотеками. Если на этот момент, среда программирования была запущена - ее необходимо закрыть, и запустить заново. После этого библиотека будет доступна в меню Скетч/Импортировать библиотеку.

Микросхема RTC модуля DS1307, как правило использует адрес на шине I2C равный 0x68
поэтому, необходимо проверить в библиотечных файлах, библиотеки RTClib наличие строки типа этой:
#define DS1307_ADDRESS 0x68

Если будет использоваться LCD 16x2 с I2C интерфейсом, то - понадобиться библиотека LiquidCrystal_I2C. Можно скачать здесь :
http://dvrobot.ru/lc...
Как подключить к среде программирования Arduino - см. выше

ВАЖНО : при использовании I2C устройств - в скетче, библиотека Wire - должна быть объявлена первой, иначе - будут ошибки компиляции.

По этому примеру - все....

в следующем - присоединение термо-датчика DS18B20, и создание несложного терморегулятора.....


Изменено 24.12.13 автор Z0RS
2013-12-21 добавлено 21/12/2013 15:57:48#1907148

Постоянный посетитель




257 4
Новосибирск
11 час. назад
попробовал на другом компьютере...
http://saveimg.ru/sh...
2014-03-13 добавлено 13/03/2014 13:38:29#1948833

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
lisenkow

А Вы какую конкретно модель платы подключаете?
На ней бутлоадер залит?
Вообще, если просто любой терминальной программой (например гипертерминалом) попытаться присоединиться - то соединение создается?

Можно так попробовать:
В гипертерминале создать новое соединение, на порту соответствующем виртуальному порту платы. При создании соединения использовать следущюии параметры:
Скорость 9600,
бит данных = 8,
четность = нет,
стоповые биты = 1,
управление потоком = аппаратное

При удачном соединении не должно выскакивать ошибок, потом, будет идти время соединения в статусной строке внизу программы, и при нажатии клавиши ENTER на плате ардуино будет взмаргивать светодиод....

Если все так, то значит проблеммы с бутлоадером, если не так, то проблемы с присоединением, с драйверами/настройкой виртуального компорта или настройками порта в программе.

Потом, еще проверьте какая скорость установлена на виртуальном ком-порту по умолчанию, иногда система выставляет 384000 или другие скорости отличные от 9600.
Необходимо выставить 9600 - это скорость по умолчанию....или если необходима другая скорость - это оговаривается в документации на плату....

Ошибки синхронизации очень часть возникают из за несоответствия скоростей портов на разных сторонах....поиграйтесь с этим параметром...
2014-03-13 добавлено 13/03/2014 13:54:55#1948839

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
Настройки порта должны быть такими:


Кстати, на приведенной Вами картине - посмотрите на что ругается программа - у Вас скорость на порту выставлена 57600....

Изменено 13.3.14 автор Z0RS
2014-03-13 добавлено 13/03/2014 13:59:29#1948843

Новичок




2
Russian Federation
2 г. назад
Есть ли у кого опыт управления реле через приемник/передатчик на 433 Мгц? В частности интересует схема для приемной части (в эфире постоянный сигнал не есть гуд).
2014-03-17 добавлено 17/03/2014 09:17:51#1950840

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
plus


Если Вы имеете ввиду девайс типа этого: http://www.ebay.com/... то это банальный удлинитель сигнала с TTL уровнем по радиоканалу 433 МГц, и высокий уровень на выходе будет означать наличие несущей в эфире.
Присоединение тоже не сложное как бы ...питание и один управляющий вход TTL на стороне передатчика, ну и TTL выход на стороне приемника, к которому можно напрямую присоединить вход релейного модуля, или другой потребитель TTL уровня.
Вот простейшая схема :
https://encrypted-tb...

Чтобы сделать использование этого модуля более "умным" и управляемым, на стороне приемника необходимо использовать более сложную логику, которая может быть реализована на каком-то микроконтроллере по-проще, например на серии ATMEL TINY. При использовании 2 микроконтрорллеров при обмене данными можно реализовать несложный протокол, результатом работы которого будет отсутствие постоянной несущей в эфире для обеспечения высокого выходного уровня, наличие защиты от чужого сигнала, и контроль передачи/приема.

В принципе, мне кажется для этих модулей должны быть готовые библиотеки....хоть в Вашем случае для управления реле они особо и не нужны....

И есть еще вариант, где все вышеперечисленное реализовано в "железе", причем удлиняется уже не один канал с TTL уровнями, а несколько, и все кодирования/декодирования реализованы в МК на платах:
http://www.ebay.com/...

Но цена, конечно уже другая...
2014-03-17 добавлено 17/03/2014 16:24:10#1951026

Новичок




2
Russian Federation
2 г. назад
Спасибо за ответ. Жаба душит использовать на стороне приема arduino, хотя есть библиотека VirtualWire (здесь описание ВОЗМОЖНО СПАМ. Если вы хотите открыть ссылку, скопируйте ее в адресную строку самостоятельно
). Думаю на простой логике что-то придумать, чтобы не писать лишний код для взаимосвязи двух микрух.
2014-03-17 добавлено 17/03/2014 16:44:47#1951038

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
plus
Жаба душит использовать на стороне приема arduino


Да не обязательно ардуино использовать....Хотя какую нибудь NANO или MICRO рублей за 100 - было бы весьма логично, легко программируемо и бюджетно.
Можно и просто собрать несложную схемку на кусочке монтажки, на которую поставить
проц типа http://www.ebay.com/...
Пару конденсаторв, резисторов и кварц....но по цене будет так же, как NANO без USB. Не будет смысла заморачиваться....
Вообще весьма бюджетных вариантов много....
2014-03-17 добавлено 17/03/2014 17:21:52#1951052

Новичок




30
Тихорецк
4 мес. назад
Добрый день!!
Нужна консультация (заранее очень благодарен!!!)
Что хочеться:
управление светом, температурой, удо, фильтром включение выключение, оповещение звуковое: утечкой воды, утечка СО2, PH замеры, управление CO2, + управление через WEB интерфейс iphone,
что для ЭТО НУЖНО!???
что есть у меня на данный момент :
SainSmart Mega2560 R3 + 3.2" TFT Touch LCD SD Card + TFT Shield Kit For Arduino 1 штука
5V 4 Channel Electronic Relay Module Shield for Arduino ARM PIC AVR DSP 10A 2 штуки
RTC I2C DS1307 AT24C32 Real Time Clock Module For Arduino AVR PIC 51 ARM 1 штука

посоветуйте подскажите ПО будет переделанно из
картинка
2014-03-21 добавлено 21/03/2014 13:39:09#1952973

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
Для того, чтобы организовать
Миххаил
управление через WEB интерфейс iphone


- по крайней мере, необходимо иметь либо сетевую плату (EtherNet), либо аналогичный шилд.
Эти устройства, как правило, подключаются посредством I2C интерфейса, и имеют соответствуюие библиотеки....одну из плат я уже описывал в этой теме. Но с использованием сетевых плат - есть одна проблема, а именно : функция передачи сформированного в буффере сообщения - имеет недетерминированную длительность....т.е. может выполняться довольно длительное время...т.к. процессор на плате один, и он не многозадачный, то можно потерять по времени некоторые другие события, например отключения или включения чего либо....Естественно это справедливо при использовании стандартных библиотек. Отказавшись от стандартных библиотечных функций - это можно разрешить, но программирование становиться очень сложным, и новичку это будет сделать очень сложно, практически невозможно.
Платы EtherNet существуют 2х основных типов :

на чипе ENC28J60. Например http://www.ebay.com/...

и на чипе W5100. На основе этого чипа - есть и шилды и отдельные платы. Пример шилда http://www.ebay.com/...

Использование W5100 - является более предпочтительным, когда требуется снижать нагрузку на микропроцессор основной платы Arduino, т.к. сетевые устройства на основе W5100 многие операции выполняют на микросхеме W5100, а в случае ENC28J60 - нагрузка на основной процессор платы - больше.

Кроме сетевой платы, необходимо написать код самого WEB сервера...

Потом, для организации контроля за протечками - потребуются сенсоры с TTL или с аналоговым или цифровым интерфейсным выходом...они есть в продаже на том же ebay.com

Ну и так...далее...
А вообще, Вы начинаете с очень непростой задачи....
2014-03-21 добавлено 21/03/2014 15:35:04#1953021

Свой на Aqa.ru




1199 267
Ростов-на-Дону
8 час. назад
Z0RS

Добрый день. На вашей блок-схеме с диммированием светодиодов Arduino получает питание от блока питания через преобразователь напряжения, правильно? Получатся, блок питания постоянно включен в сеть. В связи с этим вопрос: блок питания потребляет все время постоянную мощность в не зависимости от подключенной к нему нагрузки? Т.е. если светодиоды выключены, блок потребляет ту же мощность, что и при включенных? Это уже вопрос экономии денег за свет. Если это так, то может запитать aruino через что-то маломощное, а уже основной блок питания (и всю цепочку диодов) подключать к 220В через релейное соединение? Или я ошибаюсь?
ЗЫ.Спасибо за тему, по информативности она может поспорить со специализированными форумами "ардуинистов" .
2014-03-22 добавлено 22/03/2014 05:03:11#1953335

Новичок




30
Тихорецк
4 мес. назад
ZORS
Огромное спасибо что откликнулись так быстро!!
Не могли бы вы помочь с выбором остальных комплектующих (по образованию программист думаю напишу что нужно)))
в планах передача данных по Wi-Fi не по лану!!! или же проще и лучше по GSM ??
не могли бы вы с сылками дать что мнее еще нужно??
имеюю в виду: сенсоры, реле для компресоров, помп и так далее!!
тели я выбрал драйвера!!!
и можно ваш скайп??
2014-03-22 добавлено 22/03/2014 08:55:13#1953354

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
Дядька-рыбомор
Добрый день. На вашей блок-схеме с диммированием светодиодов Arduino получает питание от блока питания через преобразователь напряжения, правильно? Получатся, блок питания постоянно включен в сеть. В связи с этим вопрос: блок питания потребляет все время постоянную мощность в не зависимости от подключенной к нему нагрузки? Т.е. если светодиоды выключены, блок потребляет ту же мощность, что и при включенных?

Нет, конечно....блок питания без нагрузки потребляет ток холостого хода, и мощность соответственно. Как правило это несколько процентов от номинальной мощности.
Ардуино запитано от одного Б\П для экономии. Для увеличения надежности схемы, можно запитать от отдельного б\п и сделать схему использования резервного источника, аккумулятора, например.

Дядька-рыбомор
ЗЫ.Спасибо за тему, по информативности она может поспорить со специализированными форумами "ардуинистов" .


Пожалуйста!

Миххаил
Не могли бы вы помочь с выбором остальных комплектующих (по образованию программист думаю напишу что нужно)))
в планах передача данных по Wi-Fi не по лану!!! или же проще и лучше по GSM ??

Я, если честно, не знаю...
По сложности программирования - это сопоставимые задачи, если делать двухсторонний обмен.
В любом случае, если будет использоваться EtherNet - будут присутствовать задержки неопределенной длительности при обработке данных этого протокола....и следовательно программирование задач с контролем времени - усложниться...

С выбором конкретных моделей модулей WiFi или GSM - не подскажу, вопрос очень широкий, и конечный выбор оборудования зависеть только от Ваших требований.

Модулей существует много разных, самый простой способ облегчить себе жизнь с выбором того или иного модуля - сначала найти на него документацию, и библиотеку функций с кодом примеров. Затем посмотреть код примеров и определить, насколько хорошо вы понимаете те идеи, которые заложены в реализации библиотечных функций...если все понятно - то такой модуль можно приобретать.

Вообще если позволяют средства - лучше брать уже "раскрученные" шилды, т.к. для них все есть, и библиотеки, и примеры.
Вот пример шилда с GSM : http://www.ebay.com/...


Миххаил
не могли бы вы с сылками дать что мне еще нужно??

Как я могу знать что ВАМ нужно?
Некоторые примеры периферии, такие как релейный модуль, датчик температуры - я уже приводил в этой теме....остальное аналогичное оборудование можете подобрать сами...


Миххаил
и можно ваш скайп??


Не пользуюсь скайпом....впрочем как и аськой - практически не пользуюсь.
2014-03-22 добавлено 22/03/2014 17:52:49#1953555

Завсегдатай




460 39
Москва
6 мес. назад
Z0RS

Пришли тут мне арудино, но вот незадача - вместо i2c дисплея - обычный. Пока играюсь второй день, даже что-то получается. Но копаясь в инете наткнулся на такую штучку:

http://www.aliexpres...

Это очень плохо или терпимо - просто цена вроде более-менее. Цель - контроль Ph при подаче co2.
2014-03-22 добавлено 22/03/2014 17:58:45#1953558

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
arch07
Пришли тут мне арудино, но вот незадача - вместо i2c дисплея - обычный.

Ну не страшно....впринципе, продаются отдельные модули I2C интерфейса. Например для дисплея размерностью 16Х2 подойдет такой : http://www.ebay.com/...

А при наличии достаточного количества цифровых портов OUTPUT - можно и без I2С использовать модуль дисплея. I2С - используется "не от хорошей жизни" - для экономии портов.

В случае, когда используется дисплей напрямую на портах вывода - необходимо использовать другую библиотеку - она есть в стандартной поставке среды программирования ARDUINO и называется эта библиотека просто LiquidCrystal. Кстати, в примерах к этой библиотеке можно увидеть, как определяются порты для подключения дисплея.
Так, что можете использовать ваш дисплей, я так понимаю что с количеством портов у Вас пока проблем нет.


arch07
...копаясь в инете наткнулся на такую штучку:
http://www.aliexpres...
Это очень плохо или терпимо - просто цена вроде более-менее. Цель - контроль Ph при подаче co2.


По цене - нормально. Считайте, 2 операц.усилителя (ОУ)это 100-150 рублей, платка, разъемы делали еще рублей 150, электрод дешевый - 600-700 рублей.....вообщем если сами бы собрали - получилось либо так же, либо дороже...Производители таких наборов выигрывают на эффекте масштаба производства.

Понятно, что все преобразование предется писать самому, термокомпенсации нет, но ее можно реализовать, и если реализовывать то все равно пришлось бы программно, и что-то уж очень низкую точность указывают до 0,1 единицы....

Вообще, попадались и другие аналогичные наборы - может еще имеет смысл по-выбирать, по искать ? Для того чтобы сравнивать, и выбрать лучшее.
2014-03-22 добавлено 22/03/2014 18:43:14#1953575

Завсегдатай




460 39
Москва
6 мес. назад
Z0RS

насчет дисплея - китайцы мне все равно либо пришлют i2c модуль, либо вернут бабки - я пока 5 баксов запросил за 3 бакса я уже нашел подобный модуль на мой 2004 (четырехстрочный) дисплей. Вот тока ждать его еще 2-3 недели. потому и обидно.
По поводу подключения без i2c - я в курсе, но по шине - решение изящней: лишние порты и проводов меньше. Думаю нагрузка на проц не сильно выше.

Сильно поразила разница в размерах платы мега и нано. Я нано досель не видел. Така махонька, а скока могет.

ПО Ph - мой химический тест от SERA имеет диапазон 4,5 - 9,0, шаг цветовой шкалы 0,5. Т.е. точность 0,25. Для пресняка вроде хватает. с учетом погрешностей 0,1 единицы набора вроде неплохо.
А что дает термокомпенсация? Насколько она актуальна в полосе температур аквариума? сколько может наврать электрод при разнице температур градусов 5? И как калибровать все это? на плате только один потенциометр. Как я понимаю калибровать стоит по 3 точкам - желательно внизу, в середине и в конце диапазона. В наборе вообще тока одна бутылочка.
А если еще температуру учитывать - тут вообще 9 точек калибровки минимум надо вводить.
Программно я понимаю - имеем напряжение, по точкам калибровки привязываем их к значениям pH. промежуточные значения вычисляем линейной интерполяцией.
Ну еще вводим поправку на температуру (благо датчиков температуры герметичных я набрал). С этим pH вообще вопросов полно - но запускать co2 без контроля стремно. Понятно, потом он нафик не нужен будет - процедура отладится и все заработает на "автомате", но пока заработает - можно и животину заморить.

P.S. Еще глупый вопросик - как правильно подключить кнопку? Что-бы избежать дребезга? Задача запустить выполнение скрипта, который выполняется по времени по нажатию кнопки. Понятно, что на кнопку назначаем аппаратное прерывание и она запускает скрипт независимо от того наступило расчетное время или нет.
пример: имеем NANO, кнопку. подключаем кнопку между D2 и +5V - нужен еще резистор 10 кОм от D2 на землю?

Изменено 22.3.14 автор arch07
2014-03-22 добавлено 22/03/2014 21:05:25#1953634

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
arch07
По поводу подключения без i2c - я в курсе, но по шине - решение изящней: лишние порты и проводов меньше. Думаю нагрузка на проц не сильно выше.

Да. Для процессора разница в нагрузках, конечно, незначительна.

Кстати, такие модули, которые используются с дисплеями, можно использовать для расширения количества портов ВВОДА/ВЫВОДА, без каких либо ограничений, и сложностей. Собственно, основой таких модулей и является микросхема - расширитель портов (I\O ports expander).

На микросхему PCF8574, на основе которой сделан I2C модуль для дисплея размерностью 16Х2, кстати есть готовая библиотека : https://github.com/s...
Я обязательно, ее попробую, когда придут модули. Сделаю обзор, т.к. иногда требуется увеличить количество портов, из-за того, что некоторые вопросы и задачи не были учтены при покупке базовой модели платы ARDUINO.

arch07
Сильно поразила разница в размерах платы мега и нано. Я нано досель не видел. Така махонька, а скока могет.

Ну "могет" то по большому счету - не плата, а микроконтроллер, на ней установленный. А размеры... да ...маленькие.


arch07
А что дает термокомпенсация? Насколько она актуальна в полосе температур аквариума? сколько может наврать электрод при разнице температур градусов 5?

Для Ваших требований к точности измерения pH - термокомпенсация даст не много.

arch07
И как калибровать все это? на плате только один потенциометр.

Для калибровки на плате вообще нет ничего. Плата то очень простая - это просто усилитель сигнала с очень высоким входным сопротивлением. Потенциометр, который на ней находится определяет коэффициент усиления предусилителя, и служит для согласования разных электродов с одной платой.

Т.к. бывают электроды с сопротивлением в десятки мегоом (так называемые низкоомные) и в сотни и тысячи мегаом, для каждого из них, по идее необходимо менять входную часть, согласующую выходное сопротивление электрода и входное сопротивление предусилителя. Но иногда, в простейших случаях, пытаются это изменением коэффициента усиления (GAIN) сделать, для этого и потенциометр. Потом, может быть небольшой проблемой, отсутствие регулировки смещения напряжение на электроде.
Плата выдаст смещенный (вот только не знаю на сколько, по идее нужно не менее 500 mV) и усиленный потенциал электрода. Назовем это "исправленным" потенциалом электрода.

В Вашем случае калибровка будет выглядеть, как запоминание значения исправленного потенциала электрода в двух точках ( как правило с pH=7.0 pH=4.01). Наборы для приготовления буферных растворов с указанными pH - есть в продаже на ebay http://www.ebay.com/...
Однако...они подорожали....я брал десяток по цене около 40 руб.

Из этого набора нужны только 2 - с с pH=7.00 pH=4.01. Кстати о термокомпенсации - обратите внимание при какой температуре указнанные на упаковке значения pH соответствуют действительности.

Калиброваться лучше по указанным pH, т.к. например буффер с pH=6.86 обладает меньшей точность, из за особенностей химических соединений входящих в состав. Если измеритель использовался бы в морском аквариуме то лучше калиброваться по точкам с pH=7.00 pH=10.01

Далее, при калибровке программа запомнит два значения и все остальные значения между ними или за ними, будут вычисляться как линейная интерполяция, с использованием простейшей функции вида f(x)= ax + b. Ну это в самом простейшем случае, и без термокомпенсации.

Вообщем, Вы практически все правильно понимаете.....осталось дело за малым - реализовать...
2014-03-22 добавлено 22/03/2014 22:47:15#1953684

Новичок




46
Germany
2 г. назад
Вот для этого кода нужно плавное включение света в заданное время и плавное выключение в другое заданное время. Помогите разобраться.

// Библиотеки необходимые для работы модуля часов
#include "Wire.h"
#include "DS1307new.h"

// библиотека экрана
#include "LiquidCrystal.h"
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

int hours;
int minutes;
int LW = 3;
int LR = 11;
int LB = 12;
int On_Time =0;
int Off_Time =0;
int Curent_Time =0;

void setup(){
Serial.begin(9600);
lcd.begin(16, 2); // запускаем библиотеку экрана
pinMode(LW, OUTPUT);
pinMode(LR, OUTPUT);
pinMode(LB, OUTPUT);
}

void loop(){
analogWrite(10, 100);
RTC.getTime();// получить время от модуля
RTC.hour;
RTC.minute;
printTimeToSerial(); // выводим полученное время в лог
printTimeToLCD();; // выводи время на экран
lcd.setCursor(0, 1); // Set the cursor to column 0, line 1
doSerialCommands(); // слушаем и выполняем команды из Serial
On_Time=(20*60+27);
Off_Time=(20*60+29);
Curent_Time=RTC.hour*60+RTC.minute;//текущее время
if(On_Time < Off_Time) //Проверка, таймер в течении одних суток?
{
if (Curent_Time >= On_Time && Curent_Time <= Off_Time)
for(int fadeValue = 0; fadeValue <= 255; fadeValue +=3)
{
analogWrite(LR, fadeValue);
}
else
for(int fadeValue = 255; fadeValue >= 0; fadeValue -=3)
{
analogWrite(LR, fadeValue);
}
}
else // если сутки сменились
{
if ((Curent_Time >= On_Time && Curent_Time <= 2820)||(Curent_Time >= 0 && Curent_Time <= Off_Time))//2820=24часа*60
for(int fadeValue = 0; fadeValue <= 255; fadeValue +=3)
{
analogWrite(LR, fadeValue);
}
else
for(int fadeValue = 255; fadeValue >= 0; fadeValue -=3)
{
analogWrite(LR, fadeValue);
}
}
}

// Выводит текущие время в Serial
void printTimeToSerial(){

byte static prevSecond=0; // тут будем хранить, сколько секунд было при прошлом отчете

if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись
Serial.print(RTC.hour); // часы

Serial.print(":"); // разделитель
Serial.print(RTC.minute);

Serial.print(":");
Serial.println(RTC.second);

prevSecond=RTC.second; // запомнили когда мы "отчитались"
}
}

// Выводит текущие время на LCD

void printTimeToLCD(){
byte static prevSecond=0; // тут будем хранить, сколько секунд было при выводе

if(RTC.second!=prevSecond){ // что-то делаем только если секунды поменялись
lcd.setCursor(11,0); // устанавливаем позицию курсора

if(RTC.hour<10)lcd.print(" ");
lcd.print(RTC.hour); // часы

lcd.print( (RTC.second % 2)?" ":":"); // разделитель моргает

if(RTC.minute<10)lcd.print(0); // лидирующий ноль, если нужен
lcd.print(RTC.minute);

prevSecond=RTC.second; // запомнили когда мы "отчитались"
}
}

// устанавливает часы модуля на какое-то заранее определенное время
void setSomeTime(){
RTC.stopClock();// останавливаем часы
RTC.fillByHMS(20,24,0); // "подкручиваем стрелки на 2000
RTC.setTime();// отправляем "подкрученное время" самому модулю
RTC.startClock(); // и опять запускаем часы
}

// слушает из Serial команды и выполняет их. Каждая команда - один символ.
// доступны команды:
// s - установить время указанное в функции setSomeTime()
void doSerialCommands(){
if(Serial.available()){ // что-нибудь пришло?
char ch=Serial.read(); // читаем что пришло

switch(ch){
case 's': // команда установки времени
setSomeTime(); // устанавливаем
break;

// тут, в будущем, мы можем добавлять дополнительные команды
default:;
// на неизвестную команду - ничего не делаем
};
}
}
2014-03-24 добавлено 24/03/2014 02:19:52#1954163

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
kirex05


Ваша основная ошибка - это использование конструкций типа нижеприведенной внутри главного цикла, т.е. внутри бесконечного безусловного цикла, организованного специальной и обязательной функцией loop()

if(On_Time < Off_Time) //Проверка, таймер в течении одних суток?
{
if (Curent_Time >= On_Time && Curent_Time <= Off_Time)
for(int fadeValue = 0; fadeValue <= 255; fadeValue +=3)
{
analogWrite(LR, fadeValue);
}
else
for(int fadeValue = 255; fadeValue >= 0; fadeValue -=3)
{
analogWrite(LR, fadeValue);
}
}

Эта конструкция буде много раз повторена в цикле и каждый раз при совпадении условий if (Curent_Time >= On_Time && Curent_Time <= Off_Time)
будет выполнен ваш цикл изменения яркости

for(int fadeValue = 0; fadeValue <= 255; fadeValue +=3)
{
analogWrite(LR, fadeValue);
}

Причем это будет выполнено с частотой процессора, т.е. яркость от 0 до 100 процентов будет увеличена за несколько микросекунд, что будет незаметно человеческому глазу....тем более у Вас шаг инкремента = 3. Т.е. пока условия выполняются светодиод будет вспыхивать с частотой главного цикла. Нарастание яркости будет очень кратковременным, а остальное время светодиод находится в состоянии максимальной яркости. В итоге, при этих условиях, светодиод будет гореть с яркостью чуть меньше максимальной....

Выход в том, чтобы делать приращения значения, которое пишется в аналоговый порт (ШИМ) не в каждом повторении главного цикла, а тогда когда это нужно, исходя из длительность периода увеличения яркости.

Или можно, после функции analogWrite(LR, fadeValue); добавить задержку в цикл изменения яркости, например функцией delay(), подобрав в качестве аргумента значение, которое будет равно длительности периода увеличения яркости светодиода, выраженное в миллисекундах, деленное на 255.

Но это очень и очень плохой путь...только для тестирования и опробования разных идей...для рабочей программы это использовать нельзя, т.к. delay() будет останавливать главных цикл loop() и контроль других событий времени - станет невозможным, или очень некачественным.

Чтобы понять, как можно сделать, так чтобы главный цикл не был загружен задержками, и внутри него оставалась возможность обрабатывать другие события времени - посмотрите пример в данной теме с закатом и рассветом, там показано, как организовывать подобные конструкции внутри главного цикла loop().

Изменено 24.3.14 автор Z0RS
2014-03-25 добавлено 25/03/2014 00:27:36#1954463

Новичок




46
Germany Wolfsegg
2 г. назад
Z0RS


Да поймите просто, что я в программировании почти полный ноль. Поэтому и прошу помощи у знающих людей.
Я понял смысл того, что вы написали, но как воплотить всё это в реальность для меня проблема.
2014-03-25 добавлено 25/03/2014 02:17:35#1954477

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
kirex05
Да поймите просто, что я в программировании почти полный ноль. Поэтому и прошу помощи у знающих людей.
Я понял смысл того, что вы написали, но как воплотить всё это в реальность для меня проблема.


Да все понятно.....просто пути стать более удаленным от нуля я Вам указал.

Один из этих путей - это изучение и использование чужого опыта. Я еще раз предлагаю по-изучайте пример с рассветом и закатом. Это пример рабочий....он корректно отрабатывает в диапазоне одних суток, но можно изменив константу количества секунд в сутках заставить этот код отрабатывать и в других интервалах.

Специально для вас привожу ссылку на обновленный код с расширенными комментариями:

http://my-files.ru/4...

А описание принципов работы - читайте на 2й странице темы. Код проще некуда. В главном цикле меньше 2х десятков строк кода. Некоторые строки разбиты на несколько частей для того чтобы код в редакторе убирался на ширину экрана, обычно я делаю такое разбиение по какому нибудь логическому или арифметическому оператору. Для того чтобы это исправить можно применить к тексту автоформатирование. Тогда, автоматический редактор приведет код к классическому виду с отступами по стандарту. Автоформатирование находится в меню сервис...может такой код для Вас будет нагляднее...

В другом случае, если у Вас существует желание, ничего не изучать, и чтобы кто-то просто написал Вам полностью комплектное ПО для контроллера - то лучше обращаться к программистам фрилансерам на соответстующих сайтах...там бывает толковый народ со скромными запросами по оплате....
2014-03-25 добавлено 25/03/2014 11:12:45#1954558

Новичок




46
Germany Seubersdorf
2 г. назад
Z0RS


Спасибо за пример.
Подскажите где я допустил ошибку. Не меняется максимальная яркость по каналам, всегда на максимум.

#include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC
#include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC


#define PWM_LW_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LW_MAX 128 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LW_PIN 11 //Пин порта, где будет ШИМ LW

#define PWM_LR_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LR_MAX 200 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LR_PIN 3 //Пин порта, где будет ШИМ LR

#define PWM_LB_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LB_MAX 255 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LB_PIN 12 //Пин порта, где будет ШИМ LB

#define mn 60UL //Дополнительные константы для удобства
#define hr 3600UL //Отражают соответствующие количества секунд
#define d 86400UL

RTC_DS1307 RTC;

long sunrise_start = 11*hr+28*mn; //Начало восхода в 9 - 45
long sunrise_duration = 1*mn; //Длительность восхода 30 минут
long sunset_start = 11*hr+30*mn; //начало заката в 21-15
long sunset_duration = 1*mn; //Длительность заката 30 минут
long moonrise_start = 11*hr+30*mn ; //Начало луны в 9 - 45
long moonrise_duration = 1*mn; //Длительность восхода
long moonset_start = 11*hr+32*mn; //Конец луны в 11
long moonset_duration = 1*mn; //Длительность заката луны
//********************************************************************************************
void setup(){


Wire.begin(); //Инициируем I2C интерфейс
RTC.begin(); //Инициирум RTC модуль
analogWrite(PWM_LW_PIN, PWM_LW_MIN); //Пишем в порт минимальное значение
analogWrite(PWM_LR_PIN, PWM_LR_MIN);
analogWrite(PWM_LB_PIN, PWM_LB_MIN);
//RTC.adjust(DateTime(__DATE__, __TIME__));
} // КОНЕЦ ИНИЦИАЛИЗАЦИИ

//********************************************************************************************
void loop() // ПРОГРАММЫй безусловный ЦИКЛ
{

long pwm;
DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла
long Day_time = myTime.unixtime() % 86400; //сохраняем в переменную - время в формате UNIX
//*********************************************************************************************
// обработка интервала до восхода и после заката
//*********************************************************************************************
if ((Day_time<sunrise_start) || //Если с начала суток меньше чем начало восхода
(Day_time>=sunset_start+sunset_duration)) { //Или больше чем начало заката + длительность
pwm = PWM_LW_MIN; //Величина для записи в порт равна минимуму
pwm = PWM_LR_MIN;

//*********************************************************************************************
// обработка интервала восхода
//*********************************************************************************************
}else if ((Day_time>=sunrise_start) && //Если с начала суток больше чем начало восхода
(Day_time<sunrise_start+sunrise_duration)){ //И меньше чем начало восхода + длительность

pwm = ((Day_time - sunrise_start)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration; //Вычисляем для рассвета величину для записи в порт ШИМ
pwm = ((Day_time - sunrise_start)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;

//*********************************************************************************************
// обработка интервала заката
//*********************************************************************************************
}else if ((Day_time>=sunset_start) && //Если начала суток больше чем начало заката и меньше чем
(Day_time<sunset_start+sunset_duration)){ //начало заката плюс длительность

pwm = ((sunset_start+sunset_duration - Day_time)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration; //Вычисляем для заката величину для записи в порт ШИМ
pwm = ((sunset_start+sunset_duration - Day_time)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;

//********************************************************************************************
// обработка интервала от конца рассвета и до начала заката,
// когда свет должен быть включен на максимальную яркость
//********************************************************************************************
}else {
pwm = PWM_LW_MAX; //Устанавливаем максимальную величину для записи в порт ШИМ
pwm = PWM_LR_MAX;
}

analogWrite(PWM_LW_PIN, pwm); //Пишем в порт вычисленное значение
analogWrite(PWM_LR_PIN, pwm);

// обработка интервала до восхода луны и после заката
//*********************************************************************************************
if ((Day_time<moonrise_start) || //Если с начала суток меньше чем начало восхода
(Day_time>=moonset_start+moonset_duration)) { //Или больше чем начало заката + длительность
pwm = PWM_LB_MIN; //Величина для записи в порт равна минимуму

//*********************************************************************************************
// обработка интервала восхода луны
//*********************************************************************************************
}else if ((Day_time>=moonrise_start) && //Если с начала суток больше чем начало восхода
(Day_time<moonrise_start+moonrise_duration)){ //И меньше чем начало восхода + длительность

pwm = ((Day_time - moonrise_start)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration; //Вычисляем для рассвета величину для записи в порт ШИМ

//*********************************************************************************************
// обработка интервала заката луны
//*********************************************************************************************
}else if ((Day_time>=moonset_start) && //Если начала суток больше чем начало заката и меньше чем
(Day_time<moonset_start+moonset_duration)){ //начало заката плюс длительность

pwm = ((moonset_start+moonset_duration - Day_time)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration; //Вычисляем для заката величину для записи в порт ШИМ

//********************************************************************************************
// обработка интервала от конца рассвета и до начала заката луны,
// когда свет должен быть включен на максимальную яркость
//********************************************************************************************
}else {
pwm = PWM_LB_MAX; //Устанавливаем максимальную величину для записи в порт ШИМ
}

analogWrite(PWM_LB_PIN, pwm); //Пишем в порт вычисленное значение

}//------------Конец ЦИКЛА-----------------------------
2014-03-25 добавлено 25/03/2014 13:31:46#1954578

Новичок




46
Germany Seubersdorf
2 г. назад
Спасибо, уже разобрался
2014-03-25 добавлено 25/03/2014 13:58:25#1954587

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
kirex05

Напишите точную маркировку вашего процессора на плате.

И еще...этот код, который я привел в качестве примера нельзя "тупо в лоб" использовать для управления несколькими каналами ШИМ.
Я проанализирую, что Вы напрограммировали и отвечу по-позже...пока ответьте по процессору...
2014-03-25 добавлено 25/03/2014 14:08:38#1954593

Новичок




46
Germany Seubersdorf
2 г. назад
Z0RS


ATMEGA 2560
16AU 1346


Вот конечный результат:

#include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC
#include "RTClib.h" //Подключаем библиотеку для использования модуля часов реального времени RTC
// библиотека экрана
#include "LiquidCrystal.h"
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);


#define PWM_LW_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LW_MAX 128 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LW_PIN 11 //Пин порта, где будет ШИМ LW

#define PWM_LR_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LR_MAX 200 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LR_PIN 3 //Пин порта, где будет ШИМ LR

#define PWM_LB_MIN 0 //Если необходим ток покоя на LED - изменить эту константу
#define PWM_LB_MAX 235 //Если необходимо ограничить максимальную яркость - уменьшить значение
#define PWM_LB_PIN 12 //Пин порта, где будет ШИМ LB

#define mn 60UL //Дополнительные константы для удобства
#define hr 3600UL //Отражают соответствующие количества секунд
#define d 86400UL

RTC_DS1307 RTC;

long sunrise_start = 11*hr+52*mn; //Начало восхода в 9 - 45
long sunrise_duration = 1*mn; //Длительность восхода 30 минут
long sunset_start = 11*hr+54*mn; //начало заката в 21-15
long sunset_duration = 1*mn; //Длительность заката 30 минут
long moonrise_start = 11*hr+54*mn ; //Начало луны в 9 - 45
long moonrise_duration = 1*mn; //Длительность восхода
long moonset_start = 11*hr+56*mn; //Конец луны в 11
long moonset_duration = 1*mn; //Длительность заката луны
//********************************************************************************************
void setup(){

Serial.begin(9600);
lcd.begin(16, 2); // запускаем библиотеку экрана
Wire.begin(); //Инициируем I2C интерфейс
RTC.begin(); //Инициирум RTC модуль
analogWrite(PWM_LW_PIN, PWM_LW_MIN); //Пишем в порт минимальное значение
analogWrite(PWM_LR_PIN, PWM_LR_MIN);
analogWrite(PWM_LB_PIN, PWM_LB_MIN);
if (! RTC.isrunning()) {
Serial.println("RTC is NOT running!");
RTC.adjust(DateTime(2014, 7, 12, 22, 48, 1));
}
//RTC.adjust(DateTime(2012, 7, 31, 21, 53, 1));
//RTC.adjust(DateTime(__DATE__, __TIME__));
} // КОНЕЦ ИНИЦИАЛИЗАЦИИ

//********************************************************************************************
void loop() // ПРОГРАММЫй безусловный ЦИКЛ
{
analogWrite(10, 100);
lcd.setCursor(0, 1);
long pwm_LW;
long pwm_LR;
long pwm_LB;
DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла
long Day_time = myTime.unixtime() % 86400; //сохраняем в переменную - время в формате UNIX
lcd.clear();
lcd.setCursor(11,0);
lcd.print(myTime.hour(),DEC);
lcd.print(":");
lcd.print(myTime.minute(),DEC);
delay(1000);
//*********************************************************************************************
// обработка интервала до восхода и после заката
//*********************************************************************************************
if ((Day_time<sunrise_start) || //Если с начала суток меньше чем начало восхода
(Day_time>=sunset_start+sunset_duration)) { //Или больше чем начало заката + длительность
pwm_LW = PWM_LW_MIN; //Величина для записи в порт равна минимуму
pwm_LR = PWM_LR_MIN;

//*********************************************************************************************
// обработка интервала восхода
//*********************************************************************************************
}else if ((Day_time>=sunrise_start) && //Если с начала суток больше чем начало восхода
(Day_time<sunrise_start+sunrise_duration)){ //И меньше чем начало восхода + длительность

pwm_LW = ((Day_time - sunrise_start)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration; //Вычисляем для рассвета величину для записи в порт ШИМ
pwm_LR = ((Day_time - sunrise_start)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;

//*********************************************************************************************
// обработка интервала заката
//*********************************************************************************************
}else if ((Day_time>=sunset_start) && //Если начала суток больше чем начало заката и меньше чем
(Day_time<sunset_start+sunset_duration)){ //начало заката плюс длительность

pwm_LW = ((sunset_start+sunset_duration - Day_time)*(PWM_LW_MAX-PWM_LW_MIN)) / sunrise_duration; //Вычисляем для заката величину для записи в порт ШИМ
pwm_LR = ((sunset_start+sunset_duration - Day_time)*(PWM_LR_MAX-PWM_LR_MIN)) / sunrise_duration;

//********************************************************************************************
// обработка интервала от конца рассвета и до начала заката,
// когда свет должен быть включен на максимальную яркость
//********************************************************************************************
}else {
pwm_LW = PWM_LW_MAX; //Устанавливаем максимальную величину для записи в порт ШИМ
pwm_LR = PWM_LR_MAX;
}

analogWrite(PWM_LW_PIN, pwm_LW); //Пишем в порт вычисленное значение
analogWrite(PWM_LR_PIN, pwm_LR);

// обработка интервала до восхода луны и после заката
//*********************************************************************************************
if ((Day_time<moonrise_start) || //Если с начала суток меньше чем начало восхода
(Day_time>=moonset_start+moonset_duration)) { //Или больше чем начало заката + длительность
pwm_LB = PWM_LB_MIN; //Величина для записи в порт равна минимуму

//*********************************************************************************************
// обработка интервала восхода луны
//*********************************************************************************************
}else if ((Day_time>=moonrise_start) && //Если с начала суток больше чем начало восхода
(Day_time<moonrise_start+moonrise_duration)){ //И меньше чем начало восхода + длительность

pwm_LB = ((Day_time - moonrise_start)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration; //Вычисляем для рассвета величину для записи в порт ШИМ

//*********************************************************************************************
// обработка интервала заката луны
//*********************************************************************************************
}else if ((Day_time>=moonset_start) && //Если начала суток больше чем начало заката и меньше чем
(Day_time<moonset_start+moonset_duration)){ //начало заката плюс длительность

pwm_LB = ((moonset_start+moonset_duration - Day_time)*(PWM_LB_MAX-PWM_LB_MIN)) / moonrise_duration; //Вычисляем для заката величину для записи в порт ШИМ

//********************************************************************************************
// обработка интервала от конца рассвета и до начала заката луны,
// когда свет должен быть включен на максимальную яркость
//********************************************************************************************
}else {
pwm_LB = PWM_LB_MAX; //Устанавливаем максимальную величину для записи в порт ШИМ
}

analogWrite(PWM_LB_PIN, pwm_LB); //Пишем в порт вычисленное значение

}//------------Конец ЦИКЛА-----------------------------


Изменено 25.3.14 автор kirex05

Изменено 25.3.14 автор kirex05
2014-03-25 добавлено 25/03/2014 14:16:35#1954597

Свой на Aqa.ru




693 77
Выкса
11 мес. назад
kirex05


А этот код, который Вы привели в предыдущем сообщении - у меня работает. Я выкинул из него все что относится к LCD, т.к. он у меня не подключен, сделал для отладки длительность рассвета и заката по 3 минуты. По портам ШИМ на 11 пине и на 3 пине, этот код корректно отработал все интервалы.

Кстати при отладке ненужно пихать в код всякую непотребщину...мне пришлось все это выкидывать и тратить на это время....больше я этого делать не буду...
Приводите в пример очищенный кусок кода который можно компилировать и отлаживать сразу....

А что касается канала управления лунным светом, то с ним нужно поступать по другому...
Т.к. тут есть переход через границу суток, то приведенный прием с ним работать не будет. Необходимо сделать другое время начала суток для отработки этого канала.

Например, установим, что сутки для обработки лунного света начинаются в 20 часов ровно. В секундах это 72000.
Ддя того, чтобы сменить время начала суток в системе UNIXTIME необходимо к прочтенному времени с RTC прибавить наше смещение, затем записать остаток от деления полученной величины в отдельную переменную и для обработки интервалов лунного света - использовать именно эту переменную.

В коде нужно определить константу - смещение
#drfine moonLightOffset 72000UL

потом вот так мы определяем время начало суток для операций с дневным светом в 2х каналах:
long Day_time = myTime.unixtime() % 86400; //сохраняем в переменную - время в формате UNIX

А вот так нужно определить время начала суток для операций с лунным светом:
long MoonDay_time = (myTime.unixtime() + moonLightOffset) % 86400; //сохраняем в переменную - время в формате UNIX

НО интервалы восхода луны и заката луны - нужно задать относительно измененного вренени начала суток для луны, т.е. относительно Смещения - moonLightOffset. Например вот так:

long moonrise_start = 2*hr+30*mn; //Начало восхода луны в 22 часа 30 минут (это с учетом смещения)
long moonrise_duration = 30*mn; //Длительность восхода луны
long moonset_start = 12*hr+45*mn; //Начало заката луны в 8 часов 45 минут (на следующие астрономические сутки)
long moonset_duration = 30*mn; //Длительность заката луны

И соответственно, в блоке проверки условий для луны использовать вышеприведенные переменные...
Надеюсь, сами вставите это в код....

И еще....не используйте всеже функцию delay в главном цикле loop(). И в целях отладки не делайте длительность рассвета и заката равными одной минуте...делайте хотя бы 3 минуты.
2014-03-25 добавлено 25/03/2014 16:36:27#1954662

<< 12 45678910 >> Создать новую темуБыстрый ответ