/* Fuoz.cpp * * Created: 26.06.2020 13:19:36 * Author : Nikolay.Korsakov */ //#include #include #include #include int Out = 9; int offOut = 10; volatile int F14 = 3; //Флаг 1 и 4 //volatile int rps = 0; // обороты двигателя в секунду volatile long TimeSpark = 0; //расчётное время до ВМТ. int rpm = 0; // Обороты в минуту. float TS; //расчётное время искрообразования с учётом УОЗ volatile int nUg = 0; volatile int t2 = 0; volatile long nCountRPM = 0; volatile long nCountRx = 0; volatile long nCountRPM_old = 0; int dr = 1; //Массив задержек УОЗ имеет 16 уровней расхода воздуха по МАР, наподобие SECU. Массив сохраним в еепром, иначе зймёт много ОЗУ. Не стал заморачиваться и полностью редактировать каждый уровень по отдельности(просто скопировал). //Думаю каждый всё равно под себя будет редактировать сам. Первая строка массива должна соответствовать углам холостого хода, т.к. концевика карбюратора пока нет. const uint16_t retlw[16][77] PROGMEM = {{83,166,222,190,187,185,166,151,138,128,119,122,145,156,157,162,154,150,147,144,145,146,147,148,148,149,147,145,143,138,137,133,131,128,127,123,120,117,115,114,111,109,106,104,102,100,98,96,94, 92,91,89,87,86,84,83,81,80,79,78,78,76,75,74,73,72,71,70,69,69,68,67,66,66,65,64,63}, {500,400,444,381,344,343,308,318,292,276,280,267,266,265,255,263,258,254,250,250,240,233,231,225,217,213,208,204,201,194,189,186,185,182,180,175,171,169,167,163,163,163,159,156,156,153,150,150,147,148,148,145,143,140,138,136,136,134, 132,135,133,131,129,127,125,123,121,120,118,116,115,113,112,110,109,108,106}, {208,167,431,512,500,444,400,394,368,346,339,333,328,309,329,311,300,294,288,279,271,267,263,262,256,250,244,242,240,232,228,224,220,216,213,207,204,199,196,192,189,187,183,179,177,173,170,168,165,162,160,158,155,152,149,147,144,142, 140,138,135,133,131,129,127,126,124,122,120,119,117,116,114,113,111,110,108}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,180,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}, {183,183,183,183,183,183,175,170,166,164,162,162,162,162,164,165,167,169,171,173,175,177,188,182,186,182,178,174,170,167,163,160,157,154,151,149,146,144,141,139,136,134,132,130,128,126,124,122,120,118,116,115,113,111,109,108,106,105, 103,101,100,98,97,95,94,93,91,90,89,87,86,84,83,82,81,79,78}}; // до 8000 об/мин. */ volatile long nCountRPM_old2 = 0; long ledt = 0; int nADC_Conv = 0; int retlw10 = 45; int nRetlw = 0; volatile int nADC; //Значение входа ДАД. int nAD_OK = 0; int nADOK = 0; int nOK = 0; volatile long CKPS = 0; volatile int mCKPS = 0; volatile long nCountCKPS_imp = 0; volatile int nCountCKPS_1 = 0; volatile int nCountCKPS_0 = 0; volatile int dlit = 0; volatile int dlitn = 0; volatile int UOZ = 0; volatile int Zub = 42; volatile int Zub14 = 12; float Dlit = 0; volatile int ZUB = 0; volatile int TS48 = 0; volatile int TS48TS = 0; volatile int nTS48TS = 0; volatile int nTS = 1; volatile float Dlrpm = 0; volatile int discr = 0; volatile int discrn = 0; volatile int Marker = 0; volatile int nAD22 = 0; volatile int SinMet = 0; volatile int dlitn_old = 0; volatile int Fst = 0; volatile int rasch = 0; volatile int A=0; volatile int dwel = 3800; //накопление зададим 3.8 мс. volatile int dwelzub = 0; //угловые импульсы перед накоплением volatile int DWZub = 3; //... /* Функция инициализация АЦП */ void ADC_Init(){ ADCSRA |= (1 << ADEN) // Включаем АЦП |(1 << ADPS1)|(1 << ADPS0); // устанавливаем предделитель преобразователя на 8 ADMUX |= (0 << REFS1)|(1 << REFS0) //выставляем опорное напряжение, как внешний ИОН |(0 << MUX0)|(0 << MUX1)|(0 << MUX2)|(0 << MUX3); // снимать сигнал будем с входа PC0 } void setup() { DDRC = (0 << PINC0); //pinMode(0, INPUT); //Вход для ДАД. DDRD = (0 << PIND2)|(0 << PIND3); //pinMode(2, INPUT); //pinMode(1, INPUT); //Вход октан корректора +/-10 градусов. DDRB = (1 << PINB1)|(1 << PINB2)|(1 << PINB5); //pinMode(9, OUTPUT); pinMode(10, OUTPUT); pinMode(13, OUTPUT); DDRD = (1 << PIND6)|(1 << PIND7); //pinMode(6, OUTPUT);pinMode(7, OUTPUT); //DDRB = (0 << 0); //pinMode(8, INPUT); //PORTB |= (1 << PB0); //digitalWrite (8, HIGH); PORTD &= ~ (1 << PIND6); //digitalWrite (6, LOW); PORTC &= ~ (1 << PINC0); //digitalWrite (0, LOW); PORTB |= (1 << PINB1); //digitalWrite (9, HIGH); PORTB |= (1 << PINB2); //digitalWrite (10, HIGH); PORTB |= (1 << PINB5); //digitalWrite (13, HIGH); PORTD &= ~ (1 << PIND7); //digitalWrite (7, LOW); PORTD &= ~ (1 << PIND2); //digitalWrite (2, LOW); PORTD |= (1 << PIND3); //pinMode(3, INPUT_PULLUP); // инициализация Timer1 cli(); // отключить глобальные прерывания TCCR1A = 0; // установить регистры в 0 TCCR1B = 0; //OCR1AL = 0b00101000; OCR1AH=0x00; OCR1AL=0x28; //OCR1A = 40; // установка регистра совпадения 40 TCCR1B |= (1 << WGM12); // включение в CTC режим //LDI OCR1AL,0x28 // Установка битов CS10 и CS12 на коэффициент деления 8 TCCR1B |= (1 << CS11); //TCCR1B |= (1 << CS12); //TCCR1A=0x40;//при совпадении уровень OC1A меняется на противоположный //TCCR1B=0x0A;//Делитель частоты 8 //TIMSK1 = 0x01;//разрешаем прерывание по совпадению TIMSK1 |= (1 << OCIE1A); // включение прерываний по совпадению sei(); // включить глобальные прерывания //EICRA |= (1< 8000) rpm = 8000; if (rpm <= 60) { nRetlw = 0; retlw10 = 1; goto R1;} //Если обороты очень низкие, то значение задержки УОЗ равно 0 мкс. else retlw10 = (rpm/100)-4; //Расчёт номера ячейки массива задержек УОЗ. if (retlw10 <= 0) nRetlw = 4000; else { nRetlw = pgm_read_word (&retlw[nAD22][retlw10])*10;} //Выбор значения задержки из массива с учетом расположения массива в еепроме. //else { nRetlw = retlw*10;} // вычисленная задержка между срабатываниями датч. холла минус УОЗ. (мкс). R1: F14 = 0; // Выбор канала икрообразования для (ВМТ-2,3). TS = (nRetlw); if (dlit == 1) dlit = dlitn; //в реальных условиях эта коррекция не потребуется, программа реагирует на короткий импульс в зоне синрометки схемы симуляции. Dlit = ((dlit+dlitn)*19.84); //19.84 ZUB = (TS/Dlit)+1; TS48 = (ZUB*Dlit)-TS; discr = TS48/20; if (discr == dlit) discr=discr-1; if (discr > dlit) discrn = discr - dlit; else discrn = 0; if (discrn > dlitn) discrn = dlitn-1; dwelzub = dwel/Dlit; DWZub = dwelzub + ZUB; //Serial.print("CKPS_imp = "); //Serial.println(nCountCKPS_imp); //Serial.print("discr "); //Serial.println(discr); //Serial.print("Dlit "); //Serial.println(Dlit); //Serial.println(DWZub); //Serial.print("dlitn "); //Serial.println(ZUB); //Serial.print("discrn "); //Serial.println(discrn); //rasch = 1; //флаг расчётов A=0; nCountCKPS_imp = 0; PORTD &= ~(1 << PIND6); //закончить математику } void CKPScount () { if ((1 << PIND2) & CKPS) { //если пин2 = 1 то... if (mCKPS == 0) { //если фронт то ++nCountCKPS_imp; // инкремент счётчика зубьев if (nCountCKPS_imp == 55) A=1; //флаг указатель места для расчётов. mCKPS = 1; // флаг того что фронт был dlitn = nCountCKPS_0; //сохраняем кол-во дискрет таймера низкого уровня импульса nCountCKPS_0 = 0; //обнуляем счётчик дискрет таймера низкого уровня импульса } ++nCountCKPS_1; //инкремент счётчика дискрет таймера высокого ур. импульса } else { //если пин2 = 0 то... /*if (CKPS == 0)*/ if (mCKPS == 1){ //если спад то dlit = nCountCKPS_1; //сохраняем кол-во дискрет таймера выс. уровня импульса nCountCKPS_1 = 0; //обнуляем счётчик дискрет таймера выс. уровня импульса mCKPS = 0; // флаг того что спад был dlitn_old = dlit*2; //сохраняе предыдущее зн. дискрет низк. ур. для детектир. синхрометки } ++nCountCKPS_0; //инкремент счётчика дискрет таймера низк. ур. импульса if (nCountCKPS_0 > dlitn_old ) { nCountCKPS_imp = 0; //определяем синхрометку if (A==1) RPM1 (); } //при условии что указатель места расчётов действует, выполнить математику. Исключает повторное попадание в вычисления. } } ISR (TIMER1_COMPA_vect) { // Подпрограмма таймера 21мкс. //PORTD |= (1 << PIND6); CKPS = PIND; //аналог digitalRead (2); CKPScount (); // ПП счётчика угловых импульсов и детектор синхрометки. //Процедура накопления и искрообразования. if (nCountCKPS_imp == 50-DWZub) PORTB |= (1 << PINB2); if (nCountCKPS_imp == 50-ZUB) {if (discrn == 0)/*проверяем флаг попадания искры по выс. ур. углового импульса*/ { if (nCountCKPS_1 == discr) PORTB &= ~(1 << PINB2); } else {if (nCountCKPS_0 == discrn) PORTB &= ~(1 << PINB2);}} //отмеряем интервал времени от расчётного зуба ДУИ if (nCountCKPS_imp == 20-DWZub) PORTB |= (1 << PINB1); if (nCountCKPS_imp == 20-ZUB) {if (discrn == 0)/*проверяем флаг попадания искры по выс. ур. углового импульса*/ { if (nCountCKPS_1 == discr) PORTB &= ~(1 << PINB1); } else {if (nCountCKPS_0 == discrn) PORTB &= ~(1 << PINB1);}} //PORTD &= ~(1 << PIND6); } int main(void) { //atmel_start_init(); setup(); ADC_Init(); while (1) { do{ ADCSRA |= (1 << ADSC); // Начинаем преобразование } while ((ADCSRA & (1 << ADIF)) == 0); // пока не будет выставлено флага об окончании преобразования nADC = (ADCL|ADCH << 8); // Считываем полученное значение // nADC = analogRead(0); if (nADC > 354) nADC = 354; if (nADC < 22) nADC = 22; if (nADC < 177) {PORTD |= (1 << PIND7);} //digitalWrite (7, HIGH); индикатор нагрузки на двиг по ДАДу. else {PORTD &= ~(1 << PIND7);} //digitalWrite (7, LOW); nAD22 = (nADC/22)-1; //Вычисление расхода воздуха, максимум 16 зон. if (nCountCKPS_imp == 20) { PORTB |= (1 << PINB5); //digitalWrite (13, HIGH); // } if (nCountCKPS_imp == 25) { PORTB &= ~(1 << PINB5); // Индикатор ВМТ } if (nCountCKPS_imp == 50) { PORTB |= (1 << PINB5); } if (nCountCKPS_imp == 55) { PORTB &= ~(1 << PINB5); } // Индикатор ВМТ+180 (2 и 3 цилиндров) } }