Бесплатная отправка SMS из Arduino без GSM модуля


Понадобилось мне слать SMS из ардуинины себе на телефон. Да так, что бы без заморочек с GSM, сим картами и оплатой. Под катом то, что из этого вышло.

Раз GSM не подходит, то слать придется через интернет. В закромах имелся сверх дешевый Wi-Fi модуль ESP8266. Про его предварительную настройку можно почитать в этой отличной статье ссылка.
Перво-наперво полез гуглить различные интернет-сервисы для отправки SMS. Сервисов оказалось много, но вот подходящего среди них не оказалось. Либо 10 SMS в день, либо хотят денег. Да и капчи ардуинине не по зубам. Но тут совершенно случайно наткнулся на на интересный сервис своего мобильного оператора (MTS BY) — всего за 1$ можно подключить услугу приема email в виде SMS ссылка. Что же, полностью бесплатно не получилось, и после оплаты я получил почтовый адрес вида 375XXYYYYYYY@sms.mts.by ( где XX и YYYYYYY — код сети и номер). То есть все свелось к банальной отправке email из arduino.
Но не тут-то было. Оказывается в последнее время все уважающие себя почтовые сервера отказываются принимать почту по 25 порту и без шифрования. А с другими связываться не хотелось, как и привязываться к своему домашнему серверу. Нагуглил вот такой сервис ссылка. В базовом бесплатном варианте дают 6к писем в месяц, что для моего домашнего использования хватает с головой. После регистрации идем в настройки и видим адрес smtp сервера, порт, логин и сгенерированный нам пароль.
Быстро накатал скетч, отправляю email 375XXYYYYYYY@sms.mts.by и… Облом. Отправляю на обычную почту — приходит. Пытался так и эдак переделывать заголовок — все равно письма исчезают в безднах серверов МТС, явно попадая в котел спам фильтра.
Значит нужно «отмыть» почту. В качестве сервиса отмывки выбрал (тихо ненавидимый мною за рекламу) mail.ru. Для отмывки в настройках почты, в разделе «Фильтры и пересылка», создал новое правило:

Настройки

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

Далее скучные технические подробности.
В качестве платы взял Arduino Mega 2560, так как в нем целых три дополнительных последовательных порта (хотя можно и обычный UNO, только дебажить будет сложнее).
ESP8266 подключен: GND -> GND, VCC и CH_PD -> +3.3V, RX -> TX3, TX -> RX3. Скорость ESP8266 настроена на 115200 бод.
Для общения с smtp сервером нужно закодировать свои логин и пароль в Base64.
Можно воспользоваться консолью Linux:
openssl enc -base64 <<< ’email@gmail.com’
openssl enc -base64 <<< ‘password’
Или же каким-либо онлайн сервисом, например ссылка.
Ну и собственно код скетча. После включения отправляется СМС и код уходит в вечный цикл. Дополнительные библиотеки не использовал.

Код

#define SSID "wi-fi_login" // ваш SSID #define PASS "wi-fi_password" // ваш пароль Wi-Fi  #define SMTPServer "s02.atomsmtp.com" //smtp сервер #define SMTPPort "2525" // smtp порт #define MailLogin "smtp_example@gmail.com" // логин для smtp #define MailLoginBase64 "dWd1LCBrb25lNG5vCg==" //логин для smtp в Base64 #define MailPasswordBase64 "aHJlbiB0YW0K" // пароль для smtp в Base64 #define MailRelay "example@mail.ru" // промежуточная почта для "отмывания" email #define PhoneNumber "375290000000" // номер телефона #define Message "Hello from Arduino!" //сообщение  #define SERIAL_RX_BUFFER_SIZE 256 #define SERIAL_TX_BUFFER_SIZE 256  void setup() { 	delay(2000); 	Serial3.begin(115200); 	Serial3.setTimeout(5000); 	Serial.begin(115200); // для отладки 	Serial.println("Init"); 	Serial3.println("AT+RST"); // сброс и проверка, что модуль готов 	if(WiteString("Ready", 5000)) { 		while(Serial3.available()) { Serial3.read();} 		Serial.println("WiFi - Module is ready"); 	}else{ 		Serial.println("Module dosn't respond."); 		while(1); 	} 	delay(100);  	Serial3.println(" AT+CIPMODE=0"); 	WiteString("OK"); 	while(Serial3.available()) { Serial3.read();}  	Serial3.println("AT+CIPMUX=1"); 	WiteString("OK"); 	while(Serial3.available()) { Serial3.read();}  	// try to connect to wifi 	boolean connected = false; 	for(int i=0;i<5;i++) { 		if(connectWiFi()) { 			connected = true; 			break; 		} 	} 		if (!connected) { 		while(1); 	} } void loop() { 	String cmd = "AT+CIPSTART=0,\"TCP\",\""; 	cmd += String(SMTPServer); 	cmd += "\"," + String(SMTPPort); 	Serial3.println(cmd);  	if(WiteString("Linked", 5000)) { 		while(Serial3.available()) { Serial3.read();} 		Serial.println("Link"); 	} 	else { 		Serial.println("Link fail"); 		while (1); 	}  	if (WiteString("OK", 2000)) { 		while(Serial3.available()) { Serial3.read();} 	} 	else { 		while (1); 	}    	Send("HELO 1.2.3.4", true); 	Send("AUTH LOGIN", true); 	Send(MailLoginBase64, true); 	Send(MailPasswordBase64, true); 	Send("MAIL FROM:<" + String(MailLogin) + ">", true); 	Send("RCPT TO:<" + String(MailRelay) + ">", true); 	Send("DATA", true); 	Send("Subject:SMS", false); 	Send("To:\"" + String(PhoneNumber) + "\" <" + String(PhoneNumber) + "@sms.mts.by>", false); 	Send("From: <" + String(MailLogin) + ">", false); 	Send("", false); 	Send(Message, false); 	Send(".", true); 	Send("QUIT", true);  	while(1) {}; }   boolean connectWiFi() {   Serial3.println("AT+CWMODE=1");   while (!Serial3.available())	{ delay(10);}   while (Serial3.available()) {Serial3.read();}   String cmd="AT+CWJAP=\"";   cmd+=SSID;   cmd+="\",\"";   cmd+=PASS;   cmd+="\"";   Serial3.println(cmd);    if(WiteString("OK", 8000)){     Serial.println("Connected to WiFi.");     return true;   }else{     Serial.println("Can not connect to the WiFi.");     return false;   } }  bool Send(String S, bool wite) { 	Serial3.print("AT+CIPSEND=0,"); 	Serial3.println(S.length()+2); 	while (!Serial3.available()) { delay(10);} 	if(Serial3.find(">")){ 	}else{ 		Serial3.println("AT+CIPCLOSE=0"); 		delay(1000); 		return false; 	} 	Serial3.print(S + "\r\n");//добаяляем перевод строки 	if (WiteString("OK", 15000)) { 		if (wite) { 			WiteString("+IPD", 15000); 			while(Serial3.available()) { 				Serial3.read();}} 		return true;} 	else { 		return false;} }  void WiteString(String S) { 	int L = S.length(); 	String T = String(" "); 	while(1) { 		if (Serial3.available()) { 			char c = Serial3.read(); 			T = T + String(c); 			if (T.length() > L) T = T.substring(1); 			if (S.charAt(0) == T.charAt(0)) 			if (S.compareTo(T) == 0) return; 		} 		else { 			delay(1); 		} 	} }  bool WiteString(String S, int Time) { 	int L = S.length(); 	String T = String(" "); 	while(Time>0) { 		if (Serial3.available()) { 			char c = Serial3.read(); 			T = T + String(c); 			if (T.length() > L) T = T.substring(1); 			if (S.charAt(0) == T.charAt(0)) 			if (S.compareTo(T) == 0) return true; 		} 		else { 			delay(1); 			Time--; 		} 	} 	return false; }  String WiteString(int Time) { 	String T = String(""); 	while(Time>0) { 		if (Serial3.available()) { 			char c = Serial3.read(); 			T = T + String(c); 		} 		else { 			delay(1); 			Time--; 		} 	} 	return T; }

ссылка на оригинал статьи http://habrahabr.ru/post/245805/

Электрофокусер на базе отладочной платы Arduino Uno, часть 3

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

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

Код микроконтроллера

Код микроконтроллера разрабатывался и отлаживался в среде Arduino 1.0.5-r2, последняя версия доступна на githab`е.

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

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

  1. Инициализировать фокусер — Setup();
  2. Периодически снимать состояние кнопок и потенциометра с пульта ДУ, управлять индикацией состояния светодиодами;
  3. Общаться с ПО на ноутбуке по RS232 — serialEvent() и SendCmd();
  4. И управлять шаговым двигателем, вращая его с заданной скоростью в заданном направлении, считая шаги с учетом режима микрошага, при необходимости контролирую выход за заданные границы — StepperClass;

Пару слов о Loop()

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

Вращение мотора осуществляется через вызов глобальной функции Roll(), которая транслирует его далее на StepperClass.Roll(), мигая при этом светодиодом на пине motorled.
При изменении текущей скорости любым способом меняется яркость светодиода на пине speedled.

При достаточно долгом бездействии (задается в ReleaseTime) снимается напряжение с двигателя (ШД имеют свойство активно кушать ток и греться). Безусловна, эта опция «на любителя». По-хорошему, после точной фокусировки фокусер трогать нельзя. В идеале — его необходимо механически зафиксировать, если это предусмотрено конструкцией фокусера. Если этого не сделать, то сняв ток с ШД, мы можем получить небольшое смещение положения фокусера, то есть небольшую расфокусировку. В каждом конкретном случае нужно проверять, приводит ли снятие напряжение к смещению фокусера, и если да – отключать автоматическое снятие напряжения в скетче и, либо снимать его вручную (предварительно заблокировав фокусер фиксатором), либо вообще не снимать.

Лирическое отступление на тему библиотеки управления ШД

Существует довольно много библиотек, которые позволяют буквально сходу начать работать с ШД, не разбираясь в деталях. Я попробовал несколько разных, больше всего мне понравилась AccelStepper . Она достаточно популярна, имеет официальные ответвления, например от Adafruit. Для данной и всех подобных задачах она вполне подходит, я пользовался ей в течение примерно полугода. Библиотека универсальная, она не ориентирована на какой-то конкретный драйвер ШД. При инициализации мы указываем управляющие пины — и вперед. Рекомендую!

Но и у нее есть недостатки. Главный из них — нет поддержки микрошага. В ряде задач это крайне неудобно. Скорости в библиотеке задаются в оборотах в секунду, а позиция в шагах. Очевидно, что сменив режим микрошага, мы получим иную скорость, и неправильное положение. Если режим микрошага не меняется — ничего страшного, единожды вводим поправочные коэффициенты. Но если режим микрошага динамически переключается, ситуация сильно усложняется. Один из вариантов — делать обертку (wrapper), которая запоминает режим и автоматически пересчитывает координаты и скорости. Что я и делал до поры до времени.

В данном проекте использование AccelStepper вполне приемлемо и оправдано. Я столкнулся с некоторыми странностями и как минимум с одним багом (если поставить скорость в 0 и шагнуть — управление не возвращается, зависаем), но в целом — рекомендую к использованию.

Разработка собственного класса для управления ШД — вынужденный шаг. В другом проекте работа с микрошагом для меня это стала критически важной и промучившись какое время я написал свою библиотеку, существенно более простую, но зато с поддержкой микрошага и ориентированную на работу с линейкой драйверов от Polulu (A4988, DRV8825). Библиотека очень маленькая, выложена на github, текст заголовочника содержит комментарии.

Библиотека будет дорабатываться и обновляться. В честности, есть планы по существенной доработке функции Roll() с целью повышения точности и плавности хода (учет пропущенных по времени шагов, режим «догоняем»).

Использовать разные библиотеки в близких проектах мне не хотелось, поэтому фокусер так же был переведен на StepperClass.

И еще одно лирическое отступления о единицах измерения

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

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

Протокол управления фокусером по RS232

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

168 ID команды (1 байт) параметр команды 13 10

Контрольной суммы нет, размер команды не ограничивается (только разумным размером буфера приема — 255 байт) и в посылке не предопределен. При приеме команды происходит накопление буфере до тех пор, пока не придет идентификатор конца команды #13#10. После этого идентификатор команды и параметр команды выделяются из буфера и команда выполнятся. Пропуск идентификатора начала или конца команды может привести к пропуску одной команды. На практике это не критично. Более подробно команды и параметры опишу в следующей части, тут это не так важно.

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

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

Тонкости адаптации и настройки, а так же некоторые грабли

Регулировка тока на А4988 и пропуск шагов

Драйвер ШД А4988 имеет встроенный ограничитель тока, подаваемого на ШД. Штука очень полезная и важная. Как ей пользоваться описано на сайте разработчика. Но у нее есть один интересный эффект. Как мы знаем, при снижении силы тока падает крутящий момент. Как ни странно, конкретно на А4988 в режиме микрошага это может выражаться в регулярном 100% пропуске шагов на определенной фазе. Поэтому в режиме 1/16 запросто можно получить вместе 16 шагов, только 4, или 8. Добавляем тока – и все хорошо.

Подключение ШД

При подключении ШД к драйверу желательно не перепутать отводы между парами (см. схемы подключения биполярных ШД). Перепутать отводы внутри пары не страшно, получите вращение в другую сторону. Рекомендую первым делом прозвонить пары отводов и проверить сопротивление обмоток, соответствует ли оно тому, что вам обещали.
Один раз мне продали ШД под номинальное напряжение 12В, а оказалось, что на самом деле он рассчитан на 2.8В. А я удивлялся — почему он у меня как-то странно ходит, драйвер греется, ардуинка иногда выключается…

Максимальная скорость вращения, пауза между шагами и микрошаг

У любого ШД есть максимальная скорость вращения. Обычно — это сотни оборотов в секунду. С точки зрения управления ШД это значит, что существует некий минимальный интервал времени между шагами. Пытаться делать шаги чащи не только бесполезно, но даже вредно — ШД будет дергаться, свистеть, гудеть, но нормально ходить не будет. Это еще одна возможность получить ШД, не желающий ходить нормально. Максимальную скорость производитель указывает тоже далеко не всегда, так что вполне вероятно ее придется определять опытным путем.

Важный и интересный момент, о котором обычно не пишут — как использование режима микрошага влияет на максимальную скорость и минимальную длительность паузы между шагами соответственно. Отвечаю – использование микрошага практически никак не влияет на максимальную скорость вращения. По крайней мере, несущественно в рамках данной работы. А вот на длительность паузы между шагами — очень даже влияет. Чем более мелкий шаг мы используем, тем чаще нужно давать команду на следующий шаг. В качестве эксперимента я провел тестирование одного из своих двигателей и получил вот такую вот картину:

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

Легко заметить, что максимальная скорость 0,161 была достигнута в режиме 1/8 микрошага с интервалом между шагами в 125 микросекунд (чистая удача, на полном шаге ее тоже наверняка удалось бы получить с интервалом где-то около 1200). Чуть меньшая скорость 0,139 была получена дважды, в режиме полного шага с интервалом1250 микросекунд, и в режиме 1/16 шага с интервалом 50 микросекунд. Близкая скорость 0,135 была получена в режиме 1/4 микрошага с интервалом 300 микросекунд. Получается, что при переходе от полного шага к 1/16 шага для сохранения текущей скорости интервал между шагами нужно сократить ровно в 25 раз (но не в 16! ).
Так же видно, что в режиме 1/32 микрошага максимальную скорость получить было бы невозможно. В этом случае нас ограничивается время выполнения loop(), которое на Arduino Uno составляет порядка 30 микросекунд на пустом цикле (по крайней мере так было на «китайце», где я проводил эксперименты).

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

Что нужно поменять в скетче для адаптации под другой двигатель

  • Максимальное и минимальное значение скорости. Задается в MIN_SPEED_DELAY и MAX_SPEED_DELAY как интервал между шагами в микросекундах. Можно нащупать опытным путем;
  • Микрошаг. Задается исходя из возможностей двигателя в DEFAULT_MS. Если крутящего момента хватает — лучше оставить 1/16;
  • Кол-во шагов на оборот, задается в STEP_PER_REVOLUTION;
  • Нужно ли снимать напряжение с мотора при простое и время бездействия в IsRelease и ReleaseTime соответственно.

На этом пожалуй все. Совершенно не освещенным осталось приложение под Windows для удаленного управления — программная панель управления фокусером. Возможно изложу в 4-ой части, но пока есть сомнения в целесообразности.

ссылка на оригинал статьи http://habrahabr.ru/post/245653/

Как сделать греческие буквы в формулах прямым шрифтом в LaTeX

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

Это картинка, которая показывает, как будут выглядеть формулы, написанные в LaTeX, если подключить мой пакет:

Если кому-то такое вдруг понадобилось, то см. под кат.

Готового пакета для LaTeX, реализующего такую функцию, я не нашёл. Поиск решения привёл к использованию пакета mathptm, но с этим пакетом формулы начинают выглядеть как в Word’e. Латинские символы становятся промежуточными между обычным и полужирным начертанием. Также теряется полужирное начертание у заголовков \section, \subsection.

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

Всё оформлено в виде трёх пакетов:

  • rumathgrk — определяет прямые греческие символы
    например \alphaup — прямая буква «альфа» \betaup — прямая буква «бета» и т.д.
  • rumathgrk1 — переопределяет стандартные греческие символы ( \alpha, \beta и т.п.), чтобы они были прямыми
  • fixint — переопределяет интегралы, чтобы они были прямыми. Нужно заметить, что класс disser с опцией fixint делает то же самое.

Для использования подключить в преамбуле любой из этих пакетов в любых сочетаниях. Чтобы использовать пакет fixint, нужно подключить пакет amsmath. Пакеты совместимы с популярным набором стилей для оформления диссертаций disser.

Вот пример минимального документа:

\documentclass[a4paper,12pt]{article} \usepackage[koi8-r]{inputenc} \usepackage[russian]{babel} \usepackage{hyperref} \usepackage{mathtext} \usepackage{amsmath} \usepackage{fixint}  % здесь подключили наши пакеты \usepackage{rumathgrk1} % теперь греческие буквы и интегралы будут переопределены  \begin{document}   % В этих формулах греческие буквы печатаются прямым шрифтом \begin{equation} S(\omega)=F[s(t)]=\int\limits_{-\infty}^{+\infty}s(t)\mbox{e} ^{-j\omega t} dt \end{equation}  \begin{equation}  F=\frac{q_1 q_2}{4\pi \varepsilon_0 \varepsilon r^2} \end{equation}   \end{document} 

Если прямые интегралы и греческие буквы в документе станут больше не нужны, то нужно просто убрать из преамбулы пакеты rumathgrk1 и fixint.

Забирать готовые пакеты можно с Гитхба: отсюда В Linux если установлен git, это можно сделать командой:

git clone https://github.com/ra3xdh/rumathgrk 

Для установки в Linux и TeXlive в консоли перейти в директорию с пакетом и выполнить команду:

make install 

В Windows пакеты не тестировались, но тоже должно работать. Устанавливать для MiKTeX их надо вручную. Допускается использование с любыми целями.

И в заключение замечу, что мне больше нравятся стандартные наклонные греческие буквы и интегралы из LaTeX.

ссылка на оригинал статьи http://habrahabr.ru/post/245785/