Страница 5 из 8 ПерваяПервая 12345678 ПоследняяПоследняя
Показано с 41 по 50 из 71
  1. #41
    Пользователь
    Регистрация
    21.07.2010
    Возраст
    44
    Сообщений
    82
    Вес репутации
    186

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Цитата Сообщение от Chip Посмотреть сообщение
    Выполнение процедуры по таймеру.
    PHP код:
    //Выполнение процедуры по таймеру.
    #include <MsTimer2.h>
      
    static boolean output HIGH;
      
    void flash_led() 
    {
      
    digitalWrite(13, (output==HIGH) ? output=LOW output=HIGH);
    }

    void setup() 
    {
      
    MsTimer2::set(500flash_led); // 500ms интервал вызова процедуры
      
    MsTimer2::start();
    }

    void loop() 
    {
    //Здесь будет ваш код

    Спасибо!!! Таймер - это сила
    Переделываю весь код под модульность, с вызовом процедур по таймеру.
    Прикручиваю плавное изменение ШИМ....
    С уважением, Дмитрий.
    тел. 8 9I6 855 7Ч 95

  2. #42
    Пользователь
    Регистрация
    21.07.2010
    Возраст
    44
    Сообщений
    82
    Вес репутации
    186

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Так, я так понял что MsTimer2 позволяет только одно прерывание делать?
    Пока ответа не нашел - подключил Metro.h, но здесь тоже вопрос возник, хотя, может и не по душу этой библиотеки. Привожу текущий код:
    PHP код:
    /*
    Программа термоконтроля за системой охлаждения ДВС. Использует плавную регулировку по ШИМ.
    Может применяться и в других проектах, где исходные данные будет выдавать термистор (терморезистор).
    В качестве исходных данных - 1 проводной температурный датчик (термистор(терморезистор))
    двигателя с которого берется информация на штатную приборную панель автомобиля.
    Т.к. датчик имеет нелинейную зависимость сопротивления (падения напряжения),
    то необходима аппроксимация по заранее известным точкам. Чем выше температура,
    тем ниже сопротивление и больше падение напряжения.
    Для достоверной работы программы нужно ввести значения проходящего через датчик напряжения при
    различных температурах, желательно во всем диапазоне его работы.
    За аппроксимацию спасибо SBorovkov.
    */

    #include <Metro.h> //Библиотека регулярных действий по интервалу времени
    #include <MyLiquidCrystalRus.h> //Библиотека ЖК дисплея
    MyLiquidCrystalRus lcd(1211105432); //Используем ЖК дисплей
    #include <avr/pgmspace.h>  //Подключаем макрос PROGMEM

    //*********************Параметры для работы термоконтроля ОЖ двигателя
    #define EngineTemp1Count 14 //Количество точек аппроксимации
    #define DestinationEngineTemp 90        //Определяем нужную температуру двигателя
    #define EngineTempSensorPin 0 // Аналоговый вход для температурного датчика ОЖ ДВС
    #define EnginePowerVentPin 6 //ШИМ выход на вентиляторы основного радиатора ДВС
    //Задаем точки аппроксимации. Первая цифра - разность из 1024 и значения на входе от датчика
    //(сделано для того чтобы развернуть график зависимости и сделать так чтобы с ростом температуры значение увеличивалось)
    //не переводил в напряжение чтобы не морочиться и оперировать целыми числами с достаточной точностью;
    //вторая цифра - значение температуры (заранее измеренное) при данном значении на выходе с датчика.
    uint16_t EngineTemp1[EngineTemp1Count][2PROGMEM = {{0,0}, {471,46}, {635,56}, {702,64}, {723,71}, {729,75}, {764,80}, {793,85}, {81190}, {83695}, {862102}, {872110}, {882120}, {890130}};
    //************************Процедуры по таймеру*************************
    Metro PWMengineMetro Metro(10);  //Плавное изменение мощности вентиляторов каждые ХХ миллисекунд 
    Metro LCDoutMetro Metro(250);   //Выводим информацию на ЖК каждые ХХ миллисекунд 

        
    int EngineCurrentVentPWM//Текущая мощность вентиляторов ОЖ двигателя

    void setup() {
        
    Serial.begin(9600);
        
    lcd.begin(162);
        
    lcd.setCursor(0,0);
        
    lcd.print("****************");
        
    lcd.setCursor(0,1); 
        
    lcd.print("****************");
        
    delay(1000);
    }

    void loop() {
    //**********************Расчет всех параметров на основе температуры ОЖ двигателя  
        
    int EngineTargetVentPWM//Целевая точка мощности вентиляторов ОЖ двигателя
    //    int EngineCurrentVentPWM; //Текущая мощность вентиляторов ОЖ двигателя
        
    int EnginePowerVentPercent//Мощность вентиляторов на ОЖ двигателя в %
        
    int EngineTargetVentPercent//Задаваемая мощность вентиляторов на ОЖ двигателя в %
        
    uint16_t EngineRealTemp//Расчетное значение реальной температуры ОЖ двигателя
        
    int i;
        
    int EngineCount 20//Количество значений для усреднения
        
    int EngineIn 0//Начальная точка суммирования
        
    int EngineInSrednee//Усредненное значение со входа
        
    uint16_t EngineInTemp;  //Входное значение с датчика температуры
        
    uint16_t EngineInLeftTemp;
        
        
    //Цикл усреднения значения
        
    for (0EngineCounti++) {
        
    EngineIn EngineIn analogRead(EngineTempSensorPin);
        }
        
    EngineInSrednee EngineIn EngineCount//Вычисляем среднее значение

        
    EngineInTemp 1024 EngineInSrednee//Переворачиваем график падения напряжения
        
    i=EngineTemp1Count;
        do
        {
        
    i--;
        
    EngineInLeftTemp=pgm_read_word(&EngineTemp1[i][0]);
        }
        while ((
    i>=0)&&(EngineInTemp<EngineInLeftTemp));
        
    uint16_t EngineInRightTemp=pgm_read_word(&EngineTemp1[i+1][0]);
        
    uint16_t EngineOutLeftTemp=pgm_read_word(&EngineTemp1[i][1]);
        
    uint16_t EngineOutRightTemp=pgm_read_word(&EngineTemp1[i+1][1]);

        
    EngineRealTemp=EngineOutLeftTemp+(EngineOutRightTemp-EngineOutLeftTemp)*(EngineInTemp-EngineInLeftTemp)/(EngineInRightTemp-EngineInLeftTemp); //Вычисление значения реальной температуры

      
    float EngineVoltIn = (5.00 1024.00 EngineInSrednee); //Переводим входные данные к абсолютному значению напряжения для мониторинга
      
      //Если температура входит в определнные значения - запускаем вентиляторы на определенную мощность.
        
    if (EngineRealTemp DestinationEngineTemp 5EngineTargetVentPWM 0;
        if (
    EngineRealTemp >= DestinationEngineTemp 5EngineTargetVentPWM 36;
        if (
    EngineRealTemp >= DestinationEngineTemp 4EngineTargetVentPWM 72;
        if (
    EngineRealTemp >= DestinationEngineTemp 3EngineTargetVentPWM 108;
        if (
    EngineRealTemp >= DestinationEngineTemp 2EngineTargetVentPWM 144;
        if (
    EngineRealTemp >= DestinationEngineTemp 1EngineTargetVentPWM 180;    
        if (
    EngineRealTemp >= DestinationEngineTempEngineTargetVentPWM 216;
        if (
    EngineRealTemp >= DestinationEngineTemp 1EngineTargetVentPWM 255;
        
    EnginePowerVentPercent 100.00/255.00*EngineCurrentVentPWM//Вычисляем значение в процентах текущей мощности вентиляторов   
        
    EngineTargetVentPercent 100.00/255.00*EngineTargetVentPWM//Вычисляем значение в процентах задаваемой мощности вентиляторов

    //**********************Процедура плавного изменения мощности вентиляторов
    if (PWMengineMetro.check() == 1) { 
    if (
    EngineCurrentVentPWM EngineTargetVentPWM && EngineCurrentVentPWM 0){
    EngineCurrentVentPWM--;
    analogWrite(EnginePowerVentPinEngineCurrentVentPWM); // Уменьшаем мощность
    }
    if (
    EngineCurrentVentPWM EngineTargetVentPWM && EngineCurrentVentPWM 255)
    {
    EngineCurrentVentPWM++;
    analogWrite(EnginePowerVentPinEngineCurrentVentPWM); // Увеличиваем мощность
    }
    }

    //***********************Выводим все что нам нужно на ЖК дисплей
    if (LCDoutMetro.check() == 1){ 
    //  lcd.clear();
      
    lcd.setCursor(0,0);
      
    lcd.print("ВЛТ:");
      
    lcd.setCursor(4,0);
      
    lcd.print(EngineVoltIn); //Входное напряжение с датчика
      
    lcd.setCursor(8,0);
      if (
    EngineVoltIn 2.70) {
      
    lcd.print(" ТМП:");
      
    lcd.setCursor(13,0);
      
    lcd.print("MIN"); //Ниже минимальной точки аппроксимации
      
    }
      else if (
    EngineVoltIn 0.65){
      
    lcd.print(" ТМП:");
      
    lcd.setCursor(13,0);
      
    lcd.print("MAX"); //Выше максимальной точки аппроксимации
      
    }
      else {
      
    lcd.print(" ТМП:");
      
    lcd.setCursor(13,0);
      
    lcd.print(EngineRealTemp); //Аппроксимированная температура
      
    lcd.print("  ");    
      }
      
    lcd.setCursor(0,1);
      
    lcd.print("МОЩНОСТЬ:");
      
    lcd.setCursor(9,1);
      
    lcd.print(EnginePowerVentPercent); //Мощность вентиляторов
      
    lcd.print("  ");  
      
    lcd.setCursor(12,1);  
      
    lcd.print("%");
      
    lcd.setCursor(13,1);
      
    lcd.print(EngineTargetVentPercent); //Заданная мощность вентиляторов
      
    lcd.print("  ");    
    }  

    Вопрос: Почему мне пришлось вынести int EngineCurrentVentPWM в глобальные переменные, иначе не работает плавная регулировка... тупо стоит на 0.

    Ну и так, посмотрите, правильно ли двигаюсь? Может что-то можно оптимизировать или сделать более рациональным?
    Последний раз редактировалось paranom; 17.08.2010 в 03:24.
    С уважением, Дмитрий.
    тел. 8 9I6 855 7Ч 95

  3. #43
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Скажи, ты раньше на чем-то програмил? Уж слишком быстро разбираешься!

    Теперь ответы :-)

    У самого микроконтроллера AtMega168 три таймера. Но насколько я понял, как минимум один, и может два из используется встроенными структурами, которые обеспечивают работу систем Arduino. Итого - старайся выкрутиться одним таймером. Кстати, при грамотной его обработке его хватит в 90% не очень сложных случаев.
    К примеру, есть функции, которые надо вызывать каждые 50мс, а есть такие, которые надо вызывать каждую секунду. Ставишь таймер на 50мс и каждый 20 вызов таймера вызываешь ежесекундную функцию.

    По поводу переменной EngineCurrentVentPWM: Если ты объявил переменную глобальной (вне каких-либо функций) она существует все время выполнения программы. Соответственно, она хранит значение все время, пока программа выполняется.
    Если ты объявил переменную внутри функции, то эта переменная существует только внутри функции (либо еще меньше). Как код только из функции вышел, переменная исчезла и не занимает память. Когда произойдет следующий вход в функцию, переменная будет заново создана и будет иметь случайное значение, если ты ее не проинициализируешь.

    Соответственно, твоя функция loop вызывается постоянно. Но при каждом вызове все объявленные внутри переменные создаются заново! И их надо инициализировать, прежде чем из них что-то считать. Кстати, компилятор тебе наверняка выдавал предупреждения на счет чтения неинициализированных переменных.

    Когда ты перенес переменную EngineCurrentVentPWM вне loop, ты создал ее глобальной - она существует все время выполнения программы (т.е. вечность, поскольку loop вызывается вечно).

  4. #44
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Попробую объяснить понятнее про область видимости.

    Существует четыре области видимости: локальная, функция, файл и класс.
    Локальная:
    Есть блок, ограниченный фигурными скобками
    {
    ...
    int variable
    ...
    }
    Переменная существует с момента объявления и до закрывающей скобки блока.
    Как только скобка закрылась, переменная исчезла. Вместо троеточия может быть любой код. В том числе содержащий еще блок {...}


    Область видимости - функция
    int func(void)
    {
    ...
    int variable;
    ...
    }

    В таком случае переменная существует от момента определения и до конца функции. Как только функция завершила свою работу, переменная перестала существовать.

    Глобальная функция, область видимости - файл.

    int Counter;
    void loop()
    {
    Counter++;
    }

    Переменная существует все время выполнения программы.


    Пример -
    Код:
    int Counter;
    void Init(void)
    {
      Counter=5;
    }
    
    void loop(void)
    { // 1
     Counter++;
     int i;
     for (i=0;i<5;i++)
     { //2
       int j;
       j=i*2;
       if (j=10)
       { //3 
         int k;
         k=j+5;
         if (k>12)
         { //4
           ....
         }  //4
       } //3
     } //2
    } //1
    Переменная Counter объявлена глобальной. Соответственно, к ней можно обратиться в обеих функциях и переменная будет чество хранить значение.

    Переменная i объявлена с областью видимости - функция. К ней нельзя обратиться в фенкции init. Более того, значение переменной i в момент входа в функцию не определено и может быть абсолютно любым! К этой переменной можно обратиться в любом месте функции loop - с момента ее объявления и до конца выполнения функции, пока не закроется скобка с номером 1.

    Переменные j и k объявлены с локальной областью видимости. Переменная j существует пока процессор не выполнит закрывающую скобку 2. Переменная k - пока процессор не выполнит закрывающую скобку 3. Соответственно, при КАЖДОМ входе в цикл, переменная j имеет неизвестное значение.

    А теперь разумный вопрос - а зачем это все!?
    Ответа два:
    1. не всегда хочется, чтобы в любом месте кода были видны все остальные переменные.
    К примеру, пишешь мелкую функцию, внутри нее цикл от 1 до 10, она сделала свое дело и закончила работу. Она асболютно сепаратная - никого не волнует как у нее внутри называется переменная цикла. И если переменную цикла объявить внутри самой функции, то в результате переменная исчезнет по выходу из функции. Таким образом в каждой функции твоего модуля может быть определена переменная i и в каждой функции эта переменная будет своя!

    2. Компилятор при смотри на область видимости и соответственно размещает переменные в памяти. Вышли из области видимости переменной - память, занимаемую переменной освободили. Нужно занять под новую переменную - пожалуйста, снова выделит.

  5. #45
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Кстати, компиляторы нынче шибко умные...
    К примеру, компилятор понимает, что функция func - ничего не делает, просто перекладывает локальные переменные туда-сюда. И вообще не включает эту функцию с результат компиляции. Соответственно, вызова func тоже нет...
    Код:
    void func(void)
    {
     uint8_t i;
     uint8_t j=0;
     for (i=0;i<10;i++)
      j=j+i;
     uint8_t k;
     k=j+1;
     for (i=0;i<10;i++)
      k=k+i;
    }
    
    int main(void)
    {
    	func();
    }

  6. #46
    Пользователь
    Регистрация
    21.07.2010
    Возраст
    44
    Сообщений
    82
    Вес репутации
    186

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Спасибо, огромное! Теперь стало многое понятным.
    Цитата Сообщение от SBorovkov
    Скажи, ты раньше на чем-то програмил? Уж слишком быстро разбираешься!
    Ты знаешь, жизнь слишком коротка чтобы что-то в ней не понять. И тяжелее понять людей, чем машину ))) Если серьезно - то что есть опыт в радиотехнике и логических схемах в частности (в детстве баловался элементарной логикой и регистрами сдвига) + бэйсик со времен zxspectrum + php )))

    Цитата Сообщение от SBorovkov
    Существует четыре области видимости: локальная, функция, файл и класс.
    С областью видимости переменных я все понял.


    Цитата Сообщение от SBorovkov
    По поводу переменной EngineCurrentVentPWM: Если ты объявил переменную глобальной (вне каких-либо функций) она существует все время выполнения программы. Соответственно, она хранит значение все время, пока программа выполняется.
    Если ты объявил переменную внутри функции, то эта переменная существует только внутри функции (либо еще меньше). Как код только из функции вышел, переменная исчезла и не занимает память. Когда произойдет следующий вход в функцию, переменная будет заново создана и будет иметь случайное значение, если ты ее не проинициализируешь.
    Вот здесь мне не совсем понятно... EngineCurrentVentPWM у меня, по идее, может существовать только в рамках void loop, т.к. везде, где переменная используется находится в рамках функции loop. Так какого ей надо в глобали? И что значит проинициализировать?
    С уважением, Дмитрий.
    тел. 8 9I6 855 7Ч 95

  7. #47
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    На самом деле программа arduino выглядит примерно так:

    int main(void)
    {
    Init()
    Setup();
    for (;
    loop();
    }

    Предположим ты объявил переменную EngineCurrentVentPWM внутри loop().
    В этом случае, каждый раз, когда выполнение заходит в выполнение loop() (а он это делает как только завершится прошлый вызов loop, согласно коду выше), выделяется место под переменную EngineCurrentVentPWM и эта переменная каждый раз имеет некоторое, заранее неопределенное, значение. Каждый раз, когда код выходит из loop, память под все переменные функции loop освобождается.

    Проинициализировать = присвоить значение.

  8. #48
    Пользователь
    Регистрация
    21.07.2010
    Возраст
    44
    Сообщений
    82
    Вес репутации
    186

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Цитата Сообщение от SBorovkov Посмотреть сообщение
    На самом деле программа arduino выглядит примерно так:

    int main(void)
    {
    Init()
    Setup();
    for (;
    loop();
    }

    Предположим ты объявил переменную EngineCurrentVentPWM внутри loop().
    В этом случае, каждый раз, когда выполнение заходит в выполнение loop() (а он это делает как только завершится прошлый вызов loop, согласно коду выше), выделяется место под переменную EngineCurrentVentPWM и эта переменная каждый раз имеет некоторое, заранее неопределенное, значение. Каждый раз, когда код выходит из loop, память под все переменные функции loop освобождается.

    Проинициализировать = присвоить значение.
    Т.е. вывод EngineCurrentVentPWM в глобальную переменную неизбежен? В общем, я так понял, не стоит париться по этому поводу?
    С уважением, Дмитрий.
    тел. 8 9I6 855 7Ч 95

  9. #49
    Модератор
    Регистрация
    06.07.2008
    Возраст
    46
    Сообщений
    414
    Вес репутации
    436

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Считай, что да. В небольших программах переменные, в которых хранится некое текущее состояние, статус, настройки и тому подобное часто делают глобальными.

  10. #50
    Пользователь
    Регистрация
    21.07.2010
    Возраст
    44
    Сообщений
    82
    Вес репутации
    186

    По умолчанию Re: Как точно вычислить температуру со штатного датчика двигателя?

    Понял. Спасибо. Продолжу сегодня работу и, скорее всего, вынесу результат в отдельную тему, т.к. Могут возникнуть вопросы еще по железу.
    С уважением, Дмитрий.
    тел. 8 9I6 855 7Ч 95

Страница 5 из 8 ПерваяПервая 12345678 ПоследняяПоследняя

Информация о теме

Пользователи, просматривающие эту тему

Эту тему просматривают: 1 (пользователей: 0 , гостей: 1)

Ваши права

  • Вы не можете создавать новые темы
  • Вы не можете отвечать в темах
  • Вы не можете прикреплять вложения
  • Вы не можете редактировать свои сообщения
  •