SIM800L, передача данных в тоновом режиме
- Войдите на сайт для отправки комментариев
Доброго всем времени суток.
Хотел бы поделится со всеми одной своей разработкой. Может данная информация окажется кому-то полезной. На своей даче я реализовал автоматическую систему полива. Реализована она на готовых электроных таймерах. Один таймер включает насос типа "малыш", погруженный в колодец. Вода поступает в бочку. Бочка - 200 литров. Набор воды обычно происходит через день с 21:00 до 21:20. Другой таймер открывает соленойдный клапан, и подогретая окружающей средой вода поступает в систему капельного полива. Открытие клапана происходит ежедневно с 15:00 до 20:30. И все бы хорошо, но система питается от 220VAC. Бывают отключения электричества. Может засориться магистральный фильтр. И пр... Одним словом, необходимо отслеживать изменения уровня воды в бочке. Было принято решение разработать устройство. Вот оно:Устройство состоит из четырех модулей:
- Arduino Nano;
- GSM-модуль SIM800L;
- блок питания 220VAC/5VDC;
- понижающий DC-регулятор.
Выходное напряжение DC-регулятора установлено на уровне 4.18 вольт. От него запитывается SIM800L. При этом уровне напряжения SIM (по АТ запросу) выдает заряд аккумулятора около 100%. Вообще, от этого регулятора SIM работает очень стабильно.
Arduino и SIM в любой момент могут быть извлечены из устройства (просто, для удобства)
Хотелось бы отметить, что у Arduino Nano есть один несомненно большой плюс. Это наличие готового USB разъема. Нет необходимоти тащить ноут на дачу. Программу можно корректировать с телефона через ArduinoDroid. Можно отследить ход выполнения программы через Serial (опять же с телефона).
На первых трех аналоговых входах реализован кондуктометрический датчик. К ним и к GND подключаются электроды на разных уровнях в бочке. GND является общим электродом и подключается на самое дно бочки. Электроды на входах А0, А1 и А2 подключаются на нижнем, среднем и верхнем уровнях бочки соответственно. Как всем нам известно, значения на аналоговых входах может меняться от 0 до 1024. Значение более 1020 означает, что данный уровень водой не достигнут. Пороговое значение, при котором уровень считается достигнутым в программе установлен равным 800 (исходя из экспериментов проведенных в ванной). После установки устройства на месте, пороговое значение будет скорректированно для каждого уровня.
И так... Каков функционал данного устройства... При изменении уровня в бочке, оно звонит "хозяину". При этом мы не знаем, увеличился уровень или уменьшился. Да, конечно, можно было бы просто послать SMS-ку, и указать в ней что да как... Но исходящие SMS платны. Я не жадный, но дело принципа. Дача находится в 30-ти километрах от дома. Но это уже другой регион. Соответственно, роуминг. На этом наши сотовые операторы незаслуженно (я так считаю) наживаются. Поэтому, вместо того, чтоб слать SMS-ки, устройство нам будет звонить, а мы будем этот звонок игнорировать. Мы лучше сами позвоним на устройство, переключимся на телефоне на DTMF-приемник и в тоновом режиме примем текущие значения уровней в бочке:
Судя по картинке, бочка пуста (полив прошел успешно).
Симку нужно покупать с посекундным тарифом без каких либо ежемесячных платежей. Тогда ваши расходы на нее будут составлять 0.00 руб в месяц.
Данный способ передачи информации может быть использован и для других целей (показания датчиков и пр.). Так же в тоновом режиме можно удаленно управлять устройствами с телефона.
А так выглядит Serial Monitor, если устройство функционирует нормально:
А вот и программа:
#include <SoftwareSerial.h> SoftwareSerial mySerial(2, 3); // RX, TX int ch = 0; String val = ""; //переменная для приема данных от GSM-модуля int level_1=0; //переменная 1-го уровня int level_2=0; //переменная 2-го уровня int level_3=0; //переменная 3-го уровня int level_11=0; //промежуточная переменная 1-го уровня int level_22=0; //промежуточная переменная 2-го уровня int level_33=0; //промежуточная переменная 3-го уровня String Level="AT+VTS="; //переменная формирования АТ команд для передачи в GSM-модуль String L_1=""; String L_2=""; String L_3=""; unsigned long time; unsigned long time1=0; void setup() { digitalWrite(A0, 1); //включаем подтягивающий резистор аналогового входа А0 (уровень 1) digitalWrite(A1, 1); //включаем подтягивающий резистор аналогового входа А1 (уровень 2) digitalWrite(A2, 1); //включаем подтягивающий резистор аналогового входа А2 (уровень 3) if(analogRead(A0)>800) level_1=level_11=0; else level_1=level_11=1; //устанавливаем порог для уровня 1 раным 800 if(analogRead(A1)>800) level_2=level_22=0; else level_2=level_22=1; //устанавливаем порог для уровня 2 раным 800 if(analogRead(A2)>800) level_3=level_33=0; else level_3=level_33=1; //устанавливаем порог для уровня 3 раным 800 delay(20000); //время на инициализацию модуля Serial.begin(19200); //открываем COM-порт mySerial.begin(19200); //открываем порт GSM-модуля mySerial.println("AT+CLIP=1"); //включаем АОН delay(100); mySerial.println("AT+VTD=4"); //устанавливаем длительность в тоновом режиме равной 0,4сек delay(100); mySerial.println("ATD+79ХХХХХХХХХ;"); //звоним на свой номер delay(16000); mySerial.println("ATH0"); //разрываем связь через 16 сек delay(100); } void loop() { L_1=String(analogRead(A0)); //переводим "цифру" в String L_2=String(analogRead(A1)); //переводим "цифру" в String L_3=String(analogRead(A2)); //переводим "цифру" в String if (mySerial.available()) { //если GSM модуль что-то послал нам, while (mySerial.available()) { //сохраняем входную строку в переменную val ch = mySerial.read(); val += char(ch); delay(10); } if (val.indexOf("RING") > -1) { //если звонок обнаружен, то проверяем номер if (val.indexOf("79ХХХХХХХХХ") > -1) { //если номер звонящего наш Serial.println("--- MASTER RING DETECTED ---"); digitalWrite(13, HIGH); //включаем светодиод mySerial.println("ATA"); //устанавливаем соединение delay(1000); //задержка для включения DTMF-ресивера на телефоне mySerialLevel(); //отправляем значения уровней на DTMF-ресивер mySerial.println("ATH0"); //разрываем связь digitalWrite(13, LOW); //выключаем светодиод } } else Serial.println(val); //печатаем в монитор порта пришедшую строку val = ""; //обнуляем переменную val } time = millis(); if((time-time1)>=5000){ //раз в 5 секунд выводим значения уровней на монитор Serial.print(L_1); //выводим на монитор значение уровня 1 Serial.print("\t"); //табуляция Serial.print(L_2); //выводим на монитор значение уровня 2 Serial.print("\t"); //табуляция Serial.print(L_3); //выводим на монитор значение уровня 3 Serial.print("\t"); //табуляция SerialLevel(); //выводим на монитор сформированную АТ команду //Serial.print(time); //выводим на монитор значение времени Serial.println(""); //перенос строки time1=time; } CheckLevel(); //проверяем значения уровеней //в случае изменения звоним на свой номер } /***функция формирования AT+VTS команды для отслеживания в Serial ***/ void SerialLevel(){ Level+=char(34); Level+=L_1[0]; Level+=','; Level+=L_1[1]; Level+=','; if(L_1[2]>47&&L_1[2]<58) { Level+=L_1[2]; Level+=','; } if(L_1[3]>47&&L_1[3]<58) { Level+=L_1[3]; Level+=','; } Level+='#'; Level+=','; Level+=L_2[0]; Level+=','; Level+=L_2[1]; Level+=','; if(L_2[2]>47&&L_2[2]<58) { Level+=L_2[2]; Level+=','; } if(L_2[3]>47&&L_2[3]<58) { Level+=L_2[3]; Level+=','; } Level+='#'; Level+=','; Level+=L_3[0]; Level+=','; Level+=L_3[1]; if(L_3[2]>47&&L_3[2]<58) { Level+=','; Level+=L_3[2]; } if(L_3[3]>47&&L_3[3]<58) { Level+=','; Level+=L_3[3]; } Level+=char(34); Serial.print(Level); Level="AT+VTS="; } /***функция формирования AT+VTS команды для GSM-модуля ***/ void mySerialLevel(){ Level+=char(34); Level+=L_1[0]; Level+=','; Level+=L_1[1]; Level+=','; if(L_1[2]>47&&L_1[2]<58) { Level+=L_1[2]; Level+=','; } if(L_1[3]>47&&L_1[3]<58) { Level+=L_1[3]; Level+=','; } Level+='#'; Level+=','; Level+=L_2[0]; Level+=','; Level+=L_2[1]; Level+=','; if(L_2[2]>47&&L_2[2]<58) { Level+=L_2[2]; Level+=','; } if(L_2[3]>47&&L_2[3]<58) { Level+=L_2[3]; Level+=','; } Level+='#'; Level+=','; Level+=L_3[0]; Level+=','; Level+=L_3[1]; if(L_3[2]>47&&L_3[2]<58) { Level+=','; Level+=L_3[2]; } if(L_3[3]>47&&L_3[3]<58) { Level+=','; Level+=L_3[3]; } Level+=char(34); mySerial.println(Level); delay(15000); //while (1) {if(mySerial.available())break;}; Level="AT+VTS="; } /*** функция проверки изменения уровней ***/ void CheckLevel(){ if(analogRead(A0)>800) level_1=0; else level_1=1; //проверяем изменение уровня 1 if(analogRead(A1)>800) level_2=0; else level_2=1; //проверяем изменение уровня 2 if(analogRead(A2)>800) level_3=0; else level_3=1; //проверяем изменение уровня 3 if(level_1!=level_11||level_2!=level_22||level_3!=level_33){ // если один из уровней изменился mySerial.println("ATD+79ХХХХХХХХХ;"); //звоним на свой номер delay(16000); mySerial.println("ATH0"); //разрываем связь через 16 сек delay(60000); //делаем задержку на "дребезг зеркала воды" level_11=level_1; //запоминаем текущее значение уровня 1 в промежуточной переменной level_22=level_2; //запоминаем текущее значение уровня 2 в промежуточной переменной level_33=level_3; //запоминаем текущее значение уровня 3 в промежуточной переменной }; }
какая полная команда AT+VTS дается ?
сделайте дополнительные пояснения по коду, местами описав что и как делаетс.
так будет проще вникнуть.
Для того, что бы на экране телефона получить это
команда должна выглядеть так: AT+VTS="1,0,2,3,#,1,0,2,3,#1,0,2,3"
кстати, а подскажите, в последнем примере генерится дтмф, но там еще вроде есть коанды генерации коротких звуковых тоновых сигналов - не дтмф.. не пробовали генерить? а принимать другим сим800 ??
В данном приборе SIM800 как раз и передает короткие тоновые сигналы. Вопрос терминологии...
там кроме дтмф есть и другое.. ладно. наверное вы не в курсе.
Заинтриговал. Что другое? Каков принцип работы? Поищу в мануале (знать бы что искать)...
Принцип работы моего устройства подобен тому, когда звонишь в какую-нить контору, а тебе в ответ: "Здрасте, если вам нужно то-то, то жми 1. Если другое, то жми 2. Иначе - 3. Может все-таки об одном и том же говорим?
Почитайте описание 1.09
Встречал, что гсм модуль может передавать "АДЕМКО" протокол, и достаточно быстро.
ДТМФ - медленный, вам удавалось дтмф передавать несколько цифр в секунду, например 5-7цифр или более?
у меня чтото не получилось, 1-2 цифры и все..
Не могу найти 1.09. У меня есть только 1.01. Если можно ссылку, плиз...
он на официальном сайте симкома есть. 1.01 - очень старый.
Нашел. По поводу скорости... Мне удавалось передавать 4-5 цифры/сек, но иногда бывали искажения. Пришлось увеличить длительность (строка 35).
насколько понял - при передаче абоненту сотовой связи, дтмф генерит последняя БС оператора связи.
а вот АДЕМКО можно передать бе участия БС станций, быстрее.
можно выложить для всеобщего обозрения 1.09 скачанную, а то там регистрация.......
Даже нужно. В поисковике искал так: SIM800_Series_AT_Command_Manual_V1.09
Если найдете в мануале про "адемко", скажите номер страницы, плиз...
про адемко я читал в анонсах на этот модуль.
Можно ссылку на анонс?
сейчас не найду.
На стр.154 нашел "AT+CLDTMF Local DTMF Tone Generation". Может это?.. Поддерживается только SIMCOM.
это помоему в динамик играет..
Dron, можно ли с вами как то связаться по имейл или вк/вайбер? А то есть куча вопросов по SIM80L ver.2.0, а задать некому...
legionercheg, пишите сюда nosikovandrey@mail.ru. Правда, опыт у меня не велик, но чем смогу, помогу... А какие-то вопросы можно обсудить и на форуме.
Отправил письмо.
Dron, письмо отправил, но ответа от вас не получил. Вы мне правильный адрес указали?
Тем, кто пробует повторить устройство... Уменьшил порог срабатывания с 800 на 400. А то слишком чувствительность большая получилась. Срабатывает и от утренней росы (в четвертом часу утра), и от дождя. Аналоговые входы все живы. Думаю, ничего с ними не случится.
А не пробовал ли кто-нибудь здесь включать SIM800L в режиме передачи данных, как обычный проводной dial-up модем?
По документации набор номера с символом ; в конце - голосовой вызов, а без ; - вызов для передачи данных.
Пробую, но ATD без ; в конце сразу выдает ERROR.
Куда копать?
А не пробовал ли кто-нибудь здесь включать SIM800L в режиме передачи данных, как обычный проводной dial-up модем?
По документации набор номера с символом ; в конце - голосовой вызов, а без ; - вызов для передачи данных.
Пробую, но ATD без ; в конце сразу выдает ERROR.
Куда копать?
сначала у оператора поинтересуйся - поддерживает он услугу CSD передачи данных или нет. а уже потом и копать можно.
///сначала у оператора поинтересуйся - поддерживает он услугу CSD передачи данных или нет. а уже потом и копать можно.
Ага. Была както тема, хотели ЧМ сигнал по GSM передать. Тон передается первые пару секунд, а затем исчезает. Ох и надолбались пацаны с этим! Два дня искали чего сигнал пропадает. Оказалось оператор не поддерживает.
Заинтересовала ваша статья. Хочу реализовать почти такую-же идею измерения уровня, только используя ультразвуковой датчик и СМС. Необходимо по входящему звонку на GSM модуль заставить Arduino отбиться, произвести замер уровня воды в емкости и ответить по СМС на звонивший номер.
Программирование для меня сложная штука, куда легче было коммутировать модули. "Сконструировал" сырой код используя известный ультразвуковой скетч и скетч по отправке СМС, а так же немного вашего кода в части контроля входящего вызова.
Ввиду того что запрашивать уровень воды необходимо 1 раз в час, отсылка СМС выльется в копеечку, поэтому переделываю программу под GPRS.