Подскажите с функцией tone

Тема в разделе "Arduino & Shields", создана пользователем Batman, 10 июн 2020.

  1. Batman

    Batman Нуб

    Всех приветствую.
    Бьюсь безуспешно второй день с функцией tone.
    Задача алгоритма, вычислить частоту входного сигнала.
    Затем умножить ее или разделить, и выдать на другой пин ардуино конвертированную частоту. Генерация реализована через tone
    И вроде все OK, когда на вход подается реальная частота.
    Но если от входа отключить сигнал, то на выходе появляется меандр 30Гц(вижу его осциллографом). Хотя в исходнике прописано условие, если частота меньше 40ГЦ, то noTone.

    Код (C++):
    int Htime;       // целочисленная переменная для хранения времени высокого логического уровня
    int Ltime;       // целочисленная переменная для хранения времени низкого логического уровня
    float Ttime;     // переменная для хранения общей длительности периода
    float frequency_in_raw; // переменная для хранения частоты входной
    float frequency_in_avg; // переменная для хранения частоты входной
    float frequency_in_avg_rez; // переменная для хранения частоты входной
    float frequency_out; // переменная для хранения частоты
    int i=0;



    void setup()
    {
      // устанавливаем скорость передачи данных последовательного соединения.
      Serial.begin(9600);
      pinMode(2,INPUT);
    }

    void loop()
    {
      for(i=0;i<3;i++)
        {
      Htime=pulseIn(2,HIGH);    // прочитать время высокого логического уровня
      Ltime=pulseIn(2,LOW);     // прочитать время низкого логического уровня
      Ttime = Htime+Ltime;
      frequency_in_raw=1000000/Ttime;  // получение частоты из Ttime в микросекундах
      frequency_in_avg+=frequency_in_raw;
      Serial.println(frequency_in_raw);
        }
      if (i=4)
      {
        frequency_in_avg_rez= frequency_in_avg/3;
        frequency_in_avg=0;
     
        Serial.println(frequency_in_avg_rez);
       Serial.println(' ');
        i=0;
       }


    frequency_out=frequency_in_avg_rez*5; //коэффициент корреляции

    Serial.println(frequency_out);
      Serial.println('.');
    // delay(5);

        if (frequency_in_avg_rez<40 & frequency_in_avg_rez<4000)
        {
        noTone(8);
        }
     
        if (40<frequency_in_avg_rez)
        {
       tone(8, frequency_out);
        }

    }
     
    Последнее редактирование: 10 июн 2020
  2. Un_ka

    Un_ka Гуру

    Что в монитор com порта выводит?
     
  3. Batman

    Batman Нуб

    Код (C++):
    .
    inf
    inf
    inf
    inf
    inf
    .
    inf
    inf
    inf
    inf
    inf
    .
    inf
    inf
    inf
    inf
    inf
    .
     

    это если ничего на вход не подаю
     
  4. akl

    akl Гуру

    (frequency_in_avg_rez<40 & frequency_in_avg_rez<4000)
    немного не понял - тут побитовое сложение какое-то?
    хотя, если оба результата равны единице, то должно работать и так наверно

    надо при помощи вывода в компорт определить какие значения принимают эти переменные и заходит ли программа вообще в это условие

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

    Кстати а вдруг это & вообще воспринимается компилятором как адрес? ведь приоритет у адреса больше чем у операторов сравнения, а значит это как бы адрес перед переменной.
    короче попробуй вместо него && поставить. хотя вряд ли компилятор тупее меня. но вдруг
     
    Последнее редактирование: 10 июн 2020
  5. Batman

    Batman Нуб

    Логическое умножение, И. Согласен исправил. Но результат такой же.
    Даже правильнее ||

    Вывод не в воздухе, подтянут к земле.

    Я полагаю, что у меня какая то ошибка в коде, И поэтому получается такое поведение функции tone.
     
    Последнее редактирование: 10 июн 2020
  6. b707

    b707 Гуру

    30 Гц это не частота, это у вас 30 раз в секунду Тоне то включается. то выключается
     
  7. ZAZ-965

    ZAZ-965 Гуру

    @Batman, pulseIn() возвращает unsigned long, а у вас Htime и Ltime int.
     
  8. b707

    b707 Гуру

    По коду - во-первых, запись if (i=4) - явно не то, что вы хотели тут написать. Разницу между сравнением и присваиванием понимаете?

    Ну а во-вторых, обьясните, с чего вдруг у вас i станет равно 4 ? У вас же нигде в программе i не меняется, как выставили i =0 . так и оно и остается
     
  9. Batman

    Batman Нуб

    исправил. спс

    исправил.

    в цикле for
     
  10. b707

    b707 Гуру

    Батенька, да вы самых азов не знаете!
    Переменная i в цикле for и переменная, которую вы ввели в начале программы - две совершенно разные переменные.
    Почитайте что-нибудь на тему "Область видимости переменных"
     
  11. Batman

    Batman Нуб

    согласен, матчасть пойду учить. но ведь работало)

    в мониторе порта появляются верные значения

    1) измерение 1
    2) измерение 2
    3)измерение 3
    4) среднее
     
  12. b707

    b707 Гуру

    в этом коде работать НЕ МОГЛО.
    скорее всего исходный код был написан немного по другому. но вы со своими знаниями на это просто не обратили внимания.
     
  13. Batman

    Batman Нуб

    вот именно этот код, выдает в монитор порта нижеприведенные значения, когда на вход подаешь меандр 50гц.

    Код (C++):
    int Htime;       // целочисленная переменная для хранения времени высокого логического уровня
    int Ltime;       // целочисленная переменная для хранения времени низкого логического уровня
    float Ttime;     // переменная для хранения общей длительности периода
    float frequency_in_raw; // переменная для хранения частоты входной
    float frequency_in_avg; // переменная для хранения частоты входной
    float frequency_in_avg_rez; // переменная для хранения частоты входной
    float frequency_out; // переменная для хранения частоты
    int i=0;



    void setup()
    {
      // устанавливаем скорость передачи данных последовательного соединения.
      Serial.begin(9600);
      pinMode(2,INPUT);
    }

    void loop()
    {
      for(i=0;i<3;i++)
        {
      Htime=pulseIn(2,HIGH);    // прочитать время высокого логического уровня
      Ltime=pulseIn(2,LOW);     // прочитать время низкого логического уровня
      Ttime = Htime+Ltime;
      frequency_in_raw=1000000/Ttime;  // получение частоты из Ttime в микросекундах
      frequency_in_avg+=frequency_in_raw;
      Serial.println(frequency_in_raw);
        }
      if (i=4)
      {
        frequency_in_avg_rez= frequency_in_avg/3;
        frequency_in_avg=0;
        Serial.println(frequency_in_avg_rez);
       Serial.println(' ');
        i=0;
       }


    frequency_out=frequency_in_avg_rez*2; //коэффициент корреляции

    //Serial.println(frequency_out);
      Serial.println('.');
    // delay(5);

        if (frequency_in_avg_rez<40)
        {
        noTone(8);
        }
        if (40<frequency_in_avg_rez)
        {
       tone(8, frequency_out);
        }

    }

    Код (C++):
    48.29
    48.37
    48.37
    48.34
    .
    48.35
    48.28
    48.33
    48.32
    .
    48.33
    48.34
    48.33
    48.34
    .
    48.33
    48.16
    48.25
    48.25
    .
    48.33
    48.33
    48.34
    48.34
     
     
  14. Batman

    Batman Нуб

    изначально код был взят отсюда, https://radioprog.ru/post/573
    я лишь дописал три измерения, вместо одного.

    но самое главное, что все моменты я исправлю(ибо учусь), и не упираюсь, знаю что ошибки есть.
    не понятно почему функция tone 30гц на выходе дает. или же не функция. и не понимаю, как это исправить.
     
    Последнее редактирование: 10 июн 2020
  15. b707

    b707 Гуру

    ну да, все верно, у вас одна ошибка наложилась на другую :)

    Поскольку вы написали if ( i = 4) вместо "i == 4". то условие у вас оказалось всегда истинным (независимо от значения i )
    Строго говоря, никакое IF тут вообще не нужно, у вас программа выполняется последовательно - сначала проходит цикл for. потом исполняется усреднение и выдается результат.

    Чтобы убедится, что я прав - можете провести два эксперимента:
    1. Исправьте неверное условие i = 4 на правильное - i == 4 - код должен перестать печатать усредненное значение.
    2. Полностью удалите условие if ( i = 4) c окружающими скобками (содержание оставьте) - код будет продолжать работать как ни в чем не бывало
     
  16. Batman

    Batman Нуб

    b707, спасибо if убрал. действительно оно не нужно :rolleyes:


    теперь другой вопрос возник, функция tone минимально берет 31hz
    https://www.arduino.cc/reference/en/language/functions/advanced-io/tone/

    а мне нужно от 10гц, входящую 50гц превратить в 10.


    может быть посоветуете простенький пример, с помощью которого можно генерировать низкочастотный меандр?
     
  17. b707

    b707 Гуру

    для таких низких частот можно хоть обычный блинк применить.
    50 мс высокий уровень, 50 мс низкий - на выходе меандр 10 гц
     
  18. Batman

    Batman Нуб

    имхо не по шеншую, :eek:
    выходная частота будет от 10гц до 1000гц.
     
  19. b707

    b707 Гуру

    до 50 Гц блинк, выше - tone () :)
     
  20. Batman

    Batman Нуб

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