Тема касается генерации ДТМФ с помощью двух пинов Ардуины. Может кому пригодится. В аналоговой технике - либо двух-полярное питание, либо искусственная средняя точка. Именно поэтому часто возникает вопрос с полярностью электролитических конденсаторов на входе. Цифра, превращаемая в аналоговый сигнал, не всегда корректно формирует среднюю точку. В коде не было это учтено, поэтому генерируемый сигнал "скакал серединой" относительно 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); } /////////////////////////////////////////////////////////////////
В предыдущем коде формировалась "средняя точка напряжения " между пакетами передачи. Для БПФ желательна четкая средняя точка между каждой двух-тоновой посылкой. Поэтому немного изменен алгоритм. Код (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 мСек - Пауза между знаками
Еще немного изменен код Код (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 мСек - Пауза между знаками При равной длительности тона и паузы иногда происходит невыполнение последующей команды.