Проблемы с управлением солнечной батареей

AndreiR
Offline
Зарегистрирован: 13.08.2022

Всем привет! 

Использую ардуино в качестве хобби и как правило использую в очень простых проектах. Однако знакомый попросил помощи в управлении солнечными батареями. С железом не очень дружу, но железо(несколько реле,нужное напряжение для срабатывания реле)  сделал коллега с работы и оно работает.

Проблема: Поставили ардуино и железо на месте для управления солнечной панелью. Выставляю стетч для отработки поворотов вправо, влево, вниз и вверх с интервалом в одну минуту. Все работает прекрасно, панель исполняет то, что нужно. Когда выставляю длинный промежуток(24 часа), то знакомый утверждает, что скетч отработал полный цикл один день(однако запустили мы в 15:00, а не в 10 утра, чтоб пройти ровно сутки) и на следующий день управление перестало работать. Не могу теперь понять, толи явная ошибка в коде, толи у нас где-то в силовой системе идет просадка питания. Прошу помощи в просматривании логики когда. Если там есть явные ошибки, то какие? 

Сам скетч:

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

использую Arduino Uno, питание от блока питания 9V, напряжение на стабилизаторе не проседает, выход ардуино стабильные 5V выдает. Сама ардуино старая, может ли сам контроллер некорректно срабатывать?

В loop прописано 5 циклов для поворота вправо, по 2 цикла вверх и вниз и один для поворота влево. 

Буду очень благодарен за любую помощь! 

#include <RTClib.h>

const byte contrPin2 = 11; // вверх
const byte contrPin3 = 10; // вниз
const byte contrPin4 = 8;  // влево
const byte contrPin5 = 9;  //вправо
int kaitseParemPin = 5; // защита при повороте вправо
int kaitseVasakPin = 7; // защита при повороте влево
int checkEndParem; // перееменная для контроля статуса правого защитного механизма
int checkEndVasak; // перееменная для контроля статуса левого защитного механизма

uint8_t hour1 = 10;   // вверх:1 время:10:00, поворот:20 sek
uint8_t minute1 = 0; 
uint8_t second1 = 20; 

uint8_t hour2 = 11;  //вправо:1 время:11:00, поворот:23 sek
uint8_t minute2 = 0; 
uint8_t second2 = 23; 

uint8_t hour3 = 13; //вправо:2 время:13:00, поворот:66 sek
uint8_t minute3 = 0; 
uint8_t second3 = 59; 
uint8_t minute31 = 1; 
uint8_t second31 = 6;

uint8_t hour4 = 13; // вверх:2,  время:13:15, поворот:10 sek
uint8_t minute4 = 15; 
uint8_t second4 = 10;

uint8_t hour5 = 15;  // вправо:3, время:15:00, поворот:80 sek
uint8_t minute5 = 0; 
uint8_t second5 = 59;
uint8_t minute51 = 1; 
uint8_t second51 = 20;

uint8_t hour6 = 16; // вниз:1, время:16:00, поворот:8 sek 
uint8_t minute6 = 0; 
uint8_t second6 = 8;

uint8_t hour7 = 17; //вправо:4 время:17:00, поворот:59 sek
uint8_t minute7 = 0; 
uint8_t second7 = 59;
 
uint8_t hour8 = 18;  // вниз:2, время:18:00, поворот:26 sek
uint8_t minute8 = 0; 
uint8_t second8 = 26;

uint8_t hour9 = 19; //вправо:5 время:19:00, поворот:59 sek
uint8_t minute9 = 0; 
uint8_t second9 = 59;

uint8_t hour10 = 3; //влево время:03:00, поворот:260 sek
uint8_t minute10 = 3; 
uint8_t second10 = 59;
uint8_t minute101 = 4; 
uint8_t second101 = 20;
RTC_DS1307 rtc;
void setup() {
   if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

//rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // выставление времени модулю DS1307, взятие текущего времени компьютера
  pinMode(contrPin2, OUTPUT);
  pinMode(contrPin3, OUTPUT);
  pinMode(contrPin4, OUTPUT);
  pinMode(contrPin5, OUTPUT);
  pinMode(kaitseParemPin, INPUT);
  pinMode(kaitseVasakPin, INPUT);
Serial.begin(9600);


}

void loop() {

DateTime now = rtc.now(); // считывание времени временного модуля DS1307
checkEndParem = digitalRead(kaitseParemPin); // считывание состояния правого защитного механизма, где 0-не замкнут, 1-замкнут
checkEndVasak = digitalRead(kaitseVasakPin); // считывание состояния левого защитного механизма, где 0-не замкнут, 1-замкнут


if (now.hour()   == hour2 &&
      now.minute() == minute2 &&
      now.second()   <=  second2 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH); /* Если часы и минуты с модуля времени равны заданным в переменных и защитный механизм не замкнут и ардуино видит временной модуль,
      то активировать пин на количество секунд в переменной для поворота конструкции вправо*/
}

else if ((now.hour()   == hour3 &&
      now.minute() == minute3 &&
      now.second()   <=  second3 &&
      checkEndParem == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour3 &&
      now.minute() == minute31 &&
      now.second()   <=  second31 &&
      checkEndParem == 0 && rtc.begin() == 1)) {
      digitalWrite(contrPin5, HIGH);
}

else if ((now.hour()   == hour5 &&
      now.minute() == minute5 &&
      now.second()   <=  second5 &&
      checkEndParem == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour5 &&
      now.minute() == minute51 &&
      now.second()   <=  second51 &&
      checkEndParem == 0 && rtc.begin() == 1)) {
      digitalWrite(contrPin5, HIGH);
}

else if (now.hour()   == hour7 &&
      now.minute() == minute7 &&
      now.second()   <=  second7 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH);
}

else if (now.hour()   == hour9 &&
      now.minute() == minute9 &&
      now.second()   <=  second9 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH);
}

else {
  digitalWrite(contrPin5, LOW);
}

if (now.hour()   == hour1 && 
      now.minute() == minute1 &&
      now.second()   <=  second1 && rtc.begin() == 1) {
      digitalWrite(contrPin2, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль, то активировать пин
      на количество секунд в переменной для поднятия конструкции вверх */
}

else if (now.hour()   == hour4 &&
      now.minute() == minute4 &&
      now.second()   <=  second4 && rtc.begin() == 1) {
      digitalWrite(contrPin2, HIGH);
}

else {
  digitalWrite(contrPin2, LOW);
}

if (now.hour()   == hour6 &&
      now.minute() == minute6 &&
      now.second()   <=  second6 && rtc.begin() == 1) {
      digitalWrite(contrPin3, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль, то активировать пин
      на количество секунд в переменной для опускания конструкции вниз */
}

else if (now.hour()   == hour8 &&
      now.minute() == minute8 &&
      now.second()   <=  second8 && rtc.begin() == 1) {
      digitalWrite(contrPin3, HIGH);
}
else {
  digitalWrite(contrPin3, LOW);
}

if ((now.hour()   == hour10 &&
      now.minute() <= minute10 &&
      now.second()   <=  second10 &&
      checkEndVasak == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour10 &&
      now.minute() == minute101 &&
      now.second()   <=  second101 &&
      checkEndVasak == 0 && rtc.begin() == 1)) 
      {
      digitalWrite(contrPin4, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль и левый защитный механизм
      не активирован, то активировать пин на количество секунд в переменной для поворота конструкции влево */
}
else {
  digitalWrite(contrPin4, LOW);
}

//printTime(now); // вывод времени на Serial Monitor, использую только когда проверяю исправность временного модуля.

}

/*void printTime(DateTime time) {
  Serial.print("TIME: ");
  Serial.print(time.year(), DEC);
  Serial.print('/');
  Serial.print(time.month(), DEC);
  Serial.print('/');
  Serial.print(time.day(), DEC);
  Serial.print(") ");
  Serial.print(time.hour(), DEC);
  Serial.print(':');
  Serial.print(time.minute(), DEC);
  Serial.print(':');
  Serial.println(time.second(), DEC);
}
*/

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Боюсь, что вот это понятно только Вам

AndreiR пишет:
Выставляю стетч для отработки поворотов вправо, влево, вниз и вверх с интервалом в одну минуту. Все работает прекрасно, панель исполняет то, что нужно. Когда выставляю длинный промежуток(24 часа), то знакомый утверждает, что скетч отработал полный цикл один день(однако запустили мы в 15:00, а не в 10 утра, чтоб пройти ровно сутки) и на следующий день управление перестало работать.

Что Вы выставляете? Где выставляете? Через какой интерфейс? Или Вы переменные в скетче меняете? Тогда что про Ваш выложенный скетч - это он не работает? Или после "выставления"? Какой знакомый утверждает? Какие 15 и 10 и на какой день престало работать. И, кстати, что значит "перестало работать" - что стало делать? Ничего, вертеть постоянно, загорелось?

Давайте-ка толком.

AndreiR
Offline
Зарегистрирован: 13.08.2022

Добрый вечер!

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

Солнечная установка стоит на участке у знакомого, для которого и писался скетч.(сам там не присутсвую постоянно). При тестировании на месте: брал этот скетч, который выставил на форум и менял время в переменных на то, в какой момент там находился. Т.е. я был там примерно в 13:00, поменял переменные первого цикла на 13:02(hour1 = 13, minute1 = 2, second1 = 20 второго на 13:03(hour2 = 13, minute2 = 3,second2 = 23),третьего на 13:04 чтобы в живую увидеть, что раз в минуту мой скетч поварачивает панель в нужные стороны, как должно быть по задумке. Раз в минуту отработка прошла успешно. После этого я поменял время переменных в этом же скетче на те, которые просил знакомый. Т.е. первый цикл в 10:00(hour1 = 10,minute1 = 0, second1 = 20) второй в 11:00(hour2 = 11,minute2 = 0, second2 = 23 третий в 13:00 и т.д. По итогу загрузил я этот скетч в ардуино примерно в 15:00 и все оставшиеся циклы до следующего утра были успешно выполнены(последний сработал в 3 утра и повернул панель в начальное положение влево)(опять же со слов знакомого, сам лично видел исполнение в 15:00). А вот в 10:00(поднятие панели вверх)  должно было начаться новое выполнение и оно не началось. Как утверждает этот знакомый, панель просто ничего не делает, т.е. вообще не вертится.

Загружал скетч в ардуино через USB, используя arduino IDE софт. 

Почему ничего не происходит, непонятно от слова совсем... В наличии есть новая arduino uno, но нужно перепаивать контакты на месте, чтобы установить новую. От этого возник такой вопрос: может ли контроллер в ардуино от старости или неверном использовании вести себя некорректно?

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

Спасибо!

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Давайте, я посмотрю либо завтра, либо в понедельник.

Пока лишь отмечу, что у Вас возможно использование Serial в строке №60 до его инициализации в строке №71.

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

mixail844
Offline
Зарегистрирован: 30.04.2012

AndreiR пишет:

#include <RTClib.h>


const byte contrPin2 = 11; // вверх
const byte contrPin3 = 10; // вниз
const byte contrPin4 = 8;  // влево
const byte contrPin5 = 9;  //вправо
int kaitseParemPin = 5; // защита при повороте вправо
int kaitseVasakPin = 7; // защита при повороте влево
int checkEndParem; // перееменная для контроля статуса правого защитного механизма
int checkEndVasak; // перееменная для контроля статуса левого защитного механизма

uint8_t hour1 = 10;   // вверх:1 время:10:00, поворот:20 sek
uint8_t minute1 = 0; 
uint8_t second1 = 20; 

uint8_t hour2 = 11;  //вправо:1 время:11:00, поворот:23 sek
uint8_t minute2 = 0; 
uint8_t second2 = 23; 

uint8_t hour3 = 13; //вправо:2 время:13:00, поворот:66 sek
uint8_t minute3 = 0; 
uint8_t second3 = 59; 
uint8_t minute31 = 1; 
uint8_t second31 = 6;

uint8_t hour4 = 13; // вверх:2,  время:13:15, поворот:10 sek
uint8_t minute4 = 15; 
uint8_t second4 = 10;

uint8_t hour5 = 15;  // вправо:3, время:15:00, поворот:80 sek
uint8_t minute5 = 0; 
uint8_t second5 = 59;
uint8_t minute51 = 1; 
uint8_t second51 = 20;

uint8_t hour6 = 16; // вниз:1, время:16:00, поворот:8 sek 
uint8_t minute6 = 0; 
uint8_t second6 = 8;

uint8_t hour7 = 17; //вправо:4 время:17:00, поворот:59 sek
uint8_t minute7 = 0; 
uint8_t second7 = 59;
 
uint8_t hour8 = 18;  // вниз:2, время:18:00, поворот:26 sek
uint8_t minute8 = 0; 
uint8_t second8 = 26;

uint8_t hour9 = 19; //вправо:5 время:19:00, поворот:59 sek
uint8_t minute9 = 0; 
uint8_t second9 = 59;

uint8_t hour10 = 3; //влево время:03:00, поворот:260 sek
uint8_t minute10 = 3; 
uint8_t second10 = 59;
uint8_t minute101 = 4; 
uint8_t second101 = 20;
RTC_DS1307 rtc;
void setup() {
   if (! rtc.begin()) {
    Serial.println("Couldn't find RTC");
    while (1);
  }

//rtc.adjust(DateTime(F(__DATE__), F(__TIME__))); // выставление времени модулю DS1307, взятие текущего времени компьютера
  pinMode(contrPin2, OUTPUT);
  pinMode(contrPin3, OUTPUT);
  pinMode(contrPin4, OUTPUT);
  pinMode(contrPin5, OUTPUT);
  pinMode(kaitseParemPin, INPUT);
  pinMode(kaitseVasakPin, INPUT);
Serial.begin(9600);


}

void loop() {

DateTime now = rtc.now(); // считывание времени временного модуля DS1307
checkEndParem = digitalRead(kaitseParemPin); // считывание состояния правого защитного механизма, где 0-не замкнут, 1-замкнут
checkEndVasak = digitalRead(kaitseVasakPin); // считывание состояния левого защитного механизма, где 0-не замкнут, 1-замкнут


if (now.hour()   == hour2 &&
      now.minute() == minute2 &&
      now.second()   <=  second2 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH); /* Если часы и минуты с модуля времени равны заданным в переменных и защитный механизм не замкнут и ардуино видит временной модуль,
      то активировать пин на количество секунд в переменной для поворота конструкции вправо*/
}

else if ((now.hour()   == hour3 &&
      now.minute() == minute3 &&
      now.second()   <=  second3 &&
      checkEndParem == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour3 &&
      now.minute() == minute31 &&
      now.second()   <=  second31 &&
      checkEndParem == 0 && rtc.begin() == 1)) {
      digitalWrite(contrPin5, HIGH);
}

else if ((now.hour()   == hour5 &&
      now.minute() == minute5 &&
      now.second()   <=  second5 &&
      checkEndParem == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour5 &&
      now.minute() == minute51 &&
      now.second()   <=  second51 &&
      checkEndParem == 0 && rtc.begin() == 1)) {
      digitalWrite(contrPin5, HIGH);
}

else if (now.hour()   == hour7 &&
      now.minute() == minute7 &&
      now.second()   <=  second7 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH);
}

else if (now.hour()   == hour9 &&
      now.minute() == minute9 &&
      now.second()   <=  second9 &&
      checkEndParem == 0 && rtc.begin() == 1) {
      digitalWrite(contrPin5, HIGH);
}

else {
  digitalWrite(contrPin5, LOW);
}

if (now.hour()   == hour1 && 
      now.minute() == minute1 &&
      now.second()   <=  second1 && rtc.begin() == 1) {
      digitalWrite(contrPin2, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль, то активировать пин
      на количество секунд в переменной для поднятия конструкции вверх */
}

else if (now.hour()   == hour4 &&
      now.minute() == minute4 &&
      now.second()   <=  second4 && rtc.begin() == 1) {
      digitalWrite(contrPin2, HIGH);
}

else {
  digitalWrite(contrPin2, LOW);
}

if (now.hour()   == hour6 &&
      now.minute() == minute6 &&
      now.second()   <=  second6 && rtc.begin() == 1) {
      digitalWrite(contrPin3, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль, то активировать пин
      на количество секунд в переменной для опускания конструкции вниз */
}

else if (now.hour()   == hour8 &&
      now.minute() == minute8 &&
      now.second()   <=  second8 && rtc.begin() == 1) {
      digitalWrite(contrPin3, HIGH);
}
else {
  digitalWrite(contrPin3, LOW);
}

if ((now.hour()   == hour10 &&
      now.minute() <= minute10 &&
      now.second()   <=  second10 &&
      checkEndVasak == 0 && rtc.begin() == 1) ||
      (now.hour()   == hour10 &&
      now.minute() == minute101 &&
      now.second()   <=  second101 &&
      checkEndVasak == 0 && rtc.begin() == 1)) 
      {
      digitalWrite(contrPin4, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль и левый защитный механизм
      не активирован, то активировать пин на количество секунд в переменной для поворота конструкции влево */
}
else {
  digitalWrite(contrPin4, LOW);
}

//printTime(now); // вывод времени на Serial Monitor, использую только когда проверяю исправность временного модуля.

}

/*void printTime(DateTime time) {
  Serial.print("TIME: ");
  Serial.print(time.year(), DEC);
  Serial.print('/');
  Serial.print(time.month(), DEC);
  Serial.print('/');
  Serial.print(time.day(), DEC);
  Serial.print(") ");
  Serial.print(time.hour(), DEC);
  Serial.print(':');
  Serial.print(time.minute(), DEC);
  Serial.print(':');
  Serial.println(time.second(), DEC);
}
*/

 

сдаеться мне , что в какой то момент времени ,механизм доходит до крайнего положения вверх и в сторону и из за того что checkEndParem  = 1 и checkEndVasak  = 1 , и при следующем цикле , ниодно условие в if не истино

и да , я бы тоже переписал на некий массив/сценарий "действий" . каждый элемент массива содержал в себе информацию о текущем действии : время начала действия ,время конца (или продолжительность) , фунцкия дейстивя(включить мотор )  , условие окончания.

b707
Offline
Зарегистрирован: 26.05.2017

Чисто языкознательный интерес- kaitse, parem, vasak - это что за язык? Турецкий?

mifar
Offline
Зарегистрирован: 07.04.2021

mixail844 пишет:

сдаеться мне , что в какой то момент времени ,механизм доходит до крайнего положения вверх и в сторону и из за того что checkEndParem  = 1 и checkEndVasak  = 1 , и при следующем цикле , ниодно условие в if не истино

Концевики участвуют только в поворотах, подъем/опускание работает без условий.

b707 пишет:
Чисто языкознательный интерес- kaitse, parem, vasak - это что за язык? Турецкий?

похоже эстонский

AndreiR
Offline
Зарегистрирован: 13.08.2022

b707 пишет:
Чисто языкознательный интерес- kaitse, parem, vasak - это что за язык? Турецкий?

Добрый день,

Да-это эстонский. Как-то уже машинально пишется на эстонском. Комменты тоже были все на эст.языке. Не сразу даже осознал, что тут вряд ли поймут :))

 

 

AndreiR
Offline
Зарегистрирован: 13.08.2022

mifar]</p> <p>[quote=mixail844 пишет:

сдаеться мне , что в какой то момент времени ,механизм доходит до крайнего положения вверх и в сторону и из за того что checkEndParem  = 1 и checkEndVasak  = 1 , и при следующем цикле , ниодно условие в if не истино

Концевики участвуют только в поворотах, подъем/опускание работает без условий.

Добрый день,

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

AndreiR
Offline
Зарегистрирован: 13.08.2022

ЕвгенийП пишет:

Давайте, я посмотрю либо завтра, либо в понедельник.

Пока лишь отмечу, что у Вас возможно использование Serial в строке №60 до его инициализации в строке №71.

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

 

Буду очень признателен! Честно говоря, с функциями так и не разобрался до конца, времени не хватает. Готовые брал и пользовал, а самому как-то пока не сложилось в голове. Да и тут бы просто разобраться, где проблема.

mifar
Offline
Зарегистрирован: 07.04.2021

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

AndreiR пишет:
Да и тут бы просто разобраться, где проблема.
Вы не поняли моей главной мысли. Как раз в коротком (в несколько раз) коде разобраться "где проблема" будет намного проще.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:
все оставшиеся циклы до следующего утра были успешно выполнены(последний сработал в 3 утра и повернул панель в начальное положение влево)

AndreiR] [quote=mifar пишет:
mixail844 пишет:
сдаеться мне , что в какой то момент времени ,механизм доходит до крайнего положения вверх и в сторону и из за того что checkEndParem = 1 и checkEndVasak = 1 , и при следующем цикле , ниодно условие в if не истино
Концевики участвуют только в поворотах, подъем/опускание работает без условий.

По моему здесь не до конца разобрались

Т. е. верно ли , что в конце всех поворотов панель не замыкает концевик?

b707
Offline
Зарегистрирован: 26.05.2017

AndreiR пишет:

насколько я понимаю, то даже при срабатывании защиты скетч не останавливает работу, как в случае с вариантами delay(), а просто пропускает это условие и идет дальше.


вот тут либо вы что-то не понимаете, либо в программе что-то не так с логикой. Зачем нужен такой концевик, который не останавливает работу в крайнем положении?

mifar
Offline
Зарегистрирован: 07.04.2021

Дим-мычъ пишет:

По моему здесь не до конца разобрались

Т. е. верно ли , что в конце всех поворотов панель не замыкает концевик?

А где здесь концевик?

if (now.hour()   == hour1 && 
      now.minute() == minute1 &&
      now.second()   <=  second1 && rtc.begin() == 1) {
      digitalWrite(contrPin2, HIGH); /* если часы и минуты равны заданным в переменных и ардуино видит часовой модуль, то активировать пин
      на количество секунд в переменной для поднятия конструкции вверх */
}

По коду подъем/опускание должно работать в любом случае. Другой вопрос - а различает ли этот знакомый что панель поднялась/опустилась? Я бы добавил еще два светодиода для индикации срабатывания концевиков. Ну и как уже предлагал выше, уменьшить интервалы и прогнать код в железе или любом симуляторе.

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

mifar пишет:

А где здесь концевик?

Верно, его нет.

По интервалам, самое то по моему.

Можно закомментировать работу с модулем, и считать "своими силами"

Вот набросал на скорую руку, вроде работает. Время в 10 раз быстрее. Немного скетч подкорректировать.

uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint32_t last_millis = 0;

void setup() {
  Serial.begin(9600);
  delay(300);
}

uint8_t now_hour() {
  uint8_t temp = hour_;
  return temp;
}
uint8_t now_minute() {
  uint8_t temp = minute_;
  return temp;
}
uint8_t now_second() {
  uint8_t temp = second_;
  return temp;
}


void loop() {


  if (millis() - last_millis >= 100) {
    last_millis = millis();
    second_++;
    if (second_ > 59) {
      second_ = 0;
      minute_++;
    }
    if (minute_ > 59) {
      minute_ = 0;
      hour_++;

    }
    if (hour_ > 23) {
      hour_ = 0;
    }
    Serial.print(now_hour());
    Serial.print(" ");
    Serial.print(now_minute());
    Serial.print(" ");
    Serial.println(now_second());

  }

}

Ещё сделать резервную копию

AndreiR
Offline
Зарегистрирован: 13.08.2022

Добрый вечер!

Спасибо всем за комментарии! Сьездил сегодня на место и нашел проблему, но легче от этого не стало... Загрузил скетч для просмотра работы модуля времени DS1307 и обнаружил, что модуль завис на времени 8:20:33 позавчера, т.е. 12.08.2022. Записал в модуль текущее время и сейчас установка работает(прогнал циклы в ускоренном режиме, как советовали выше и сейчас выставил обратно первичное время). Модуль работает от питания ардуино 3,3V с собственной батарейкой и проработал он недели 2 точно без проблем и при выключенном питании тоже не сбрасывалось время и тем более не зависало. Кто-нибудь сталкивался с зависанием таким? Можно ли как-то контролировать, что часики тикают и в случае чего производить какой-то рестарт? В данный момент добавлена только проверка связи модуля времени с ардуино и если ардуино перестает видеть модуль, то любой цикл перестает работать. В данном же случае ардуино видит модуль, но время замерзло. Это достаточно плохо хотя бы потому, что если в момент подьема вверх или опускании зависнет модуль, то он будет изнашивать механизм подьема до тех пор, пока не сядет аккумулятор.

AndreiR
Offline
Зарегистрирован: 13.08.2022

Дим-мычъ пишет:

mifar пишет:

А где здесь концевик?

Верно, его нет.

По интервалам, самое то по моему.

Можно закомментировать работу с модулем, и считать "своими силами"

Вот набросал на скорую руку, вроде работает. Время в 10 раз быстрее. Немного скетч подкорректировать.

uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint32_t last_millis = 0;

void setup() {
  Serial.begin(9600);
  delay(300);
}

uint8_t now_hour() {
  uint8_t temp = hour_;
  return temp;
}
uint8_t now_minute() {
  uint8_t temp = minute_;
  return temp;
}
uint8_t now_second() {
  uint8_t temp = second_;
  return temp;
}


void loop() {


  if (millis() - last_millis >= 100) {
    last_millis = millis();
    second_++;
    if (second_ > 59) {
      second_ = 0;
      minute_++;
    }
    if (minute_ > 59) {
      minute_ = 0;
      hour_++;

    }
    if (hour_ > 23) {
      hour_ = 0;
    }
    Serial.print(now_hour());
    Serial.print(" ");
    Serial.print(now_minute());
    Serial.print(" ");
    Serial.println(now_second());

  }

}

Ещё сделать резервную копию

 

Добрый вечер!

Первый раз пробовал делать через millis(), но тут совсем не хватило опыта и в результате получил такое действие: первый цикл срабатывал раз в 24 часа, второй раз в 25 часов и тд. Т.е. после запуска ардуино первое срабатывание происходило спустя сутки, а вот дальше я не допонял чисто математически, что 25+25 = 50,26+26 = 52 и это дает сдвиг на 1 час каждый день. Т.е. спустя неделю первый поворот вправо бы сработыл не в 11 утра, а в 11+7=18.00. Тогда мне и посоветовали попробовать модуль времени. Сама идея с модулем времени кажется мне проще с точки зрения расчетов, так как один раз уже "погорел" с millis().

По срабатыванию защиты: замыкаться ни левый, не правый не должны в конце исполнения. Установлены исключительно для того, что если будет сильный ветер и из-за этого каждый поворот пойдет быстрее, чем планировалось. Тогда в конце концов достингет своей конечной точки куда быстрее нужного и может спалить насос.(панель в длину 8-10 метров и в высоту 5-6м, поэтому ветер достаточно сильно влияет на скорость поворота)

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:

Добрый вечер!

Первый раз пробовал делать через millis()

Мой пример лишь для проверки. Если с ним работает - значит дело в модуле, железе.

Удобно в ускоренном времени смотреть, что надо в сериал выводить.

Но раз нашли причину, значит уже не нужно

P.S. По поводу работы модуля - я бы попробовал обращаться к нему пореже, напр. каждые 100мс



void loop() {
  if (millis() - last_millis >= 100) {//каждые 100мс
    last_millis = millis();

    //здесь Ваш код

  }
}

 

Upper
Offline
Зарегистрирован: 23.06.2020

AndreiR пишет:

 Модуль работает от питания ардуино 3,3V с собственной батарейкой и проработал он недели 2 точно без проблем и при выключенном питании тоже не сбрасывалось время и тем более не зависало.

Не понял про питание от ардуино 3,3 V. По даташиту микросхема DS1307 предназначена для работы от 4.5V до 5,5 V

AndreiR
Offline
Зарегистрирован: 13.08.2022

Upper пишет:

AndreiR пишет:

 Модуль работает от питания ардуино 3,3V с собственной батарейкой и проработал он недели 2 точно без проблем и при выключенном питании тоже не сбрасывалось время и тем более не зависало.

Не понял про питание от ардуино 3,3 V. По даташиту микросхема DS1307 предназначена для работы от 4.5V до 5,5 V

Добрый вечер,

Спасибо за информацию! Переставлю на контакт 5 V, но информацию о 3,3V взял с какого-то примера подключения и подумал, что раз резеврная батарейка 3-3,3V, то и основного такого же достаточно.

AndreiR
Offline
Зарегистрирован: 13.08.2022

Дим-мычъ пишет:

AndreiR пишет:

Добрый вечер!

Первый раз пробовал делать через millis()

Мой пример лишь для проверки. Если с ним работает - значит дело в модуле, железе.

Удобно в ускоренном времени смотреть, что надо в сериал выводить.

Но раз нашли причину, значит уже не нужно

P.S. По поводу работы модуля - я бы попробовал обращаться к нему пореже, напр. каждые 100мс



void loop() {
  if (millis() - last_millis >= 100) {//каждые 100мс
    last_millis = millis();

    //здесь Ваш код

  }
}

 

 

Спасибо! Добавил

AndreiR
Offline
Зарегистрирован: 13.08.2022

AndreiR пишет:

Добрый вечер!

Спасибо всем за комментарии! Сьездил сегодня на место и нашел проблему, но легче от этого не стало... Загрузил скетч для просмотра работы модуля времени DS1307 и обнаружил, что модуль завис на времени 8:20:33 позавчера, т.е. 12.08.2022. Записал в модуль текущее время и сейчас установка работает(прогнал циклы в ускоренном режиме, как советовали выше и сейчас выставил обратно первичное время). Модуль работает от питания ардуино 3,3V с собственной батарейкой и проработал он недели 2 точно без проблем и при выключенном питании тоже не сбрасывалось время и тем более не зависало. Кто-нибудь сталкивался с зависанием таким? Можно ли как-то контролировать, что часики тикают и в случае чего производить какой-то рестарт? В данный момент добавлена только проверка связи модуля времени с ардуино и если ардуино перестает видеть модуль, то любой цикл перестает работать. В данном же случае ардуино видит модуль, но время замерзло. Это достаточно плохо хотя бы потому, что если в момент подьема вверх или опускании зависнет модуль, то он будет изнашивать механизм подьема до тех пор, пока не сядет аккумулятор.

Попробую сам ответить на свой же вопрос, темболее Дим-мычъ натолкнул на мысль использования счетчика ардуино. К сожалению, в наличии нету запасного модуля DS1307, в магазине обещали через 1-2 недели поставить, но сама идея такая, может что-то и выйдет(скорее всего код неверный, так как протестить не на чем):

 

#include <DS1307.h> // добавление еще одной библиотеки для задания времени(такую еще не пробовал)
int array_seconds[8]; //запись секунд в массив с модуля DS1307


void loop() {
 
 
if(rtc.begin == 1) // если ардуино видит DS1307
{
long TimeForCheck = millis();
int i = 0;
while(millis() - TimeForCheck < 8000) // отсчет в течение 8 секунд
{
array_seconds[i] = now.second; // запись секунд с модуля DS1307
i++;
}
if(array_second[0] == array_second[6]) // сравнение, если два значения одинаковы, то значит модуль перестал считать время
{
  rtc.setTime(now.hour, now.minute, now.second); // задать новое время с помощью библиотеки DS1307.h используя последнее время до застывания
  rtc.setDate(now.day, now.month, now.year);
}

}

}

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:

 раз резеврная батарейка 3-3,3V, то и основного такого же достаточно.

Upper всё верно говорит. Пересмотрел даташит - от 3В модуль только продолжает "хронометраж" времени. Выполнять команды - надо 4.5 - 5.5В. Так что , видимо, это главная причина сбоев.

mifar
Offline
Зарегистрирован: 07.04.2021

AndreiR пишет:
в наличии нету запасного модуля DS1307, в магазине обещали через 1-2 недели поставить,

Берите сразу DS3231 и точность лучше и зависать не будет

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:

Попробую сам ответить на свой же вопрос, темболее Дим-мычъ натолкнул на мысль использования счетчика ардуино. К сожалению, в наличии нету запасного модуля DS1307, в магазине обещали через 1-2 недели поставить, но сама идея такая, может что-то и выйдет(скорее всего код неверный, так как протестить не на чем):

 

#include <DS1307.h> // добавление еще одной библиотеки для задания времени(такую еще не пробовал)
int array_seconds[8]; //запись секунд в массив с модуля DS1307


void loop() {
 
 
if(rtc.begin == 1) // если ардуино видит DS1307
{
long TimeForCheck = millis();
int i = 0;
while(millis() - TimeForCheck < 8000) // отсчет в течение 8 секунд
{
array_seconds[i] = now.second; // запись секунд с модуля DS1307
i++;
}
if(array_second[0] == array_second[6]) // сравнение, если два значения одинаковы, то значит модуль перестал считать время
{
  rtc.setTime(now.hour, now.minute, now.second); // задать новое время с помощью библиотеки DS1307.h используя последнее время до застывания
  rtc.setDate(now.day, now.month, now.year);
}

}

}

 

P.S. Даже если модуль времени 100% исправен, как по мне , защита всё равно нужна.

Лучше поставить ещё два концевика.

И да, код выше не рабочий.

 

А вот простейший пример программного выявления остановки времени.

Но от неверных значений конечно это не спасёт, только от остановки.

uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint8_t second_x = 0;
uint32_t last_millis = 0;
uint32_t last_millis_check = 0;

void setup() {
  Serial.begin(9600);
  delay(300);
}

uint8_t now_hour() {
  uint8_t temp = hour_;
  return temp;
}
uint8_t now_minute() {
  uint8_t temp = minute_;
  return temp;
}
uint8_t now_second() {
  uint8_t temp = second_;
  return temp;
}



void loop() {

  if (millis() - last_millis >= 1000) {
    last_millis = millis();
    second_x = second_;  // сохраняем значение секунд
    second_++;
    if (second_ > 59) {
      second_ = 0;
      minute_++;
    }
    if (minute_ > 59) {
      minute_ = 0;
      hour_++;

    }
    if (hour_ > 23) {
      hour_ = 0;
    }
    //====================
    if ( minute_ > 1){  // внедряем ошибку,    
        second_ = 0;    // останавливаем время начиная со второй минуты  
    }     
    //===================

    if (millis() - last_millis_check >= 1500) //если прошло больше одной секунды
    {  
      last_millis_check = millis();
      
       // ==== ПРОВЕРКА НА ОШИБКУ ===
      if (second_x == second_) {    // сравниваем значение прошлой и новой секунды
        Serial.println("ERROR");  //здесь остановить мотор
        while (1);
      }
    }
    Serial.print(now_hour());
    Serial.print(" ");
    Serial.print(now_minute());
    Serial.print(" ");
    Serial.println(now_second());
  }
}


 

AndreiR
Offline
Зарегистрирован: 13.08.2022

Дим-мычъ пишет:

AndreiR пишет:

Попробую сам ответить на свой же вопрос, темболее Дим-мычъ натолкнул на мысль использования счетчика ардуино. К сожалению, в наличии нету запасного модуля DS1307, в магазине обещали через 1-2 недели поставить, но сама идея такая, может что-то и выйдет(скорее всего код неверный, так как протестить не на чем):

 

#include <DS1307.h> // добавление еще одной библиотеки для задания времени(такую еще не пробовал)
int array_seconds[8]; //запись секунд в массив с модуля DS1307


void loop() {
 
 
if(rtc.begin == 1) // если ардуино видит DS1307
{
long TimeForCheck = millis();
int i = 0;
while(millis() - TimeForCheck < 8000) // отсчет в течение 8 секунд
{
array_seconds[i] = now.second; // запись секунд с модуля DS1307
i++;
}
if(array_second[0] == array_second[6]) // сравнение, если два значения одинаковы, то значит модуль перестал считать время
{
  rtc.setTime(now.hour, now.minute, now.second); // задать новое время с помощью библиотеки DS1307.h используя последнее время до застывания
  rtc.setDate(now.day, now.month, now.year);
}

}

}

 

P.S. Даже если модуль времени 100% исправен, как по мне , защита всё равно нужна.

Лучше поставить ещё два концевика.

И да, код выше не рабочий.

 

А вот простейший пример программного выявления остановки времени.

Но от неверных значений конечно это не спасёт, только от остановки.

uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint8_t second_x = 0;
uint32_t last_millis = 0;
uint32_t last_millis_check = 0;

void setup() {
  Serial.begin(9600);
  delay(300);
}

uint8_t now_hour() {
  uint8_t temp = hour_;
  return temp;
}
uint8_t now_minute() {
  uint8_t temp = minute_;
  return temp;
}
uint8_t now_second() {
  uint8_t temp = second_;
  return temp;
}



void loop() {

  if (millis() - last_millis >= 1000) {
    last_millis = millis();
    second_x = second_;  // сохраняем значение секунд
    second_++;
    if (second_ > 59) {
      second_ = 0;
      minute_++;
    }
    if (minute_ > 59) {
      minute_ = 0;
      hour_++;

    }
    if (hour_ > 23) {
      hour_ = 0;
    }
    //====================
    if ( minute_ > 1){  // внедряем ошибку,    
        second_ = 0;    // останавливаем время начиная со второй минуты  
    }     
    //===================

    if (millis() - last_millis_check >= 1500) //если прошло больше одной секунды
    {  
      last_millis_check = millis();
      
       // ==== ПРОВЕРКА НА ОШИБКУ ===
      if (second_x == second_) {    // сравниваем значение прошлой и новой секунды
        Serial.println("ERROR");  //здесь остановить мотор
        while (1);
      }
    }
    Serial.print(now_hour());
    Serial.print(" ");
    Serial.print(now_minute());
    Serial.print(" ");
    Serial.println(now_second());
  }
}


 

 

Большое спасибо! Как раз именно этого и не хватало, а у самого не хватило мозга правильно это сделать. Попробую внедрить и потестировать. Так как я уже своими глазами увидел, что время разок зависло(питание уже поправил на 5V как по мануалу и должно быть,пока что работает исправно), но на всякий случай...Техника есть техника. Главное здесь, да, чтоб не зависло в момент начала подьема, иначе спалю ему насос, а это  досточно большие деньги. К слову, и установка то там с заливкой бетона и тд и тп стоила столько, что я даже не знаю через сколько лет он эту сумму отобьет, хоть и питает она в сезон весь дом и что-то даже государству продает.

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

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

Еще раз спасибо, после выходных дам обратную связь:)

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:

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

 Вообще - то я здесь ,в Песочнице,  в Ардуинку играюсь, а речь, как я вижу , идёт о дорогостоящем оборудовании)).

Как по мне, Ардуино не очень подходит для этих целей.

Пусть лучше хозяин купит к панели солнечный трекер, и чтобы его установили специалисты ИМХО.

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

AndreiR пишет:

 и что-то даже государству продает.

эта тема вообще тупиковая, если вы готовы принять N-ое количество энергии в сеть под это самое количество надо держать по парами и резерв да и цена приёмки-продажи отличаются чуть ли не на порядок, здесь пробегала тема, где ТС имел желание избыток энергии по ненагруженным фазам скидывать для нагрева воды в бойлере, а не отдавать в общую сеть за сущие копейки...

AndreiR
Offline
Зарегистрирован: 13.08.2022

Дим-мычъ пишет:

 Вообще - то я здесь ,в Песочнице,  в Ардуинку играюсь, а речь, как я вижу , идёт о дорогостоящем оборудовании)).

Как по мне, Ардуино не очень подходит для этих целей.

Ну здесь я бы не согласился. Ардуинка, может и больше как игрушка, но это контроллер как и все остальные, при этом еще и дешевый. Задача контроллера, каким бы он не был, просто исполнять задачу. Я сам тружусь инженером, просто немножко в другую сферу направление, но автоматики у нас дорогостоящей много и ставили спецы и обслуживают спецы и тд и тп. И то что она дорогая(десятки тысяч евро) не говорит о том, что она безотказная...Тоже ломаются компоненты и вызывать приходится фирму и платить за обслуживание тоже достаточно дорого. Сами если полезем, то наверное какие-то поломки и ликвидируем, но тут сразу нарушение договора вступает в силу и оттуда последствия и тд и тп. Цена за контроллер вырастает в десятки а то и больше раз в случае, когда в силу вступает так называемая "обратная связь" от железа. Наличие логов, показ что вышло из строя или что не сработало и по какой причине. Такая обратная связь дает шанс быстрее среагировать оператору и вызвать надлежащую службу для устранения проблемы, но и по пути количество техники для контроля растет. Отсюда и суммы большие.

В моем же случае взято как "хобби" и было сразу оговорено, что делаю за спасибо и не супер то силен в этом. Так прямо и сказал "работать по итогу будет, но гарантий об отказоустойчивости и всем прочем-это извини". На это было получено согласие и все риски со сломанным мотором он берет на себя если вдруг что. Ну и плюс он понимает, что моторы в любом случае нужно будет чинить или менять, поэтому в данном случае желание сделать хотя бы автоматику бесплатно и быть уверенным, что я в случае чего, сьезжу на место не за 80 евро/час за вызов плюс ремонт, а просто по знакомству и погляжу, что в ардуине нашей случилось:))

Вот как-то примерно так. В любом случае за помощь спасибо! Доверяй интернету, но проверяй как говорится.

AndreiR
Offline
Зарегистрирован: 13.08.2022

ua6em пишет:

AndreiR пишет:

 и что-то даже государству продает.

эта тема вообще тупиковая, если вы готовы принять N-ое количество энергии в сеть под это самое количество надо держать по парами и резерв да и цена приёмки-продажи отличаются чуть ли не на порядок, здесь пробегала тема, где ТС имел желание избыток энергии по ненагруженным фазам скидывать для нагрева воды в бойлере, а не отдавать в общую сеть за сущие копейки...

 

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

мне озвучивали эту тему практически из первых уст, так что зелёная энергетика и единая энергосистема вещи несовместимые однако

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

AndreiR пишет:

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

 Ну это другое дело, хозяин - барин)).

Тогда вот ещё пример использования таймера Watchdog. Может помочь при зависании ардуинки.

Добавил в скетч из #25.



uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint8_t second_x = 0;
uint32_t last_millis = 0;
uint32_t last_millis_check = 0;
bool ERROR_ = false;


void setup() {
  Serial.begin(9600);
  delay(300);

  cli(); //==== НАСТРОЙКА WD таймера =======
  WDTCSR |= (1 << WDCE) | (1 << WDE);//разрешаем изменения в настройке WDT
  WDTCSR = (1 << WDIE) | (1 << WDP0) | (1 << WDP1) | (1 << WDP2); //прерывание
  sei();                                                 //по срабатыванию WDT
} //======================================            тайм-аут 2 сек

uint8_t now_hour() {
  uint8_t temp = hour_;
  return temp;
}
uint8_t now_minute() {
  uint8_t temp = minute_;
  return temp;
}
uint8_t now_second() {
  uint8_t temp = second_;
  return temp;
}


ISR( WDT_vect ) {
  ERROR_ = true;
}


void loop() {

  if (!ERROR_) {

    if (millis() - last_millis >= 1000) {
      last_millis = millis();
      second_x = second_;  // сохраняем значение секунд
      second_++;
      if (second_ > 59) {
        second_ = 0;
        minute_++;
      }
      if (minute_ > 59) {
        minute_ = 0;
        hour_++;

      }
      if (hour_ > 23) {
        hour_ = 0;
      }
      //====================
      if ( minute_ > 1) { // внедряем ошибку,
        second_ = 0;    // останавливаем время начиная со второй минуты
      }
      //===================

      if (millis() - last_millis_check >= 1500) //если прошло больше одной секунды
      {
        last_millis_check = millis();

        asm volatile("wdr\n\t"); //перезапуск WDT, закоментировать для проверки

        // ==== ПРОВЕРКА НА ОШИБКУ ===
        if (second_x == second_)    // сравниваем значение прошлой и новой секунды
          ERROR_ = true;

      }
      Serial.print(" ");
      Serial.print(now_hour());
      Serial.print("  ");
      Serial.print(now_minute());
      Serial.print("  ");
      Serial.println(now_second());
    }
  }
  else {
    Serial.println("ERROR");  //здесь остановить мотор
    while (1);
  }
}

 И ещё мысля: почему бы не использовать токовую защиту для мотора?

P.S. Ещё вариант остановки мотора прямо из обработчика

ISR( WDT_vect ) {

WDTCSR = 0x00; //выключаем прерывание от WDT
  sei();                   
  Serial.println("ERROR");  //здесь остановить мотор
 
  while (1); 
}

 

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

Оказывается в Протеусе хорошо работает этот модуль.

Ради интереса набросал программку , попробовал, как в #3 ЕвгенийП советовал скомпоновать, но на много лучше не получилось. Будем  дальше учиться. Концевики не делал, всё же Протеус, только временные интервалы и программная защита от остановки времени + WDT.

С модулем лучше синхронизироваться через SOUT и опрашивать его раз в секунду по прерыванию ИМХО

Если делать в железе, то я бы завершал цикл "парковкой" на концевик, что-бы начинать всегда с одного и того же места

#include <Wire.h>

#define SDA A4
#define SCL A5
#define SOUT 2 //выход SQW/OUT модуля 
uint8_t hour_ = 0;
uint8_t minute_ = 0;
uint8_t second_ = 0;
uint8_t second_m = 0;
uint8_t n = 0;

uint8_t mem_last_sec[4] = {255, 255, 255, 255};
bool CHANGE_ = false;


unsigned long time_mass[5][3] = { //нужное время задать в секундах 
  {2400, 2410, 1},  //   00.40 вверх(1)  10 сек
  {2460, 2470, 2}, //  00.41 вправо(2)  10 сек
  {2520, 2540, 2},  //  00.42 вправо(2)  20 сек
  {2580, 2590, 1}, //  00.43 вверх(1)  10 сек
  {3000, 3040, 3} //  00.50 влево(3)  40 сек
};

void setup() {

  pinMode(SOUT, INPUT); //

  //EIMSK |= (1 << INT0);// настройка прерывания
  EIMSK = 0x01; //INT0
  //EICRA |= (1 << ISC01);//
  EICRA = 0x02; //по задн. фронту

  Serial.begin(9600);
  delay(300);

  Wire.begin();
  Wire.beginTransmission(0x68);
  Wire.write(0x07); //включаем тактирование на выходе
  Wire.write(0x10); // SQW/OUT  1Герц
  Wire.endTransmission();

  cli(); //==== НАСТРОЙКА WD таймера =======
  WDTCSR |= (1 << WDCE) | (1 << WDE);//разрешаем изменения в настройке WDT
  WDTCSR = 0x47; //WDIE = 1; WDE = 0; тайм аут 2 сек
  sei();         //прерывание по срабатыванию WDT
}

ISR( INT0_vect) {//синхронизируемся с модулем
  CHANGE_ = true; // по заднему фронту
}


ISR( WDT_vect ) {//если не был сброшен WDT

  WDTCSR &= ~(1 << WDIE); //выключаем прерывания от WDT
  EIMSK = 0x00; //запрещаем прерывание INT0 1.Эти две строчки нужны только для работы
  sei();        //                          2. Serial.print() в прерывании
  Serial.println("ERROR WDT");  //здесь остановить мотор
  while (1);
}


void check_time(unsigned long now_time) {//проверяем соответствие тек. времени
  // и поставленных задач
  bool TRUE_ = false;

  for (uint8_t n = 0; n < 5; n++) {
    if (now_time >= time_mass[n][0] && now_time <= time_mass[n][1]) {
      TRUE_ = true; //если текущее время совпадает с установленным

      if (time_mass[n][2] == 1) // проверяем задание для этого времени
        Serial.println("POVOROT VVERH");
      if (time_mass[n][2] == 2)
        Serial.println("POVOROT NAPRAVO");
      if (time_mass[n][2] == 3)
        Serial.println("POVOROT NALEVO");
    }
  }
  if (!TRUE_)//если тек.время не совпадает с установленным
    Serial.println("OSTANOVKA MOTORA");
}


void read_DS_time() { // читаем текущее время из модуля
  uint8_t temp_sec_reg, temp_min_reg, temp_hour_reg;

  Wire.beginTransmission(0x68);// адрес I2с 0x68
  Wire.write(0); // адрес первой ячейки
  Wire.endTransmission();
  Wire.requestFrom(0x68, 3);//запрос 3-х байтов

  temp_sec_reg = Wire.read(); //читаем регистры модуля
  temp_min_reg = Wire.read();
  temp_hour_reg = Wire.read();
  //распаковываем регистры
  second_ = ((temp_sec_reg & 0b01110000) >> 4) * 10 + (temp_sec_reg & 0b00001111);
  minute_ = ((temp_min_reg & 0b01110000) >> 4) * 10 + (temp_min_reg & 0b00001111);
  hour_ = ((temp_hour_reg & 0b00110000) >> 4) * 10 + (temp_hour_reg & 0b00001111);

}


void loop() {

  if (CHANGE_) {//если поднялся флаг изменения секунды
    CHANGE_ = false;
    delayMicroseconds(16); //на всякий случай, чтобы успел обновиться модуль
    // скорее и не нужна, проверить в железе
    read_DS_time();

    for (uint8_t i = 3; i > 0; i--) { // "скользящий" массив для хранения
      mem_last_sec[i] =  mem_last_sec[i - 1]; //значений последних 4 секунд
    }
    mem_last_sec[0] = second_;  //

    // тек. время в секундах
    unsigned long now_time = (unsigned long)hour_ * 3600 + (unsigned long)minute_ * 60 + (unsigned long)second_;
    Serial.print(" ");
    Serial.print(hour_);
    Serial.print("  ");
    Serial.print(minute_);
    Serial.print("  ");
    Serial.println(second_);

    asm volatile("wdr\n\t"); //перезапуск WDT, закоментировать для проверки

    check_time(now_time); // проверка выполнения задач по времени

    Serial.println(mem_last_sec[0]);
    Serial.println(mem_last_sec[1]);
    Serial.println(mem_last_sec[2]);
    Serial.println(mem_last_sec[3]);
    Serial.println("  ");

    // ==== ПРОВЕРКА НА ОШИБКУ ===
    if (mem_last_sec[3] == mem_last_sec[0]) {// сравниваем значение прошлой[3] и новой[0] секунды
      EIMSK = 0x00; //запрещаем прерывание INT0
      Serial.println("ERROR SEC");  //здесь остановить мотор
      WDTCSR &= ~(1 << WDIE); //выключаем прерывания от WDT
      while (1);
    }

  }
}

Выключатель имитирует обрыв/пропадание связи с модулем))

P.S. Извиняюсь,  гифка , ожидал получше будет смотреться

inspiritus
Offline
Зарегистрирован: 17.12.2012

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

это какой же привод стоит, если его ветром доворачивает ? Серва штоле?

Правильнее привязываться не ко времени, а к интенсивности освещенности панели

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

корректировать панель можно по нарастанию освещенности с небольшим перепробегом после максимума.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

inspiritus пишет:

это какой же привод стоит, если его ветром доворачивает ? Серва штоле?

у меня на супраловской 2х метровой антенне ветер кирпичную стену выворачивает )))

Дим-мычъ
Offline
Зарегистрирован: 20.03.2021

inspiritus пишет:

Правильнее привязываться не ко времени, а к интенсивности освещенности панели

Это точно. 

Хотя здесь и так дали ТС-у советов с избытком, но , как я понял, он в Ардуино начинающий

AndreiR пишет:
Честно говоря, с функциями так и не разобрался до конца, времени не хватает. Готовые брал и пользовал, а самому как-то пока не сложилось в голове. Да и тут бы просто разобраться, где проблема.

А так да, по интенсивности лучше, чем вслепую крутить... Да ещё надо-бы пару кнопок, менюшку, экранчик, хотя-бы время установить, если что.