Набор номера как на старом телефоне

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

Есть стационарные телефонные аппараты у которых нет провода между трубкой и базой, но есть провод к розетке АТС. В нашем проекте у телефона останется провод между трубкой и базой, но пропадёт провод к розетке, так как связь будет осуществляться по сети GSM.

Описание работы ретро GSM телефона:

  • После подачи питания дождитесь кратковременного колокольного звонка, он оповещает о том, что модем GSM зарегистрирован в сети сотового оператора связи.
  • Телефон может принимать входящие звонки если трубка лежит на телефоне.
  • Можно снять трубку (при отсутствии входящего звонка) для перехода в режим «я занят».
  • Для ответа на входящий звонок нужно поднять трубку.
  • Для завершения разговора нужно положить трубку на телефон.
  • Набираемый номер должен состоять из 11 цифр и начинаться с цифры 7 или 8.
  • Можно набирать номера 01, 02, 03, 04, 100, предварительно указав код города 8(495).
  • Можно набирать номера 101, 102, 103, 104, 112.
  • Ввод цифр номера осуществляется поворотом заводного диска до нужной цифры с последующим самовозвратом диска в исходное положение.
  • Для совершения исходящего вызова выполните следующие действия:
    • Поднимите трубку при отсутствии входящего вызова.
    • Дождитесь появления гудка в трубке, он сигнализирует о наличии связи с сотовым оператором, следовательно, готовности к набору номера.
    • Наберите номер вызываемого абонента.
    • Если Вы ошиблись, опустите, поднимите трубку и повторите набор заново.
    • Во время набора номера гудок в трубке должен пропасть. Вместо него, во время возврата заводного диска, имитируется звук «щелчков» от набора номера.
    • После ввода последней (одиннадцатой) цифры номера дождитель появления сигнала вызова (длинные гудки или мелодия), или сигнала занят (короткие гудки).
    • Если абонент ответит на Ваш вызов, то установится голосовое соединение.
    • Если абонент разорвёт голосовую связь, Вы услышите сигнал занят (короткие гудки).
  • Завершить вызов, набор, соединение или разговор можно в любое время повесив трубку.
  • Динамик в телефонной трубке излучает звуки разговора и сигнал вызова (длинные гудки или мелодия), а все остальные сигналы формируются звукоизлучателем (зуммером), так же установленным в телефонную трубку.

Нам понадобится:

  • Arduino / Piranha UNO.
  • GSM/GPRS Shield A6.
  • Battery Shield.
  • Звук разговора и сигналов (можно выбрать один из вариантов):
    • Динамик + микрофон + зуммер с генератором (в корпусе трубки телефона).
    • Гарнитура с микрофоном + Trema зуммер с генератором.
  • Колокольный звонок (можно выбрать один из вариантов):
    • Колокольный звонок телефона + Trema силовой ключ + повышающий DC-DC преобразователь.
    • Звонок из соленоида + колокол + Trema силовой ключ + повышающий DC-DC преобразователь.
    • Звонок из сервопривода + колокол.
  • Дисковый номеронабиратель (если его нет в корпусе телефона).
  • Трема кнопка (если в корпусе телефона нет кнопки опускания трубки).
  • Корпус телефона.
    Для реализации проекта нам необходимо установить библиотеку:

  • iarduino_GSM.
  • Библиотеки SoftwareSerial и Servo входят в стандартный набор Arduino IDE.

О том как устанавливать библиотеки, Вы можете ознакомиться на странице Wiki — Установка библиотек в Arduino IDE.

Схема сборки:

Arduino / Piranha UNO:

Если Вы собираетесь разместить устройство в корпусе телефона, найдите место для установки Arduino / Piranha UNO и закрепите её.

Batery Shield:

Установите Battery Shield на Arduino / Piranha UNO:
Во время установки Battery Shield должен быть в выключенном состоянии.

GSM/GPRS Shield:

На Battery Shield установите GSM/GPRS Shield A6:

На плате GSM/GPRS Shield A6 имеется слот для SIM-карт и переключатель UART. Установите SIM-карту в слот, выберите положение переключателя RX-7/TX-8.

Trema Shield:

На GSM/GPRS Shield A6 установите Trema Shield:

Номеронабиратель:

Подключите номеронабиратель к выводам GND, D5, D6 и Трема кнопку к выводу D4:

Если Вы собираете устройство в корпусе телефона, то вместо Trema кнопки подключите кнопку фиксации опускания трубки, между выводами GND и D4).

Колокольный звонок:

Подключите модули управления колокольным звонком:

Напряжение питания 5В подводится на вход повышающего DC-DC преобразователя, а напряжение с его выхода (уровень напряжения регулируется потенциометром преобразователя) подводится к соленоиду или родной катушке звонка телефона, через Trema силовой ключ, управление которым осуществляется через вывод D2.

Колокольный звонок можно собрать не на соленоиде, а на сервоприводе, подключив его к выводу D2:

Преимуществом данной схемы является меньшее число деталей. Но в скетче нужно присвоить переменной modeBEEL значение 2 (разкомментировать строку в начале скетча), а так же указать углы сервопривода при которых боёк касается колокола и удаляется от него (углы указываются в функции funcBELL в конце скетча).

Устройство ввода/вывода звука:

Если Вы собираетесь разместить динамик, микрофон и зуммер в трубке телефона, то подключите их согласно схеме: (трубка соединяется с аппаратом четырехпроводным кабелем).

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

Если Вы не собираетесь размещать элементы ввода/вывода звука в телефонной трубке, то более простым вариантом является использование гарнитуры, которая подключается к соответствующему разъёму на плате GSM/GPRS Shield A6, а сигналы «готов к набору» и «занято» будут выводиться отдельно, через Trema зуммер, так же подключённый к выводу D3.

Если Вы не собираетесь размещать элементы ввода/вывода звука в телефонной трубке, но и не желаете использовать гарнитуру, то реализуйте вот такую схему:

Полная схема устройства:

Пример схемы с использованием гарнитуры и колокольного звонка на базе соленоида:

Код программы (скетч):

В скетче предусмотрена возможность выбора типа колокольного звонка modeBEEL=0,1,2 и алгоритма работы кнопки фиксирующей опускание телефонной трубки flgHANG=0,1. Для выбора необходимого значения закомментируёте существующее и разкомментируйте требуемое.

В скетче используются библиотеки iarduino_GSM, SoftwareSerial и Servo (две последние входят в стандартный набор Arduino IDE).

//  Телефонный аппарат с импульсным номеронабирателем на базе GSM/GPRS Shield A6
//  ============================================================================
                                             //
//  Определяем номера выводов:               //
    uint8_t pinBELL  = 2;                    // Вывод (выход) используемый для подключения силового ключа (для включения звонка вызова).
    uint8_t pinBEEP  = 3;                    // Вывод (выход) используемый для подключения излучателя звука (для вывода гудков в трубке).
    uint8_t pinHANG  = 4;                    // Вывод (вход)  используемый для подключения кнопки (NC) фиксирующей опускание телефонной трубки.
    uint8_t pinDIAL  = 5;                    // Вывод (вход)  используемый для подключения шунтирующего контакта (NO) номеронабирателя.
    uint8_t pinPULSE = 6;                    // Вывод (вход)  используемый для подключения тактирующего контакта (NC) номеронабирателя.
    uint8_t pinRX    = 7;                    // Вывод (вход)  используемый как линия RX (приём   ) программной шины UART (данные от GSM/GPRS Shield к  Arduino).
    uint8_t pinTX    = 8;                    // Вывод (выход) используемый как линия TX (передача) программной шины UART (данные к  GSM/GPRS Shield от Arduino).
                                             //
//  Определяем тип колокольного звонка:      //
    uint8_t modeBEEL = 0;                    // Колокольный звонок собран на соленоиде (электромагнитной катушке, собственном звонке телефона).
//  uint8_t modeBEEL = 1;                    // Колокольный звонок собран на электромоторе с бойком закреплённым к его ротору.
//  uint8_t modeBEEL = 2;                    // Колокольный звонок собран на сервоприводе  с бойком закреплённым к его качалке.
                                             //
//  Определяем алгоритм работы кнопки:       //
    bool    flgHANG  = 0;                    // 0-(NC) контакты кнопки замкнуты   при лежащей трубке.
//  bool    flgHANG  = 1;                    // 1-(NO) контакты кнопки разомкнуты при лежащей трубке.
                                             //
//  Объявляем переменные и функции:          //
    bool    flgPowerON = true;               // Определяем флаг подачи питания.
    uint8_t cntPULSE;                        // Объявляем переменную для подсчёта импульсов в последней набранной цифре (10 импульсов для цифры 0).
    uint8_t cntDigits;                       // Объявляем переменную для подсчёта набранных цифр номера.
    char    strNumber[12];                   // Объявляем строку для хранения номера вызываемого/вызывающего телефона (11 символов номера + символ конца строки).
    void    funcBELL(bool);                  // Объявляем функцию управления звонком (true - подаёт один колокольный звон, false - выключает колокольный звонок).
                                             //
//  Подключаем библиотеки:                   //
    #include <iarduino_GSM.h>                // Подключаем библиотеку iarduino_GSM для работы с GSM/GPRS Shield.
    #include <SoftwareSerial.h>              // Подключаем библиотеку SoftwareSerial для программной реализации шины UART.
    #include <Servo.h>                       // Подключаем библиотеку Servo для работы с сервоприводом (если колокольный звонок собран на сервоприводе).
                                             //
//  Создаём объекты:                         //
    iarduino_GSM   gsm;                      // Создаём объект gsm для работы с функциями и методами библиотеки iarduino_GSM.
    SoftwareSerial softSerial(pinRX, pinTX); // Создаём объект softSerial указывая выводы платы Arduino используемые в качестве линий RX и TX программной шины UART.
    Servo          srv;                      // Создаём объект srv для работы с функциями и методами библиотеки Servo (если колокольный звонок собран на сервоприводе).
                                                                                                            //
void setup(){                                                                                               //
    Serial.begin(9600);                                                                                     // █ Инициируем связь с монитором последовательного порта на скорости 9600 бит/сек.
    if(modeBEEL==2){srv.attach(pinBELL);}                                                                   // Назначаем объекту srv управление сервоприводом подключённым к выводу pinBELL           (если колокольный звонок собран на сервоприводе).
    else{pinMode(pinBELL,OUTPUT); digitalWrite(pinBELL,LOW);}                                               // Переводим вывод pinBELL  в режим выхода и устанавливаем на нём уровень логического «0» (если колокольный звонок собран на соленоиде/электромагните/электромоторе).
    pinMode(pinBEEP,  OUTPUT); digitalWrite(pinBEEP,  LOW );                                                // Переводим вывод pinBEEP  в режим выхода и устанавливаем на нём уровень логического «0».
    pinMode(pinHANG,  INPUT ); digitalWrite(pinHANG,  HIGH);                                                // Переводим вывод pinHANG  в режим входа  и подтягиваем его к Vcc.
    pinMode(pinDIAL,  INPUT ); digitalWrite(pinDIAL,  HIGH);                                                // Переводим вывод pinDIAL  в режим входа  и подтягиваем его к Vcc.
    pinMode(pinPULSE, INPUT ); digitalWrite(pinPULSE, HIGH);                                                // Переводим вывод pinPULSE в режим входа  и подтягиваем его к Vcc.
                                                                                                            //
    funcBELL(false);                                                                                        // Отключаем колокольный звонок входящего вызова.
    gsm.begin(softSerial);                                                                                  // Инициируем работу GSM/GPRS Shield, указывая объект (или класс) для работы с её шиной UART.
                                                                                                            //
//  Ждём готовность GSM/GPRS Shield к работе:                                                               //
    while(gsm.status()!=GSM_OK){delay(1000);}                                                               // Ждём завершения регистрации модема в сети оператора связи.
                                                                                                            //
//  Переводим звук на гарнитуру (к ней подключена трубка):                                                  //
    gsm.SOUNDdevice(GSM_HEADSET);                                                                           // Для громкой связи нужно вместо GSM_HEADSET указать GSM_SPEAKER.
                                                                                                            //
//  Информируем о готовности модуля кратковременным включением колокольного звонка:                         //
    if(flgPowerON){                                                                                         //
//  Если функция setup() выполняется в первый раз:                                                          //
        uint32_t i = millis() + 1000;                                                                       // Определяем длительность звонка готовности модуля.
        while(i>millis()){ funcBELL(true); } funcBELL(false);                                               // Включаем и отключаем колокольный звонок.
        flgPowerON = false;                                                                                 // Сбрасываем флаг подачи питания.
    }                                                                                                       //
    Serial.println(F("Готов к работе!"));                                                                   // █ Можно добавить код выполняемый однократно после готовности аппарата при подаче питания.
}                                                                                                           //
                                                                                                            //
void loop (){                                                                                               //
    /******* СОВЕРШАЕМ ИСХОДЯЩИЙ ЗВОНОК *******/                                                            // Для исходящего звонка нужно поднять трубку и набрать номер.
    if(digitalRead(pinHANG)^flgHANG){                                                                       // Если на входе pinHANG установлена логическая «1» (трубка снята).
//  Если трубка снята:                                                                                      //
        delay(100);                                                                                         // Подавляем дребезг поднятия трубки.
//      Готовимся к набору номера:                                                                          // 
        cntDigits = 0;                                                                                      // Сбрасываем счетчик набранных цифр номера (номер ещё не набирался).
        strNumber[0]='';                                                                                  // Чистим строку набираемого номера.
        digitalWrite(pinBEEP, LOW);                                                                         // Отключаем тоновый сигнал в трубке телефона (если он был включён).
        Serial.println(F("Трубка снята, проверяем готовность к набору номера ..."));                        // █ Можно добавить код выполняемый однократно при поднятии трубки для набора номера, до проверки наличия связи с оператором.
//      Проверяем готовность GSM/GPRS Shield к работе:                                                      //
        if(gsm.status()!=GSM_OK){                                                                           //
//      Если модуль не готов к работе (например, ошибка регистрации в сети):                                //
            Serial.println(F("Перезагрузка модуля"));                                                       // █ Выводим сообщение о перезагрузке модуля.
//          Заново инициируем работу с модулем:                                                             //
            setup();                                                                                        //
        }                                                                                                   //
//      Информируем о готовности к набору номера:                                                           //
        digitalWrite(pinBEEP, HIGH);                                                                        // Включаем тоновый сигнал в трубке телефона (оповещая о готовности к набору номера).
        Serial.println(F("Можно набирать номер ..."));                                                      // █ Можно добавить код выполняемый однократно при поднятии трубки для набора номера, после проверки связи с оператором.
        while(digitalRead(pinHANG)^flgHANG){                                                                // Входим в цикл, который будет завершён опусканием трубки на телефон.
//      Цикл выполняется всё время, пока снята трубка:                                                      //
            if(!digitalRead(pinDIAL)){                                                                      // Если шунтирующая контактная группа номеронабирателя замкнулась (значат набор цифры), то ...
//          Если начинается набор очередной цифры номера:                                                   //
                delay(20);                                                                                  // Подавляем дребезг шунтирующей контактной группы номеронабирателя.
                digitalWrite(pinBEEP, LOW);                                                                 // Отключаем тоновый сигнал в трубке телефона (если он был включён).
                cntPULSE=0;                                                                                 // Сбрасываем счётчик поступивших импульсов от номеронабирателя.
                Serial.print(F("Набирается цифра ... "));                                                   // █ Можно добавить код выполняемый однократно перед набором каждой цифры номера
                while(!digitalRead(pinDIAL) && (digitalRead(pinHANG)^flgHANG)){                             // Если чтение импульсов набираемой цифры разрешено (шунтирующие контакты номеронабирателя замкнуты) и трубка снята, то ...
//              Цикл выполняется пока набирается очередная цифра номера:                                    //
                    if(digitalRead(pinPULSE)){                                                              // Если поступил тактирующий импульс (импульсная контактная группа номеронабирателя разомкнулась), то ...
//                      Фронт импульса:                                                                     //
                        digitalWrite(pinBEEP, HIGH);                                                        // Включаем тоновый сигнал в трубке телефона.
                        delay(5);                                                                           // Подавляем дребезг импульсной контактной группы номеронабирателя.
                        digitalWrite(pinBEEP, LOW);                                                         // Отключаем тоновый сигнал в трубке телефона.
                        while(digitalRead(pinPULSE) && (digitalRead(pinHANG)^flgHANG)){delay(5);}           // Ждём завершения тактирующего импульса (замыкания импульсной контактной группы номеронабирателя) или опускания трубки.
//                      Спад импульса:                                                                      //
                        delay(5);                                                                           // Подавляем дребезг импульскной контактной группы номеронабирателя.
                        cntPULSE++;                                                                         // Увеличиваем счётчик полученных импульсов.
                    }                                                                                       //
                }                                                                                           //
                delay(20);                                                                                  // Подавляем дребезг шунтирующей контактной группы номеронабирателя.
//              Очередная цифра номера набрана:                                                             //
                if(cntPULSE){                                                                               // Если от импульсной контактной группы номеронабирателя поступил хотя бы 1 импульс, то ...
//              Если цифра набрана корректно (во время набора поступил хотя бы один импульс)                //
                    if(cntPULSE>=10){cntPULSE=0;}                                                           // Если поступило 10 импульсов, значит набрана цифра 0.
                    strNumber[cntDigits]=cntPULSE+48;                                                       // Сохраняем код набранной цифры в строку с набираемым номером.
                    cntDigits++;                                                                            // Переходим к следующей цифре набираемого номера.
                    strNumber[cntDigits]='';                                                              // Сохраняем код конца строки.
                    Serial.println(cntPULSE);                                                               // █ Можно добавить код выполняемый однократно после набора каждой цифры номера.
                }                                                                                           //
//              Проверяем введённые цифры номера:                                                           //
                if(     cntDigits==11                                                                       // Если набрано 11 цифр  номера *(***)***-**-** - обычный номер.
                    || (cntDigits==7 && strncmp("8495100", strNumber, 8)==0)                                // Если набрано 7  цифр  номера 8(495)100       - точное время    (городской).
                    || (cntDigits==6 && strncmp("849501",  strNumber, 7)==0)                                // Если набрано 6  цифр  номера 8(495)01        - пожарная служба (городской).
                    || (cntDigits==6 && strncmp("849502",  strNumber, 7)==0)                                // Если набрано 6  цифр  номера 8(495)02        - полиция         (городской).
                    || (cntDigits==6 && strncmp("849503",  strNumber, 7)==0)                                // Если набрано 6  цифр  номера 8(495)03        - скорая помощь   (городской).
                    || (cntDigits==6 && strncmp("849504",  strNumber, 7)==0)                                // Если набрано 6  цифр  номера 8(495)04        - газовая служба  (городской).
                    || (cntDigits==3 && strncmp("101",     strNumber, 4)==0)                                // Если набрано 3  цифры номера 101             - пожарная служба.
                    || (cntDigits==3 && strncmp("102",     strNumber, 4)==0)                                // Если набрано 3  цифры номера 102             - полиция.
                    || (cntDigits==3 && strncmp("103",     strNumber, 4)==0)                                // Если набрано 3  цифры номера 103             - скорая помощь.
                    || (cntDigits==3 && strncmp("104",     strNumber, 4)==0)                                // Если набрано 3  цифры номера 104             - газовая служба.
                    || (cntDigits==3 && strncmp("112",     strNumber, 4)==0)                                // Если набрано 3  цифры номера 112             - экстренные оперативные службы.
                ){                                                                                          //
//              Если номер набран полностью, то инициируем вызов ...                                        //
                    if(gsm.CALLdial(strNumber)){                                                            // Инициируем исходящий голосовой вызов на номер указанный в строке strNumber.
//                  Если исходящий вызов инициирован, ждём завершения набора номера ...                     //
                        Serial.println((String) "Набор номера " + strNumber + " ...");                      // █ Можно добавить код выполняемый однократно при начале набора номера.
                        while(gsm.CALLstatus()==GSM_CALL_OUT_DIAL && (digitalRead(pinHANG)^flgHANG)){}      // Цикл выполняется пока установлено состояние вызова "набирается номер" и снята трубка.
                        while(gsm.CALLstatus()==GSM_CALL_OUT_DIAL && (digitalRead(pinHANG)^flgHANG)){}      // Повторяем цикл на случай кратковременного изменения статуса вызова.
                        while(gsm.CALLstatus()==GSM_CALL_OUT_DIAL && (digitalRead(pinHANG)^flgHANG)){}      // Повторяем цикл на случай кратковременного изменения статуса вызова.
                        if(gsm.CALLstatus()==GSM_OK){                                                       //
//                      Если произошёл обрыв связи с оператором:                                            //
                            Serial.println(F("произошёл обрыв связи с оператором."));                       // █ Можно добавить код выполняемый однократно при обрыве связи с оператором.
                        }                                                                                   //
                        if(gsm.CALLstatus()==GSM_CALL_OUT_BEEP){                                            // Если установилось состояние вызова "дозвон", то ...
//                      Если начался дозвон, то ждём пока вызываемый абонент не ответит ...                 //
                            Serial.println(F("Ожидание ответа ..."));                                       // █ Можно добавить код выполняемый однократно при поступлении гудков у вызываемого абонента.
                            while(gsm.CALLstatus()==GSM_CALL_OUT_BEEP && (digitalRead(pinHANG)^flgHANG)){}  // Цикл выполняется пока установлено состояние вызова "дозвон" и снята трубка.
                            delay(500);                                                                     // Даём время для установки состояния вызова - "соединён".
                        }                                                                                   //
                        if(gsm.CALLstatus()==GSM_CALL_ACTIVE){                                              // Если установилось состояние вызова "соединён", то ...
//                      Если установлено активное голосовое соединение ...                                  //
                            Serial.println(F("Исходящее голосовое соединение установлено."));               // █ Можно добавить код выполняемый однократно при установлении активного голосового соединения.
                            while(gsm.CALLstatus()==GSM_CALL_ACTIVE && (digitalRead(pinHANG)^flgHANG)){}    // Цикл выполняется пока установлено активное голосовое соединение и снята трубка.
//                          Если голосовое соединение разорвано или его требуется разорвать ...             // 
                        }                                                                                   //
                        Serial.println(F("Разговор завершён."));                                            // █ Можно добавить код выполняемый однократно в момент завершения разговора.
                    }                                                                                       //
//                  Разрываем голосовое соединение, если разговор завершён опусканием трубки:               //
                    gsm.CALLend();                                                                          // Разъединяем голосовое соединение.
//                  Выводим короткие звуковые сигналы в трубку телефона...                                  //
                    while(digitalRead(pinHANG)^flgHANG){                                                    // Цикл выполняется пока снята трубка.
                        if(millis()%1000<500){digitalWrite(pinBEEP, HIGH);}                                 // Выводим   тоновый сигнал в трубке телефона в течении первых 500 мс каждых  1000 мс.
                        else                 {digitalWrite(pinBEEP, LOW );}                                 // Отключаем тоновый сигнал в трубке телефона в течении остального времени из 1000 мс.
                    }                         digitalWrite(pinBEEP, LOW );                                  // Отключаем тоновый сигнал в трубке телефона.
                }                                                                                           //
            }                                                                                               //
            gsm.CALLend();                                                                                  // Разъединяем голосовое соединение, если нам позвонили пока поднята трубка (до или в момент набора номера).
        }                                                                                                   //
        Serial.println(F("Трубка опущена на аппарат."));                                                    // █ Можно добавить код выполняемый однократно в момент опускания трубки на аппарат.
    }else{                                                                                                  //
    /******* ПРИНИМАЕМ ВХОДЯЩИЙ ЗВОНОК *******/                                                             // Для приёма входящих звонков трубка должна быть опущена.
//  Если трубка лежит на телефоне:                                                                          //
        delay(100);                                                                                         // Подавляем дребезг опускания трубки.
        digitalWrite(pinBEEP, LOW);                                                                         // Отключаем тоновый сигнал в трубке телефона (если он был включён).
        Serial.println(F("Трубка лежит на аппарате, режим ожидания звонка ..."));                           // █ Можно добавить код выполняемый однократно в момент перехода в режим ожидания входящего звонка
        while(!digitalRead(pinHANG)^flgHANG){                                                               // Входим в цикл, который будет завершён поднятием трубки с телефона.
//      Цикл выполняется всё время, пока трубка не поднята:                                                 //
            if(gsm.CALLavailable(strNumber)){                                                               // Функция CALLavailable() возвращает true если есть входящий дозванивающийся вызов, номер вызывающего абонента сохраняется в строку strNumber.
//          Если есть входящий вызов в режиме дозвона, то ждём ответа поднятием трубки ...                  //
                Serial.println((String)"Входящий вызов "+strNumber+", ждём поднятия трубки ...");           // █ Можно добавить код выполняемый однократно в момент поступления входящего звонка
                while(gsm.CALLavailable() && !(digitalRead(pinHANG)^flgHANG)){                              // Цикл выполняется пока есть входящий вызов в режиме дозвона и трубка не поднята.
//              Информируем колокольными звонками о наличии входящего вызова:                               //
                    while(millis()%4000<2000){funcBELL(true);}                                              // Включаем колокольный звонок в течении первых 2000 мс каждых 4000 мс.
                                              funcBELL(false);                                              // Отключаем колокольный звонок в течении остального времени.
                }                                                                                           //
                delay(100);                                                                                 // Подавляем дребезг поднятия трубки.
//              Проверяем почему был завершён цикл ожидания ответа ...                                      //
                if(digitalRead(pinHANG)^flgHANG){                                                           // Если трубка снята.
//              Если цикл завершён по причине поднятия трубки:                                              // 
                    Serial.println(F("Трубка снята, отвечаем на звонок"));                                  // █ Можно добавить код выполняемый однократно в момент поднятия трубки для ответа на входящий звонок.
                    if(gsm.CALLavailable()){                                                                // Функция CALLavailable() возвращает true если есть входящий дозванивающийся вызов.
//                  Если вызывающий абонент всё ещё ждёт ответа (поднятия трубки) ...                       //
                        gsm.CALLup();                                                                       // Отвечаем на вызов.
//                      Ждём пока состояние вызова "дозвон" не сменится ...                                 //
                        while(gsm.CALLstatus()==GSM_CALL_IN_BEEP){;}                                        // Функция CALLstatus() возвращает статус текущего голосового вызова, значение GSM_CALL_IN_BEEP указывает на наличие входящего дозванивающегося вызова.
                        if(gsm.CALLstatus()==GSM_CALL_ACTIVE){                                              // Функция CALLstatus() возвращает статус текущего голосового вызова, значение GSM_CALL_ACTIVE указывает на наличие активного голосового соединения.
//                      Если установлено активное голосовое соединение ...                                  //
                            Serial.println(F("Входящее голосовое соединение установлено."));                // █ Можно добавить код выполняемый однократно при установлении активного голосового соединения.
                            while(gsm.CALLstatus()==GSM_CALL_ACTIVE && (digitalRead(pinHANG)^flgHANG)){}    // Цикл выполняется пока установлено активное голосовое соединение и снята трубка.
                        }                                                                                   //
//                      Если голосовое соединение разорвано или требуется разорвать ...                     // 
                        Serial.println(F("Разговор завершён."));                                            // █ Можно добавить код выполняемый однократно в момент завершения разговора.
//                      Разрываем голосовое соединение, если разговор завершён опусканием трубки:           //
                        gsm.CALLend();                                                                      // Разъединяем голосовое соединение, это требуется если мы инициировали разрыв соединения опусканием трубки.
                    }                                                                                       //
//                  Выводим короткие звуковые сигналы в трубку телефона...                                  //
                    while(digitalRead(pinHANG)^flgHANG){                                                    // Цикл выполняется пока снята трубка.
                        if(millis()%1000<500){digitalWrite(pinBEEP, HIGH);}                                 // Выводим   тоновый сигнал в трубке телефона в течении первых 500 мс каждых  1000 мс.
                        else                 {digitalWrite(pinBEEP, LOW );}                                 // Отключаем тоновый сигнал в трубке телефона в течении остального времени из 1000 мс.
                    }                         digitalWrite(pinBEEP, LOW );                                  // Отключаем тоновый сигнал в трубке телефона.
                }else{                                                                                      //
//              Если цикл завершён по причине сброса вызова:                                                // 
                    Serial.println(F("Вызов завершён по причине сброса вызова"));                           // █ Можно добавить код выполняемый однократно в момент сброва вызова.
                }                                                                                           //
            }else{                                                                                          //
//          Если входящих вызовов в режиме дозвона нет:                                                     //
                if(gsm.status()!=GSM_OK){                                                                   //
//              Если модуль не готов к работе (например, ошибка регистрации в сети):                        //
                    Serial.println(F("Перезагрузка модуля"));                                               // █ Выводим сообщение о перезагрузке модуля.
//                  Заново инициируем работу с модулем:                                                     //
                    setup();                                                                                //
                }                                                                                           //
            }                                                                                               //
        }                                                                                                   //
    }                                                                                                       //
}                                                                                                           //
                                                                                                            //
//  Функция управления колокольным звонком:                                                                 // В зависимости от параметра (f) функция либо отключает колокольный звонок, либо подаёт один колокольный звон входящего вызова.
void funcBELL(bool f){                                                                                      // В данной функции можно регулировать тональность колокольного звонка, меняя задержку delay().
    if(modeBEEL==0){                                                                                        //
//  Если колокольный звонок собран на соленоиде (электромагнитной катушке):                                 //
        if(f){digitalWrite(pinBELL, HIGH); delay(20);                                                       // Если установлен флаг f, то: - подаём высокий уровень на выход pinBELL (силовой ключ замкнётся  , через катушку потечёт ток и боёк ударит о колокол),    ждём 20 мс.
              digitalWrite(pinBELL, LOW ); delay(20);                                                       //                             - подаём низкий  уровень на выход pinBELL (силовой ключ разомкнётся, катушка будет обесточена и боёк удалится от колокола), ждём 20 мс.
        }else{digitalWrite(pinBELL, LOW );}                                                                 // Если сброшен флаг f, то     - подаём низкий  уровень на выход pinBELL (силовой ключ разомкнётся, катушка будет обесточена и боёк удалится от колокола).
    }else if(modeBEEL==1){                                                                                  //
//  Если колокольный звонок собран на электромоторе:                                                        //
        if(f){digitalWrite(pinBELL, HIGH);}                                                                 // Если установлен флаг f, то  - подаём высокий уровень на выход pinBELL (силовой ключ замкнётся  , электромотор включится и боёк на его роторе начнёт бить по колоколу).
        else {digitalWrite(pinBELL, LOW );}                                                                 // Если сброшен флаг f, то     - подаём низкий  уровень на выход pinBELL (силовой ключ разомкнётся, электромотор отключится и боёк перестанет бить по колоколу).
    }else if(modeBEEL==2){                                                                                  //
//  Если колокольный звонок собран на сервоприводе:                                                         //
        if(f){srv.write(50); delay(20);                                                                     // Если установлен флаг f, то: - поворачиваем сервопривод на угол при котором боёк закреплённый к его качалке ударит о колокол,     ждём 20 мс.
              srv.write(60); delay(20);                                                                     //                             - поворачиваем сервопривод на угол при котором боёк закреплённый к его качалке удалится от колокола, ждём 20 мс.
        }else{srv.write(60);}                                                                               // Если сброшен флаг f, то     - поворачиваем сервопривод на угол при котором боёк закреплённый к его качалке удалится от колокола.
    }                                                                                                       //                               Вместо углов 50° и 60° необходимо указать Ваши углы (значение подбирается экспериментально).
}                                                                                                           //

В разделе функции funcBELL отвечающем за управление сервоприводом указаны углы 50° и 60° (три последние строки). Если Вы используете колокольный звонок на сервоприводе, измените угол 50° на тот при котором сервопривод ударяет бойком по колоколу, а угол 60° на тот при котором боёк удаляется от него.

Алгоритм работы скетча:

До кода Setup() определяются номера выводов, тип колокольного звонка, алгоритм работы кнопки фиксирующей опускание трубки, объявляются переменные и функции, подключаются библиотеки, и создаются объекты для работы с ними.

В коде setup() конфигурируются выбранные выводы, инициируется работа GSM/GPRS Shield, звук переводится на разъём гарнитуры, выполняется цикл ожидания готовности GSM/GPRS Shield к работе (регистрация в сети оператора). И после выполнения всех указанных действий выполняется оповещение о готовности к работе, путем включения колокольного звонка на 1 секунду.

Код цикла loop() разделён на две основные части: совершение исходящих звонков (данная часть выполняется если телефонная трубка снята) и приём входящих вызовов (данная часть выполняется если трубка лежит на телефоне).

Совершение исходящих звонков состоит из следующих действий:

  • Обнуление переменных, проверка связи с оператором, вывод сигнала в трубку телефона о готовности к работе.
  • Дальнейшие действия происходят в отдельном цикле, выход из которого возможен только если положить трубку на телефон. Так же в этом цикле постоянно сбрасывается голосовое соединение, не давая другим абонентам позвонить нам при снятой трубке.
  • Если начинается набор номера, то отключаем сигнал в телефонной трубке, подсчитываем количество импульсов набираемых цифр. После каждой введённой цифры из значение добавляется в строку с номером, которая проверяется на корректность (достижение 11 знаков, или совпадение с коротким номером). При желании Вы можете добавить или удалить некоторые короткие номера из скетча.
  • Если номер в строке корректен, то производится его набор, с дальнейшей проверкой состояния связи. Если связь установлена, то выполняется пустой цикл ожидания её разрыва.
  • При разрыве голосового соединения выполняется цикл вывода коротких звуковых сигналов в телефонную трубку. Этот цикл выполняется постоянно, пока не положить трубку на телефон.

Приём входящих вызовов состоит из следующих действий:

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

В конце скетча определена функция управления колокольным звонком. Данная функция принимает один параметр типа bool (true — ударить в колокол и освободить его / false — освободить колокол). В зависимости от значения переменной modeBEEL функция работает с колокольными звонками собранными на базе соленоида, родного звонка телефона, сервопривода или электромотора.

Ссылки:

  • Библиотека iarduino_GSM.
  • Arduino / Piranha UNO.
  • GSM/GPRS Shield A6.
  • Wiki — GSM/GPRS Shield A6.
  • Battery Shield.
  • Wiki — Battery Shield.
  • Динамик.
  • Микрофон.
  • Зуммер с генератором.
  • Trema силовой ключ.
  • Повышающий DC-DC преобразователь
  • Соленоид.
  • Сервопривода.
  • Дисковый номеронабиратель.
  • Трема кнопка.

Kuksillo,
22 августа 2016, 12:01

Программы Android Звонилки

Скачать на Трешбоксе

Android 3.2+   Другие версии

Rotary Dialer 1.3. Скриншот 1

Rotary Dialer 1.3. Скриншот 2

Rotary Dialer 1.3. Скриншот 3

Rotary Dialer 1.3. Скриншот 4

Rotary Dialer 1.3. Скриншот 5

Rotary Dialer 1.3. Скриншот 6

Rotary Dialer 1.3. Скриншот 7

Номеронабиратель, иммитируюший старый телефонный аппарат. Смотрится интересно. При наборе номера слышно соответствующий звук.

Лучший Telegram-канал про технологии (возможно)

Telegram-канал создателя Трешбокса про технологии

Скачать Rotary Dialer 1.3

5,1 МБ

RU

Проверен

Вирусы не найдены


QR

Разрешения (8)

Android 3.2+

Все платформы

Добавил: Cyanidesh

Скачать Rotary Dialer 1.2

4,7 МБ

RU

Проверен

Вирусы не найдены


QR

Разрешения (7)

Android 2.3+

Все платформы

Добавил: vasyash

Скачать Rotary Dialer 1.1

4 МБ

Проверен

Вирусы не найдены


QR

Разрешения (7)

Android 1.6+

Все платформы

Последнее изменение: 22 августа 2016, 12:01

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

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

Если нужно ответить кому-то конкретно,
лучше нажать на «Ответить» под его комментарием

Время прочтения
5 мин

Просмотры 17K

image

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

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

Кроме телефонного аппарата нужны следующие устройства:

  • любой кнопочный мобильный телефон;
  • литий-ионный аккумулятор типоразмера 18650 и устройство для его зарядки (Power bank);
  • кабель разветвитель USB BF micro (мама) -2 x USB BM micro (папа);
  • контроллер на микросхеме ATtiny2313.

Электроника

Схема связки микроконтроллера с мобильником и номеронабирателем.

image

Первым делом, следует припаять к контактам кнопок мобильного телефона, шлейф проводов и соединить с контроллером. А контроллер научить набирать номер при наборе соответствующих цифр на диске. Скорее всего компоновка кнопок у большинства мобильников будет аналогичная. Для моей схемы, необходимо: по одному общему проводу на группы кнопок 1-4-7, 2-5-8-0 и 3-6-9 и по проводу на каждую цифру; по паре проводников на кнопки вызова, отмены и на кнопку переключения с одной SIM карты на вторую.

image

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

При наборе номера на диске, размыкается пара контактов (нормально замкнутые НЗ контакты, зеленый-желтый провод). Количество размыканий (Р) соответствует цифре набора, допустим при наборе «1» = З-Р-З, «2» = З-Р-З-Р-З и т.д. При достижении пальцем упора, замыкается другая пара контактов, кратковременно (белый-коричневый). Используя эти две пары контактов можно запрограммировать процесс набора номера.

image

Плата контроллера выполнена с учетом формы аппарата и расположения контактной группы под трубкой.

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

image

image

Power bank (на фото в черном корпусе) продолжает работать как источник, начиная с нагрузки примерно 20мА, если будет меньше он отключится в спящий режим. Поэтому около рычага был вмонтирован геркон, который при поднятии трубки подает питание к светодиоду, через сопротивление (на принципиальной электрической схеме не изображен). Светодиод, как нагрузку, следует использовать помощнее, маленький не подойдет. Также можно питать схему непосредственно от контактов аккумулятора, но тогда нужно настроить питание микроконтроллера на низкое напряжение, при прошивке fuse битов. От аккумулятора идет питание платы контроллера и мобильного телефона. Зарядка аккумулятора Power bank осуществляется через USB шнур. Даже без ухода в спящий режим, емкость аккумулятора для питания платы контроллера и мобильного телефона, хватает на две недели автономной работы.

image

image

Можно вмонтировать гарнитуру мобильного телефона в трубку, вместо капсюлей микрофона и динамика. Но я пошел другим путем и переделал трубку с капсюлями и аудио разъемом «3,5мм». Подключение: основания разъема — на желтый и белый провода («-» микрофона (360Ω) и «-» динамика (340 Ω)); второго от основания кольца — на коричневый («+» микрофона); третьего от основания кольца — на зеленый («+» динамика). Цвета проводов для каждой модели аппаратов отличаются! Добавочные сопротивления были подобраны исходя из сопротивлений катушек гарнитуры, микрофона (2000Ω) и динамика (45 Ω). Для других моделей мобильного телефона сопротивления должны отличаться. Экспериментируйте с мобильниками, с которыми уже простились, не факт, что они выживут после таких манипуляций!

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

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

Алгоритм работы контроллера

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

while(1)
{
1. Процедура кратковременного нажатия на кнопку «отмена звонка» от кнопки под трубкой (при снятой трубке контакт постоянно замкнут).
2. Если на PA1 есть 0 (НР контакт замкнут, трубка снята), то переходим по коду ниже:
— Включаем PD4 (выход моб. телефона из режима сна);
— Выключаем PD4.
3. Если на PA1 есть 1 (НР контакт разомкнут, нажали кнопку, отмена вызова при входящем), то переходим по коду ниже:
— Запуск счетчика таймера кнопки под трубкой.
Если контакты кнопки под трубкой были разомкнуты менее 3,1 сек, то далее по коду ниже:
— Включаем PD2 (отмена вызова при входящем звонке);
— Выключаем PD2;
— Обнуление номера, для нового набора при исходящем звонке.
Если контакты кнопки под трубкой были разомкнуты, более и равно 3,1 сек, то далее по коду ниже:
— Обнуление состояния контактов кнопки под трубкой, чтобы начать цикл заново
— Обнуление номера, для нового набора при исходящем звонке.
4. Процедура опроса контактов PD0 и PD1:
— Если на PD1 есть 0 (НР контакт замкнут) и на PD0 есть 1 (НЗ контакт разомкнут), то переходим по коду ниже:
— Счетчик набранной цифры номера (от 0 до 9);
— Если на PD0 есть 0 (НЗ контакт замкнут), то переходим по коду ниже;
— Если на PD1 есть 1 (НР контакт разомкнут), то переходим по коду ниже;
— Счетчик количества набранных цифр (всего 11: 87.ХХ.ХХХХХХХ).
5. Процедура автоматического переключения на вторую SIM карту (на другой оператор связи, в зависимости от префикса кода номера, 3-я и 4-я цифры):
— Выделение десятков в префиксе p10=n*10;
— Выделение единиц в префиксе p1=n;
— Формирование префикса для условия ниже;
— Если префикс оператора №1 переключение на SIM1. При следующем наборе, если префикс тот же, переключения на SIM1 не произойдет
— Включаем PD3
— Выключаем PD3
— Если префикс оператора №2 переключение на SIM2. При следующем наборе, если префикс тот же, переключения на SIM2 не произойдет
— Включаем PD3
— Выключаем PD3
6. Процедура включения светодиода «переключение на SIM1»:
— чтобы светодиод не работал при ждущем режиме;
— переключение.
7. Включение выводов портов PB и PD для кнопок 0-9.
8. Процедура вызова по набранному номеру.
}

Пятый пункт для автоматического переключения на другую SIM карту, кому-то будет не нужен, и его можно исключить. Код достаточно примитивный (if{} else{} в бесконечном цикле), поэтому и работает стабильно.

Старайтесь при конструировании не повредить корпус сверлением и пилением, используя штатные отверстия и щели. Наверняка GSM стандарт окончательно устареет, появятся новые стандарты связи, которые можно будет использовать, внедрив в этот же ретро-корпус.

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

September 19 2018, 20:10

Category:

  • История
  • Cancel

Документальный ролик, показывающий, как пользоваться новым телефоном.

«В субботу в полночь в Нью-Йорке все старые номера телефонов заменят на новые. Вместо прежней службы операторов начнёт работать автоматическая система набора. В течение недели жителям города пришлют новые телефонные справочники.

Как пользоваться телефоном с дисковым набором?

Перед тем, как кому-либо позвонить, проверьте номер в новом справочнике. Затем снимите трубку и послушайте сигнал – он должен быть непрерывным. Такой сигнал показывает, что линия готова, можно звонить. Держа в одной руке трубку, набирайте на диске нужный номер. Например, вам нужно набрать 233. Вы ставите палец на цифру 2 и отводите диск в сторону до упора, а затем отпускаете, позволяя диску вернуться в исходное положение. Таким же образом набираются все остальные цифры. Далее вам остаётся только ждать соединения – вы услышите длинный прерывистый сигнал. Если линия занята, сигнал будет частым.»

Понравилась статья? Поделить с друзьями:
  • На углях полярные зори телефона номер телефона
  • Набор добавочного номера на стационарном телефоне
  • На углях когалым номер телефона
  • Набор добавочного номера на мобильном телефоне
  • На телефоне стоит переадресация на неизвестный номер