Управление муфтой 4вд по скорости и газу

Тема в разделе "Схемотехника, компоненты, модули", создана пользователем mihaj109, 4 окт 2020.

  1. SergeiL

    SergeiL Оракул Модератор

    А это не коррелируется с со схемой "спд3.jpg" cигнал SPD.
    Так как на картинке работать не будет. Если на входе 12В импульсы - диод не пропустит.
     
  2. parovoZZ

    parovoZZ Гуру

    20К в делителе е пойдёт. Необходимо не более 10К. Нижний резистор делителя любого номинала.
     
  3. mihaj109

    mihaj109 Нерд

    сспасибо!
     
  4. mihaj109

    mihaj109 Нерд

    я очень извинюь, не в том направлении нариовал... но диод спасет синал на мозги? не повлияют резисторы для ардуино, на логические 0 и 1т для мозгов машины?
     
  5. mihaj109

    mihaj109 Нерд

    Ура! наконец получилось посчитать импульсы с данных о скорости. Где-то на тоета форумах находил данные по частоте - и они совпали. При 60 км/ч частота около 42 Гц и период 24мс. Поизучал эти прерывания, так до конца и не разобрался. Данные считал по коду алексгивер, но немного изменим его
    Код (C++):
    // измеряем длину импульсов на 2 пине
    // расчёт каждые 100мс
    void setup() {
      Serial.begin(9600);
      attachInterrupt(0, isr, RISING);  // прерывание на D2
    }
    uint32_t tmr;
    volatile int counter = 0;
    void isr() {
      counter++;  // импульсы считаем тут
    }
    void loop() {
      if (millis() - tmr >= 100) {
        long prd = (millis() - tmr) / counter;
        counter = 0;
        Serial.println(prd);  // в миллисекундах
        tmr = millis();
      }
    }
    Вопрос может и глупый, но без него я не могу в голове сложить картину.
    №1 войды иср и луп работают параллельно друг другу или друг за другом циклично?
    Алгоритм такой: при достижении 80км/ч (17мсек) муфта отключается. при снижении до 60 (24мсек) снова включается. Лично мне не нужно знать сккорость/период имп-сов каждый луп, и выводить в сериал тоже нет. мне надо , чтоб алгоритм выполнялся. Но как я понял длительность всё равно надо где-то считать. и тут вопрос
    №2 При скорости 10км/ч импульс =140мсек, расчет происходит каждые 100. Что случится в таком случае? prd будет равно 140,100 или случайная величина меньше 100? я это к чему - при низкой скорости, мне не нужно, чтоб тормозился луп, который опрашивает педаль газа. в таком случае самая большая задержка будет 100мсек или она будет равна длительности реального импульса? или можно этот расчет перенести в войд иср?
    Вопрос №3 в моем коде используется таймер2 для увеличения частоты шим на 3пине. прерывания на пин2 не помешают нормальному исполнению кода? и нужно ли убирать delay из луп? т.е. при тапке в пол мне не важно какая скорость, должно работать при любой. просто повлияет ли это на следующий подсчет импульса?..
    Код (C++):
     for  (; funkcia > 175; funkcia = 104)       //тапка в пол
      {
        analogWrite (PWM, 150);               //на муфту 8В - 150 или 7В - 130, чтоб не буксануть на светофоре
        delay (1500);                             // на секунду              вможет сделать 2/2 сек
        for ( int y = 150; y > 1; y--)            //затем плавно до нуля
        {
          analogWrite (PWM, y);                   // опускаем напр. муфты, чтоб легче ехала, оставляя всех позадли
          delay (10);                             // втечение секунды
        }
    либо как вариант использовать пульсИн, там можно ограничить там-аут, например 30мсек. Может так будет эффективнее?
     
  6. parovoZZ

    parovoZZ Гуру

    Там что, несколько ядер, чтобы в параллель программу выполнять?
    ISR - обработчик прерывания останавливает выполнение текущей инструкции до тех пор, пока не выполнится программа прерывания.
     
  7. SergeiL

    SergeiL Оракул Модератор

    В момент срабатывания, текущую уже не остановить, она выполнится до конца.
    Следующая будет приостановлена прерыванием, если это прерывание разрешено.
     
  8. mihaj109

    mihaj109 Нерд

    Если период большой, например полсекунды, у меня луп встанет на эти полсекунды? Мне так не нужно. я могу тогда как-то игнорировать долгие периоды?
     
  9. mihaj109

    mihaj109 Нерд

    поправьте если я неправильно понял. при появлении импульса луп паузится буквально на мгновение, в иср добавляется единица, и луп продолжается выполняться. Это всё быстро правильно? просто при большом периоде импульса, в prd иногда будут оставаться старые значения, правильно? ну а при маленьком периоде, луп просто чаще будет паузиться. хм.. я переживал за маленькую скорость, а теперь надо переживать за большую..
    мне кажется пульсИн будет эффективнее, нет? там можно ограничить там-аут, например 30мсек. и не терять время в лупе или это создаст свои проблемы?
     
  10. mihaj109

    mihaj109 Нерд

    А здесь, я так понимаю импульсы считаются уже не в лупе. но при этом чем дольше импульс, тем больше паузится луп, правильно?
    Код (C++):
    #define Tone_PIN 12 // выход частоты– см. в тексте
    #define IN_PIN 2 //вход обнаружения частоты

    volatile unsigned long ttime = 0;        //Время срабатывания датчика
    volatile unsigned long time_old = 0;        //Предыдущее время
    volatile uint8_t flag=0;

    void setup() {
      pinMode(IR_PIN, OUTPUT); //на выход
      pinMode(IN_PIN, INPUT); //вывод обнаружения частоты на вход
      attachInterrupt(0, impuls, RISING);   //Прерывание по нарастающему фронту на D2
      Serial.begin(9600);
    // tone(Tone_PIN, 8);
    delay(1000);
    }

    void impuls(){
        if(flag!=1) ttime =micros()-time_old;
        time_old = micros();
    }

    void loop() {
          flag=1; //чтобы ttime не изменилось в процессе вывода
            Serial.println(ttime);
           if (ttime!=0) {//на случай отсутствия частоты
           float f = 1000000/float(ttime); // Вычисляем частоту сигнала в Гц
            Serial.println(f,1);}
          flag=0;
          delay(500);
    }
     
  11. b707

    b707 Гуру

    Поясните, откуда этот вывод?
    Не надо придумывать - смотрите в исходник.
    Время работы прерывания никак не зависит от частоты импульса, луп тормозится только на время выполнения этих двух строк:
    Код (C++):
     if(flag!=1) ttime =micros()-time_old;
        time_old = micros();
    ни в коем случае
     
    Последнее редактирование: 18 окт 2020
  12. b707

    b707 Гуру

    Обязательно, этот ваш код никуда не годится, его надо переписывать без delay
    Код (C++):
    for  (; funkcia > 175; funkcia = 104)       //тапка в пол
      {
        analogWrite (PWM, 150);               //на муфту 8В - 150 или 7В - 130, чтоб не буксануть на светофоре
        delay (1500);                             // на секунду              вможет сделать 2/2 сек
        for ( int y = 150; y > 1; y--)            //затем плавно до нуля
        {
          analogWrite (PWM, y);                   // опускаем напр. муфты, чтоб легче ехала, оставляя всех позадли
          delay (10);                             // втечение секунды
        }
     
  13. mihaj109

    mihaj109 Нерд

    Попробовал тут на скорую руку. пульсИн работает, но выдает меньшее значение, примерно на треть. на крайний случай сойдет, но попытаюсь разобраться с этими прерываниями
    тот длинный код я не тестировал, не до конца понял, зато попробовал короткий .поигрался задержкой и меня это устроило. при медленном импульсе, я просто получаю -1 или 100.
    А вместо делэй так можно?
    Код (C++):

    uint32_t myTimer1;

    voidsetup(){}
    voidloop(){
    for(; funkcia >175; funkcia =104)     //тапка в пол
    {
        analogWrite (PWM, 150);             //на муфту 8В - 150 или 7В - 130, чтоб не буксануть на светофоре
     
    if(millis() - myTimer1 >= 1000){ // вместо delay (1000);    
    myTimer1 = millis()
    }             // на секунду            
       for(int y =150; y >1; y--)           //затем плавно до нуля
       {
          analogWrite (PWM, y);                 // опускаем напр. муфты, чтоб легче ехала, оставляя всех позадли
       
    if(millis() - myTimer1 >= 10){ // вместо delay (10);    
    myTimer1 = millis()
    // втечение секунды
       }

    }
     
  14. parovoZZ

    parovoZZ Гуру

    эффективнее работать с таймером напрямую. Он (таймер) будет сам считать период между импульсами, сам фильтровать фронт, когда подсчёт закончится, сам положит значение в регистр счёта (capture). Далее можно самому забирать это значение или заставить таймер вызывать обработчик прерывания. Тут уж кому как удобнее. Все эти пульсины - это игрушки для школьников.
     
  15. mihaj109

    mihaj109 Нерд

    Тему не забросил.
    Написал я код с прерываниями, но почему-то на муфту подается сильно меньшее напряжение, чем должно. Посмотрите пожалуйста,что я набросал, может где-то ошибся. Получается значение funkcia маленькое, ну там до 50 доходит, хотя должно до 100 доходить и мне показалось, что отзывчивость хуже стала. т.е. если раньше мгновенно напряжение на муфте менялось
    , то теперь как-будто чуть тормозит. управление по скорости вроде норм отрабатывает. Может это из-за частых прерываний? но там до 15мсек. не знаю много это или нет
    Код (C++):
    #define PWM 3                //на транзистор, управляющий муфтой
    #define GAZ A0               // сигнал с педали газа 1.48-4.4 В
    float funkcia = 0;           //пепременная функции y=4x-6, идет на pwm
    const float a = 0.3609;       // =255*20/1024/13,8 (это 4)    13.8 напр борт сети.
    const float b = 109.2989;      // =255*(6-0,085)/13,8 (это 6)
    int gaz;                       // педаль газа 0 - 1023
    volatile uint32_t tmr;
    volatile int counter = 0;
    volatile long prd;
    void setup()
    {
      pinMode (PWM, OUTPUT);     //Выводим на пин пвм(3) шим
      //  увеличение частоты шим Пины D3 и D11 - 31.4 кГц
      TCCR2B = 0b00000001;  // 1
      TCCR2A = 0b00000001;  // phase correct
      Serial.begin(9600);
      attachInterrupt(0, isr, RISING);  // прерывание на D2
    }

    void isr()
    {
      counter++;  // импульсы считаем тут
    }

    void loop()
    {
      gaz = analogRead(GAZ);                       // Педаль газа от 300 (1.5В) до 800
      funkcia = analogRead(GAZ) * a - b;          //При макс на муфте 13.8В функция пересчитана под биты ацп
      /////////  если педаль не нажата  //////////
      if (gaz < 310) funkcia = 0;               //При меньше 1.48В по мнению МК , на муфте 0

      ///////////  обычный блок   ///////////

      if (gaz > 573) funkcia = 100;       // при педали больше 2.8, напр на муфте 5.2В
      analogWrite (PWM, funkcia);             // иначе от 0 до 5.2 В по формуле y=4x-6

     
        if (millis() - tmr >= 1000)
        {
        prd = (millis() - tmr) / counter;  // сигнал скорости. 35мсек - 40кмч, 25- 60 кмч
        counter = 0;
        tmr = millis();
        }
     
        if (prd <=35)                                //при 40кмч и больше на муфте 0
        {
          uint32_t tmr2 = millis();
          analogWrite (PWM, 0);
          while (prd <=35)                  
          {
            if (millis() - tmr2 >= 500)
            {
            prd = (millis() - tmr2) / counter;
            counter = 0;
            tmr2 = millis();
         
            }
          }
        }
     
    }
     
  16. mihaj109

    mihaj109 Нерд

    Нашел еще такой код, на таймере. чем он лучше\хуже прерываний?
    Код (C++):
    void setup() {
      Serial.begin(9600);
      // настройка таймера 1 на внешнее тактирование
      TCCR1A = 0;
      TCCR1B = 0b00000110;
    }
    uint32_t tmr;
    void loop() {
      if (millis() - tmr >= 500) {
        long prd = (millis() - tmr) / TCNT1;
        prd = 1000 / prd;
        TCNT1 = 0;      // TCNT1 - счётчик таймера 1
        Serial.println(prd);  // в миллисекундах
        tmr = millis();
      }
    }