Разработка силовой электроники по ряду причин является одной из сложнейших областей электроники — цена ошибки тут очень высока, при этом разработка силовых преобразователей всегда привлекала любителей, DIYщиков и не только. Наверняка вам хотелось собрать мощный блок питания для какого-то своего проекта? Или может быть online UPS на пару кВт и не разориться? А может частотник в мастерскую?
Сегодня я расскажу о своем небольшом открытом проекте, а точнее о его части, который позволит шагнуть в мир разработки силовой электроники любому желающему и при этом остаться в живых. В качестве демонстрации возможностей я покажу как за 15 минут собрать инвертор напряжения из 12В DC в 230В AC с синусом на выходе. Заинтриговал? Поехали!
Причины появления проекта
В последние пару лет разработка силовых преобразователей составляет около 90% моих заказов, основные трудозатраты уходят в основном на разработку ПО и макетирование, проектирование схемотехники + финальная трассировка платы от общих затрат составляет обычно не более 10-15%. Тут приходит понимание, что процесс макетирования, в который входит разработка ПО, необходимо как-то сократить и оптимизировать.
Выхода как всегда есть минимум два: купить готовую отладку, например, у Texas Instrumets или Infineon, но они обычно заточены под конкретную задачу и стоят от 500 до 5000$, при этом нет гарантии, что будет похожий заказ и данное вложение с высокой вероятностью просто не окупится.
Второй вариант — делать самому, но делать основательно это почти тоже самое, что запустить "+1 ревизию железа", что выльется в дополнительные траты для заказчика. Если делать не основательно, то как обычно все будет на соплях и где-нибудь что-то отвалится и пока макет, комплектующие и сроки.
Спустя какое-то время, я обратили внимание на очевиднейшее решение. Оно настолько простое и очевидное, что долго удивлялся почему такого еще не сделал тот же TI или Infineon. Сейчас расскажу о своем «просветление».
Давайте рассмотрим несколько наиболее популярных топологий силовых преобразователей:
Теперь еще раз внимательно посмотрите. Я нарисовал специально без обвязки, только ключевые компоненты, чтобы было понятнее. Что общего в этих топологиях? Первым делом бросается в глаза то ряд общих моментов:
- Все топологии включают в себя основные компоненты — конденсаторы, транзисторы и индуктивность (дроссель или трансформатор). Это 3 кита силовой электроники;
- Транзисторы включены везде одинаково и образуют так называемый «полумост». Из него построены почти все топологии преобразователей;
- Вариант включения связки «полумост + конденсатор» не меняется на всех топологиях. Меняется тип индуктивности и варианты включения полумостов.
Из этого можно сделать вывод, что имея некий стандартный модуль в виде связки «полумост + конденсатор» можно построить любой преобразователь, добавляя лишь нужный дроссель или трансформатор. Поэтому очевидным решения для упрощения прототипирования было создание вот такого модуля:
Борьба добра со злом
К сожалению ограниченное количество часов в сутках и банальная лень диктуют свои условия. К необходимости изготовить данный модуль я пришел еще год назад, но реализация постоянно переносилась под лозунгом — «на следующих выходных точно сделаю!».
Наверно идея так бы и осталась лежать на полке, если бы не 2 события. Во-первых, ко мне пришли в один месяц 2 заказчика и каждый хотел сложный и интересный в реализации преобразователь, а главное готовы были очень хорошо заплатить. Хотя учитывая, что он из Европы, то может для них этого и дешево еще оказалось)) Оба проекта для меня были интересны, например, один из них «трехфазный стабилизатор напряжения с гальванической развязкой (sic!)», то есть 3-х фазный PFC + 3 мостовых преобразователя (phase shifted) + синхронный выпрямитель + 3-х фазный инвертор. Все это на SiC и очень компактное. В общем я взялся за 2 больших заказа, каждый из них по ~800 человеко-часов и срок 6 месяцев. В итоге меня «заставили» искать пути оптимизации.
Во-вторых, мне неожиданно написали ребята из компании PCBway, многие наверняка у них платы заказывали, и предложили по сотрудничать. Они очень активно поддерживают открытые железячные проекты, то есть ту самую инициативу CERN — Open Source Hardware. Сотрудничество простое, понятное для обеих сторон — они снабжают меня бесплатно платами для моих проектов, а я их открываю, ну и выкладываю на их сайте, в других местах уже по желанию. Для меня это стало дополнительной мотивацией, а главное совесть моя чиста, т.к. я уже несколько лет заказываю у них платы и на прототипы, и для серийного производства при этом рассказываю о них знакомым и партнерам. Теперь мне за это еще и плюшка в виде бесплатных плат для мелких проектов, можно чаще писать на хабр))
И тут лед тронулся, было решено создать не просто описанный ранее модуль, а целый комплект разработчика силовой электроники и сделать его открытым и доступным каждому.
Структура проекта
В начале статьи я упомянул, что расскажу сегодня лишь про одну часть — это силовой модуль полумоста. Он один уже позволяет создать преобразователь, просто прикрутив управляющую схему, например, отладку STM32-Discovery, Arduino, TMS320, TL494 или чем вы там владеете. Привязка к какой либо платформе или МК нет вообще.
Только это не весь проект, а часть)) Из чего состоит готовый силовой преобразователь? В первую очередь силовая часть, чтобы она заработала нужен некий модуль управления, чтобы понять что происходит нужна индикация, а чтобы понять что происходит с безопасного расстояния еще и интерфейс, например, Modbus RTU или CAN.
В итоге общая структура проекта выглядит так:
Вероятно в будущем еще напишу программку для расчета трансформаторов и дросселей, как обычных, так и планарных. Пока что так. Разные части диаграммы в черновом варианте уже реализована и обкатаны в двух проектах, после небольших доработок по ним так же будут написаны статьи и доступны исходники.
Силовой модуль полумоста
Теперь пришло время подробнее посмотреть на сегодняшнего героя. Модуль универсален и позволяет работать с транзисторами Mosfet и IGBT, как низковольтными, так и высоковольтными ключами до 1200В.
Особенности модуля:
- Гальваническая развязка управляющей (цифровой) стороны от силовой. Напряжение пробоя изоляции 3 кВ;
- Верхний и нижний ключ независимы, каждый имеет свой гальванически развязанный драйвер и гальванически развязанный dc/dc;
- Применен современный драйвер от компании Infineon — 1EDC60I12AHXUMA1. Импульсный ток открытия/закрытия — 6А/10А. Максимальная частота — 1 МГц (проверено до 1.5 МГц стабильно);
- Аппаратная защита по току: шунт + ОУ + компаратор + оптрон;
- Максимальный ток — 20А. Ограничен не ключами, а размером радиатора и толщиной медных полигонов.
В статье фигурирует 1-я ревизия модуля, она полностью рабочая, но будет 2-я ревизия, в которой устранятся чисто конструктивные недочеты и поменяются разъемы на более удобные. После завершения создания документации, закинул gerber в PCBway и мне через 6 дней в дверь постучался курьер и вручил вот такую прелесть:
Еще через неделю наконец-то привезли на собаках комплектующие из одного прекрасного отечественного магазина. В итоге все было смонтировано:
Перед тем, как двигаться дальше, давайте посмотрим на принципиальную схему модуля. Скачать ее можно тут — PDF.
Тут ничего сложного или магического нет. Обычный полумост: 2 ключа внизу, 2 вверху, можете паять по одному. Драйвер как выше писал из семейства 1ED, очень злой и бессмертный. Везде по питанию есть индикация, включая +12В на выходе dc/dc. Защита реализована на логическом элементе AND, в случае превышения тока компаратор выдаст +3.3В, они засветят оптрон и он притянет один из входов AND к земле, что означает установление лог.0 и ШИМ-сигнал с драйверов пропадет. AND с 3-мя входами использован специально, в следующей ревизии планирую сделать еще и защиту от перегрева радиатором и завести сигнал ошибки туда же. Все исходники будут в конце статьи.
Собираем макет инвертора
Долго думал на чем бы продемонстрировать работу модуля, чтобы и не сильно скучно, и полезно, и не сильно сложно, чтобы повторить мог любой. Поэтому остановился на инверторе напряжения, такие используют для работы с солнечными панелями, если что-то бахнет по низковольтной стороне — не страшно, а по высоковольтной — просто когда включите не суйте туда руки.
Сам инвертор до безобразия простой, кстати, МАП Энергия клепают именно такие, вот вам пример даже коммерческой реализации сей идеи. Работа инвертора заключается в том, чтобы сформировать из постоянного напряжения 12В переменное синусоидальной формы с частотой 50 Гц, ведь именно с таким привык работать обычный трансформатор на 50 Гц. Я использую какой-то советский, вроде ОСМ, 220В обмотка заводская и используется как вторичка, а первичная ~8В намотана медной шиной. Выглядит это так:
И это чудовище всего на 400 Вт! Вес трансформатора около 5-7 кг по ощущениям, если уронить на ногу, то в армию точно не возьмут. Собственно в этом и заключается минус инверторов с «железными» трансформаторами, они огромные и тяжелые. Плюс их в том, что данные инверторы оооочень простые, не требует никакого опыта для создания и конечно же дешевые.
Теперь давайте соединим модули и трансформатор. На самом деле модуль для разработчика должен представляться просто как «черный ящик» у которого есть вход 2-х ШИМов и 3 силовых вывода: VCC, GND и собственно выход полумоста.
Теперь из этих «черных ящиков» давайте изобразим наш инвертор:
Ага, понадобилось всего 3 внешних элемента: трансформатор + LC фильтр. Для последнего дроссель я изготовил просто намотав провод от модуля до трансформатора на кольцо из материала Kool Mu размер R32 с проницаемость 60, индуктивность около 10 мкГн. Конечно же дроссель надо бы рассчитать, но нам же надо за 15 минут)) Вообще если будете гонять что-то подобное на 400 Вт, то нужно кольцо размером R46 (это внешний диаметр). Емкость — 1-10 мкФ пленка, этого достаточно. На самом деле в качестве экономии можно конденсатор не ставить, ибо емкость обмотки трансформатора здоровая… в общем у китайцев и МАПа именно так и сделали)) Дроссель выглядит вот так:
Остается накинуть тестовую нагрузку на выход, у меня это пара светодиодных лампочек на 20 Вт (ничего другого наглядного не оказалось под рукой), сами они кушают 24Вт, КПД однако. Так же ток холостого хода трансформатора около 1А. С АКБ будет кушать около 5А. В итоге имеем такой стенд:
Так же в макете используется АКБ Delta HR12-17 соответственно на 12В и емкостью 17 А*ч. Управлять преобразователем будем с отладочной платы STM32F469-Discovery.
Код
Изначально для управления предполагалось использовать мою STM32VL-Disco, полученную на выставке еще в 2010-м, но так случилось, что именно на этом макете ей суждено было умереть уже когда весь код написан и макет запущен. Забыл про щупы осциллографа и объединил 2 земли, аминь. В итоге все было переписано на STM32F469NIH6, именно эта отладка имелась под рукой, поэтому будет 2 проекта: для F100 и для F469, оба проверены. Проект собран для TrueSTUDIO, версия эклипса от ST.
#include "main.h"
/********************************************* Sinus table **********************************************************/
uint16_t sinData[240] =
{0,13,26,39,52,65,78,91,104,117,130,143,156,169,182,195,207,220,233,246,258,271,284,296,309,321,333,346,358,370,
382,394,406,418,430,442,453,465,477,488,500,511,522,533,544,555,566,577,587,598,608,619,629,639,649,659,669,678,688,697,
707,716,725,734,743,751,760,768,777,785,793,801,809,816,824,831,838,845,852,859,866,872,878,884,891,896,902,908,913,918,
923,928,933,938,942,946,951,955,958,962,965,969,972,975,978,980,983,985,987,989,991,993,994,995,996,997,998,999,999,999,
999,999,999,998,997,996,995,994,993,991,989,987,985,983,980,978,975,972,969,965,962,958,955,951,946,942,938,933,928,923,
918,913,908,902,896,891,884,878,872,866,859,852,845,838,831,824,816,809,801,793,785,777,768,760,751,743,734,725,716,707,
697,688,678,669,659,649,639,629,619,608,598,587,577,566,555,544,533,522,511,500,488,477,465,453,442,430,418,406,394,382,
370,358,346,333,321,309,296,284,271,258,246,233,220,207,195,182,169,156,143,130,117,104,91,78,65,52,39,26,13,0};
uint16_t sinStep;
uint8_t sinStatus;
/******************************************** Used functions ********************************************************/
void StartInitClock (void) {
RCC->CR |= RCC_CR_HSEON; // Enable HSE
while (!(RCC->CR & RCC_CR_HSERDY));
FLASH->ACR |= FLASH_ACR_LATENCY_5WS;
RCC->PLLCFGR = 0x00;
RCC->PLLCFGR |= RCC_PLLCFGR_PLLM_3; // Div for HSE = 8
RCC->PLLCFGR |= RCC_PLLCFGR_PLLN_4 | RCC_PLLCFGR_PLLN_5 | RCC_PLLCFGR_PLLN_6 | RCC_PLLCFGR_PLLN_7; // PLL mult x240
RCC->PLLCFGR |= RCC_PLLCFGR_PLLSRC; // Source HSE
RCC->CR |= RCC_CR_PLLON;
while((RCC->CR & RCC_CR_PLLRDY) == 0){}
RCC->CFGR &= ~RCC_CFGR_SW;
RCC->CFGR |= RCC_CFGR_SW_PLL; // Select source SYSCLK = PLL
while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_1) {} // Wait till PLL is used
RCC->CR |= RCC_CR_PLLSAION;
while ((RCC->CR & RCC_CR_PLLSAIRDY) == 0) {}
}
void EnableOutputMCO (void) {
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // Enable clock port A
GPIOA->MODER &= ~GPIO_MODER_MODER8;
GPIOA->MODER |= GPIO_MODER_MODER8_1; // Alternative PP
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR8; // Very high speed
RCC->CFGR |= RCC_CFGR_MCO1; // Source PLL
RCC->CFGR &= ~RCC_CFGR_MCO1PRE; // Div = 1
}
void InitIndicatorLED (void) {
/*
* LED1 - PG6
* LED2 - PD4
* LED3 - PD5
* LED4 - PK3
*/
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOGEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIODEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOKEN;
GPIOG->MODER &= ~GPIO_MODER_MODER6;
GPIOG->MODER |= GPIO_MODER_MODER6_0; // Output PP
GPIOD->MODER &= ~GPIO_MODER_MODER4;
GPIOD->MODER |= GPIO_MODER_MODER4_0; // Output PP
GPIOD->MODER &= ~GPIO_MODER_MODER5;
GPIOD->MODER |= GPIO_MODER_MODER5_0; // Output PP
GPIOK->MODER &= ~GPIO_MODER_MODER3;
GPIOK->MODER |= GPIO_MODER_MODER3_0; // Output PP
}
void EnableIndicatorLED (void) {
GPIOG->BSRR |= GPIO_BSRR_BR_6;
GPIOD->BSRR |= GPIO_BSRR_BR_4;
GPIOD->BSRR |= GPIO_BSRR_BR_5;
GPIOK->BSRR |= GPIO_BSRR_BR_3;
}
void InitLowPWM (void) {
/*
* TIM1-CH1 - PA8
* TIM1-CH1N - PB13
*/
RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
/*********** GPIO **********/
GPIOA->MODER &= ~GPIO_MODER_MODER8;
GPIOA->MODER |= GPIO_MODER_MODER8_1; // Alternative output PP
GPIOA->AFR[1] |= GPIO_AFRH_AFRH0_0; // Select TIM1-CH1
GPIOB->MODER &= ~GPIO_MODER_MODER13;
GPIOB->MODER |= GPIO_MODER_MODER13_1; // Alternative output PP
GPIOB->AFR[1] |= GPIO_AFRH_AFRH5_0; // Select TIM1-CH1N
/*********** Timer *********/
TIM1->PSC = 2400-1; // div for clock: F = SYSCLK / [PSC + 1]
TIM1->ARR = 1000; // count to 1000
TIM1->CR1 &= ~TIM_CR1_CKD; // div for dead-time: Tdts = 1/Fosc = 41.6 ns
TIM1->CCR1 = 500; // duty cycle 50%
TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE; // enable PWM complementary out to PB15 and to PA10
TIM1->CCER &= ~TIM_CCER_CC1NP; // active high level: 0 - high, 1 - low
TIM1->CCMR1 &= ~TIM_CCMR1_OC1M;
TIM1->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1; // positiv PWM1_CH3 and PWM1_CH3N
TIM1->BDTR &= ~TIM_BDTR_DTG; // clear register
TIM1->BDTR |= TIM_BDTR_DTG_2 | TIM_BDTR_DTG_1 | TIM_BDTR_DTG_0; // value dead-time: = 31*Tdts = 32*41,6ns = 1.29us
TIM1->BDTR |= TIM_BDTR_MOE | TIM_BDTR_AOE; // enable generation output and dead-time
TIM1->CR1 &= ~TIM_CR1_DIR; // count up: 0 - up, 1 - down
TIM1->CR1 &= ~TIM_CR1_CMS; // aligned on the front signal: 00 - front; 01, 10, 11 - center
TIM1->CR1 |= TIM_CR1_CEN; // start count
}
void InitSinusPWM (void) {
/*
* TIM3-CH1 - PB4
* TIM3-CH2 - PC7
*/
RCC->APB1ENR |= RCC_APB1ENR_TIM3EN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN;
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN;
/*********** GPIO **********/
GPIOB->MODER &= ~GPIO_MODER_MODER4;
GPIOB->MODER |= GPIO_MODER_MODER4_1; // Alternative output PP
GPIOB->AFR[0] |= GPIO_AFRL_AFRL4_1; // Select TIM3-CH1
GPIOC->MODER &= ~GPIO_MODER_MODER7;
GPIOC->MODER |= GPIO_MODER_MODER7_1; // Alternative output PP
GPIOC->AFR[0] |= GPIO_AFRL_AFRL7_1; // Select TIM3-CH2
/*********** Timer *********/
TIM3->PSC = 5-1; // div for clock: F = SYSCLK / [PSC + 1]
TIM3->ARR = 1000; // count to 1000
TIM3->CCR1 = 0; // duty cycle 0%
TIM3->CCR2 = 0; // duty cycle 0%
TIM3->CCER |= TIM_CCER_CC1E; // enable PWM out to PA8
TIM3->CCER &= ~TIM_CCER_CC1P; // active high level: 0 - high, 1 - low
TIM3->CCER |= TIM_CCER_CC2E; // enable PWM complementary out to PA9
TIM3->CCER &= ~TIM_CCER_CC1P; // active high level: 0 - high, 1 - low
TIM3->CCMR1 &= ~(TIM_CCMR1_OC1M | TIM_CCMR1_OC2M);
TIM3->CCMR1 |= TIM_CCMR1_OC1M_2 | TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC2M_2 | TIM_CCMR1_OC2M_1; // positiv PWM1_CH1 and PWM1_CH2
TIM3->CR1 &= ~TIM_CR1_DIR; // count up: 0 - up, 1 - down
TIM3->CR1 &= ~TIM_CR1_CMS; // aligned on the front signal: 00 - front; 01, 10, 11 - center
TIM3->CR1 |= TIM_CR1_CEN; // start count
}
void InitStepSinus (void) {
RCC->APB1ENR |= RCC_APB1ENR_TIM6EN; // enable clock for basic TIM6
TIM6->PSC = 5-1; // div, frequency 24 kHz
TIM6->ARR = 1000; // count to 1000
TIM6->DIER |= TIM_DIER_UIE; // enable interrupt for timer
TIM6->CR1 |= TIM_CR1_CEN; // start count
NVIC_EnableIRQ(TIM6_DAC_IRQn); // enable interrupt TIM6_DAC_IRQn
}
/************************************* Main code *********************************************/
int main (void) {
StartInitClock();
// EnableOutputMCO();
InitIndicatorLED();
InitLowPWM();
InitSinusPWM();
InitStepSinus();
EnableIndicatorLED();
while(1)
{
}
}
/****************************** Interrupts ******************************************************/
void TIM6_DAC_IRQHandler (void) {
TIM6->SR &= ~TIM_SR_UIF;
if (sinStatus == 0) {TIM3->CCR1 = sinData[sinStep];}
if (sinStatus == 1) {TIM3->CCR2 = sinData[sinStep];}
sinStep++;
if (sinStep >= 240) {
sinStep = 0;
sinStatus = sinStatus ? 0 : 1;
}
}
Вообще в своей другой статье ооочень подробно и наглядно рассказал как формировать синусоидальный сигнал, как писать код и прочее прочее. Прочитать можно — тут.
Прочитали? Хотите собрать? Держите проект:
Запускаем код, вооружаемся осциллографом и идем далее. Первым делом проверяем наличие сигналом на входе драйверов, должно быть вот так:
Стоит обратить внимание, что я на один полумост (модуль) подаю 2 сигнала, рисующих синус, а на другой 2 сигнала задающие 50 Гц. При чем одна диагональ «красный+желтый», а другая «синий+зеленый». В статье, что дал выше про это подробно написано, если вдруг не поняли. Теперь как подали сигналы, накидываем на оба полумоста +12В и GND от лабораторного блока питания. Сразу АКБ не советую, если где-то ошиблись, то может сгореть что-то. Защита на плате спасает от превышения тока, но не от явных косяков, когда плюс и минус перепутали, а вот лабораторник спасает. 12В и 1А для тестов хватит. Берем щуп осциллографа, его земляной провод на выход первого полумоста, а сам щуп на выход другого полумоста и должна быть такая картинка:
Где синус спросите вы? Дело в том, что сопротивление входа осциллографа большое и он не представляет из себя нагрузку, поэтому ток не протекает и синусу взяться не откуда. Добавим нагрузку, я смастерил из резисторов 10 Ом нагрузку 90 Ом просто включив последовательно 9 штук. Цепляем нагрузку к выходам полумостов и видим такую картину:
У вас так же? Значит пришла пора подключать дроссель, трансформатор, нагрузку и пробовать запускать. Achtung! Нельзя включать данный макет без нагрузки, ибо на холостом ходе на выходе может быть до 350...380В. Чтобы такого не было нужна нагрузка или ОС. Последней у нас не будет, это тема отдельной стать, можете в качестве факультатива прикрутить П-регулятор простейший, шаблон проекта у вас уже есть.
Включение
После включения получаем на выходе около 230В, выход конечно не стабилизированный и будет плавать 230В +-30В, для тестов пойдет, в другой статье доработаем макет как решусь рассказать про П и ПИ-регуляторы и их реализацию.
Теперь можно насладиться результатом работы, а при необходимости упихать все в коробку и даже применить в хозяйстве или на даче для обеспечения себя светом и прочими прелестями.
Вы наверняка заметили задержку между «щелчком», то есть подачей питания на Discovery и включением ламп — это время, которое МК потратил на инициализацию. Эту задержку можно уменьшить, если писать в регистр разом одну цифру, а не дробить запись регистра на кучу строк. Я раздробил исключительно для наглядности. Хотя и это не страшно, с кодом на HAL задержка в 3 раза дольше и народ как-то живет с ним))
Пока не забыл, исходники проекта:
Благодарности и планы
В ближайшее время я планирую написать про DSP board и по управлять уже не с отладки discovery, а уже со «специализированного» модуля. Платы 2-й ревизии на него уже пришли от тех же PCBway, жду компоненты и сразу писать.
Надеюсь статья и сама идея вам понравились. В дальнейшем на этих же модулях покажу как собрать частотник, mppt контроллер, а может и еще чего интересного. Если у вас есть вопросы, то не стесняйтесь их задавать в комментариях или в личку, если у вас вдруг нет полноценного аккаунта, постараюсь ответить на все вопросы.
Теперь немного благодарностей компании PCBway, на самом деле очень хорошо, что они поддерживают open source движуху. Может скоро железячники даже догонять софтописателей по количеству и качеству открытых проектов.
Комментариев нет:
Отправить комментарий