Arduino:Примеры/GSMExamplesMakeVoiceCall: различия между версиями

Материал из Онлайн справочника
Перейти к навигацииПерейти к поиску
м (Замена текста — «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">» на «<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">»)
 
Нет описания правки
Строка 24: Строка 24:
Сначала импортируем библиотеку '''GSM'''.
Сначала импортируем библиотеку '''GSM'''.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
#include <GSM.h>
#include <GSM.h>
</syntaxhighlight>
</syntaxhighlight>
Строка 30: Строка 30:
Функционал '''SIM'''-карты может быть заблокирован '''PIN'''-кодом. В таком случае нам потребуется директива #define, с помощью которой мы определим этот '''PIN'''-код как константу. Если у '''SIM'''-карты '''PIN'''-кода нет, вы можете оставить это место пустым.
Функционал '''SIM'''-карты может быть заблокирован '''PIN'''-кодом. В таком случае нам потребуется директива #define, с помощью которой мы определим этот '''PIN'''-код как константу. Если у '''SIM'''-карты '''PIN'''-кода нет, вы можете оставить это место пустым.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
#define PINNUMBER ""
#define PINNUMBER ""
</syntaxhighlight>
</syntaxhighlight>
Строка 36: Строка 36:
Создаем экземпляры классов, которые будем использовать. В данном примере вам понадобятся '''GSM''' и '''GSMVoiceCall'''.
Создаем экземпляры классов, которые будем использовать. В данном примере вам понадобятся '''GSM''' и '''GSMVoiceCall'''.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
GSM gsmAccess;  
GSM gsmAccess;  
GSMVoiceCall vcs;
GSMVoiceCall vcs;
Строка 43: Строка 43:
Создаем несколько переменных для хранения телефонного номера, на который будем звонить.
Создаем несколько переменных для хранения телефонного номера, на который будем звонить.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
String remoteNumber = "";
String remoteNumber = "";
char charbuffer[20];
char charbuffer[20];
Строка 50: Строка 50:
В секции setup() инициализируем последовательную передачу данных на компьютер. Она будет использоваться для передачи телефонного номера на '''Arduino'''. Запустив коммуникацию, отправляем на '''Serial Monitor''' сообщение, информирующее о начале работы скетча.  
В секции setup() инициализируем последовательную передачу данных на компьютер. Она будет использоваться для передачи телефонного номера на '''Arduino'''. Запустив коммуникацию, отправляем на '''Serial Monitor''' сообщение, информирующее о начале работы скетча.  


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void setup(){
void setup(){


Строка 59: Строка 59:
Создаем локальную переменную для отслеживания статуса соединения. Она нужна для того, чтобы скетч не начинал работать до тех пор, пока '''SIM'''-карта не подключится к сети.
Создаем локальную переменную для отслеживания статуса соединения. Она нужна для того, чтобы скетч не начинал работать до тех пор, пока '''SIM'''-карта не подключится к сети.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
boolean notConnected = true;
boolean notConnected = true;
</syntaxhighlight>
</syntaxhighlight>
Строка 65: Строка 65:
Подключаемся к сети, вызывая функцию gsmAccess.begin(). В качестве аргумента в ней будет '''PIN'''-код '''SIM'''-карты. Ставим эту функцию в секции while(), чтобы постоянно проверять статус соединения. Когда модем подключится, gsmAccess.begin() вернет значение '''GSM_READY'''. Используем его, как сигнал для того, чтобы присвоить переменной notConnected значение true или false. В противном случае на '''Serial Monitor''' появится сообщение о том, что подключиться не удалось.
Подключаемся к сети, вызывая функцию gsmAccess.begin(). В качестве аргумента в ней будет '''PIN'''-код '''SIM'''-карты. Ставим эту функцию в секции while(), чтобы постоянно проверять статус соединения. Когда модем подключится, gsmAccess.begin() вернет значение '''GSM_READY'''. Используем его, как сигнал для того, чтобы присвоить переменной notConnected значение true или false. В противном случае на '''Serial Monitor''' появится сообщение о том, что подключиться не удалось.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
while(notConnected)
while(notConnected)
   {
   {
Строка 80: Строка 80:
Заканчиваем секцию setup()выводом сообщения на '''Serial Monitor''' о том, что настройка связи прошла успешно, а также с предлагаем пользователю ввести телефонный номер.
Заканчиваем секцию setup()выводом сообщения на '''Serial Monitor''' о том, что настройка связи прошла успешно, а также с предлагаем пользователю ввести телефонный номер.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
Serial.println("GSM initialized.");
Serial.println("GSM initialized.");
   Serial.println("Enter phone number to call.");
   Serial.println("Enter phone number to call.");
Строка 90: Строка 90:
Для начала проверяем буфер последовательного порта на предмет того, есть ли там информация, которую мы можем сосчитать. Если есть, записываем ее в локальную переменную.
Для начала проверяем буфер последовательного порта на предмет того, есть ли там информация, которую мы можем сосчитать. Если есть, записываем ее в локальную переменную.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
void loop()
void loop()
{
{
Строка 96: Строка 96:
   {
   {
     char inChar = Serial.read();
     char inChar = Serial.read();
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">


Если в буфере есть символ новой строки, проверяем, не содержит ли вписанный телефонный номер более '''20 цифр''' (теоретически, вы никогда не сможете набрать номер, где цифр будет больше '''20-ти''').
Если в буфере есть символ новой строки, проверяем, не содержит ли вписанный телефонный номер более '''20 цифр''' (теоретически, вы никогда не сможете набрать номер, где цифр будет больше '''20-ти''').


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
if (inChar == '\n')
if (inChar == '\n')
     {
     {
Строка 109: Строка 109:
Выводим номер, по которому собираемся звонить, на '''Serial Monitor'''.
Выводим номер, по которому собираемся звонить, на '''Serial Monitor'''.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
Serial.print("Calling to : ");
Serial.print("Calling to : ");
         Serial.println(remoteNumber);
         Serial.println(remoteNumber);
Строка 117: Строка 117:
Телефонный номер будет храниться в строке под названием remoteNumber. Для функции voiceCall() требуется массив char, поэтому копируем эту строку в массив под названием charbuffer.
Телефонный номер будет храниться в строке под названием remoteNumber. Для функции voiceCall() требуется массив char, поэтому копируем эту строку в массив под названием charbuffer.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
remoteNumber.toCharArray(charbuffer, 20);
remoteNumber.toCharArray(charbuffer, 20);
</syntaxhighlight>
</syntaxhighlight>
Строка 125: Строка 125:
Чтобы активировать функцию hangCall() – и тем самым прервать звонок – отправляем символ новой строки.
Чтобы активировать функцию hangCall() – и тем самым прервать звонок – отправляем символ новой строки.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
if(vcs.voiceCall(charbuffer))
if(vcs.voiceCall(charbuffer))
         {
         {
Строка 136: Строка 136:
Завершив звонок, очищаем переменную, в которой хранится телефонный номер.
Завершив звонок, очищаем переменную, в которой хранится телефонный номер.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
Serial.println("Call Finished");
Serial.println("Call Finished");
         remoteNumber="";
         remoteNumber="";
Строка 145: Строка 145:
Если номер, введенный в '''Serial Monitor''', содержит больше '''20 цифр''', очищаем строку remoteNumber и начинаем снова.
Если номер, введенный в '''Serial Monitor''', содержит больше '''20 цифр''', очищаем строку remoteNumber и начинаем снова.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
else
else
       {
       {
Строка 156: Строка 156:
Если при считывании информации с '''Serial Monitor''' оказывается, что среди входящих символов нет символа новой строки или возврата строки, добавляем его к строке remoteNumber и закрываем секцию loop().  
Если при считывании информации с '''Serial Monitor''' оказывается, что среди входящих символов нет символа новой строки или возврата строки, добавляем его к строке remoteNumber и закрываем секцию loop().  


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
else
else
     {
     {
Строка 170: Строка 170:
Убедитесь, что '''Serial Monitor''' настроен таким образом, что при нажатии на клавишу ввода будет отсылаться только символ новой строки.
Убедитесь, что '''Serial Monitor''' настроен таким образом, что при нажатии на клавишу ввода будет отсылаться только символ новой строки.


<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS" enclose="div">
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
/*
/*
Голосовой звонок при помощи Arduino
Голосовой звонок при помощи Arduino

Версия от 12:32, 20 мая 2023

Перевод: Максим Кузьмин
Проверка/Оформление/Редактирование: Мякишев Е.А.


Голосовой звонок[1]

Этот скетч при помощи платы Arduino и модуля GSM Shield позволяет делать звонок на удаленный телефонный номер, введенный через Serial Monitor. Чтобы слышать человека на том конце связи и иметь возможность отправлять свой голос, вам надо будет подключить к Shield динамик и микрофон.

Необходимое оборудование

  • Плата Arduino;
  • Модуль Arduino + Telefonica GSM/GPRS Shield;
  • Микрофон и динамик, подключенные к Shield;
  • SIM-карта;

Цепь

Изображение Arduino GSM Shield поверх Arduino Uno

Код

Сначала импортируем библиотеку GSM.

#include <GSM.h>

Функционал SIM-карты может быть заблокирован PIN-кодом. В таком случае нам потребуется директива #define, с помощью которой мы определим этот PIN-код как константу. Если у SIM-карты PIN-кода нет, вы можете оставить это место пустым.

#define PINNUMBER ""

Создаем экземпляры классов, которые будем использовать. В данном примере вам понадобятся GSM и GSMVoiceCall.

GSM gsmAccess; 
GSMVoiceCall vcs;

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

String remoteNumber = "";
char charbuffer[20];

В секции setup() инициализируем последовательную передачу данных на компьютер. Она будет использоваться для передачи телефонного номера на Arduino. Запустив коммуникацию, отправляем на Serial Monitor сообщение, информирующее о начале работы скетча.

void setup(){

  Serial.begin(9600); 
  Serial.println("Make Voice Call");

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

boolean notConnected = true;

Подключаемся к сети, вызывая функцию gsmAccess.begin(). В качестве аргумента в ней будет PIN-код SIM-карты. Ставим эту функцию в секции while(), чтобы постоянно проверять статус соединения. Когда модем подключится, gsmAccess.begin() вернет значение GSM_READY. Используем его, как сигнал для того, чтобы присвоить переменной notConnected значение true или false. В противном случае на Serial Monitor появится сообщение о том, что подключиться не удалось.

while(notConnected)
  {
    if(gsmAccess.begin(PINNUMBER)==GSM_READY)
      notConnected = false;
    else
    {
      Serial.println("Not connected");
      delay(1000);
    }
  }

Заканчиваем секцию setup()выводом сообщения на Serial Monitor о том, что настройка связи прошла успешно, а также с предлагаем пользователю ввести телефонный номер.

Serial.println("GSM initialized.");
  Serial.println("Enter phone number to call.");
}

Код в секции loop() принимает от Serial Monitor входящие байты и делает голосовой звонок.

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

void loop()
{
  while (Serial.available() > 0)
  {
    char inChar = Serial.read();
<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">

Если в буфере есть символ новой строки, проверяем, не содержит ли вписанный телефонный номер более '''20 цифр''' (теоретически, вы никогда не сможете набрать номер, где цифр будет больше '''20-ти''').

<syntaxhighlight lang="c" line="GESHI_NORMAL_LINE_NUMBERS|GESHI_FANCY_LINE_NUMBERS">
if (inChar == '\n')
    {
      if (remoteNumber.length() < 20)
      {

Выводим номер, по которому собираемся звонить, на Serial Monitor.

Serial.print("Calling to : ");
        Serial.println(remoteNumber);
        Serial.println();

Телефонный номер будет храниться в строке под названием remoteNumber. Для функции voiceCall() требуется массив char, поэтому копируем эту строку в массив под названием charbuffer.

remoteNumber.toCharArray(charbuffer, 20);

Чтобы послать вызов, воспользуемся функцией vcs.voiceCall(), «скормив» ей номер, до которого хотим дозвониться. Проверяем статус соединения при помощи функции getvoiceCallStatus().

Чтобы активировать функцию hangCall() – и тем самым прервать звонок – отправляем символ новой строки.

if(vcs.voiceCall(charbuffer))
        {
          Serial.println("Call Established. Enter line to end");
          while(Serial.read()!='\n' && (vcs.getvoiceCallStatus()==TALKING));          
          vcs.hangCall();
        }

Завершив звонок, очищаем переменную, в которой хранится телефонный номер.

Serial.println("Call Finished");
        remoteNumber="";
        Serial.println("Enter phone number to call.");
      }

Если номер, введенный в Serial Monitor, содержит больше 20 цифр, очищаем строку remoteNumber и начинаем снова.

else
      {
        Serial.println("That's too long for a phone number. I'm forgetting it"); 
        remoteNumber = "";
      }
    }

Если при считывании информации с Serial Monitor оказывается, что среди входящих символов нет символа новой строки или возврата строки, добавляем его к строке remoteNumber и закрываем секцию loop().

else
    {
      if(inChar!='\r')
        remoteNumber += inChar;
    }
  } 
}

Загрузив код, открываем Serial Monitor. Увидев сообщение «Enter phone number to call» (т.е. «Введите телефонный номер, на который хотите позвонить»), впишите нужный телефонный номер и нажмите клавишу ввода.

Убедитесь, что Serial Monitor настроен таким образом, что при нажатии на клавишу ввода будет отсылаться только символ новой строки.

/*
Голосовой звонок при помощи Arduino

Этот скетч для Arduino GSM Shield позволяет делать голосовой звонок 
на удаленный телефонный номер, который вы вводите через Serial Monitor.
Когда все будет настроено, откройте Serial Monitor и, увидев сообщение READY, впишите телефонный номер. 
Убедитесь, что Serial Monitor настроен таким образом,
чтобы при нажатии на клавишу ввода отсылался только символ новой строки.

Цепь:
* GSM Shield
* Подключенные к Shield динамик и микрофон. 
Без них ни отправлять, ни получать голосовые сообщения будет нельзя.

Создан в марте 2012 Хавьером Зорзано (Javier Zorzano).

Этот код не защищен авторским правом.
*/

// Библиотеки:
#include <GSM.h>

// PIN-код:
#define PINNUMBER ""

// Создаем экземпляры классов GSM и GSMVoiceCall:
GSM gsmAccess; // включая параметр «true» для активации отладки
GSMVoiceCall vcs;

String remoteNumber = "";  // номер, по которому вы будете звонить
char charbuffer[20];

void setup()
{

  // Инициализируем последовательную передачу данных и ждем открытия порта:
  Serial.begin(9600);
  while (!Serial) {
    ; // ждем подключения последовательного порта (нужно только для Leonardo)
  }

  Serial.println("Make Voice Call");  //  "Делаем голосовой звонок"

  // Состояние соединения:
  boolean notConnected = true;

  // Запускаем GSM Shield.
  // Если у вашей SIM-карты есть PIN, делаем его параметром функции gsmAccess.begin():
  while (notConnected)
  {
    if (gsmAccess.begin(PINNUMBER) == GSM_READY)
      notConnected = false;
    else
    {
      Serial.println("Not connected");  //  "Подключиться не удалось"
      delay(1000);
    }
  }

  Serial.println("GSM initialized.");  //  "GSM инициализирован."
  Serial.println("Enter phone number to call.");  //  "Введите телефонный номер, на который будем звонить."

}
void loop()
{

  // Добавляем в строку любые входящие символы:
  while (Serial.available() > 0)
  {
    char inChar = Serial.read();
    // Если это символ новой строки, значит, делаем звонок:
    if (inChar == '\n')
    {
      // Убедитесь, что телефонный номер не слишком длинен:
      if (remoteNumber.length() < 20)
      {
        // Дайте пользователю знать, что вы звоните:
        Serial.print("Calling to : ");  //  "Звоним на: "
        Serial.println(remoteNumber);
        Serial.println();

        // Звоним на указанный номер:
        remoteNumber.toCharArray(charbuffer, 20);


        // Проверяем, сняли ли на том конце трубку:
        if (vcs.voiceCall(charbuffer))
        {
          Serial.println("Call Established. Enter line to end");  //  "Связь установлена. Введите символ новой строки, чтобы закончить"
          // Ждем получения символа новой строки:
          while (Serial.read() != '\n' && (vcs.getvoiceCallStatus() == TALKING));
          // и вешаем «трубку»:
          vcs.hangCall();
        }
        Serial.println("Call Finished");  //  "Звонок окончен"
        remoteNumber = "";
        Serial.println("Enter phone number to call.");  //  "Введите телефонный номер, на который хотите позвонить."
      }
      else
      {
        Serial.println("That's too long for a phone number. I'm forgetting it");  //  "Слишком длинный номер. Такие у меня в голове не помещаются"
        remoteNumber = "";
      }
    }
    else
    {
      // Чтобы отправить сообщение, добавьте к нему последний символ:
      if (inChar != '\r')
        remoteNumber += inChar;
    }
  }
}

См.также

  1. GSM Constructor
  2. GSM.begin()
  3. GSM.shutdown()
  4. GSMVoiceCall Constructor
  5. getVoiceCallStatus()
  6. ready()
  7. voiceCall()
  8. answerCall()
  9. hangCall()
  10. retrieveCallingNumber()

Внешние ссылки