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

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

  1. Un_ka

    Un_ka Гик

    Цикл не капризный, компилятор ещё не такое простит. А правильно было бы написать , если у вас переменная вне цикла инициализирована:
    Код (C++):
    for( ;i<3;i++)
     
  2. akl

    akl Гуру

    так как раз не очень правильно. инициализация переменной это всего лишь инициализация, а перед работой цикла надо еще чтобы у нее было правильное начальное значение, поэтому правильно как раз вот так
    Код (C++):
    for(i=0;i<3;i++)
    потому что иначе может быть невозможно понять с какого числа начнется счет
    то есть инициализация это и есть установление начального значения, но в любом случае это лучше делать непосредственно в цикле, иначе легко запутаться. По крайней мере в этом простом случае где надо тупо досчитать от нуля до 3.

    насчет области видимости тоже не понял. у него же i глобальная, так что в цикле это как раз она и есть.


    pulsein() тоже останавливает программу - оно ждет пока наступит тот или иной уровень сигнала чтобы начать отсчет. насколько я понял. по крайней мере если она без прерываний используется.
    чтобы сделать эту программу нормально походу придется научиться обращаться непосредственно с таймером атмеги.
    Хотя можно чуть проще - использовать для измерения входного сигнала прерывания. но это будет все равно кривее чем выход по таймеру
     
    Последнее редактирование: 11 июн 2020
  3. b707

    b707 Гуру

    я бы не торопился, пусть ТС сначала выложит тот код, что у него "не заработал".
     
  4. parovoZZ

    parovoZZ Гуру

    так можно рассуждать, когда в программировании как рыба в воде. А когда вчера в первый раз открыл IDE с примером, то блинк с делэем в самый раз. Через пару месяцев активного обучения можно уже пытаться что-то потяжелее брать на грудь.
     
  5. b707

    b707 Гуру

    а если не с делеем, а на миллис - то и не новичку вполне пойдет.

    Повторяю. нет смысла гадать - надо видеть код, почему у ТС "не пошло".
    Можно, конечно, заморочится с таймером, но на атмеге для таких частот подойдет только таймер1, 16 битный - а его жалко на такую ерунду расходовать :)
     
  6. Batman

    Batman Нуб

    Код я исправил.
    Теперь на таймере генерирую и 5 и 10и 1000гц.

    Но новая проблема. Не происходит захват, как положено, длительности импульса через функцию pulseIn.
    Вот осциллограмма того что приходит на вход Ардуино. А в монитор порта летит рандом.


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


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

    void loop()
    {
      for(i=0;i<3;i++)
        {
      Htime=pulseIn(2,HIGH,100000);    // прочитать время высокого логического уровня
      Ltime=pulseIn(2,LOW,100000);     // прочитать время низкого логического уровня
      Ttime = Htime+Ltime;
      frequency_in_raw=1000000/Ttime;  // получение частоты из Ttime в микросекундах
      frequency_in_avg+=frequency_in_raw;
      Serial.println(frequency_in_raw);
        }
     
        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/3; //коэффициент корреляции

    Serial.println(frequency_out);
    Serial.println('.');
    // delay(5);
    if(5>frequency_out>1000)
    {
       digitalWrite(9, LOW);
      }


    if(5<frequency_out<1000)
      {
      Timer1.setFrequency(frequency_out*2);                 // настроить частоту таймера в Гц
      Timer1.outputEnable(CHANNEL_A, TOGGLE_PIN);   // в момент срабатывания таймера пин будет переключаться
      }


     
        /*if (frequency_in_avg_rez<35)
        {
        noTone(8);
        }
        if (35<frequency_in_avg_rez)
        {
       tone(8, frequency_out);
        }*/


    }
     
  7. Batman

    Batman Нуб

    Вот такой сигнал приходит на вход Ардуино.
    [​IMG]
     
  8. b707

    b707 Гуру

    где вы вычитали подобные условия?
    Код (C++):
    if(5>frequency_out>1000)
    подсказка - в С/С++ они работают совсем не так, как вы думаете
     
  9. Batman

    Batman Нуб

    Подсказку изучу)) но вроде раньше когда в codevision avr что то пробовал делать с АЦП. Такое условие работало
     
  10. b707

    b707 Гуру

    так оно "работает". - в том смысле что компилируется и ошибок нет
    только результат немного не тот, что вы ожидаете
    Попробуйте записать его, например, вот так
    Код (C++):
    if  ( (5>frequency_out ) >1000)
    и посчитайте результат
     
  11. b707

    b707 Гуру

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

    Batman Нуб

    B707, спасибо большое за о обязательно изучу дополнительно.

    Сейчас другая проблема вылезла. не получается посчитать сигнал, который я выше приводил на осциллограмме. Считает что то, но это рандомные значения.
     
  13. b707

    b707 Гуру

  14. b707

    b707 Гуру

    а для "Спасибо" на форуме есть кнопка :)
     
  15. Batman

    Batman Нуб

    Чтобы не плодить темы.
    Алгоритм выше я звел, все работает. Но вычисление среднего занимает время. От этого прибор к которому подключена ардуино показывает изменяющееся значение скачками. Показывает одно, через две секунды прыгает на другое, еще через две прыгает на третье. А нужно плавное изменение.

    Как я понял, мне нужно вычисление бегущего среднего.
    Нашел пример(https://alexgyver.ru/lessons/filters/#среднее-арифметическое),
    Код (C++):
    // бегущее среднее
    float expRunningAverage(float newVal) {
      static float filVal = 0;
      filVal += (newVal - filVal) * k;
      return filVal;
    }

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


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

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

    // бегущее среднее
    float expRunningAverage(float frequency_in_raw) {
      static float frequency_in_avg = 0;
      frequency_in_avg += (frequency_in_raw - frequency_in_avg) * k;
      return frequency_in_avg;
    }

       

    //   frequency_in_avg_rez= frequency_in_avg/3;
    //   frequency_in_avg=0;
    // Serial.println(frequency_in_avg_rez);
    // Serial.println(' ');



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

    Serial.println(frequency_out);
    Serial.println('.');
    // delay(5);
    if  (frequency_out<5)
    {
       Timer1.stop();
     
      }


    if(frequency_out>5)
      {
      Timer1.setFrequency(frequency_out*2);                 // настроить частоту таймера в Гц
      Timer1.outputEnable(CHANNEL_A, TOGGLE_PIN);   // в момент срабатывания таймера пин будет переключаться
      }


    }

    но на строке float expRunningAverage(float frequency_in_raw) {
    получаю ошибку:

    что оно хочет ? :eek:

     
  16. Un_ka

    Un_ka Гик

    Функцию не надо объявлять внутри другой функции!
     
  17. akl

    akl Гуру

  18. Batman

    Batman Нуб

    прочитал, но все равно не поминаю. :rolleyes:
    пример отсюда , http://arduino.ru/Reference/FunctionDeclaration
    Код (C++):
    int myMultiplyFunction(int x, int y){
      int result;
      result = x * y;
      return result;
    }
    [​IMG]


    в моем случае

    Код (C++):
    float expRunningAverage(float frequency_in_raw) {
      static float frequency_in_avg = 0;
      frequency_in_avg += (frequency_in_raw - frequency_in_avg) * k;
      return frequency_in_avg;
    }
    Я вижу это как, функция expRunningAverage которая возвращает значение float frequency_in_avg, параметр передаваемый в функцию frequency_in_raw тип float
     
  19. Batman

    Batman Нуб

    ааа, то есть можно все сделать вот так. верно?
    Код (C++):
    int Htime;       // целочисленная переменная для хранения времени высокого логического уровня
    int Ltime;       // целочисленная переменная для хранения времени низкого логического уровня
    int Ttime;     // переменная для хранения общей длительности периода
    float  frequency_in_raw; // переменная для хранения частоты входной
    static float frequency_in_avg; // переменная для хранения частоты входной
    int frequency_in_avg_rez; // переменная для хранения частоты входной
    int frequency_out; // переменная для хранения частоты
    int i=0;
    float k = 0.1;
    #include "GyverTimers.h"


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

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

    // бегущее среднее
    //  static float frequency_in_avg = 0;
      frequency_in_avg += (frequency_in_raw - frequency_in_avg) * k;



    // Serial.println(frequency_in_avg_rez);
    // Serial.println(' ');



    frequency_out=frequency_in_avg/1; //коэффициент корреляции

    Serial.println(frequency_out);
    Serial.println('.');
    // delay(5);
    if  (frequency_out<5)
    {
       Timer1.stop();
     
      }


    if(frequency_out>5)
      {
      Timer1.setFrequency(frequency_out*2);                 // настроить частоту таймера в Гц
      Timer1.outputEnable(CHANNEL_A, TOGGLE_PIN);   // в момент срабатывания таймера пин будет переключаться
      }


    }
     
  20. akl

    akl Гуру

    можно сделать и так, но лучше все таки научиться применять функции.
     
    b707 нравится это.