Микродоработка кода дтмф генератора

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем Ariadna-on-Line, 8 апр 2021.

  1. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Тема касается генерации ДТМФ с помощью двух пинов Ардуины. Может кому пригодится.
    В аналоговой технике - либо двух-полярное питание, либо искусственная средняя точка. Именно поэтому часто возникает вопрос с полярностью электролитических конденсаторов на входе. Цифра, превращаемая в аналоговый сигнал, не всегда корректно формирует среднюю точку. В коде не было это учтено, поэтому генерируемый сигнал "скакал серединой" относительно GND. Перезарядка разделительного конденсатора на выходе приводила к выбросам напряжения. Из-за этого терялось начало сигнала. Введенные команды ( откоментированы) устраняют недочеты исходника библиотечного примера кода.
    Код (C++):

    #include <Tone.h>

    Tone freq1;
    Tone freq2;

    const int DTMF_freq1[] = { 1336, 1209, 1336, 1477, 1209, 1336, 1477, 1209, 1336, 1477, 1633, 1633, 1633, 1633, 1209, 1477 };
    const int DTMF_freq2[] = {  941,  697,  697,  697,  770,  770,  770,  852,  852,  852,  697,  770,  852,  941,  941,  941 };
                             //  0     1     2     3     4     5     6     7     8     9     A     B     C     D     *     #
    /////////////////////////////////////////////////////////////////
    void setup()
    {
      Serial.begin(9600);         // PinA --резистор 10K---> ДТМФ <--- резистор 10K-- PinB

      pinMode(11, OUTPUT);        // Установим комплементарные потенциалы на выводах
      pinMode(12, OUTPUT);        // чтобы задать "среднюю точку" для аналоговой части.
      digitalWrite(11, HIGH);     // Этим предотвращаются выбросы напряжения от
      digitalWrite(12, LOW);      // перезарядки разделительных конденсаторов.
      delay(1000);

      freq1.begin(11);
      freq2.begin(12);
    }
    /////////////////////////////////////////////////////////////////
    void playDTMF(uint8_t number, long duration)
    {
      freq1.play(DTMF_freq1[number], duration);
      freq2.play(DTMF_freq2[number], duration);
    }
    /////////////////////////////////////////////////////////////////
    void loop()
    {
        int i;
        uint8_t phone_number[] = { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 };  // Любая комбинация 0-9, A-D, *, #

      for(i = 0; i < sizeof(phone_number); i ++)
      {
      Serial.print(phone_number[i], 1);
      Serial.print(' ');

      playDTMF(phone_number[i], 500);
      delay(100);          
      }                           // Функция PlayDTMF() не возвращает выходы в исходное
      delay(400);                 // состояние. В течении 500mC не дает управлять выходами
      pinMode(11, OUTPUT);        // Поэтому требуется эта задержка.
      pinMode(12, OUTPUT);        // Чтобы задать "среднюю точку" для аналоговой части.
      digitalWrite(11, HIGH);     // Этим предотвращаются выбросы напряжения от
      digitalWrite(12, LOW);      // перезарядки разделительных конденсаторов.

      Serial.println();
      delay(3000);
    }
    /////////////////////////////////////////////////////////////////
     
    Последнее редактирование: 9 апр 2021
  2. Ariadna-on-Line

    Ariadna-on-Line Гуру

    В предыдущем коде формировалась "средняя точка напряжения " между пакетами передачи. Для БПФ желательна четкая средняя точка между каждой двух-тоновой посылкой. Поэтому немного изменен алгоритм.
    Код (C++):
      playDTMF(phone_number[i], N);    // N мСек - длительность двух-тона.
      delay(N);                        //Значение длительности паузы должно быть равно
      pinMode(11, OUTPUT);             // значению длительности двух-тона. Стандарт - N >= 100 мСек.
      pinMode(12, OUTPUT);             // Это потому, что два процесса работают параллельно.
      digitalWrite(11, LOW);           //
      digitalWrite(12, HIGH);          //
      delay(200);                      // 200 мСек - Пауза между знаками
     
    Последнее редактирование: 29 апр 2021
  3. Ariadna-on-Line

    Ariadna-on-Line Гуру

    Еще немного изменен код
    Код (C++):
    playDTMF(phone_number[i], N);      // N мСек - длительность двух-тона.
      delay(N + 2);                    // Значение длительности паузы должно быть чуть больше
      pinMode(11, OUTPUT);             // значения длительности двух-тона. Стандарт - N >= 100 мСек.
      pinMode(12, OUTPUT);             // Это потому, что два процесса работают параллельно.
      digitalWrite(11, LOW);           //
      digitalWrite(12, HIGH);          //
      delay(200);                      // 200 мСек - Пауза между знаками
    При равной длительности тона и паузы иногда происходит невыполнение последующей команды.