Контроллер светодиодного светильника для морского аквариума. TLC5940 + Arduino Nano + RTC-modul + DALLAS-DS18B20
- Войдите на сайт для отправки комментариев
Всем добрый день.
Начал заниматься Ардуино месяца два назад. Стоит задача сделать светодиодный светильник с шестью каналами и 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(); }
закройте код спойлером!!!! (сверните его)
А почему
массив же размерностью 6?
И еще, если не секрет, зачем 12-разрядный шим?
когда наступит событие блока 220 - 228 ? сомнения у меня, что это произойдет.
И еще я бы посоветовал сделать так
попробуйте снимать лог интересующего блока (остальные в коммент) в значениях "время и PWM" чтобы отделить баги кода от багов железа.
Я так и не понял назначение
может все же ему жестко сказать когда у него рассвет а когда закат ? А после старта привязать PWM к millis . Тогда и обнулять дату и время не нужно.
А почему
массив же размерностью 6?
И еще, если не секрет, зачем 12-разрядный шим?
Логично. Поправил. К сожалению это осталось от того, как q у меня менялось с 1 по 7. Потом начала компилятор на память жаловаться, пришлось вернуться с индексации с 0 по 5. Поправлю. Спасибо. Но не уверен, что это может как то влиять. ну записывает она всякую муть в 6 канал... ну и пусть... но все равно спасибо.
12 битный шим - плавность. Возможно излишняя, но в этом еще больший плюс.
И еще я бы посоветовал сделать так
Если честно, то моих знаний на понимание этого кода не хватает. Но попробую двинуться в этом направлении.
когда наступит событие блока 220 - 228 ? сомнения у меня, что это произойдет.
У меня тоже сомнения. Но я пока не понял, как можно раз в сутки заполнить массив нолями...
попробуйте снимать лог интересующего блока (остальные в коммент) в значениях "время и PWM" чтобы отделить баги кода от багов железа.
Я так и не понял назначение
может все же ему жестко сказать когда у него рассвет а когда закат ? А после старта привязать PWM к millis . Тогда и обнулять дату и время не нужно.
Я и так пытаюсь снимать лог print-ами, значение time_all - это количество секунд с начала дня. По этому значению и ориентируются условия для подачи команд на TLC для выполения fade-команд.
А.е. я могу сразу один раз в сути давать команду в милисекундах:
tlc_addFade (q, start, finish, startMillis, endMillis+fadeTime);
А потом просто в цикле void спамить апдэйт:
tlc_updateFades();
?
Я кажется так пробовал. Он отказывался работать... сейчас еще раз попробую..
Эти #define IDX_SUNRISE_FINISH 1 дают возможность не запоминать по какому индексу что храниться в массиве.
Что то вы непонятное затеяли. У вас аквариум или новогодняя переливающаяся елка? Зачем шесть каналов, зачем 12бит? Рыбки ведь они живые и охренеют от такого разнообразия. Рассвет он рассвет, закат он закат, причем плавный даже на 8битах и происходят они один раз в сутки. ИМХО.
Что то вы непонятное затеяли. У вас аквариум или новогодняя переливающаяся елка? Зачем шесть каналов, зачем 12бит? Рыбки ведь они живые и охренеют от такого разнообразия. Рассвет он рассвет, закат он закат, причем плавный даже на 8битах и происходят они один раз в сутки. ИМХО.
Просто у меня морской аквариум. И разный тип кораллов обитает на разной глубине. А в зависимости от глубины меняется и спектр солнечного излучения к которому эти кораллы привыкли и живут под ним. Поэтому: на первом канале драйвер с диодами 395nm, второ 420, 452, 475, 510, и 7600К холодный белый. Вот и получается, что пока подстроишь все каналы так, как кораллам нравится, сесь... устанешь. Выглядит спектр примерно так:
Что касается 12бит, то тут я не завод, поэтому приходится делать с запасом. Например, если я в два раза перестараюсь с мощностью диодов, то мне придется сделать общую мощность в 50%, а это при 8 битах уже 125. А 125 уже существенно заметные рывки освещенности. При 12битах эта проблема исчезает как таковая, при том, что стоимость на сегодняшний день этому всего 70 рублей.
Эти #define IDX_SUNRISE_FINISH 1 дают возможность не запоминать по какому индексу что храниться в массиве.
Спасибо за код.
Про #define почитаю, если найду. )
Никаких обнуления в начале суток не нужно.
Но это только заготовка, а не готовый код.
И не форматируйте if как у вас в коде. Я глаза сломал. :)
Спасибо большое. Но это вроде называется классы, а я в них вообще не разбираюсь..., а делать то, в чем не разбираешься, не благодарное занятие. Хотя в любом случае попробую использовать Ваш код. Вдруг и в классах разберусь... )
Это не классы, а структура.
Т.е. Serial.print() - не смущает, а array[i].sunRiseFinish смущает?
Это явно нагляднее двумерного массива. Я даже имена дал почти по русски
Чем array[i].sunRiseFinish хуже array[i][0]?
Не надо бояться.
Вот тут http://arduino.ru/forum/programmirovanie/taimer-i-shim#comment-137556
уже пытаются использовать мой код. Можно объединить усилия.
Дело в том, что я смотрю на код и не вижу моментов управления TLC. А у меня это главная проблема. Мои IF-ы в принципе работают корректно. Был один вопрос, со сбросом дня, и Вы его мне подсказали.
Что касается структуры, да и вообще внешнего вида, безусловно Ваш код красивее, компактней, но самое главное сейчас корректная отработка микросхемой TLC этой tlc_addFade (q, 0, 4095, startMillis, endMillis+fadeTime); и этой tlc_updateFades(); команды. А они то как раз у меня и не работают.
Да не нужно никакого сброса дня.
Вы сами себе жизнь усложняете.
Во-первых, у вас был выход за границы массива. А это вообще неизвестно на что могло повлиять.
Во-вторых, дело ваше.
Удачи.
Да не нужно никакого сброса дня.
Вы сами себе жизнь усложняете.
Во-первых, у вас был выход за границы массива. А это вообще неизвестно на что могло повлиять.
Во-вторых, дело ваше.
Удачи.
Сейчас изучаю скетч по ссылке. Там немного подругому сделано, но смысл тот же.
Границу массива давно пофиксил. Это никак не повлияло на корректную работу... Ищу ошибку. Надеюсь ошибка не в ДНК )))
Спасибо за помощь.
Решил минимально облегчить скетч и проверить корректную работу TLC.
Вот такой скетч
Выполняет одну единственную функцию рассвета с 0% до 100% за 20минут. И все равно. Рассвет идет где то 18 минут. А потом сбрасывается в ноль и за 2 минуты пытается снова пройти с 0%, но не успевает и включается на 100%.
Подскажите, где ошибка?
Я посмотрел эту библоитеку.
Там косяк.
tlc_fades.h
190 примерно строка
А я в Tlc.set() не полез, т.к. сразу не понял, как это делать, ибо раз в секудну дискретность, а миллисекунды у меня сразу "не родились"... При этом увидив fade, мне показалось, что это решение... а вон, оно как получается (((
Раз в секунду - дискретности не будет. Поверьте мне, кораллы 10 ШИМ не оценят. :)
Так этот ШИМ не для кораллов, а для меня )))))
Попробуйте 8 битный. Я пробовал. Не вижу дискретности.
Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128
Ок. Дело ваше.
Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128
здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?
Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128
здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?
Все нормально работало. Кажется неделю простоял. Но работало на стенде. Боевое устройство не делал.
Я сделал 8 битный. На низких значениях видно очень отчетливо. Во всяком случае до 15 из 256. А как раз вот эти низкие значени и очень красивы в кораллах... А если мне потребуется уменьшить общую мощность, например на 50%, то у меня будет дискретность не 15, а 30 из 128
здравствуйте. поделитесь пожалуйста итоговым результатом. что в итоге получилось ?
Все нормально работало. Кажется неделю простоял. Но работало на стенде. Боевое устройство не делал.