Домофон, который знает, как вас зовут — своими руками

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

Вы кто такие? Я вас не звал! Пошли на х...

Вступление

Мне всегда было интересно изучать системы автоматизации домофонов. Казалось бы, в них уже внедрено все возможное: видеозапись, связь с владельцем через мобильный телефон, управление открытием дверей с помощью голосового ассистента. Но что это? Звук зуммера, который изобрели еще в 1831 году? Мы живем в эпоху передовых технологий, а здесь такой простецкий звуковой сигнал. Я решил избавиться от этого устаревшего элемента и заменить его на более приятное для слуха голосовое сопровождение. В этой статье речь пойдет не о самом домофоне, а о его важной составляющей - системе контроля доступа (СКУД), а точнее - бесконтактном считывателе меток для открытия дверей. Я пошел дальше и добавил несколько функций, которые сделают эту систему немного современной.

Видео

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

Схема

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

  • Режим контроля доступа: считывание меток и открывание дверей

  • Мастер-режим для добавления новых ключей

  • Режим сброса ключей

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

Мой светодиод имеет общий анод, поэтому в коде он включается сигналом "LOW".

Питание 12 В для устройства берется с вызывной панели домофона и подключается через понижающий преобразователь, на выходе которого напряжение равно 5 В. Открытие двери происходит стандартным для домофона способом - замыканием линии "Audio" с "+12V". В схеме для этого предусмотрен оптрон, при подключении которого важно соблюдать полярность.

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

схема

Необходимые компоненты

RFID RC522

В данном проекте используется наиболее распространенный модуль бесконтактной идентификации RFID Mifare RC522. Это устройство предназначено для бесконтактного считывания RFID меток. Считыватель MFRC-522 работает на частоте 13.56 МГц. Для подключения к ардуино буду использовать SPI интерфейс, так как он надежнее чем UART и I2C. Поддерживаемые считывателем типы карт: MIFARE S50, MIFARE S70, MIFARE UltraLight, MIFARE Pro, MIFARE DESfire.

Питание для модуля беру с 3,3В пина ардуино. Это питание идет от микросхемы CH340, которая имеет встроенный преобразователь. Однако, максимальный ток составляет всего 80 мА. Алекс Гайвер в своем блоге отмечал, что с таким питанием считыватель работает нестабильно. Вероятно, проблема заключается в недостаточном пиковом токе. Он также включил максимальное усиление для большего радиуса действия передатчика, что тоже увеличило потребление. Кроме того, ни на ардуино, ни на модуле RC-522. В цепи питания нет электролитических конденсаторов которые бы могли компенсировать все пиковые токи, которые, как я понимаю, и вызывают зависание модуля. Я сразу подключил в эту цепь конденсатор на 47 мкФ, и все работает без сбоев. Тестировал модуль в течение недели, никаких зависаний не замечено. Но так как для СКУД важна надежность и безотказность, я все равно использую идею Гайвера, в коде которого периодически сбрасывается модуль RFID.

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

RFID

MP3 проигрыватель

DFPlayer - это компактный, но многофункциональный модуль звука, способный читать звуковые файлы с TF или микро SD карт и воспроизводить их через встроенный усилитель на динамике. Управление Arduino MP3 плеером можно осуществлять автономно, подключив к его выводам кнопки. Кроме того, MP3 модулем можно управлять через интерфейс UART, подключив его к Ардуино или другому микроконтроллеру. DFPlayer выпускается на различных чипах, я насчитал 5 модификаций. В этом проекте используется плеер на микросхеме MH2024K-24SS.

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

DFPlayer

Борьба с цифровыми шумами

Во время паузы между воспроизведением треков в динамике ясно слышны цифровые шумы, создаваемые встроенным в плеер контроллером. Фильтрация питания с помощью LC-фильтров и установка линейного стабилизатора почти не помогли. Так как в плеере нет отдельного питания для усилителя и ЦАП, то эту проблему невозможно решить аппаратным способом. Вероятно, между внутренним контроллером, ЦАП и УНЧ нет встроенных LC или RC фильтров питания. А если они есть, то они не справляются со своей задачей.

Я нашел способ решить эту проблему программно. Для этого я написал отдельную функцию воспроизведения треков. Как работает эта функция? После воспроизведения трека я уменьшаю громкость до нуля, а перед воспроизведением она восстанавливается до уровня, заданного пользователем. Этот трюк существенно помог решить проблему, но в звуковой тракт в паузах все равно оставался слабый жужжащий звук. Эту проблему мне помог решить мой знакомый, ардуино-энтузиаст Герман. Он выяснил, что это жужжание исходит от UART и чтобы от него избавиться, достаточно было перепрограммировать порт TX Ардуино с выхода на вход, при этом подтянув его внутренним сопротивлением к плюсу питания.

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

Код этой функции выглядит следующим образом:

void mp3play(uint16_t track, uint16_t time)

{

pinMode(TX, OUTPUT); // восстанавливаем выход TX

mp3_play(track); // проиграть трек

mp3_set_volume (volume); //восстанавливаем громкость

delay(time); // длительность проигрывания трека

mp3_set_volume (0); // выключаем звук, уменьшаем цифровой шум

pinMode(TX, INPUT_PULLUP); // Отключаем TX убираем жужжание

}

Проблема со статусом Busy

Для отслеживания в DFPlayer статуса проигрывания трека, я сначала использовал сигнал BUSY, но он оказался непредсказуемым. В зависимости от различных факторов, после завершения воспроизведения трека на этом выводе может не появиться ожидаемая логическая единица, и плеер уходит в зависание, так как для ожидания завершения воспроизведения используется цикл while (!digitalRead(BUSY_PIN)). По этой причине для ожидания завершения проигрывания трека пришлось использовать delay().

Проблема неполного воспроизведения

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

Динамик

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

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

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

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

Динамики

Создание аудиофайлов

Я считаю наиболее подходящим TTS для создания озвучки голос Яндекс Алисы, хотя это мое субъективное мнение. Для записи фраз от Алисы я использовал колонку Яндекс Станция Мини-2, которая обладает разъемом линейного аудио выхода. Это позволяет записывать любую звуковую информацию с этой колонки. Для этого достаточно подключить аудиовыход от Яндекс.станции к линейному входу звуковой карты с помощью аудиокабеля.

Для создания голосовых фраз я использовал программу Audacity. Чтобы заставить колонку произносить нужные фразы, нужно в мессенджере Telegram добавить бота Алиса (alice_speaker_bot). Затем, в меню бота выбираем пункт "сказать колонкой что-нибудь" и отправляем ему сообщение с подготовленным текстом, который Алиса произнесет.

Для того чтобы фразы звучали как в научно-фантастических фильмах, в аудиоредакторе к звуковому файлу можно добавить эффект "Эхо". Настройки этого эффекта представлены на скриншоте ниже.

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

audacity

Корпус считывателя и его особенности

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

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

RFID

В корпусе отсутствует встроенная подсветка. Использование светодиода, светящего внутри коробки, не представляется возможным, поскольку свечение графического индикатора получается бледным и неравномерным. Кроме того, на этом месте должен быть установлен модуль RFID, и светодиод будет ему мешать. Поэтому я извлек подсветку из старого разбитого экрана от тестера LCR-T4, размер которой идеально подошел под мою задачу.

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

Подсветка

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

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

Так выглядит итоговый вариант

Сборка

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

Домофон, который знает, как вас зовут — своими руками Домофон, СКУД, Озвучка, Arduino, Своими руками, Электроника, Яндекс Алиса, Длиннопост

Внутренности в корпусе считывателя

Код для Ардуино

По скетчу особо нечего сказать. Весь код подробно закомментирован.

#include <avr/wdt.h>

#include <MFRC522.h>

#include <DFPlayer_Mini_Mp3.h>

#define BUSY_PIN 4 // Пин BUSY для MP3 пдеера

#define RST_PIN 9 // Пин RST для rfid модуля

#define SS_PIN 10 // Пин SS для rfid модуля

#define RX 2 // назначить пин RX SoftSerial

#define TX 3 // назначить пин TX SoftSerial

#define modeRes 11 // пин для сброса памяти ключей

#define look_PIN 5 // номер пина для подключения к нему реле открытия замка

#define blue_PIN 8

#define green_PIN 7

#define red_PIN 6

#define interval 2000 // интервал сброса RFID модуля в мкс

#define time_reset_mp3 600000 // интервал сброса MP3 плеера

#define volume 25 // громкость MP3 от 0 до 30

#define equalizer 0 // эквалайзер(POP=1) от 0 до 5 Normal/Pop/Rock/Jazz/Classic/Bass

#define sumName 7 // количество имен пользователей записанных на флешке начинаются с 0001.mp3, 0002.mp3 ... и т.д.

uint32_t rebootTimer=0, oldTime=0; // Переменная для таймера MFRC522 rfid(SS_PIN, RST_PIN); // Назначить пины SS и RST SoftwareSerial mySerial(RX, TX); // назначить пины RX, TX

SoftSerial

void setup()

{

// pinMode(look_PIN, OUTPUT); // пин для подключения реле открытия замка

// digitalWrite(look_PIN, LOW);

pinMode(red_PIN, OUTPUT);

pinMode(green_PIN, OUTPUT);

pinMode(blue_PIN, OUTPUT);

pinMode(modeRes, INPUT_PULLUP); // пин сброса памяти ключей mySerial.begin (9600); // Инициализация

Soft Serial mp3_set_serial (mySerial);

delay (1000);

mp3Reset(); // инициализация плеера

uint8_t memClear = digitalRead(modeRes); // проверяем состояние пина сброса памяти

if(!memClear) // Если установлена перемычка на GND и пин D11

{

digitalWrite (green_PIN, HIGH);

digitalWrite (red_PIN, HIGH);

eeprom_write_byte(0, 255); // то обнуляем счетчик ключей

mp3play (113, 13000); // память обнулена

while(true); // зависаем и ждем нажатия reset

}

SPI.begin(); // Инициализация

SPI firstStart(); // проверка наличия Мастер ключа и добавление его mp3play (109, 9500); // система активирована //

Serial.begin(115200); // Инициализация Serial //

wdt_enable(WDTO_8S); }

void loop()

{

digitalWrite (green_PIN, HIGH);

digitalWrite (red_PIN, HIGH);

digitalWrite (blue_PIN, HIGH);

uint8_t sumKey = eeprom_read_byte(0); // считываем из EEPROM с адреса 0 информацию о количестве сохраненных ключей

uint32_t master = ReadEEPROM_Long(1); // читаем из EEPROM uid мастер ключа

uint32_t uid_tmp = ReadUID(); // ждем когда приложат ключ к считывателю и Читаем UID ключа

//Serial.println(sumKey);

//Serial.println(master);

//Serial.println(uid_tmp);

if(uid_tmp == master)

{

digitalWrite (red_PIN, LOW);

digitalWrite (blue_PIN, LOW);

addKey(sumKey); // если к считывателю поднесли мастер ключ, то переходим в режим добавления новых ключей

}

if(sumKey>=0 && uid_tmp != master) // если в EEPROM больше 1 ключа и UID прочитан с RFID то сравниваем все имеющиеся в EEPROM ключи со считанным 1

{

uint8_t nameKey = searchKey(sumKey, uid_tmp); // считываем все ключи по очереди из EEPROM и сравниваем их с UID приложенного к считывателю ключа

if(nameKey > 0) // в nameKey номер(индекс) ключа

{

sumKey = eeprom_read_byte(nameKey*5); // читаем из EEPROM привязанное к uid имя пользователя //

digitalWrite (look_PIN, HIGH); // открываем замок

digitalWrite (green_PIN, LOW);

mp3play (106, 1480); // фраза "Здравствуйте"

mp3play (sumKey, 1200); // проигрываем привязанное имя пользователя к uid

mp3play (107, 5000); // фраза "Добро пожаловать"

//digitalWrite (look_PIN, LOW); // закрываем замок

} else {

digitalWrite (red_PIN, LOW);

mp3play(104, 6500); } // фраза "Доступ запрещен, Ключ не найден"

}

if (millis() - oldTime > time_reset_mp3) // интервал таймера для сброс плеера

{

oldTime = millis();

} }

//*********************************************

uint32_t ReadUID(void) // опрашиваем считыватель каждую 0,2сек

{ for (;;) // бесконечный цикл

{

ResetRFID(); // перезагружаем RFID модуль каждые 2 секунды delay(100);

if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) // Если метка найдена и она прочитана

{ return uidTolong(); // прервать цикл и возвратить UID

} } }

//-----------------------------------------

uint8_t searchKey( uint8_t sumKey, uint32_t uid ) // поиск ключа в EEPROM. sumKey-количество сохраненных ключей вEEPROM

{

for (uint8_t i = 1; i <= sumKey; i++)

{

uint32_t tmp=ReadEEPROM_Long(i*5+1); //читаем по очереди все сохраненные UID и сравниваем их с UID полученным c

RFID if(tmp == uid) { return i; } // сравниваем считанный из памяти UID с прочитанным UID и если найден, то возвращаем номер совпавшего ключа

}

return 0; // если в базе нет такого ключа то возвращаем 0

}

//---------------------------------------

void addKey(uint8_t sumKey) // sumKey-количество сохраненных ключей в EEPROM

{

mp3play(101, 15000); // для добавления нового UID после того как услышите имя которое нужно привязать к UID поднесите ключ к считывателю RFID

for (uint8_t i = 1; i <= sumName; i++) // перебираем все имена по очереди

{

mp3play(110, 1000); // проигрывание звука next

ResetRFID();

pinMode(TX, OUTPUT); // восстанавливаем выход для TX

mp3_play (i); // проигрываем в фоновом режиме в порядке возрастания все записанные на флешку имена

mp3_set_volume (volume); // устанавливаем заданную громкость

for (uint8_t ti = 0; ti < 20; ti++) // цикл таймер, 20*100мс=2 сек на опрос считывателя RFID пока проигрывается имя пользователя

{

if (rfid.PICC_IsNewCardPresent() && rfid.PICC_ReadCardSerial()) // Если определена метка и она прочитана

{ uint32_t uid = uidTolong(); // преобразуем uid из массива в ulong uint8_t dub = searchKey(sumKey, uid); // ищем в EEPROM совпадение, проверяем ключ на дубли

if(dub == 0) // если такого ключа нет в памяти то добавляем его { // или если ключ есть то в dub номер ключа

sumKey++; // инкрементируем счетчик ключей

eeprom_write_byte(0, sumKey); // счетчик ключей в EEPROM eeprom_write_byte(sumKey*5, i); // сохраняем в EEPROM привязанное к ключу имя

WriteEEPROM_Long (sumKey*5+1, uid); // сохраняем UID ключа в EEPROM delay(500); // для того,что бы имя проигралось до конца mp3play(103, 4500); // фраза "новый ключ сохранен" mp3play(112, 9000); // фраза "мастер режим завершен" return; } else { digitalWrite (blue_PIN, HIGH); delay(1000);

mp3play(111, 9000); // прочитанный ключ уже имеется в системе digitalWrite (red_PIN, HIGH);

mp3play(112, 9000); // фраза "мастер режим завершен" return; } } delay(100);

} }

mp3play(108, 9000); // Время ожидание ключа истекло.

}

//----------------------------------------

void firstStart(void) { uint8_t tmp = eeprom_read_byte(0); // проверяем записан ли мастер ключ в EEPROM if(tmp==255) // если его там нет, то нужно добавить { mp3play(100, 12500); // фраза добавить мастер ключ uint32_t uid_tmp = ReadUID(); // прочитать UID мастер ключа со считывателя RFID if( uid_tmp > 0 ) // если ключ прочитан то записываем его в EEPROM { eeprom_write_byte (0, 0); // по адресу 000 записываем счетчик ключей не более 51 шт.------------------ WriteEEPROM_Long (1, uid_tmp); // по адресу 001 может быть записан только мастер ключ mp3play(102, 3500); // фраза мастер ключ добавлен } } }

//----------------------------------------

void ResetRFID(void) // Таймер сброса RFID защита от зависания

{

if (millis() - rebootTimer > interval) // интервал таймера

{

rebootTimer = millis(); // Обновляем таймер

digitalWrite(RST_PIN, HIGH); // Сбрасываем модуль delayMicroseconds(100); // длительность сброса 100 мкс digitalWrite(RST_PIN, LOW); // Отпускаем сброс

rfid.PCD_Init(); // Инициализируем

RFID rfid.PCD_AntennaOn(); // Включаем антенну

} }

//---------------------------------------

void mp3Reset(void) // можно так же использовать как остановку трека { mp3_reset (); delay (1000);

// mp3_set_device(2); // 2-работа с SD Card. 1/2/3/4/5 U/SD/AUX/SLEEP/FLASH

// mp3_DAC (true); mp3_set_EQ (equalizer); // эквалайзер Normal/Pop/Rock/Jazz/Classic/Bass

delay (100);

mp3_set_volume (volume); // устанавливаем громкость

delay (200);

pinMode(TX, INPUT_PULLUP); // Отключаем TX, что бы в динамике исчез шум/наводка

}

//---------------------------------------

void mp3play(uint16_t track, uint16_t time)

{

pinMode(TX, OUTPUT); // восстанавливаем выход TX

mp3_play(track); // проиграть трек //

mp3_set_volume (volume); // устанавливаем заданную громкость //wdt_reset(); delay(time); // длительность проигрывания // mp3_set_volume (0); // выключаем звук, что бы не было шума в динамике

pinMode(TX, INPUT_PULLUP); // Отключаем TX, что бы в динамике исчез шум/наводка

}

//---------------------------------------

uint32_t uidTolong(void)

{

uint32_t uid_l

uid_l // преобразуем uid массив в тип uint32_t uid_l << 8) | rfid.uid.uidByte[2]); uid_l << 8) | rfid.uid.uidByte[1]);

return (uid_l << 8) | rfid.uid.uidByte[0])); //прервать цикл и передать UID

}

void WriteEEPROM_Long(uint8_t addr, uint32_t data) //преобразовать из long и сохранить в

EEPROM { eeprom_write_byte((uint8_t*)addr, data & 0xFF); eeprom_write_byte((uint8_t*)addr+1, (data & 0xFF00) >> 8); eeprom_write_byte((uint8_t*)addr+2, (data & 0xFF0000) >> 16); eeprom_write_byte((uint8_t*)addr+3, (data & 0xFF000000) >> 24); } uint32_t ReadEEPROM_Long(uint8_t addr) // считываем значение из EEPROM и преобразуем в long { uint32_t ir_code = eeprom_read_byte((uint8_t*)addr+3); ir_code = (ir_code << 8) | eeprom_read_byte((uint8_t*)addr+2); ir_code = (ir_code << 8) | eeprom_read_byte((uint8_t*)addr+1); return ((ir_code << 8) | eeprom_read_byte((uint8_t*)addr)); }

Фразы

Для отладки кода, я выкладываю фразы. Вернее их текстовый вариант.

1 - 50 - Имена пользователей

100 - В памяти устройства нет сохраненных ключей. Для начала добавьте мастер ключ. Для этого поднесите к считывателю любой ключ который вы хотите сделать основным.

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

102 - Мастер ключ добавлен!

103 - Новый ключ добавлен!

104 - Доступ заблокирован! Используемый Вами ключ отсутствует в системе.

105 - Доступ разрешен!

106 - Добрый день!

107 - Добро пожаловать!

108 - Время ожидание ключа истекло. Система бесконтактной идентификации переходит в стандартный режим работы.

109 - Система бесконтактной идентификации готова к работе.

110 - Звуковой сигнал next

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

112 - Мастер режим завершен!

113 - Включен режим обнуления памяти ключей. Все ключи удалены из памяти. Для возврата в стандартный режим не забудьте удалить перемычку и нажать кнопку сброса.

Заключение

К сожалению, я так и не смог завершить проект до конца. Компактный RFID RC522 модуль оказался неисправным. Я заказал два таких же модуля у разных продавцов, в надежде, что хотя бы один из них приедет в исправном состоянии и заработает. Но когда посылки приедут, пока неизвестно, поскольку на текущий момент они еще не отправлены. Когда я установлю считыватель на дверь и испытаю его в реальных условиях, то сниму короткий видеоотчет.

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

Ссылка на оригинал статьи

Arduino & Pi

1.4K постов20.6K подписчик

Добавить пост

Правила сообщества

В нашем сообществе запрещается:

• Добавлять посты не относящиеся к тематике сообщества, либо не несущие какой-либо полезной нагрузки (флуд)

• Задавать очевидные вопросы в виде постов, не воспользовавшись перед этим поиском

• Выкладывать код прямо в посте - используйте для этого сервисы ideone.com, gist.github.com или схожие ресурсы (pastebin запрещен)

• Рассуждать на темы политики

• Нарушать установленные правила Пикабу