Внешнее преравание и запуск по нему таймера

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

проблемка выходит с таймером



#include <CyberLib.h>
volatile boolean i = 0;
void setup() {
  D3_In;
  D9_Out;

attachInterrupt(1,impuls,FALLING); //прерывание по 3 пину
}
void loop() {
if(i==1){StartTimer1(obrobotchik, 1000);i = 0;};} //запуск таймера о обнуление флага
void obrobotchik() {D9_High;delay_ms(1);D9_Low;StopTimer1();} //после отсчета таймера
void impuls() {
    i=1;} //установка флага

пробовал запускать таймер в interrup, но ничего не дает

желтый - вход D3, синий - выход D9

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dmitriykisliy, а что вы хотели получить?

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

по описанию таймера понял, что по истечении времени (1000 мкс)



StartTimer1(obrobotchik, 1000)

программа переходит к 



void obrobotchik ()

т.е. после LOW на D2, на D9 возникнет HIGH через 1000 мкс, но или я туплю, или ATmega328 меня не понимает.

Голову ломаю 2 недели, delay не подходит, частота входа меняется (датчик Холла автомобиля) и void loop сбивается

Если есть варианты, подскажите)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dmitriykisliy, т.е. вам нужно, что б ежели кто-то дёрнет ногу порта d2 на ноль, то через 1мс  поднять ногу d9, а ещё через 1мс её опустить, так?

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

да, верно.
кто-то - это датчик Холла трамблера авто, 1 мс - это пробная величина, далее она будет функцией оборотов мотора

trembo
trembo аватар
Offline
Зарегистрирован: 08.04.2011
dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

подсчет внешних прерываний это не сложнл, а как по внешнему прерыванию запустить таймер и с выдержкой времени выполнить действие?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

вы что делаете - электронный регулятор угла опережения зажигания от оборотов движка ?

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

верно, со своим алгоритмом работы, выложу когда заработает. сейчас езжу на ардуине, лучше, чем было на штатном трамблере, но угол опережения нестабилен (из за delaymicroseconds думаю)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

http://arduino.ru/forum/proekty/fuoz-takhometr

реализация через счётчики МК и таблицу пересчёта - быстрее и точнее, чем производить матрассёты

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

dmitriykisliy пишет:

верно, со своим алгоритмом работы, выложу когда заработает. сейчас езжу на ардуине, лучше, чем было на штатном трамблере, но угол опережения нестабилен (из за delaymicroseconds думаю)

алгоритм у всех ФУОЗов одинаков - разные только кривые зависимости "обороты-времяОпережения" :)

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

про счетчик МК можно поподробнее?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

ATmega48PA/88PA/168PA/328P

14. 8-bit Timer/Counter0 with PWM

15. 16-bit Timer/Counter1 with PWM

16. Timer/Counter0 and Timer/Counter1 Prescalers

17. 8-bit Timer/Counter2 with PWM and Asynchronous Operation

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

это видел, 

а как ПРАВИЛЬНО запустить таймер 1  после прерывания? в этом и есть проблема (рис 1 пост)

в Ассемблере я 0, с библиотекой проще, но не работает(

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dmitriykisliy, тут не много тех, кто в ассемблере !=0 ;-) У меня был похожий шаблончик, подкорректировал под ваши данные. Вроде всё  как надо, снял осциллограмку -одна клетка пол миллисекунды. Синий график -кнопка, подтянута к HIGH, при нажатии соответссно ноль. Жёлтый график -выход с D9 ардуины.

 

Управление сделал через ещё одно прерывание от таймера, иначе не знаю как.. Сам скетч:


void setup() {

pinMode (3,INPUT_PULLUP); //вход
pinMode (9,OUTPUT); //выход
EICRA=(1<<ISC11)|(0<<ISC10); //настройка внешнего прерывания (falling )
EIMSK|=1<<INT1; //разрешение внешнего прерывания
TCCR1B=0; //настройка таймера1
TCCR1A=0; //настройка таймера1
TIMSK1=(1<<TOIE1); //разрешить прерываение для таймера 1

}
ISR(INT1_vect) {  //вектор внешнего прерывания
TCCR1B= _BV(WGM13)|_BV(CS10); //запуск таймера 1
TCCR1A=0; 
ICR1=8000;//установка частоты прерывания 
}


ISR (TIMER1_OVF_vect) { //вектор прерывания таймера 1 
static byte msec=0; // переменная счёта входов в прерывание
if (msec==1) PORTB |= 1<<1; //если второй вход включаем d9
if (msec==2){ // если третий вход 
    PORTB &= ~(1<<1);  //отключаем d9
    TCCR1B = _BV(WGM13); //отключаем таймер
    msec=0; //сбрасываем счёт
      }
msec++; 
}


void loop() 
{

}

 

 

 

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

RESPECT! спасибо,  попробую на работе,

как я понял выдержки времени можно менять строкой 15 (это предделитель?), ну и строками 21 и 22. Верно?

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dmitriykisliy, да в 15 строке задаёте период вызова прерывания (8000 попугаев = 1мс учитывая и прочие настройки таймера) но не более 65535,  а в прерывании таймера делаете что нужно..

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

12 строка (вектор внешнего прерывания) значит, что если на d3 falling, то запускается таймер?

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

не совсем так - посмотрите все биты управляющих регистров одного счётчика

 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

всяко нужно два счётчика - один постоянно измеряет t оборота коленвала, второй создаёт задержку искрообразования в зависимости от t оборота коленвала ( или из таблицы(быстрее и проще - но кривая зависимости ступенчатая) , или по формуле пересчёта(помедленне - но кривая зависимости непрерывная)

счётчик rpm -

1) прерывание по ризинг ( или фаллинг ) от сигнала с датчика Холла

2) обработчик прерывания - захват значения счётчика в глобальную волатильную переменную, обнуление счётчика

итого: система на каждом обороте КВ знает период или частоту, или rpm ( что по сути меры одного и того же )

......здесь рассчёт/формирование значения установки для второго счётчика, который формирует задержку искрообразования

счётчик задержки - ...........

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012
volatile unsigned int NclkTCNT1;
volatile unsigned int RPM = 0;            // обороты для Сериала
volatile byte RPM100 = 0;                 // сотни оборотов для индекса таблицы "обороты-УОЗ" - 60 значений ( на выбор )
byte AngleDelayChargeBabin [] PROGMEM =   // таблица "обороты-задержка накопления бабины" - числа пока не рассчитаны
{
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF
};
byte AngleChargeBabin [] PROGMEM =   // таблица 10 х Тзаряда - числа пока не рассчитаны
{ 
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF
};
byte AngleIgnition [] PROGMEM =   // таблица "обороты-УОЗ" - числа пока не рассчитаны
{
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF , 0xFF ,
  0xFF
};
//==============================================================================================================================
void setup( )
{
//**************************
// Счётчик_0
  DDRD = DDRD | B01000000;     //  pinMode( 6 , OUTPUT );   // OC0A - выход на коммутатор
//  PORTD = PORTD | B00000000;
  TCNT0  = 0;
  // TIMSK0 >>> OCIE0B - 2  OCIE0A - 1  TOIE0 - 0
  TIMSK0 = ( 1 << OCIE0A );
  // TCCR0A >>> COM0A1 - 7  COM0A0 - 6  COM0B1 - 5  COM0B0 - 4  WGM01 - 1  WGM00 - 0
  // OC0A - 00=disconnected , 01=Toggle , 10=Clear , 11=Set
  TCCR0A = ( 1 << COM0A1 ) | ( 0 << COM0A0 ) | ( 1 << WGM01 ) | ( 0 << WGM00 );
  // TCCR0B >>> FOC0A - 7  FOC0B - 6  WGM02 - 3  CS02 - 2  CS01 - 1  CS00 - 0
  TCCR0B = ( 1 << FOC0A ) | ( 0 << FOC0B ) | ( 0 << WGM02 ) | ( 0 << CS02 ) | ( 0 << CS01 ) | ( 0 << CS00 ) ;
  // CS >>> 0-stop, 1-/1, 2-/8, 3-/64, 4-/256, 5-/1024, 6-externalT0falling, 7-externalT0rising
//**************************
// Счётчик_1
  DDRB = DDRB | B00000000;     // pinMode( 8 , INPUT );       // вход от датчика Холла
  PORTB = PORTB | B00000001;   // digitalWrite( 8 , HIGH );   // резистор к VCC
  TCNT1  = 0;
  // TIMSK1 >>> ICIE1 - 5  OCIE1B - 2  OCIE1A - 1  TOIE1 - 0
  TIMSK1 = ( 1 << ICIE1 );
  // TCCR1A >>> COM1A1 - 7  COM1A0 - 6  COM1B1 - 5  COM1B0 - 4  WGM11 - 1  WGM10 - 0
  TCCR1A = ( 0 << WGM11 ) | ( 0 << WGM10 );
  // TCCR1B >>> ICNC1 - 7  ICES1 - 6  WGM13 - 4  WGM12 - 3  CS12 - 2  CS11 - 1  CS10 - 0
  // CS >>> 0-stop , 1-/1 , 2-/8 , 3-/64 , 4-/256 , 5-/1024, 6-externalT1falling, 7-externalT1rising
  TCCR1B = ( 0 << ICNC1 ) | ( 1 << ICES1 ) | ( 0 << WGM13 ) | ( 0 << WGM12 ) | ( 0 << CS12 ) | ( 0 << CS11 ) | ( 0 << CS10 ) ;
  // TCCR1C >>> FOC1A - 7  FOC1B - 6
//**************************
  NclkTCNT1 = 0;
//  Serial.begin( 9600 );
}
//==============================================================================================================================
ISR( TIMER1_CAPT_vect )
{
  TCNT1 = 0;
  NclkTCNT1 = ICR1 + 34;   // 34 такта - задержка от времени фронта до выполнения этой строки ДЛЯ сохранение RG-ов в стэк
  RPM = int( 96 / NclkTCNT1 * 10 ^ 7 );    // X=60/(N*16000000)=60*16000000/N=96/N*10^7
//  RPM50 = RPM % 50;   // 120 значений ( на выбор )
//  RPM100 = RPM % 100;   //  60 значений ( на выбор )
// загрузить Счётчик_2 = AngleDelayChargeBabin [ RPM100 ];
// разрешить прерывания Счётчик_2

// загрузить Счётчик_2 = AngleIgnition [ RPM100 ];
// разрешить прерывания Счётчик_2
}
//==============================================================================================================================
ISR( TIMER0_COMPA_vect )
{
  
}
//==============================================================================================================================
void loop( )
{
//  Serial.println( RPM );
  delay( 500 );
}
//=============================================================================================================================

примерно так... 

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

машина времени ещё не создана, поэтому говорить об опережении зажигания на Х гр от ВМТ можно как о задержке на 360-Х гр от ВМТ ( или на 180-Х гр от НМТ ) , НО в следующем обороте КВ

счётчик задержки - ...........

....должен сформировать временные значения и сами фронты сигнала на коммутатор бабины

апгрейд системы будет заключаться в изменении таблицы соответствия "обороты-УОЗ" ( все зависимости в авто построены на этом ) , или изменением коэффициентов в формуле пересчёта "обороты-УОЗ"

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

построение системы хардварное или софтовое - вопрос философский и вкуса.... моя за хардвар - хватит и Attyni85 :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

dmitriykisliy пишет:

если на d3 falling, то запускается таймер?

тут два варианта

1 - ст обнулён, счёт запрещён коэффициентом деления = 0 ( STOP ) , по прерыванию устанавливаем коэффициентом деления = 1, 64, ...... нужный

2 - по прерыванию обнуляем ст

......результат одинаков - запускается таймер на отсчёт чего-либо от момента начала прерывания

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

уважаемые dmitriykisliy и dimax, есть у вас время и желание вступить в симбиоз ?

....и создать адаптированную систему под вкус-цвет и потребности любого пользователя ?

кто-то логику, кто-то коды, кто-то свою машинку для испытаний :)

....моя корысть - модуль управления УОЗ старенького ( но очень распространённого ) дизелька :)

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

SU-27-16, увы,  я в автомобильной тематике полный ноль. Да и с таймерами буквально две недели как начал разбираться :)

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

dimax пишет:

SU-27-16, увы,  я в автомобильной тематике полный ноль. Да и с таймерами буквально две недели как начал разбираться :)

на то и симбиоз :)-

понял.... вы согласен ! :)

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

сорри, до нета только добрался

с расчетом прерываний проблем 0, на работе делали датчики тока и напряжения с цифровой опторазвязкой (преобразование ток-частота и напряжение-частота)

по поводу машины времени +1, это приближенный расчет, но факт то, что он лучше штатного трамблеровского с грузами и вакуумом, да и проблемы с запуском пропали...

по поводу функции или массива (таблицы) - по быстродействию, да и ступенчатости массив рулит (составлял на 100 элементов - 50 об/мин +на вакууме висит датчик холла (корректор))

скетч не опробовал, планирую на завтра

su-27-16 спс за рекомендации

 

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

в чем вопрос по дизельку? есть наработки

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

Ну заработало)

Готовый скетч





unsigned long t = 0;
volatile boolean i = 0;
volatile int zaderg, delit = 0;
volatile unsigned int Ch = 0;
unsigned int Zaderg[] = {250, 230, 223, 211, 201, 191, 183, 175, 167, 160, 154, 149, 143, 138, 133, 128, 124, 120, 238, 231, 224, 217, 211, 205, 199, 194, 188, 183, 178, 173, 169, 164, 160, 155, 151, 147, 144, 140, 137, 134, 131, 129, 126, 124, 122, 119, 117, 116, 114, 112, 110, 108, 106, 214, 211, 208, 204, 202, 199, 196, 193, 190, 188, 185, 183, 180, 178, 176, 173, 171, 169, 167, 165, 163, 161, 160, 158, 156, 155, 153, 151, 150, 148, 147, 145, 144, 142, 141, 139, 138, 137, 135, 134, 133, 132};
unsigned int Delit[] = {1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 1024, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 512, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256, 256};

void setup() {
pinMode (3,INPUT_PULLUP); //вход
pinMode (9,OUTPUT); //выход
EICRA=(1<<ISC11)|(0<<ISC10); //настройка внешнего прерывания (falling )
EIMSK|=1<<INT1; //разрешение внешнего прерывания
TCCR1B=0; //настройка таймера1
TCCR1A=0; //настройка таймера1
TIMSK1=(1<<TOIE1); //разрешить прерываение для таймера 1	 
}


ISR(INT1_vect) {  //вектор внешнего прерывания
TCCR1B= _BV(WGM13)|_BV(CS10); //запуск таймера 1
TCCR1A=0; 
ICR1=delit;//установка частоты прерывания
i = 1;
}


ISR (TIMER1_OVF_vect) {//900 - холостой ход, УОЗ = 0, т.е. повторитель заднего фронта
if (Ch < 900) {TCCR1B = _BV(WGM13); //отключаем таймер
               PORTB &= ~(1<<1); delay(1); //отключаем d9  и чуток ждем
               PORTB |= 1<<1;} //включаем d9
else if (Ch > 900) { //вектор прерывания таймера 1 
static byte msec=0; // переменная счёта входов в прерывание
if (msec==30) PORTB |= 1<<1; //если 30 вход включаем d9
if (msec==zaderg){ // если (из массива) вход 
PORTB &= ~(1<<1);  //отключаем d9
TCCR1B = _BV(WGM13); //отключаем таймер
msec=0; //сбрасываем счёт
}
msec++; 
};}


void loop() 
{if (i == 1) { i = 0; 
   Ch = 30000000/(micros() - t); t = micros();
   delit = Delit[map(Ch, 900, 5600, 0, 94)];
   zaderg = Zaderg[map(Ch, 900, 5600, 0, 94)];
};
   }

 

Строки 28 - 30 переделаю на многоискровой запуск

 

dmitriykisliy
Offline
Зарегистрирован: 03.03.2015

на холостых оборотах

чуть больше 3000 об/мин

частота около 5500 об/мин, уоз 36 градусов

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

очень хорошо, что заработало :)

критика

- неоптимальное использование коммутатора и "бабины", т.е. - лишний расход ЭлЭн....

  накопление энергии в "бабине" - const по времени.... и не должно зависеть от оборотов движка.....

- процессы в лупе и прерываниях "относительно" синхронны

есть предложения - позже обосную

за дизелёк - спасибо, всё решено - тока код надо допилить без рассчётов в коде, только через таблицы ( желание заказчика :(  )

SU-27-16
SU-27-16 аватар
Offline
Зарегистрирован: 13.08.2012

по коду - волатильными переменные стоит ( нужно ) объявлять только те, которые изменяются в прерываниях - может кто поправит ?

т.е. - 01, 03, 04 - могут быть неволатильными