Arduino циклы. Циклы в Arduino: полное руководство по использованию for, while и do-while

Как работают циклы for, while и do-while в Arduino. Какие виды циклов существуют и в чем их отличия. Как правильно использовать циклы в скетчах Arduino и избежать типичных ошибок.

Что такое циклы в Arduino и зачем они нужны

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

Основные задачи, для которых используются циклы в Arduino:

  • Повторение однотипных действий заданное количество раз
  • Выполнение операций до наступления определенного условия
  • Обработка массивов данных
  • Опрос датчиков и устройств через равные промежутки времени
  • Генерация сигналов и управление исполнительными устройствами

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


Основные виды циклов в Arduino

В Arduino используются три основных вида циклов:

1. Цикл for

Цикл for используется, когда заранее известно точное количество повторений. Он имеет следующий синтаксис:

for (инициализация; условие; изменение счетчика) {
  // Тело цикла
}

2. Цикл while

Цикл while выполняется, пока истинно заданное условие. Синтаксис:

while (условие) {
  // Тело цикла  
}

3. Цикл do-while

Цикл do-while похож на while, но гарантирует как минимум одно выполнение тела цикла:

do {
  // Тело цикла
} while (условие);

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

Цикл for в Arduino: особенности и применение

Цикл for в Arduino используется, когда точно известно количество повторений. Он состоит из трех частей:

  • Инициализация — выполняется один раз в начале
  • Условие — проверяется перед каждой итерацией
  • Изменение счетчика — выполняется после каждой итерации

Пример использования for для мигания светодиодом:

for (int i = 0; i < 5; i++) {
  digitalWrite(LED_PIN, HIGH);
  delay(500);
  digitalWrite(LED_PIN, LOW); 
  delay(500);
}

Здесь светодиод мигнет 5 раз. Цикл for удобен, когда нужно выполнить действие определенное число раз.


Цикл while в Arduino: когда и как применять

Цикл while в Arduino используется, когда неизвестно точное количество повторений, но есть условие для завершения цикла. Он продолжает выполняться, пока условие истинно.

Пример использования while для ожидания нажатия кнопки:

int buttonPin = 2;
while (digitalRead(buttonPin) == LOW) {
  // Ждем, пока кнопка не будет нажата
}

Цикл while эффективен, когда нужно выполнять действия до наступления определенного события или состояния.

Особенности цикла do-while в Arduino

Цикл do-while в Arduino гарантирует, что тело цикла будет выполнено как минимум один раз, даже если условие изначально ложно. Проверка условия происходит в конце каждой итерации.

Пример использования do-while для ввода данных:

int input;
do {
  input = Serial.parseInt();
} while (input <= 0);

Этот цикл будет запрашивать ввод, пока не будет введено положительное число. Do-while полезен, когда нужно гарантировать хотя бы одно выполнение операции.

Вложенные циклы в Arduino: возможности и ограничения

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


Пример вложенных циклов для управления матрицей светодиодов:

for (int row = 0; row < 8; row++) {
  for (int col = 0; col < 8; col++) {
    setLED(row, col, HIGH);
    delay(100);
    setLED(row, col, LOW);
  }
}

Этот код последовательно включает и выключает светодиоды в матрице 8x8. Вложенные циклы эффективны для работы с двумерными массивами и создания сложных паттернов.

Оптимизация циклов в Arduino для экономии ресурсов

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

  • Используйте цикл for вместо while, если известно число итераций
  • Выносите неизменяемые вычисления за пределы цикла
  • Используйте инкремент (++) вместо i = i + 1
  • Избегайте использования функций типа millis() внутри циклов
  • Для коротких циклов используйте цикл развертывания

Пример оптимизированного цикла:

const int iterations = 100;
const int delayTime = 10;

for (int i = 0; i < iterations; i++) {
  digitalWrite(LED_PIN, HIGH);
  delayMicroseconds(delayTime);
  digitalWrite(LED_PIN, LOW);
  delayMicroseconds(delayTime);
}

Здесь константы вынесены за пределы цикла, что уменьшает количество вычислений при каждой итерации.


Типичные ошибки при использовании циклов в Arduino

При работе с циклами в Arduino часто встречаются следующие ошибки:

  1. Бесконечные циклы из-за неправильного условия завершения
  2. Выход за границы массива при использовании индексов в циклах
  3. Неправильное изменение переменной цикла внутри тела цикла
  4. Использование delay() внутри циклов, что может привести к зависанию программы
  5. Чрезмерное использование вложенных циклов, усложняющее код

Пример кода с типичной ошибкой:

int array[5] = {1, 2, 3, 4, 5};
for (int i = 0; i <= 5; i++) {  // Ошибка: выход за границы массива
  Serial.println(array[i]);
}

Здесь цикл выполнится 6 раз, что приведет к чтению за пределами массива. Правильное условие должно быть i < 5.


While ардуино

В статье рассмотрены основы передачи данных Arduino на персональный компьютер и в обратном направлении с использованием LabView. Вам помогут навыки программирования на Arduino и создания блок-диаграм виртуальных инструментов ВИ в LabView, но даже если вы ни разу не работали в LabView или Arduino IDE, интсрукция достаточно подробная и ее должно хватить. Если вы захотите более детально ознакомиться с принципом действия сенсора LM35, рекомендую почитать его даташит. Наибольшее применение LabView нашел в сферах получение данных с измерительных приборов основная идея примера в этой статье , управления, промышленной автоматизации. Arduino - это open-source платформа, которая обеспечивает разработку интерактивных проектов.


Поиск данных по Вашему запросу:

Схемы, справочники, даташиты:

Прайс-листы, цены:

Обсуждения, статьи, мануалы:

Дождитесь окончания поиска во всех базах.

По завершению появится ссылка для доступа к найденным материалам.

Содержание:

  • Циклы FOR и WHILE в Arduino
  • While & Serial
  • Arduino циклы
  • «Робототехника на платформе Arduino»
  • 2 millis() в while [решено]
  • Основные операторы – Операторы цикла for while

ПОСМОТРИТЕ ВИДЕО ПО ТЕМЕ: Arduino Radar Project

Циклы FOR и WHILE в Arduino


Отправить комментарий. Прерывания в Ардуино. Часть 1.

Что такое прерывание Внешние прерывания attachInterrupt volatile Функции interrupts и noInterrupts Атомарно исполняемые блоки кода detachInterrupt Дребезг контактов Использование прерываний для выхода из спящего режима Запрос прерывания во время выполнения обработчика Общие рекомендации по написанию обработчиков прерываний. Функция имеет следующий синтаксис:. Данные функции служат для разрешения и запрета обработки прерываний соответственно.

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

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

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

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

Данной теме посвящены несколько моих публикаций, ссылки на них ниже:. Устранение дребезга контактов. Часть 1 - триггер Шмитта Устранение дребезга контактов. Часть 2 - микросхема MC Устранение дребезга контактов.

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

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

Ярлыки: ардуино , дребезг контактов , прерывания , atmegap Возможно, Вам будет интересно:. Комментариев нет:. Следующее Предыдущее Главная страница. Подписаться на: Комментарии к сообщению Atom.


While & Serial

Например, превышает ли входное значение заданное число. Формат оператора if следующий:. Иначе говоря, если выражение в круглых скобках истинно, выполняются операторы внутри фигурных скобок. В противном случае, фрагмент в фигурных скобках будет пропущен.

Подключаем Arduino к LabView и снимаем показания с датчика Вы можете разместить VISA Configure Serial Port внутри структуры while loop.

Arduino циклы

Отправить комментарий. Прерывания в Ардуино. Часть 1. Что такое прерывание Внешние прерывания attachInterrupt volatile Функции interrupts и noInterrupts Атомарно исполняемые блоки кода detachInterrupt Дребезг контактов Использование прерываний для выхода из спящего режима Запрос прерывания во время выполнения обработчика Общие рекомендации по написанию обработчиков прерываний. Функция имеет следующий синтаксис:. Данные функции служат для разрешения и запрета обработки прерываний соответственно. Они могут быть полезны при обращении к переменной, значение которой изменяется обработчиком прерывания описанная выше ситуация. Или если код чувствителен к времени выполнения и потому должен выполняться без прерываний.

«Робототехника на платформе Arduino»

Они встречаются абсолютно в каждом скечте, даже если вы не подозреваете об этом. В этой статье мы познакомимся поближе с циклами, узнаем, в чем отличие for от while, как можно упростить написание программы с их помощью и каких ошибок следует избегать. Если вы пока еще начинающий программист и хотите понять, что вообще такое цикл и зачем он нужен — посмотрите следующий раздел этой статьи с подробным описанием. По сравнению с FOR цикл WHILE выглядит проще, он обычно используется там, где нам не нужен подсчет числа итераций в переменной, а просто требуется повторять код, пока что-то не изменится, не наступит какие-то событие. В качестве условий может использоваться любая конструкция языка, возвращающая логическое значение.

Войти или зарегистрироваться.

2 millis() в while [решено]

Вводный раздел. Микроконтроллеры в нашей жизни сообщения учеников , контролер Ардуино сообщение учеников , структура и состав Ардуино. Среда программирования для Ардуино. Основы проектирования и моделирования электронного устройства на базе Ардуино Управление электричеством. Законы электричества. Как быстро строить схемы: макетная доска breadboard.

Основные операторы – Операторы цикла for while

Войти или зарегистрироваться. Искать только в заголовках Сообщения пользователя: Имена участников разделяйте запятой. Новее чем: Искать только в этой теме Искать только в этом разделе Отображать результаты в виде тем. Быстрый поиск. Всем привет.

Циклы for, while и do while в Arduino. Рассмотрим, как работают циклы в Ардуино, как правильно использовать операторы в скетчах и каких ошибок.

Григорий : Работа с часами реального времени DS с кирилицей разоб Arduino циклы Дата: 23 Апреля Автор: Алексей Сегодня будем изучать не менее важную часть языка программирования, как циклы. Зачем они нужны.

Циклы for, while и do while в Arduino. Рассмотрим, как работают циклы в Ардуино, как правильно использовать операторы в скетчах и каких ошибок избегать. Рассмотрим, как работают операторы циклов for, while и do while в Arduino IDE, как правильно использовать циклы в скетчах и каких ошибок следует избегать. На простых примерах продемонстрируем, как можно остановить цикл или перейти из одного цикла в другой. Для того, чтобы разобраться в правильности написания циклов, прежде всего, следует изучить виды и свойства алгоритмов в робототехнике. Ни одна программа для микроконтроллера Ардуино не обходится без цикла, например, void loop вызывается в бесконечном цикле.

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

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

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


Циклы в языке программирования С (Си) для микроконтроллеров AVR

В данной статье будут рассмотрены циклы в языке программирования Си для микроконтроллеров AVR. Будут рассмотрены циклы типа "для" (for) и циклы типа "пока" (while), будет показано как осуществить принудительное прерывание цикла и организовать бесконечный цикл. Рассмотрены вопросы вложенных циклов и формирования длительных временных задержек.

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

В языке С есть две разновидности циклов: циклы со счетчиком (типа "для" или for) и цикл с условием (типа "пока" или while). В других языках программирования, например Pascal, циклы с условием разделялись на циклы с предусловием (типа while) и циклы с пост условием (типа repeat until), но в современных языках программирования циклы с пост условием постепенно отмирают.

Циклы типа "для" (for)

Циклы типа "для" (for) применяются в ситуациях, в которых заранее известно количество повторений цикла. Поэтому в составе подобного цикла всегда есть так называемый "счетчик повторений" или "переменная цикла". Пример использования цикла for в языке представлен на следующем рисунке.

В данном примере тело цикла повторится столько раз, сколько значений "пробежит" переменная цикла i от своего начального значения, задаваемого операцией присваивания i = a, до конечного значения, задаваемого условием i < b. Изменение переменной i определяется условием присваивания вида i = i + c. Но чаще всего в циклах типа for в языке С переменная цикла изменяется за одно повторение цикла на +1 или -1, поэтому используется запись вида i++ (инкремент переменной цикла) или i-- (декремент переменной цикла). В рассмотренном примере при i = b цикл завершается и выполняется оператор, следующий за закрывающей скобкой цикла.

Рассмотрим пример цикла for, приведенный на следующем рисунке.

В этом примере на первом шаге цикла переменная i будет равна 1, перед вторым шагом произойдет ее увеличение на 1 в результате инкремента (i++) и она станет равной 2. На третьем шаге значение переменной цикла i будет равно 3. И так до тех пор, пока на пятом шаге цикла она не станет равной 5. В результате следующей операции инкрементирования (i++) переменная цикла получит значение 6, но условие i <= 5 уже не будет истинным, поэтому цикл завершится. Таким образом, тело цикла будет выполнено 5 раз.

Язык С допускает инициализацию переменной цикла в его оглавлении как показано на следующем рисунке.

Но начинающим лучше производить инициализацию переменной цикла в начале функции вместе с остальными инициализируемыми переменными – более подробно читайте об этом в статье про переменные в языке С.

Усовершенствуем программу управления миганием светодиода, рассмотренную в статье про программирование портов микроконтроллеров AVR, с помощью цикла типа "для" (for). Заставим светодиод мигать 10 раз.

Пример подобной программы представлен на следующем рисунке.

Циклы типа "пока" (while)

Цикл типа while ("пока") повторяется до тех пор, пока истинно условие цикла. Поэтому часто его называют циклом с условием. В простейшем виде запись данного цикла выглядит следующим образом:

while (условие)
{
// тело_цикла
}

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

Чтобы цикл завершился, внутри него (в его теле) должно происходить изменение какой-либо переменной, которая входит в условие цикла.

Пример:

int y;

y = 50;

while (y > 0)
{
y = y - 1;
}

В этом примере тело цикла будет повторено (выполнится) 50 раз, до тех пор пока переменная y будет больше нуля. На каждом шаге цикла значение переменной y будет уменьшаться на 1. И когда оно станет равным 0, цикл завершится.

Оператор break

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

В большинстве случаев он используется следующим образом:

if (условие1) break;

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

Бесконечные циклы

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

for(;;)
{
// тело_цикла
}

или

while (1)
{
// тело_цикла
}

Чаще применяется способ с циклом типа while – он более нагляден. Выйти из подобных циклов можно единственным образом – применив рассмотренный в предыдущем разделе оператор break.

Бесконечные циклы находят широкое распространение в программах для микроконтроллеров, потому что данные программы должны, как правило, работать постоянно до тех пор, пока устройство не обесточат. Много примеров подобных программ вы можете найти на нашем сайте в рубрике "схемы и устройства на микроконтроллерах AVR".

Вложенные циклы

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

Рассмотрим пример двух вложенных друг в друга циклов "для". Тело вложенного цикла в общей сложности будет повторено 200 раз.

В этом примере тело вложенного цикла будет выполнено 200 раз.

Формирование задержки

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

циклов Arduino добавляют тактов, почему?

Простая история:

В данном случае примеры 2 и 3 совпадают (и обычно компилятор оптимизирует код и удаляет бесполезные инструкции). В этих примерах всего 2 инструкции:

  1. PORTB |= 0b00010000;
  2. ПОРТБ &= 0b11101111;

Заключение для тех примеров код меняет только значение порта

Например 1 у вас есть 5 инструкций (1 раз за и 4 за каждую итерацию):

  1. int i = 0 (один раз для)
  2. я < 4
  3. ПОРТБ |= 0b00010000;
  4. ПОРТБ &= 0b11101111;
  5. я++

Заключение для этого примера код изменяет значение порта и обрабатывает индекс for

Чтобы понять, почему вы должны изучить, что делает компилятор и как работает процессор. Вот код сборки для ваших примеров

Пример 1

 PORTB:
        .ноль 4
петля():
        толчок рбп
        мов рбп, рсп
        mov DWORD PTR [rbp-4], 0
.L3:
        cmp DWORD PTR [rbp-4], 3
        jg .L4
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239mov DWORD PTR PORTB[rip], eax
        добавить DWORD PTR [rbp-4], 1
        джмп . l3
.L4:
        нет
        поп рбп
        рет
 

Пример 2

 ПОРТB:
        .ноль 4
петля():
        толчок рбп
        мов рбп, рсп
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        нет
        поп рбп
        рет
 

Пример 3

 ПОРТB:
        .ноль 4
петля():
        толчок рбп
        мов рбп, рсп
. L2:
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        или еакс, 16
        mov DWORD PTR PORTB[rip], eax
        mov eax, DWORD PTR PORTB[rip]
        и акс, 239
        mov DWORD PTR PORTB[rip], eax
        JMP .L2
 

воспоминаний Arduino | Воспоминания об Arduino

Сохранить Подписаться

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

После входа в систему вы будете перенаправлены обратно к этому руководству и сможете подписаться на него.

В Arduino есть 3 типа памяти:

  • Флэш-память или память программ
  • ОЗУ
  • ЭСППЗУ

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

Флэш-память — это та же технология, что и для флэш-накопителей и SD-карт. Он энергонезависим, поэтому ваша программа останется там, когда система будет выключена.

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

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

  • Статические данные — это блок зарезервированного пространства в SRAM для всех глобальных и статических переменных вашей программы. Для переменных с начальными значениями система выполнения копирует начальное значение из Flash при запуске программы.
  • Куча — Куча предназначена для динамически выделяемых элементов данных. Куча растет от вершины области статических данных вверх по мере выделения элементов данных.
  • Стек — Стек для локальных переменных и для ведения записи прерываний и вызовов функций. Стек растет от вершины памяти вниз к куче. Каждое прерывание, вызов функции и/или выделение локальной переменной вызывают рост стека. Возврат из прерывания или вызова функции вернет все пространство стека, используемое этим прерыванием или функцией.

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

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *