ЭБУ для авто

Тема в разделе "Микроконтроллеры AVR", создана пользователем Yerabdi, 25 сен 2017.

  1. Yerabdi

    Yerabdi Нуб

    Здравствуйте всем написал код в ардуино нано, для управление м102 мотора мерседес W124 с обьемом 2,0 литра.Там инжектор механический КЕ-ДЖетроник.ЭБУ для управление газовыми форсунками.
    Все работает впрыск на холостом ходу 4,5 мс, по датчику разрежение определяю нагрузку на двигателе.
    Чем больше разрежение впрыску добавляется до 10 мс, есть проблема если ставлю таймер с прерыванием 1 миллисекунд нормально работает.Но если таймер прерывание ставлю на 100 микросекунд впрыск становится то больше то меньше гонит.
    Может в коде что то не хватает или не правильно написано подскажите(частота микроконтроллера атмега328Р 16МГц)
    //*************************
    Код (C++):
    #include <avr/io.h>
    #include <avr/interrupt.h>
    volatile unsigned int Danie_Rx,Temp=0,shet_adc;
    volatile unsigned char danie_tx;
    volatile unsigned int ACP/*razrezhenie MAP */,ACP_2,ob2=0,T,ob,time_ob=0;
    volatile float acp_2=0,oborot_2=0;
    volatile unsigned char zad_t=45,zad_t2=0,zad_t3=0,otsechka,top_cor=0,zad_vpris2=0,vprisk_top2=0,top_cor2=0,zad_vpris4=0,zad_vpris5=0;
    volatile unsigned char val,ad2=0,ad,val2,sel_chanel,pauza=0,acp2,oborot,signal_xx,correct=0;
    volatile unsigned char zapusk=0,Period=0,period_2=0,off,off2,raz_xx,raz_uskor=0,signal_xx2=0;
    volatile unsigned char ch=1,zn_acp,zn_temp=0,per_adc,zn_adc,per_ch=0;
    #define PIN_INT0 PD2
    //******timer0*****
    ISR (TIMER0_COMPA_vect)
    {
         T++;//shet zadershki impulsa
         ob++;//shet oborota
       
    }
    //*********ADC***********
    ISR (ADC_vect)
    {
         for (int i=0;i<20;i++)
         {ACP=ACP+ADCW;
         }
        ACP_2=ACP/20;
        ADCSRA |=(1<<ADSC);
        return ACP_2;
    }


    int main(void)
    {   DDRC &=~(1<<PC1);//vhod MAP datchika
        DDRD &=~(1<<PD7);//vhod otsechka na XX dvigatelya
        PORTD |=(1<<PD7);
        DDRD |=(1<<PD6);//vihod na force
        PORTD &=~(1<<PD6);
        DDRD |=(1<<PD4);//vihod na klapan reduktora
        PORTD &=~(1<<PD4);
        //********ACP************
        ADCSRA |=(1<<ADEN)
        //разрешение использование АЦП
        |(1<<ADIE)|(0<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);//8 delim
        ADMUX |=(1<<REFS0)|(0<<MUX3)|(0<<MUX2)|(0<<MUX1)|(1<<MUX0);//подключили к 5В
        //arduino A1
        ADCSRA |=(1<<ADSC);
         //настраиваем вывод на вход
        DDRD &= ~(1<<PIN_INT0);
        //включаем подтягивающий резистор
        PORTD |= (1<<PIN_INT0);
        //********Timer0***********
        TCCR0A |= (1<<WGM01);  // Режим CTC (сброс по совпадению)
        TIMSK0 |=(1<<OCIE0A);  // Разрешить прерывание по совпадению
        OCR0A=24; //24 по достижении уходить в вектор прерывании, 24 равняется к 100 microsec
        TCNT0=0;
        TCCR0B |=(1<<CS01)|(1<<CS00); // CLK/64

        asm("sei");
        while(1)
        {
           vprisk_top2 = vprisk_top();//rashet zadershki vpriska topliva
           zad_vpris4 = rashet_vprisk();
           oborot = shet_ob(); //shet oborota
           top_cor = Cor();//toplivnaya karta
           otsechka = sw_but();//signal s otsechk
         
         
        }    
       
    }
    //*****rashet vprisk***
    int rashet_vprisk ()
    {
      acp2=ACP_2*0.1;
      zad_t2 = (acp2/oborot)*10;
      if ((acp2 >= 60) && (otsechka==0))//uskorenie motora
        {  
          zad_vpris2=zad_t2;
          if (oborot > 20 && acp2 > 60)
          { raz_uskor=1; top_cor2=top_cor; }
        if ((oborot < 20) && (raz_uskor == 1)&&(acp2 < 60))//pri otsecke motora na 1200 oborotah
        {zad_vpris2=0; top_cor2=0; raz_uskor=0;   }
        }
         else
         {  zad_vpris2=0; top_cor2=0; }
        //pri zapuske motora esli oboorti nizhe 300rpm    
       
        if ( otsechka == 1 )  //motor XX
        {zad_vpris2=0;top_cor2=0;
        }
        zad_t3=zad_t;
         if (T == zad_t3 )
      {PORTD &=~(1<<PD6);Period=1;}
       
    }
    //*****vprisk_top*****
    int vprisk_top ()
    {  
        asm("cli");
        //***********************
        static uint8_t prev_in_state = 0xFF;
        uint8_t in_state = PIND;              // фиксируем состояние всех входов
        static uint8_t currBit = 4;                  // бит вх in2 arduino. порта
        if ((in_state & currBit) != currBit) { // если на канале низкий уровень
        if ((prev_in_state & currBit) == currBit) { // если в прошлый раз был высокий  
       
        }
        }
        else if ((prev_in_state & currBit) != currBit) { // вх. импульс закончился ?
        // вычисляем, при каком знач.счетчика micros надо гасить соотв. выход
        zapusk++;
        if (Period==0 )//est vpris na vihode
        {
        PORTD |=(1<<PD6);
        T=0;
        }  
        if (Period == 1)//net vpriska na vihode
        {Period=0;
         }
        }
        prev_in_state = in_state; // сохраняем текущее состояние входов  
       
        //************************    
        asm("sei");
    }

    //********oboroti**************
    int shet_ob ( )
    {  
       if (zapusk == 1 && off ==0)//start sheta oborota
         {
          ob=0;    off=1;off2=0;
         }
        if (zapusk == 2 && off2 ==0)//fiksasya oborota
        {
        time_ob=ob;//sohranim znachenie oborota
        zapusk=1;off2=1;
        off=0;
        ob=0;
        ob2=(30/(time_ob*0.0001))/60;//rashet oborota v sekundu
        }
         return ob2;
     
    }
    //*********************
    //*******signal s XX *********
    int sw_but( )

    {
        static char butcount;
        if (!(PIND&(1<<PD7)))//esli podaetsya minus na vhod Pin7 nuzhno pottynut na plus 30 KOm
        {
            if (butcount < 5)
        {  butcount++;   }
        else {  signal_xx=1; }
        }      
        else
        {  if (butcount > 0)
        {butcount --;   }
          else
        {   signal_xx =0;     }
        }  
        return signal_xx;
       
    }
    //*******topliv karta*************
    int Cor ( )
    {  
        if ((oborot >= 20) && (oborot <= 80)&&(acp2 > 60)&&(raz_uskor == 1))
          { if ((oborot >= 20) && (oborot <= 25) && (acp2 >= 60)&&(acp2 <= 70))//esli oboroti vishe 1200 i Map bolshe >58
        {correct=4;
        return correct;
        }
          if ((oborot >= 20) && (oborot <= 25) && (acp2 >= 70)&&(acp2 <= 80))
        {correct=6;
        return correct;
        }
         if ((oborot >= 20) && (oborot <= 25) && (acp2 >= 80)&&(acp2 <= 90))
        {correct=8;
        return correct;
        }
          if ((oborot >= 20) && (oborot <= 25) && (acp2 >= 90)&&(acp2 <= 100))
        {correct=10;
        return correct;
        }
          if ((oborot >= 20) && (oborot <= 25) && (acp2 >= 100)&&(acp2 <= 120))
        {correct=10;
        return correct;
        }
            //*************    
        if ((oborot >= 25) && (oborot <= 33) && (acp2 >= 60)&&(acp2 <= 70))//esli oboroti vishe 1500 i Map bolshe >58
        {correct=5;
        return correct;
        }
          if ((oborot >= 25) && (oborot <= 33) && (acp2 >= 70)&&(acp2 <= 80))
        {correct=10;
        return correct;
        }
         if ((oborot >= 25) && (oborot <= 33) && (acp2 >= 80)&&(acp2 <= 90))
        {correct=15;
        return correct;
        }
          if ((oborot >= 25) && (oborot <= 33) && (acp2 >= 90)&&(acp2 <= 100))
        {correct=20;
        return correct;
        }
          if ((oborot >= 25) && (oborot <= 33) && (acp2 >= 100)&&(acp2 <= 120))
        {correct=20;
        return correct;
        }
         if ((oborot >= 33)&&(oborot <= 40) && (acp2 >= 60)&&(acp2<=70))//esli oboroti vishe 2000 i Map bolshe >58
        {correct=10;
        return correct;
        }
         if ((oborot >= 33)&&(oborot <= 40) && (acp2 >= 70)&&(acp2<=80))
        {correct=20;
        return correct;
        }
         if ((oborot >= 33)&&(oborot <= 40) && (acp2 >= 80)&&(acp2<=90))
        {correct=25;
        }
        if ((oborot >= 33)&&(oborot <= 40) && (acp2 >= 90)&&(acp2<=100))
        {correct=30;
        return correct;}
        if ((oborot >= 33)&&(oborot <= 40) && (acp2 >= 100)&&(acp2<=120))
        {correct=30;
        return correct;}
        if ((oborot>=40)&&(oborot <= 50) && (acp2 >= 60)&&(acp2<=70))//esli oboroti vishe 2500 i Map bolshe >58
        {correct=10;
        return correct;}
        if ((oborot>=40)&&(oborot <= 50) && (acp2 >= 70)&&(acp2<=80))
        {correct=10;
        return correct;}
        if ((oborot>=40)&&(oborot <= 50) && (acp2 >= 80)&&(acp2<=90))
        {correct=20;
        return correct;}
        if ((oborot>=40)&&(oborot <= 50) && (acp2 >= 90)&&(acp2<=100))
        {correct=30;
        return correct;}
        if ((oborot>=40)&&(oborot <= 50) && (acp2 >= 100)&&(acp2<=120))
        {correct=30;
        return correct;}
       
        if ((oborot>=50)&&(oborot <= 58) && (acp2 >= 60)&&(acp2<=70))//esli oboroti vishe 3000 i Map bolshe >58
        {correct=10;
        return correct;}
        if ((oborot>=50)&&(oborot <= 58) && (acp2 >= 70)&&(acp2<=80))
        {correct=20;
        return correct;}
        if ((oborot>=50)&&(oborot <= 58) && (acp2 >= 80)&&(acp2<=90))
        {correct=30;
        }
        if ((oborot>=50)&&(oborot <= 58) && (acp2 >= 90)&&(acp2<=100))
        {correct=35;
        return correct;}
        if ((oborot>=50)&&(oborot <= 58) && (acp2 >= 100)&&(acp2<=120))
        {correct=35;
        return correct;}
       
        if ((oborot >= 58)&&(oborot <= 66) && (acp2 >= 60)&&(acp2 <=70))//esli oboroti vishe 3500 i Map bolshe >58
        {correct=1;
        return correct;}
        if ((oborot >= 58)&&(oborot <= 66) && (acp2 >= 70)&&(acp2 <=80))
        {correct=20;
        return correct;}
        if ((oborot >= 58)&&(oborot <= 66) && (acp2 >= 80)&&(acp2 <=90))
        {correct=30;
        return correct;}
        if ((oborot >= 58)&&(oborot <= 66) && (acp2 >= 90)&&(acp2 <=100))
        {correct=37;
        return correct;}
        if ((oborot >= 58)&&(oborot <= 66) && (acp2 >= 100)&&(acp2 <=120))
        {correct=37;
        return correct;}
             
          }    
         else {correct=0;;  return correct;  }
    }
     
     
  2. Yerabdi

    Yerabdi Нуб

    [​IMG]
     

    Вложения:

  3. Yerabdi

    Yerabdi Нуб

    Сигнал берется от тахометра для подачи впрыска на форсы
     
  4. sslobodyan

    sslobodyan Гик

    А вы не замеряли время затрачиваемое в прерывании? Похоже, что оно как минимум равно 100мкс, а может и больше. Отсюда у рывки. Попробуйте при входе в прерывание поднять любую свободную ногу, а перед выходом опустить ее. И затем гляньте осциллографом либо цифроанализатором сколько времени нога будет поднята и с каким интервалом. Мне такой метод отладки здорово помогает.
    PS Задавать топливную карту через ифы очень не удобно. Лучше через N-мерный массив. Тогда ее можно хранить в епроме и настраивать без перекомпиляции кода. Да и накосячить в этой куче сравнений вероятность меньше.