Контроллер светодиодного светильника для морского аквариума. TLC5940 + Arduino Nano + RTC-modul + DALLAS-DS18B20

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Всем добрый день.

Начал заниматься Ардуино месяца два назад. Стоит задача сделать светодиодный светильник с шестью каналами и 12битным ШИМом. Задача для контроллера: плавно зажечь светодиоды через драйвер и вечером плавно погасить. Для 12 битного ШИМа был сделан выбор в сторону TLC5940. По примерам было все понятно и доступно.

Написал программу. И она неплохо работала при продолжительности рассвета 5 минут. Если рассвет 10 минут, то плавность куда то уходит. Рассвет визуально начинается с нулевой секунды где то с 20%, потом за на 90% времени уже 100% свечение и сбрасывается в ноль и рассвет начинается заново.

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

Собрано по этой схеме, только вместо диода - драйвер.

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

Ну и вопрос: Что я сделал не так, и что нужно еще сделать, чтоб рассветы и закаты укладывались в отведенные им временные рамки?

Сам код:

// "Недорогой контроллер на Ардуино нано + TLC5940 + DALLAS-DS18B20"
// шести канальный контроллер, 12-bit шим
// Комплектация: Arduino nano, RTC-modul, TLC5940, DALLAS-DS18B20.
// перед началом компиляции откройте монитор порта в правом верхнем углу окна программы

#include "Tlc5940.h"
#include "tlc_fades.h"
TLC_CHANNEL_TYPE channel;

#include <OneWire.h>
OneWire ds(5); // Температурный сенсор DALLAS-DS18B20 подключен к D5

#include <DS1307.h>
DS1307 rtc(A0, A1); //RTC-модуль подключен к:  SDA - > A0, SCL -> A1
    Time t;
    String stringOne = rtc.getTimeStr();

    int ventpin = 6; // управление вентилятором осуществляется с D6

    int fadeTime = 5000;
    uint32_t startMillis;
    uint32_t endMillis;
    uint32_t endDay = 86399;
    int tic[6][5];
    int start;
    int finish;
    int long Value[6];
    int long Array[6][6];
    float power = 100; // общая мощность освещения [0 - 100]
    int long time_all;
    int temp = 0;
    

void setup() {
    Serial.begin ( 115200 );  // Указвать скорость на которой работает Ваш COM-порт
    Tlc.init();
    Tlc.clear();
//    uint8_t tlc_removeFades();

    pinMode (ventpin, OUTPUT);
    
  rtc.halt(false);
/* MONDEY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY
   Три строчки ниже необходимо раскомментировать (убрать двойную дробь) при стартовой загрузки программы.
   Сразу после первой загрузки, нужно закомментировать данные строки и 
   обращаться к этой процедуре в случае сбоя в работе часов. RTC-модуль запомнит время. */
// rtc.setDOW(SUNDAY);     // изменить день недели. примеры указаны на четыре строчки выше
// rtc.setTime(11, 41, 0);   // время
// rtc.setDate(13, 9, 2015);  // дата

// Настройки светильника: <время восхода>, <продолжительность рассвета>, <мощность канала в течении "дня">, <время заката>, <продолжительность заката>
// первый канал
Array[0][0] = 600; // начало рассвета первого канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[0][1] = 630; // конец рассвета первого канала. например: 11:15 записывается как <675> (в минутах)
  Array[0][2] = 730; // начало заката первого канала. например: 20:50 записывается как <1250> (в минутах)
   Array[0][3] = 760; // окончание заката первого канала. например: 21:50 записывается как <1310> (в минутах)
    Array[0][4] = 100; // мощность первого канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[0][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика
// второй канал
Array[1][0] = 620; // начало рассвета второго канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[1][1] = 640; // конец рассвета второго канала. например: 11:15 записывается как <675> (в минутах)
  Array[1][2] = 1250; // начало заката второго канала. например: 20:50 записывается как <1250> (в минутах)
   Array[1][3] = 1310; // окончание заката второго канала. например: 21:50 записывается как <1310> (в минутах)
    Array[1][4] = 90; // мощность второго канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[1][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика
// третий канал
Array[2][0] = 630; // начало рассвета тертьего канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[2][1] = 635; // конец рассвета тертьего канала. например: 11:15 записывается как <675> (в минутах)
  Array[2][2] = 636; // начало заката тертьего канала. например: 20:50 записывается как <1250> (в минутах)
   Array[2][3] = 640; // окончание заката тертьего канала. например: 21:50 записывается как <1310> (в минутах)
    Array[2][4] = 80; // мощность тертьего канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[2][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика
// четвертый канал
Array[3][0] = 640; // начало рассвета четвертого канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[3][1] = 675; // конец рассвета четвертого канала. например: 11:15 записывается как <675> (в минутах)
  Array[3][2] = 1250; // начало заката четвертого канала. например: 20:50 записывается как <1250> (в минутах)
   Array[3][3] = 1310; // окончание заката четвертого канала. например: 21:50 записывается как <1310> (в минутах)
    Array[3][4] = 70; // мощность четвертого канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[3][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика
// пятый канал
Array[4][0] = 650; // начало рассвета пятого канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[4][1] = 675; // конец рассвета пятого канала. например: 11:15 записывается как <675> (в минутах)
  Array[4][2] = 1250; // начало заката пятого канала. например: 20:50 записывается как <1250> (в минутах)
   Array[4][3] = 1310; // окончание заката пятого канала. например: 21:50 записывается как <1310> (в минутах)
    Array[4][4] = 60; // мощность пятого канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[4][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика
// шестой канал
Array[5][0] = 660; // начало рассвета шестого канала в минутах. например: 10:00 записывается как <600> (в минутах)
 Array[5][1] = 675; // конец рассвета шестого канала. например: 11:15 записывается как <675> (в минутах)
  Array[5][2] = 1250; // начало заката шестого канала. например: 20:50 записывается как <1250> (в минутах)
   Array[5][3] = 1310; // окончание заката шестого канала. например: 21:50 записывается как <1310> (в минутах)
    Array[5][4] = 50; // мощность шестого канала в процентах в течении "дня" (в процентах). не может быть больше 100
     Array[5][5] = 0; // инвертор драйвера. Имеет значения 0 и 1. 0 - прямая логика, 1 - обратная логика

// Перевод массива в секунды
  for (int q=0; q<6; q++) {
    for (int w=0; w<4; w++) {
      Array[q][w] = Array[q][w] * 60;
    }
  }

// Сброс суточного массива
  for (int q=0; q<6; q++) {
    for (int w=0; w<5; w++) {
      tic[q][w] = 0;
    }
  }

// Вывод проверочной стартовой таблицы
  
  Serial.println ( "" );Serial.println ( "" );
  Serial.print ( "  Time: " ); Serial.print ( rtc.getTimeStr() );  Serial.println ( "   <- Check this after reset." );Serial.println ( "" );
  Serial.println ( "  Chanal  :  Sanrise  :   Day     :  Sanset   : Night     :  Led chanal: Inverse" );
  
  for (int q=0; q<6; q++) {
   
     Serial.print ( "  PWM" );
      Serial.print ( q+1 );
     for (int w=0; w<5; w++) {
       Serial.print ( "    :  " );
         if (w < 4) {
           if ( ( Array[q][w]/3600 ) < 10) {Serial.print ( "0" ); Serial.print ( Array[q][w]/3600 );
           } else {Serial.print ( Array[q][w]/3600 );}
           Serial.print ( ":" ); 
           if ((( Array[q][w]-((Array[q][w]/3600)*3600))/60) < 10) {Serial.print ( "0" );Serial.print (( Array[q][w]-((Array[q][w]/3600)*3600))/60 );
           } else {Serial.print (( Array[q][w]-((Array[q][w]/3600)*3600))/60 );}
         } else {
              if (Array[q][w] < 100) {Serial.print ( " ");}
              Serial.print ( Array[q][w]);Serial.print ( "%");Serial.print ( "      :   ");
              
              Serial.print ( Array[q][w+1]);
                }
     }
     Serial.println ( "" );
  }
      Serial.println ( "-------------------------------------------------" );
      
      // Проверка корректности ввода исходных данных
      for (int q=0; q<6; q++) {if (Array[q][4] >= 86400) {Array[q][4] = 86399; Serial.print ( "Error, check PWM" ); Serial.print ( q+1 ); Serial.println ( ", fixed the end of the sunset to 24:00" );}}
      for (int q=0; q<6; q++) {if (Array[q][5] >= 101) {Array[q][5] = 100; Serial.print ( "Error, check PWM" ); Serial.print ( q+1 ); Serial.println ( ", fixed the power led to 100%" ); }}
  for (int q=0; q<6; q++) {
    for (int w=0; w<3; w++) {
 if ( Array[q][w] > Array[q][w+1] ) {Serial.print ( "Error, check PWM" ); Serial.print ( q+1 ); Serial.println ( ", not continuity sanrise and sanset. Controller will not work correctly. Check setup. " );
 }

    }
  }
  Serial.print ( "  All powerful LEDs: " );  Serial.print ( power ); Serial.println ( "%" );
  Serial.println ( "  In service. OK." );



// Изменение мощности из процентов в значение
  for (int q=0; q<6; q++) {
     Value[q] = map (Array[q][4], 0, 100, 0, 4095) * (power/ 100);
  }

}

void loop() {

  // Константы температуры
  int tmin = 31; // минитальное значение на датчике, при достижении которого запускается вентилятор. Указывается значение в градусах. Например: "32", означает 32градуса цельсия
  int tmax = 34; // максимальное значение на датчике, служит для плавного увеличения скорости вращения вентилятора. Указывается значение в градусах. Например: "36", означает 36градуса цельсия. На превышающих значениях вентилятор работает на 100% мощности

  // Блок программы работающий с температурным датчиком и вентилятором
  byte i;
  byte present = 0;
  byte type_s;
  byte data[12];
  byte addr[8];
  float celsius;

ds.search(addr);
ds.reset(); 
ds.select(addr);
ds.write(0x44, 1);        
ds.reset();
present = ds.reset();
ds.select(addr);    
ds.write(0xBE);
for ( i = 0; i < 9; i++) {           
    data[i] = ds.read();
      }

  int16_t raw = (data[1] << 8) | data[0];
  if (type_s) {
    raw = raw << 3; //
    if (data[7] == 0x10) {
      raw = (raw & 0xFFF0) + 12 - data[6];
    }
  } else {
    byte cfg = (data[4] & 0x60);
    if (cfg == 0x00) raw = raw & ~7;  
    else if (cfg == 0x20) raw = raw & ~3; 
    else if (cfg == 0x40) raw = raw & ~1; 

  }
  celsius = (float)raw / 16.0;
      if (temp == 0) {
          Serial.print("  Temperature = ");
          Serial.print(celsius);
          Serial.println(" Celsius \n ");
          temp = 1;}

     if ( tmin <= celsius ) {
      if (map(int (celsius*100), tmin*100 , tmax*100, 0, 255) >= 255) {analogWrite (ventpin,HIGH);}
      else {analogWrite (ventpin, map(int (celsius*100), tmin*100 , tmax*100, 0, 255));}
        } else {analogWrite (ventpin, 0);}
// конец блока температуры

  
    t = rtc.getTime();
    String stringOne = rtc.getTimeStr();
     int long h = t.hour;
     int long m = t.min;
     int long s = t.sec;
     time_all = ( (h * 3600)+(m * 60)+ s  );

// Сброс состояния контроллера на новый день.
              if (time_all == 0) {
                   // Сброс суточного массива
                   for (int q=0; q<6; q++) {
                   for (int w=0; w<5; w++) {
                   tic[q][w] = 0;
                   }
                   }
              }

// Контроллер
    for (int q=0; q<7; q++) {
      
     if (time_all >= 0 && time_all < Array[q][0] && tic[q][0] == 0) { 
          
         startMillis = millis();
         endMillis = startMillis + (Array[q][0] * 1000);
         if (Array[q][5]==0) {start = 4095; finish = 4095 - Value[q];} else {start = 0; finish = Value[q];}
         tlc_addFade (q, start, start, startMillis, endMillis+fadeTime);
         tic[q][0] = 1;
         Serial.print ( rtc.getTimeStr() );Serial.print ( " PWM:" );Serial.print ( q+1 ); Serial.println ( " - mon" );
         Serial.print ( start );Serial.print ( " " );Serial.print ( finish );Serial.print ( " " );Serial.print ( startMillis );Serial.print ( " " );Serial.println ( endMillis+fadeTime );
         }
     if (time_all >= Array[q][0] && time_all <= Array[q][1] && tic[q][1] == 0) { 
          
         startMillis = millis();
         endMillis = startMillis + ((Array[q][1]-time_all)*1000);
         if (Array[q][5]==0) {start = 4095-((Value[q]*(time_all-Array[q][0]))/(Array[q][1]-Array[q][0])); finish = 4095 - Value[q];} else {start = ((Value[q]*(time_all-Array[q][0]))/(Array[q][1]-Array[q][0])); finish = Value[q];}
         tlc_addFade (q, start, finish, startMillis, endMillis+fadeTime);
         tic[q][1] = 1;
         Serial.print ( rtc.getTimeStr() );Serial.print ( " PWM:" );Serial.print ( q+1 ); Serial.println ( " -  on" );
         Serial.print ( start );Serial.print ( " " );Serial.print ( finish );Serial.print ( " " );Serial.print ( startMillis );Serial.print ( " " );Serial.println ( endMillis+fadeTime );
         }
         if (time_all >= Array[q][1] && time_all <= Array[q][2] && tic[q][2] == 0) { 
         
         startMillis = millis();
         endMillis = startMillis + ((Array[q][2]-time_all)*1000);
         if (Array[q][5]==0) {start = 4095; finish = 4095 - Value[q];} else {start = 0; finish = Value[q];}
         tlc_addFade (q, finish, finish, startMillis, endMillis+fadeTime);
         tic[q][2] = 1 ;
         Serial.print ( rtc.getTimeStr() );Serial.print ( " PWM:" );Serial.print ( q+1 ); Serial.print ( " - day " ); Serial.println ( finish );
         Serial.print ( start );Serial.print ( " " );Serial.print ( finish );Serial.print ( " " );Serial.print ( startMillis );Serial.print ( " " );Serial.println ( endMillis+fadeTime );
         }
     if (time_all >= Array[q][2] && time_all <= Array[q][3] && tic[q][3] == 0) { 
         
         startMillis = millis();
         endMillis = startMillis + ((Array[q][3]-time_all)*1000);
         if (Array[q][5]==0) {start = 4095; finish = 4095 - ((Value[q]*(Array[q][3]-time_all))/(Array[q][3]-Array[q][2]));} else {start = 0; finish = (Value[q]*(Array[q][3]-time_all))/(Array[q][3]-Array[q][2]);}
         tlc_addFade (q, finish, start, startMillis, endMillis+fadeTime);
         tic[q][3] = 1 ;
         Serial.print ( rtc.getTimeStr() );Serial.print ( " PWM:" );Serial.print ( q+1 ); Serial.println ( " - off" );
         Serial.print ( start );Serial.print ( " " );Serial.print ( finish );Serial.print ( " " );Serial.print ( startMillis );Serial.print ( " " );Serial.println ( endMillis+fadeTime );
         }
     if (time_all > Array[q][3] && time_all <= endDay && tic[q][4] == 0) { 
         
         startMillis = millis();
         endMillis = startMillis + ((endDay-Array[q][3])*1000);
         if (Array[q][5]==0) {start = 4095; finish = 4095 - Value[q];} else {start = 0; finish = Value[q];}
         tlc_addFade (q, start, start, startMillis, endMillis+fadeTime);
         tic[q][4] = 1 ;
         Serial.print ( rtc.getTimeStr() );Serial.print ( " PWM:" );Serial.print ( q+1 ); Serial.println ( " - nig" );
         Serial.print ( start );Serial.print ( " " );Serial.print ( finish );Serial.print ( " " );Serial.print ( startMillis );Serial.print ( " " );Serial.println ( endMillis+fadeTime );
         }
     }  
//  Serial.print ( millis() );Serial.print ( " " ); Serial.println ( (Array[0][1]-time_all)*1000 ); 

  tlc_updateFades();

}

 

Гриша
Offline
Зарегистрирован: 27.04.2014

закройте код спойлером!!!! (сверните его)

GraninDm
Offline
Зарегистрирован: 01.08.2013

А почему

// Контроллер
for (int q=0; q<7; q++) {

массив же размерностью 6?

И еще, если не секрет, зачем 12-разрядный шим?

Гриша
Offline
Зарегистрирован: 27.04.2014

когда наступит событие блока 220 - 228 ? сомнения у меня, что это произойдет.

GraninDm
Offline
Зарегистрирован: 01.08.2013

И еще я бы посоветовал сделать так

#define IDX_SUNRISE_BEGIN 0
#define IDX_SUNRISE_FINISH 1
...

//А обращаться к массиву 
Array[q][IDX_SUNRISE_BEGIN]

 

Гриша
Offline
Зарегистрирован: 27.04.2014

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

Я так и не понял назначение 

time_all = ( (h * 3600)+(m * 60)+ s  );

может все же ему жестко сказать когда у него рассвет а когда закат ? А после старта привязать PWM к millis . Тогда и обнулять дату и время не нужно.

 

sinnpriest
Offline
Зарегистрирован: 16.09.2015

GraninDm пишет:

А почему

// Контроллер
for (int q=0; q<7; q++) {

массив же размерностью 6?

И еще, если не секрет, зачем 12-разрядный шим?

Логично. Поправил. К сожалению это осталось от того, как q у меня менялось с 1 по 7. Потом начала компилятор на память жаловаться, пришлось вернуться с индексации с 0 по 5. Поправлю. Спасибо. Но не уверен, что это может как то влиять. ну записывает она всякую муть в 6 канал... ну и пусть... но все равно спасибо.

12 битный шим - плавность. Возможно излишняя, но в этом еще больший плюс.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

GraninDm пишет:

И еще я бы посоветовал сделать так

#define IDX_SUNRISE_BEGIN 0
#define IDX_SUNRISE_FINISH 1
...

//А обращаться к массиву 
Array[q][IDX_SUNRISE_BEGIN]

 

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

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Гриша пишет:

когда наступит событие блока 220 - 228 ? сомнения у меня, что это произойдет.

У меня тоже сомнения. Но я пока не понял, как можно раз в сутки заполнить массив нолями...

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Гриша пишет:

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

Я так и не понял назначение 

time_all = ( (h * 3600)+(m * 60)+ s  );

может все же ему жестко сказать когда у него рассвет а когда закат ? А после старта привязать PWM к millis . Тогда и обнулять дату и время не нужно.

 

Я и так пытаюсь снимать лог print-ами, значение time_all - это количество секунд с начала дня. По этому значению и ориентируются условия для подачи команд на TLC для выполения fade-команд.

А.е. я могу сразу один раз в сути давать команду в милисекундах:

tlc_addFade (q, start, finish, startMillis, endMillis+fadeTime);

А потом просто в цикле void спамить апдэйт:

tlc_updateFades();

?

Я кажется так пробовал. Он отказывался работать... сейчас еще раз попробую..

GraninDm
Offline
Зарегистрирован: 01.08.2013
seconds = h * 3600 + m * 60+ s;
if (seconds < lastSeconds)  {
  сброс в начале суток
}
lastSeconds = seconds

Эти #define IDX_SUNRISE_FINISH 1 дают возможность не запоминать по какому индексу что храниться в массиве.

bwn
Offline
Зарегистрирован: 25.08.2014

Что то вы непонятное затеяли. У вас аквариум или новогодняя переливающаяся елка? Зачем шесть каналов, зачем 12бит? Рыбки ведь они живые и охренеют от такого разнообразия. Рассвет он рассвет, закат он закат, причем плавный даже на 8битах и происходят они один раз в сутки. ИМХО.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

bwn пишет:

Что то вы непонятное затеяли. У вас аквариум или новогодняя переливающаяся елка? Зачем шесть каналов, зачем 12бит? Рыбки ведь они живые и охренеют от такого разнообразия. Рассвет он рассвет, закат он закат, причем плавный даже на 8битах и происходят они один раз в сутки. ИМХО.

Просто у меня морской аквариум. И разный тип кораллов обитает на разной глубине. А в зависимости от глубины меняется и спектр солнечного излучения к которому эти кораллы привыкли и живут под ним. Поэтому: на первом канале драйвер с диодами 395nm, второ 420, 452, 475, 510, и 7600К холодный белый. Вот и получается, что пока подстроишь все каналы так, как кораллам нравится, сесь... устанешь. Выглядит спектр примерно так:

Что касается 12бит, то тут я не завод, поэтому приходится делать с запасом. Например, если я в два раза перестараюсь с мощностью диодов, то мне придется сделать общую мощность в 50%, а это при 8 битах уже 125. А 125 уже существенно заметные рывки освещенности. При 12битах эта проблема исчезает как таковая, при том, что стоимость на сегодняшний день этому всего 70 рублей.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

GraninDm пишет:

seconds = h * 3600 + m * 60+ s;
if (seconds < lastSeconds)  {
  сброс в начале суток
}
lastSeconds = seconds

Эти #define IDX_SUNRISE_FINISH 1 дают возможность не запоминать по какому индексу что храниться в массиве.

Спасибо за код.

Про #define почитаю, если найду. )

GraninDm
Offline
Зарегистрирован: 01.08.2013
struct day {
  long int sunRiseStart;
  long int sunRiseFinish;
  long int sunSetStart;
  long int sunSetFinish;
  byte power;
  bool inversion;
} day;

#define ARRAY_LENGTH 6
#define MIN_POWER    20

struct day array[ARRAY_LENGTH];

long int seconds;

void setup() {
  DS1307 rtc(A0, A1);
  array[0].sunRiseStart = 600 * 60;
  array[0].sunRiseFinish = 630 * 60;
  array[0].sunSetStart = 700 * 60;
  array[0].sunSetFinish = 730 * 60;
  array[0].power = 100;
  array[0].inversion = 0;

  // i tak dalee
  //array[1].sunRiseStart = 0;
  //array[1].sunRiseFinish = 0;
  //array[1].sunSetStart = 0;
  //array[1].sunSetFinish = 0;
  //array[1].power = 0;
  //array[1].inversion = 0;
    
}
void loop() {
    Time time = rtc.getTime();
     seconds = time.hour * 3600 + time.min * 60 + time.sec;
     for (byte i = 0; i < ARRAY_LENGTH; i++){
       if (seconds < array[i].sunRiseStart || seconds > array[i].sunSetFinish ) {
         powerValue = MIN_POWER;
       }
       else if (seconds > array[i].sunRiseFinish && seconds < array[i].sunSetStart) {
         powerValue = array[i].power;
       }
       else if (seconds > array[i].sunRiseStart && seconds < array[i].sunRiseFinish) {
         // set proportional sun rise
         long int powerValue = (seconds - array[i].sunRiseStart) * 1024 / 
           (array[i].sunRiseFinish - array[i].sunRiseStart ) * 
           (array[i].power - MIN_POWER);
           powerValue = powerValue / 1024 + MIN_POWER;
       }
       else if (seconds > array[i].sunSetStart && seconds < array[i].sunSetFinish) {
         // set proportional sun set
         long int powerValue = (seconds - array[i].sunSetStart) * 1024 / 
           (array[i].sunSetFinish - array[i].sunSetStart) * 
           (array[i].power - MIN_POWER);
           powerValue = array[i].power - powerValue / 1024;
       }
     }
     
}

Никаких обнуления в начале суток не нужно.

Но это только заготовка, а не готовый код.

И не форматируйте if как у вас в коде. Я глаза сломал. :)

 

GraninDm
Offline
Зарегистрирован: 01.08.2013
// Для развлечения
#define HOURS *3600
#define MINUTES *60

...
array[0].sunRiseStart = 6 HOURS + 20 MINUTES;
...

 

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Спасибо большое. Но это вроде называется классы, а я в них вообще не разбираюсь..., а делать то, в чем не разбираешься, не благодарное занятие. Хотя в любом случае попробую использовать Ваш код. Вдруг и в классах разберусь... )

GraninDm
Offline
Зарегистрирован: 01.08.2013

Это не классы, а структура.

Т.е. Serial.print() - не смущает, а array[i].sunRiseFinish смущает?

Это явно нагляднее двумерного массива. Я даже имена дал почти по русски

Чем array[i].sunRiseFinish хуже array[i][0]?

Не надо бояться.

Вот тут http://arduino.ru/forum/programmirovanie/taimer-i-shim#comment-137556

уже пытаются использовать мой код. Можно объединить усилия.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Дело в том, что я смотрю на код и не вижу моментов управления TLC. А у меня это главная проблема. Мои IF-ы в принципе работают корректно. Был один вопрос, со сбросом дня, и Вы его мне подсказали.

Что касается структуры, да и вообще внешнего вида, безусловно Ваш код красивее, компактней, но самое главное сейчас корректная отработка микросхемой TLC этой  tlc_addFade (q, 0, 4095, startMillis, endMillis+fadeTime); и этой tlc_updateFades(); команды. А они то как раз у меня и не работают.

GraninDm
Offline
Зарегистрирован: 01.08.2013

Да не нужно никакого сброса дня.

Вы сами себе жизнь усложняете.

Во-первых, у вас был выход за границы массива. А это вообще неизвестно на что могло повлиять.

Во-вторых, дело ваше.

Удачи.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

GraninDm пишет:

Да не нужно никакого сброса дня.

Вы сами себе жизнь усложняете.

Во-первых, у вас был выход за границы массива. А это вообще неизвестно на что могло повлиять.

Во-вторых, дело ваше.

Удачи.

Сейчас изучаю скетч по ссылке. Там немного подругому сделано, но смысл тот же.

Границу массива давно пофиксил. Это никак не повлияло на корректную работу... Ищу ошибку. Надеюсь ошибка не в ДНК )))

Спасибо за помощь.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

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

Вот такой скетч 

#include "Tlc5940.h"
#include "tlc_fades.h"
TLC_CHANNEL_TYPE channel;

    int first = 0;
    uint32_t startMillis;
    uint32_t endMillis;

void setup() {
      Serial.begin ( 115200 );  // Указвать скорость на которой работает Ваш COM-порт
      Tlc.init();
 }

void loop() {
 if (first == 0) {
      startMillis = millis();
      endMillis = startMillis + 1200000;
      tlc_addFade (0, 4095, 0, startMillis, endMillis);
      Serial.println (" start");
      first = 1;
 }

if (tlc_fadeBufferSize == 0) Serial.println (" stop ");
  tlc_updateFades();
  
}

Выполняет одну единственную функцию рассвета с 0% до 100% за 20минут. И все равно. Рассвет идет где то 18 минут. А потом сбрасывается в ноль и за 2 минуты пытается снова пройти с 0%, но не успевает и включается на 100%.

Подскажите, где ошибка?

GraninDm
Offline
Зарегистрирован: 01.08.2013

Я посмотрел эту библоитеку.

Там косяк.

tlc_fades.h

190 примерно строка

                Tlc.set(p->channel, p->startValue + p->changeValue
                        * (int32_t)(currentMillis - startMillis)
                        / (int32_t)(p->endMillis - startMillis));

 

Здесь происходит переполнение int32.
Она видимо на таких длинных интервалах не тестировалась
 
Вычисляйте значение ШИМ сами и устанавливайте его Tlc.set()
Или попробуйте исправить в этих строках int32_t на int64_t
Но не советую, все равно можете словить косяк при обнулении millis(). Лучше устанавливайте сами.
sinnpriest
Offline
Зарегистрирован: 16.09.2015

А я в Tlc.set() не полез, т.к. сразу не понял, как это делать, ибо раз в секудну дискретность, а миллисекунды у меня сразу "не родились"... При этом увидив fade, мне показалось, что это решение... а вон, оно как получается (((

GraninDm
Offline
Зарегистрирован: 01.08.2013

Раз в секунду - дискретности не будет. Поверьте мне, кораллы 10 ШИМ не оценят. :)

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Так этот ШИМ не для кораллов, а для меня )))))

GraninDm
Offline
Зарегистрирован: 01.08.2013

Попробуйте 8 битный. Я пробовал. Не вижу дискретности.

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128

GraninDm
Offline
Зарегистрирован: 01.08.2013

Ок. Дело ваше.

Nikolaj666
Nikolaj666 аватар
Offline
Зарегистрирован: 19.01.2017

sinnpriest пишет:

Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128

здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?

sinnpriest
Offline
Зарегистрирован: 16.09.2015

Nikolaj666 пишет:

sinnpriest пишет:

Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128

здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?

Все нормально работало. Кажется неделю простоял. Но работало на стенде. Боевое устройство не делал.

sFiret
Offline
Зарегистрирован: 30.01.2018

sinnpriest пишет:

Nikolaj666 пишет:

sinnpriest пишет:

Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128

здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?

Все нормально работало. Кажется неделю простоял. Но работало на стенде. Боевое устройство не делал.

И что же в результате получилось? развитие получил проект?