Андрей Смирнов
Время чтения: ~17 мин.
Просмотров: 0

Как начать программировать arduino

Видео, демонстрирующее работу схемы

Возможные осложнения

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

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

Важно давать себе передышку после напряженных периодов и качественно отдыхать

Нужно ли знать программирование?

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

После того как программа составлена она загружается (прошивается) на плату. Ардуино в этом случае имеет неоспоримое преимущество – для программирования в большинстве случаев используется USB-кабель. Сразу после загрузки программа готова выполнять различные команды.

Начинающим работать с Arduino нужно знать две ключевые функции:

  • setup() – используется один раз при включении платы, применяется для инициализации настроек;
  • loop() – используется постоянно, является завершающим этапом настройки setup.

Пример записи функции setup():

void setup() {
	Serial.begin(9600);	// Открываем serial соединение
	pinMode(9, INPUT);	// Назначаем 9 пин входом
	pinMode(13, OUTPUT); // Назначаем 13 пин выходом
}

Функция setup() выполняется в самом начале и только 1 раз сразу после включения или перезагрузки вашего устройства.

Функция loop() выполняется после функции setup(). Loop переводится как петля, или цикл. Функция будет выполняться снова и снова. Так микроконтроллер ATmega328 (большинстве плат Arduino содержат именно его), будет выполнять функцию loop около 10 000 раз в секунду.

Также вы будете сталкиваться с дополнительными функциями:

  • pinMode – режим ввода и вывода информации;
  • analogRead – позволяет считывать возникающее аналоговое напряжение на выводе;
  • analogWrite – запись аналогового напряжения в выходной вывод;
  • digitalRead – позволяет считывать значение цифрового вывода;
  • digitalWrite – позволяет задавать значение цифрового вывода на низком или высоком уровне;
  • Serial.print – переводит данные о проекте в удобно читаемый текст.

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

  • чтение и запись в хранилище,
  • подключение к интернету,
  • чтение SD карт,
  • управление шаговыми двигателями,
  • отрисовка текста
  • и т. д.

Шаг 10. Схема подключения

Как только Вы соберёте манипулятор, и подготовите разъем Nunchuk, Вы будете готовы что бы собрать электросхему. Мы использовали щит платы управления, который был в комплекте вместе с комплектом манипулятора. Это упрощает подключение компонентов, поскольку в нем уже имеются специальные разъемы для сервомоторов, источника питания и т. д.

Подключите компоненты следующим образом:

Контроллер:

  • Контроллер контакт 6 (SCL) => Arduino Mega Контакт 21 (SCL) (на плате)
  • Контроллер контакт 1 (SDA) => Arduino Mega Контакт 20 (SDA) (на плате)
  • Контроллер контакт 3 (Vcc) => Ardino Mega Контакт 3V3 (на плате)
  • Контроллер контакт 4 (Gnd) => Arduino Mega Контакт Gnd (на плате)

Если вы используете Arduino Uno, контакты Nunchuk SCL и SDA должны быть подключены к контактам Arduino следующим образом:

  • Контроллер контакт 6 (SCL) => Arduino Uno контакт A5
  • Контроллер контакт 1 (SDA) => Arduino Uno контакт A4
  • Контроллер контакт 3 (Vcc) => Ardino Uno контакт 3V3
  • Контроллер контакт 4 (Gnd) => Arduino Uno контакт Gnd

Сервопривод:

  • Контакт Платы управления 11 => Сервопривод № 1
  • Контакт Платы управления 12 => Сервопривод №2
  • Контакт Платы управления 13 => Сервопривод № 3
  • Контакт Платы управления 8 => Сервопривод № 4
  • Контакт Платы управления 9 => Сервопривод №5
  • Контакт Платы управления 10 => Сервопривод №6

Если вы не используете плату управления, Вы должны использовать следующую конфигурацию контактов:

  • Arduino Контакт 11 => Серво #1 (Sgn)
  • Arduino Контакт 12 => Серво #2 (Sgn)
  • Arduino Контакт 13 => Серво #3 (Sgn)
  • Arduino Контакт 8 => Серво #4 (Sgn)
  • Arduino Контакт 9 => Серво #5 (Sgn)
  • Arduino Контакт 10 => Серво #6 (Sgn)
  • Arduino Контакт Gnd => Серво Gnd
  • 6В Контакт питания => Серво Vcc

Вам также необходимо подключить внешний источник питания 12 В. Мы предлогаем использовать один блок с выходом более 2A. Сервоприводы потребляют много энергии, и если блок питания недостаточно мощный, сервоприводы будут вибрировать и перегреваться. Они также потеряют свою мощность.

Не подключайте источник питания до тех пор, пока Вы не загрузите код Arduino (см. Дальнейшие шаги). На плате есть кнопка питания. Держите её в выключенном положении.

Подключите USB-кабель к Arduino и перейдите к следующему шагу.

Грибная запеканка с овсянкой

Категория:
Горячие блюда Запеканки Запеканка с грибами

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

Последовательный монитор

В онлайн-редакторе Arduino последовательный монитор доступен на боковой панели, при щелчке по нему отображается панель.

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

Если вы хотите что-то напечатать и познакомиться с Serial Monitor, вы можете попробовать:

 Examples -> 03.Analog -> AnalogInOutSerial

const int analogInPin = A0;
const int analogOutPin = 9;

int sensorValue = 0;
int outputValue = 0;

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

void loop() {
  sensorValue = analogRead(analogInPin);
  outputValue = map(sensorValue, 0, 1023, 0, 255);
  analogWrite(analogOutPin, outputValue);

  Serial.print("sensor = ");
  Serial.print(sensorValue);
  Serial.print("\t output = ");
  Serial.println(outputValue);

  delay(2);
}

Нажмите Загрузить (Upload) и посмотрите значения, напечатанные на панели.

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

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

Если вы используете другие программы, которые обмениваются данными через этот порт (например, Processing или Desktop IDE), появится сообщение о том, что порт используется другим программным обеспечением.

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

FAQ

Всё верно. Разработчики хотят иметь прибыль от своего полезного и качественного продукта.

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

Можно только по Wi-Fi?

Нет. Подключение может любым: Wi-Fi, Ethernet, и даже COM-порт через USB компьютера. Всё зависит от целей, задач и вида микроконтроллера.

Почему не использовать готовые решения?

10. Именно такая цифра — делитель стоимости подобных «готовых» устройств (в некоторых случаях меньше или больше, но какой смысл переплачивать, если с равными усилиями получается дешевле и веселее?)

Что еще можно сделать по этой технологии?

А что угодно!

  • Управляемую подсветку (меняющую цвет, яркость, режимы работы);
  • Сбор информации с самых разных датчиков (температура, влажность, давление);
  • Умные выключатели и розетки;
  • ИК-пульт (наподобие Яндекс.Пульта);
  • Управление компьютером через Алису;
  • Голосовое управление детскими игрушками;
  • Сигнализацию с постановкой на охрану голосом (и проверкой статуса).

А считывать состояния Blynk умеет?

Да, ссылка на запрос состояния выглядит так:

https://blynk-cloud.com/<ваш_токен>/get/V0

Так же можно считывать и состояния датчиков, но это тема уже совсем другой статьи 🙂

Насколько это надежно? (Китай долго не проработает…)

Ардуино (в том числе китайские версии) прошли в массах не одну проверку температурой, влажностью и временем. Лично на моем опыте собранные устройства функционируют по сей день в течение 3 лет. Что называется, слепил — и забыл.

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

А главный плюс — любое устройство в любой момент можно свободно развивать по функционалу в зависимости от приходящих в голову идей — бесценен!

Arduino

Сразу же в примерах был найден кусок, который позволял управлять средней мощностью, имея двоичное управление — вкл и выкл. Смысл простой, берём некое окно времени, скажем, 1 минута, и в цикле включаем либо выключаем нагрузку в зависимости от пройденного времени. То есть, если нам надо 50% мощности, то включаем нагрузку в первые 30 сек и выключаем в последние 30, затем цикл повторяется. Быстренько переделал это под 3 независимых реле, если мощность больше 33%, то включаю второе реле, если больше 66% — то третье, а первое включаю и выключаю по основному алгоритму. Теперь встаёт главный вопрос, а по какому алгоритму подбирать мощность? Будучи программистом по профессии сначала решил, что задачка довольно простая, холодно — добавляй, тепло — отбавляй, и попытался прикинуть всё это в уме.

Оказалось, не так и просто. Полез смотреть, как это делают в продаваемых системах, оказалось, там всё либо максимально просто, как в утюге — +1C = выкл, -1 = вкл. Но тогда мы получаем почти 4C колебаний из-за инертности системы! Это слишком грубо, ибо мы можем получать данные с точностью до десятой доли градуса. Также посмотрел алгоритмы работы с использованием температуры уличного воздуха, они оказались достаточно простые и работали на готовых таблицах, которые были заранее зашиты и просто менялись в зависимости от теплопотерь дома. Копая глубже и глубже, я докопался до промышленных установок, в них повсеместно использовали алгоритмы PID-регуляторов. И, о слава популярности, оказывается, у Arduino есть бесплатная PID-библиотека!

Пару слов о том, что такое PID применительно к нашему случаю. Смысл алгоритма в том, что мы сообщаем ему требуемое значение некоторого параметра (температура внутри дома) и в цикле передаём текущее значение, а он выдаёт нам необходимое воздействие (мощность, которую надо подать на котёл). Не вдаваясь в подробности математической модели, как же он работает с точки зрения программиста. Итак, мы имеем температуру в комнате, пусть 20C, желательную температуру 22С, и даём их нашему PID-алгоритму.

Сам алгоритм имеет 3 независимые части, по имени P, I и D. Первая часть работает крайне просто, смотрит на разницу между желательной температурой и текущей температурами. То есть чем холоднее, тем большую мощность нам даст алгоритм. Вроде бы, этого и достаточно, но ведь у нас есть постоянные теплопотери дома, то есть, чтобы держать нужную температуру, нам надо постоянно давать какую-то мощность. То есть даже если температура в комнате равна заданной, нельзя отключать котёл, а надо как-то искать какую-то мощность, равную теплопотерям. А теплопотери меняются в зависимости от температуры на улице. Вот этим и занимается вторая часть под именем I. Алгоритм пытается подобрать мощность, при которой наша температура будет постоянной. И вроде тут-то уже точно всё, но нет.

Дело в том, что сам котёл, теплоноситель, а тем более дом имеют очень большую инертность. И если вы врубили котёл на 100%, то снижать мощность нужно куда раньше, чем температура достигнет желательной, иначе даже при полном отключении мы всё равно успеем перегреть комнату градуса на 2. То же самое при понижении температуры, добавлять мощность надо ещё до того, как температура дошла до нужной. Вот этим и занимается третья часть алгоритма D. Ну теперь, конечно, всё, осталось только понять, какой части давать какой вес, а вот этим занимаются множители каждой части, которые и надо подбирать. Кстати, подбор этих множителей — отдельная и довольно сложная математическая задача, я подбирал их “на глаз”, вспоминая сказанное выше. Сначала ставил все нули, кроме P, и подбирал его так, чтобы не началось само возбуждение. Потом добавлял I, а в конце и D.

Темная тема для Arduino IDE

Очень многих раздражает простенькое оформление Arduino IDE в корпоративных цветах Arduino. Все такое белое и «слепое». Долго работать в таком цветовом решении не всегда комфортно, особенно если это ночь, вокруг темно и все спят.

Вариант темной темы под Mac. Скриншот с GitHub.

Для такого случая сторонний разработчик разработал так называемую темную тему, тему которая позволяет вернуть знакомый с детства вариант черного фона и светлого текста на нем. Тема не идеальна, так как не позволяет полностью настроить все нюансы, но ограничение это связано не с самой темой, а с ограничениями Arduino IDE. Тему, при желании, можно подредактировать самостоятельно.

Как настроить Ардуино?

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

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

  • Как уберечь Arduino и другие платы от кривых рук
  • 10 способов «убить» микроконтроллер Arduino

Алгоритм классической настройки программы Arduino выглядит так:

  • установка IDE, которую можно загрузить ниже или здесь или с сайта производителя;
  • установка программного обеспечения на используемый ПК;
  • запуск файла Arduino;
  • вписывание в окно кода разработанную программу и перенос ее на плату (используется USB кабель);
  • в разделе IDE необходимо выбрать тип конструктора, который будет использоваться. Сделать это можно в окне «инструменты» — «платы»;
  • проверяете код и жмете «Дальше», после чего начнется загрузка в Arduino.
1.8.7Код на Github
1.8.6Код на Github
1.8.5Код на Github
1.8.4Код на Github
1.8.3Код на Github
1.8.2Код на Github
1.8.1Код на Github
1.8.0Код на Github
1.6.13Код на Github
1.6.12Код на Github
1.6.11Код на Github
1.6.10Код на Github
1.6.9Код на Github
1.6.8Код на Github
1.6.7Код на Github
1.6.6Код на Github
1.6.5Код на Github
1.6.4Код на Github
1.6.3Код на Github
1.6.2Код на Github
1.6.1Код на Github
1.6.0Код на Github
1.5.8 BETAКод на Github
1.5.7 BETAКод на Github
1.5.6-r2 BETAКод на Github
1.5.5 BETAКод на Github
1.5.4 BETAКод на Github
1.5.3 BETAКод на Github
1.5.2 BETAКод на Github
1.5.1 BETAКод на Github
1.5 BETAКод на Github

Начало

Создание проекта на Arduino состоит из 3 главных этапов: написание кода, прототипирование (макетирование) и прошивка. Для того, чтоб написать код а потом прошить плату нам необходима среда разработки. На самом деле их есть немало, но мы будем программировать в оригинальной среде – Arduino IDE. Сам код будем писать на С++, адаптированным под Arduino. Скачать можно на официальном сайте. Скетч (набросок) – программа, написанная на Arduino. Давайте посмотрим на структуру кода:

Важно заметить, что обязательную в С++ функцию процессор Arduino создаёт сам. И результатом того, что видит программист есть:. Давайте разберёмся с двумя обязательными функциями

Функция вызывается только один раз при старте микроконтроллера. Именно она выставляет все базовые настройки. Функция — циклическая. Она вызывается в бесконечном цикле на протяжении всего времени работы микроконтроллера

Давайте разберёмся с двумя обязательными функциями. Функция вызывается только один раз при старте микроконтроллера. Именно она выставляет все базовые настройки. Функция — циклическая. Она вызывается в бесконечном цикле на протяжении всего времени работы микроконтроллера.

Работа схемы

Схема устройства представлена на следующем рисунке.

Первым делом необходимо соединить модуль ESP8266 с платой Arduino. Модуль ESP8266 работает с напряжением 3.3V, поэтому его нежелательно подсоединять к 5V платы Arduino поскольку это может повредить его. Соедините контакты VCC и CH_PD модуля с контактом 3.3V платы Arduino. Контакт RX модуля ESP8266 работает с напряжением 3.3V, поэтому он не будет работать правильно, если мы подсоединим его непосредственно к плате Arduino. Поэтому нам необходимо сделать делитель напряжения, который будет конвертировать 5V в 3.3V. Это можно сделать с помощью последовательного соединения трех резисторов как показано на схеме. Соедините контакт TX модуля ESP8266 с контактом 4 платы Arduino, а контакт RX модуля ESP8266 — с контактом 5 платы Arduino при помощи резисторов.

Wi-Fi модуль ESP8266 обеспечивает нашему проекту доступ в сеть интернет. Он является весьма дешевым, но в тоже время достаточно «мощным» устройством и может подсоединяться к большинству известных микроконтроллеров, поэтому он так часто используется в проектах, связанных с интернетом вещей (IOT).

Затем соединим сервомотор с платой Arduino. Соедините контакты VCC и землю сервомотора к контактам 5V и земле платы Arduino, а сигнальный контакт сервомотора – к контакту 9 платы Arduino.

Внешний вид используемого нами сервомотора показан на следующем рисунке.

Загрузка скетча и тестирование

Сохраните скетч как arduino_uart_tutorial.ino. Оставшийся шаг — загрузить эскиз на обе платы Arduino Uno. Пожалуйста, не забудьте отсоединить провода, подключенные к контактам TX0 и RX0, перед загрузкой эскиза. После успешной загрузки переподключите провода к контактам TX0 и RX0.

Работа схемы

Схема устройства представлена на следующем рисунке.

Примечание: чтобы видеть ответы модуля ESP8266 на поступающие команды откройте монитор последовательного порта (Serial Monitor) в программной среде Arduino IDE.

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

1. Сначала нам необходимо произвести тест Wi-Fi модуля при помощи передачи ему AT команды, он должен ответить OK.

2. После этого мы должны выбрать необходимый режим работы с помощью команды AT+CWMODE=mode_id , мы будем использовать Mode id =3. Полный же список доступных режимов выглядит следующим образом:
1 = Station mode (client) (режим станции, клиента)
2 = AP mode (host) (режим базовой станции, хоста)
3 = AP + Station mode (Yes, ESP8266 has a dual mode!) (режим станции + хоста – модуль ESP8266 поддерживает этот двойной режим).

3. Затем мы должны отсоединить наш Wi-Fi модуль от прежней Wi-Fi сети с помощью команды AT+CWQAP поскольку модуль ESP8266 по умолчанию автоматически соединяется с предыдущей использованной сетью Wi-Fi.

4. После этого можно сбросить модуль командой AT+RST – это необязательный шаг.

5. После этого мы должны соединить модуль ESP8266 с Wi-Fi роутером с помощью команды:AT+CWJAP=”wifi_username”,”wifi_password”.

6. После этого мы должны получить IP адрес с помощью команды AT+CIFSR, которая вернет нам IP адрес.

7. После этого нам необходимо задействовать режим мультиплексирования с помощью команды AT+CIPMUX=1 (1 для соединения с мультиплексированием и 0 для одиночного соединения).

8. Теперь сконфигурируем ESP8266 как сервер с помощью команды AT+CIPSERVER=1,port_no (port может быть 80). Теперь наш Wi-Fi готов. В представленной команде ‘1’ используется для создания сервера и ‘0’ для удаления сервера.

9. Теперь с помощью соответствующих команд можно передавать данные на созданный локальный сервер:AT+CIPSEND =id, length of data
Id = ID no. of transmit connection (номер соединения)
Length = Max length of data is 2 kb (максимальная длина данный 2 Кбайта).

10. После передачи ID (номера, идентификатора) и Length (длины данных) на сервер мы можем передавать данные, к примеру: Serial.println(“circuitdigest@gmail.com”);

11. После передачи данных нам необходимо закрыть соединение с помощью команды:AT+CIPCLOSE=0
После этого данные будет переданы на локальный сервер.

12. Теперь вы можете набрать IP адрес в строке адреса вашего браузера и нажать Enter. После этого вы увидите переданные данные на веб-странице.

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

Как будет работать наш проект

Чтобы запустить наш проект вам необходимо сделать HTML файл, который будет открывать веб-страницу. Для этого вам необходимо будет скопировать HTML код, приведенный ниже в данной статье и сохранить его в блокнот. Расширение у созданного файла должно быть ‘.html’. То есть, к примеру, если вы хотите назвать файл ‘servo’, то полностью имя файла будет ‘servo.html’, чтобы его легко можно было открыть в веб-браузере.

Теперь откройте скачанный html файл в веб-браузере, вы должны увидеть примерно следующую картинку:

После этого вставьте код программы для Arduino (приведен в конце статьи) в Arduino IDE, измените в этом коде имя пользователя и пароль для сети Wi-Fi на свои данные и загрузите программу в плату Arduino. В последовательном мониторе (Serial Monitor) вы можете увидеть IP адрес. Напечатайте этот IP адрес в поле на веб-странице. Теперь если вы будете двигать слайдер на представленной веб-странице, то сервомотор будет двигаться в соответствии с положением ползунка слайдера. Таким образом, вы можете управлять сервомотором с веб-страницы.

Принцип действия

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

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

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

Вместо трансформатора в последнее время все шире стали применяться импульсные источники питания. Они позволяют в несколько раз снизить вес и габариты блока при той же производительности.

Скетч

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

Просто помните, что в интернете часто встречается именно слово скетч в отношении работы с платами типа Ардуино.

Почему дроны и вертолеты используют именно BLDC двигатели?

Сейчас существует множество различных типов дронов – с двумя лопастями, с четырьмя лопастями и т.д. Но все они используют именно BLDC двигатели. Почему именно их, ведь BLDC двигатели стоят дороже чем обычные электродвигатели постоянного тока?

Существует несколько причин для этого:

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

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

Рейтинг автора
5
Материал подготовил
Максим Иванов
Наш эксперт
Написано статей
129
Ссылка на основную публикацию
Похожие публикации