Генератор сигнала Коленвала и распредвала

MaksVV
Offline
Зарегистрирован: 06.08.2015

Мой друг попросил меня сделать преобразователь сигнала коленчатого вала. Т.к. ему поменяли двигатель на не родной. А чтобы панель приборов показывала обороты нужно подать сигнал от старого двигателя. (Сигнал по CAN Шине в панель идет, поэтому пришлось оставить старый ЭБУ для этого)

Ардуина будет от нового двигателя получить сигнал просто тахосигнала определённой частоты.

В зависимости  от этой частоты должна меняться частота периодов выдаваемого сигнала с двух каналов ардуины.

Возможно ли такое сделать на ардуине. Вот требуемые сигналы:

Скетч я конечно сделал, но это конечно говновод ещё тот. Работает, но в зависимости от разных оборотов нижний сигнал смещается, особенно после 5000 об/мин. 

Подскажите такое возможно на ардуино? если да, готов заплатить за реализацию. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот мой мега скетч ) там каждый элемент сигнала на отдельном таймере на millis. 

#define CMP 4
#define ckp 2
volatile unsigned int int_tic=0; 
volatile unsigned long tic; 
float k=0.4;
 unsigned long prevMillisfrec = 0;


long mnog;
int RPM = 8000;
int val;
int K =100; 
unsigned long Time23, timer23 = 0;
bool timerenabled23 = 0;
#define TIMEREXPIRED23 (Time23-timer23)>12*mnog

unsigned long Time156, timer156 = 0;
bool timerenabled156 = 0;
#define TIMEREXPIRED156 (Time156-timer156)>157*mnog

unsigned long Time40_1, timer40_1 = 0;
bool timerenabled40_1 = 0;
#define TIMEREXPIRED40_1 (Time40_1-timer40_1)>29*mnog

unsigned long Time40_2, timer40_2 = 0;
bool timerenabled40_2 = 0;
#define TIMEREXPIRED40_2 (Time40_2-timer40_2)>29*mnog

unsigned long Time40_3, timer40_3 = 0;
bool timerenabled40_3 = 0;
#define TIMEREXPIRED40_3 (Time40_3-timer40_3)>29*mnog

unsigned long Time40_4, timer40_4 = 0;
bool timerenabled40_4 = 0;
#define TIMEREXPIRED40_4 (Time40_4-timer40_4)>29*mnog

unsigned long Time210_1, timer210_1 = 0;
bool timerenabled210_1 = 0;
#define TIMEREXPIRED210_1 (Time210_1-timer210_1)>196*mnog

unsigned long Time210_2, timer210_2 = 0;
bool timerenabled210_2 = 0;
#define TIMEREXPIRED210_2 (Time210_2-timer210_2)>196*mnog

unsigned long Time210_3, timer210_3 = 0;
bool timerenabled210_3 = 0;
#define TIMEREXPIRED210_3 (Time210_3-timer210_3)>196*mnog

unsigned long Time36, timer36 = 0;
bool timerenabled36 = 0;
#define TIMEREXPIRED36 (Time36-timer36)> 27*mnog


////////CKP
unsigned long ckpTime1, ckptimer1 = 0;
bool ckptimerenabled1 = 0;
#define ckpTIMEREXPIRED1 (ckpTime1-ckptimer1)>5*mnog   *k    // 1

unsigned long ckpTime2, ckptimer2 = 0;
bool ckptimerenabled2 = 0;
#define ckpTIMEREXPIRED2 (ckpTime2-ckptimer2)>20*mnog    *k  //25

unsigned long ckpTime3, ckptimer3 = 0;
bool ckptimerenabled3 = 0;
#define ckpTIMEREXPIRED3 (ckpTime3-ckptimer3)>5*mnog       *k//2

unsigned long ckpTime4, ckptimer4 = 0;
bool ckptimerenabled4 = 0;
#define ckpTIMEREXPIRED4 (ckpTime4-ckptimer4)>32*mnog     *k//65

unsigned long ckpTime5, ckptimer5 = 0;
bool ckptimerenabled5 = 0;
#define ckpTIMEREXPIRED5 (ckpTime5-ckptimer5)>6*mnog   *k  //3

unsigned long ckpTime6, ckptimer6 = 0;
bool ckptimerenabled6 = 0;
#define ckpTIMEREXPIRED6 (ckpTime6-ckptimer6)>32*mnog    *k//102

unsigned long ckpTime7, ckptimer7 = 0;
bool ckptimerenabled7 = 0;
#define ckpTIMEREXPIRED7 (ckpTime7-ckptimer7)>6*mnog     *k//4

unsigned long ckpTime8, ckptimer8 = 0;
bool ckptimerenabled8 = 0;
#define ckpTIMEREXPIRED8 (ckpTime8-ckptimer8)>32*mnog    *k//139

unsigned long ckpTime9, ckptimer9 = 0;
bool ckptimerenabled9 = 0;
#define ckpTIMEREXPIRED9 (ckpTime9-ckptimer9)>6*mnog    *k//5

unsigned long ckpTime10, ckptimer10 = 0;
bool ckptimerenabled10 = 0;
#define ckpTIMEREXPIRED10 (ckpTime10-ckptimer10)> 32*mnog*k//173

unsigned long ckpTime11, ckptimer11 = 0;
bool ckptimerenabled11 = 0;
#define ckpTIMEREXPIRED11 (ckpTime11-ckptimer11)>5*mnog*k//6

unsigned long ckpTime12, ckptimer12 = 0;
bool ckptimerenabled12 = 0;
#define ckpTIMEREXPIRED12 (ckpTime12-ckptimer12)>32*mnog*k//210

unsigned long ckpTime13, ckptimer13 = 0;
bool ckptimerenabled13 = 0;
#define ckpTIMEREXPIRED13 (ckpTime13-ckptimer13)> 5*mnog*k//7

unsigned long ckpTime14, ckptimer14 = 0;
bool ckptimerenabled14 = 0;
#define ckpTIMEREXPIRED14 (ckpTime14-ckptimer14)>32*mnog*k//247

unsigned long ckpTime15, ckptimer15 = 0;
bool ckptimerenabled15 = 0;
#define ckpTIMEREXPIRED15 (ckpTime15-ckptimer15)>6*mnog*k//8

unsigned long ckpTime16, ckptimer16 = 0;
bool ckptimerenabled16 = 0;
#define ckpTIMEREXPIRED16 (ckpTime16-ckptimer16)>32*mnog*k//284

unsigned long ckpTime17, ckptimer17 = 0;
bool ckptimerenabled17 = 0;
#define ckpTIMEREXPIRED17 (ckpTime17-ckptimer17)>6*mnog*k//9

unsigned long ckpTime18, ckptimer18 = 0;
bool ckptimerenabled18 = 0;
#define ckpTIMEREXPIRED18 (ckpTime18-ckptimer18)>32*mnog*k//321

unsigned long ckpTime19, ckptimer19 = 0;
bool ckptimerenabled19 = 0;
#define ckpTIMEREXPIRED19 (ckpTime19-ckptimer19)>6*mnog*k//10

unsigned long ckpTime20, ckptimer20 = 0;
bool ckptimerenabled20 = 0;
#define ckpTIMEREXPIRED20 (ckpTime20-ckptimer20)>32*mnog*k//358

unsigned long ckpTime21, ckptimer21 = 0;
bool ckptimerenabled21 = 0;
#define ckpTIMEREXPIRED21 (ckpTime21-ckptimer21)>5*mnog*k//11

unsigned long ckpTime22, ckptimer22 = 0;
bool ckptimerenabled22 = 0;
#define ckpTIMEREXPIRED22 (ckpTime22-ckptimer22)>32*mnog*k//395

unsigned long ckpTime23, ckptimer23 = 0;
bool ckptimerenabled23 = 0;
#define ckpTIMEREXPIRED23 (ckpTime23-ckptimer23)> 5*mnog*k//12

unsigned long ckpTime24, ckptimer24 = 0;
bool ckptimerenabled24 = 0;
#define ckpTIMEREXPIRED24 (ckpTime24-ckptimer24)>32*mnog*k//432

unsigned long ckpTime25, ckptimer25 = 0;
bool ckptimerenabled25 = 0;
#define ckpTIMEREXPIRED25 (ckpTime25-ckptimer25)>5*mnog*k//13

unsigned long ckpTime26, ckptimer26 = 0;
bool ckptimerenabled26 = 0;
#define ckpTIMEREXPIRED26 (ckpTime26-ckptimer26)> 7*mnog*k//

unsigned long ckpTime27, ckptimer27 = 0;
bool ckptimerenabled27 = 0;
#define ckpTIMEREXPIRED27 (ckpTime27-ckptimer27)> 5*mnog*k//14

unsigned long ckpTime28, ckptimer28 = 0;
bool ckptimerenabled28 = 0;
#define ckpTIMEREXPIRED28 (ckpTime28-ckptimer28)> 20*mnog*k//482

unsigned long ckpTime29, ckptimer29 = 0;
bool ckptimerenabled29 = 0;
#define ckpTIMEREXPIRED29 (ckpTime29-ckptimer29)> 5*mnog*k//15



unsigned long ckpTime30, ckptimer30 = 0;
bool ckptimerenabled30 = 0;
#define ckpTIMEREXPIRED30 (ckpTime30-ckptimer30)> 32*mnog*k

unsigned long ckpTime31, ckptimer31 = 0;
bool ckptimerenabled31 = 0;
#define ckpTIMEREXPIRED31 (ckpTime31-ckptimer31)> 6*mnog*k//16
unsigned long ckpTime32, ckptimer32 = 0;
bool ckptimerenabled32 = 0;
#define ckpTIMEREXPIRED32 (ckpTime32-ckptimer32)> 32*mnog*k
unsigned long ckpTime33, ckptimer33 = 0;
bool ckptimerenabled33 = 0;
#define ckpTIMEREXPIRED33 (ckpTime33-ckptimer33)> 6*mnog*k//17

unsigned long ckpTime34, ckptimer34 = 0;
bool ckptimerenabled34 = 0;
#define ckpTIMEREXPIRED34 (ckpTime34-ckptimer34)> 32*mnog*k

unsigned long ckpTime35, ckptimer35 = 0;
bool ckptimerenabled35 = 0;
#define ckpTIMEREXPIRED35 (ckpTime35-ckptimer35)> 6*mnog*k//18

unsigned long ckpTime36, ckptimer36 = 0;
bool ckptimerenabled36 = 0;
#define ckpTIMEREXPIRED36 (ckpTime36-ckptimer36)> 32*mnog*k

unsigned long ckpTime37, ckptimer37 = 0;
bool ckptimerenabled37 = 0;
#define ckpTIMEREXPIRED37 (ckpTime37-ckptimer37)> 5*mnog*k//19

unsigned long ckpTime38, ckptimer38 = 0;
bool ckptimerenabled38 = 0;
#define ckpTIMEREXPIRED38 (ckpTime38-ckptimer38)> 32*mnog*k

unsigned long ckpTime39, ckptimer39 = 0;
bool ckptimerenabled39 = 0;
#define ckpTIMEREXPIRED39 (ckpTime39-ckptimer39)> 5*mnog*k//20

unsigned long ckpTime40, ckptimer40 = 0;
bool ckptimerenabled40 = 0;
#define ckpTIMEREXPIRED40 (ckpTime40-ckptimer40)> 32*mnog*k

unsigned long ckpTime41, ckptimer41 = 0;
bool ckptimerenabled41 = 0;
#define ckpTIMEREXPIRED41 (ckpTime41-ckptimer41)> 6*mnog*k//21

unsigned long ckpTime42, ckptimer42 = 0;
bool ckptimerenabled42 = 0;
#define ckpTIMEREXPIRED42 (ckpTime42-ckptimer42)> 32*mnog*k

unsigned long ckpTime43, ckptimer43 = 0;
bool ckptimerenabled43 = 0;
#define ckpTIMEREXPIRED43 (ckpTime43-ckptimer43)> 6*mnog*k//22

unsigned long ckpTime44, ckptimer44 = 0;
bool ckptimerenabled44 = 0;
#define ckpTIMEREXPIRED44 (ckpTime44-ckptimer44)> 32*mnog*k

unsigned long ckpTime45, ckptimer45 = 0;
bool ckptimerenabled45 = 0;
#define ckpTIMEREXPIRED45 (ckpTime45-ckptimer45)> 6*mnog*k//23

unsigned long ckpTime46, ckptimer46 = 0;
bool ckptimerenabled46 = 0;
#define ckpTIMEREXPIRED46 (ckpTime46-ckptimer46)> 32*mnog*k

unsigned long ckpTime47, ckptimer47 = 0;
bool ckptimerenabled47 = 0;
#define ckpTIMEREXPIRED47 (ckpTime47-ckptimer47)> 5*mnog*k//24

unsigned long ckpTime48, ckptimer48 = 0;
bool ckptimerenabled48 = 0;
#define ckpTIMEREXPIRED48 (ckpTime48-ckptimer48)> 32*mnog*k

unsigned long ckpTime49, ckptimer49 = 0;
bool ckptimerenabled49 = 0;
#define ckpTIMEREXPIRED49 (ckpTime49-ckptimer49)> 5*mnog*k//25

unsigned long ckpTime50, ckptimer50 = 0;
bool ckptimerenabled50 = 0;
#define ckpTIMEREXPIRED50 (ckpTime50-ckptimer50)> 32*mnog*k

unsigned long ckpTime51, ckptimer51 = 0;
bool ckptimerenabled51 = 0;
#define ckpTIMEREXPIRED51 (ckpTime51-ckptimer51)> 5*mnog*k
unsigned long ckpTime52, ckptimer52 = 0;
bool ckptimerenabled52 = 0;
#define ckpTIMEREXPIRED52 (ckpTime50-ckptimer50)> 7*mnog  *k//900




bool t1=0;
bool t1end = 0;
bool t2=0;
bool t2end = 0;
bool t3=0;
bool t3end = 0;
bool t4=0;
bool t4end = 0;
bool t5=0;
bool t5end = 0;
bool t6=0;
bool t6end = 0;
bool t7=0;
bool t7end = 0;
bool t8=0;
bool t8end = 0;
bool t9=0;
bool t9end = 0;
bool t10=0;
bool t10end = 0;



bool tt1=0;
bool tt1end = 0;
bool tt2=0;
bool tt2end = 0;
bool tt3=0;
bool tt3end = 0;
bool tt4=0;
bool tt4end = 0;
bool tt5=0;
bool tt5end = 0;
bool tt6=0;
bool tt6end = 0;
bool tt7=0;
bool tt7end = 0;
bool tt8=0;
bool tt8end = 0;
bool tt9=0;
bool tt9end = 0;
bool tt10=0;
bool tt10end = 0;
bool tt11=0;
bool tt11end = 0;
bool tt12=0;
bool tt12end = 0;
bool tt13=0;
bool tt13end = 0;
bool tt14=0;
bool tt14end = 0;
bool tt15=0;
bool tt15end = 0;
bool tt16=0;
bool tt16end = 0;
bool tt17=0;
bool tt17end = 0;
bool tt18=0;
bool tt18end = 0;
bool tt19=0;
bool tt19end = 0;
bool tt20=0;
bool tt20end = 0;
bool tt21=0;
bool tt21end = 0;
bool tt22=0;
bool tt22end = 0;
bool tt23=0;
bool tt23end = 0;
bool tt24=0;
bool tt24end = 0;
bool tt25=0;
bool tt25end = 0;
bool tt26=0;
bool tt26end = 0;
bool tt27=0;
bool tt27end = 0;
bool tt28=0;
bool tt28end = 0;
bool tt29=0;
bool tt29end = 0;
bool tt30=0;
bool tt30end = 0;
bool tt31=0;
bool tt31end = 0;
bool tt32=0;
bool tt32end = 0;
bool tt33=0;
bool tt33end = 0;
bool tt34=0;
bool tt34end = 0;
bool tt35=0;
bool tt35end = 0;
bool tt36=0;
bool tt36end = 0;
bool tt37=0;
bool tt37end = 0;
bool tt38=0;
bool tt38end = 0;
bool tt39=0;
bool tt39end = 0;
bool tt40=0;
bool tt40end = 0;
bool tt41=0;
bool tt41end = 0;
bool tt42=0;
bool tt42end = 0;
bool tt43=0;
bool tt43end = 0;
bool tt44=0;
bool tt44end = 0;
bool tt45=0;
bool tt45end = 0;
bool tt46=0;
bool tt46end = 0;
bool tt47=0;
bool tt47end = 0;
bool tt48=0;
bool tt48end = 0;
bool tt49=0;
bool tt49end = 0;
bool tt50=0;
bool tt50end = 0;
bool tt51=0;
bool tt51end = 0;
bool tt52=0;
bool tt52end = 0;

#include <class_BUTTON.h>
unsigned long previousMillis = 0;
BUTTON button (10);
void setup() {
TCCR1A=0; TIMSK1 = 1<<TOIE1; //прерывание по переполнению


pinMode (CMP, OUTPUT);
digitalWrite (CMP,1);

pinMode (ckp, OUTPUT);
pinMode (10, OUTPUT);
digitalWrite (10,1);
digitalWrite (ckp,1);
Serial.begin (9600);
}

ISR (TIMER1_OVF_vect){ int_tic++; }

void loop() {
  button.read();
if (button.click_down){k=k+0.01;}
  
 // unsigned long currentMillis = millis();

 // if(currentMillis - previousMillis > 1000){  Serial.println (K);
 //       previousMillis = currentMillis;}  
 // val = RPM;
 // val = map(val, 200, 1440, 105, 103);
 // K = val;
pinMode (5,INPUT); // вход сигнала T1 (only для atmega328)
TCCR1B = (1<<CS10)|(1<<CS11)|(1<<CS12);//тактировани от входа Т1


unsigned long curMillisfrec = millis();
if(curMillisfrec - prevMillisfrec > 1000){  TCCR1B=0;
tic= ((uint32_t)int_tic<<16) | TCNT1; //сложить что натикало
int_tic=0; TCNT1 = 0; 

Serial.print ("Frec  "); Serial.print (tic); Serial.print ("  RPM   ");Serial.print (RPM);
Serial.print ("  k= ");Serial.println (k);
prevMillisfrec = curMillisfrec;}  
  RPM = tic*120;
  mnog=120000L/RPM;
  
  ckpTime1 = micros();
  ckpTime2 = micros();
  ckpTime3 = micros();
  ckpTime4 = micros();
  ckpTime5 = micros();
  ckpTime6 = micros();
  ckpTime7 = micros();
  ckpTime8 = micros();
  ckpTime9 = micros();
  ckpTime10 = micros();
  ckpTime11 = micros();
  ckpTime12 = micros();
  ckpTime13 = micros();
  ckpTime14 = micros();
  ckpTime15 = micros();
  ckpTime16 = micros();
  ckpTime17 = micros();
  ckpTime18 = micros();
  ckpTime19 = micros();
  ckpTime20 = micros();
  ckpTime21 = micros();
  ckpTime22 = micros();
  ckpTime23 = micros();
  ckpTime24 = micros();
  ckpTime25 = micros();
  ckpTime26 = micros();
  ckpTime27 = micros();
  ckpTime28 = micros();
  ckpTime29 = micros();
  ckpTime30 = micros();
  ckpTime31 = micros();
  ckpTime32 = micros();
  ckpTime33 = micros();
  ckpTime34 = micros();
  ckpTime35 = micros();
  ckpTime36 = micros();
  ckpTime37 = micros();
  ckpTime38 = micros();
  ckpTime39 = micros();
  ckpTime40 = micros();
  ckpTime41 = micros();
  ckpTime42 = micros();
  ckpTime43 = micros();
  ckpTime44 = micros();
  ckpTime45 = micros();
  ckpTime46 = micros();
  ckpTime47 = micros();
  ckpTime48 = micros();
  ckpTime49 = micros();
  ckpTime50 = micros();
  ckpTime51 = micros();
  ckpTime52 = micros();
  
  

if (ckptimerenabled1) {if (ckpTIMEREXPIRED1){ckptimerenabled1=0; tt1end=1;}}

if (!tt2&& tt1end) {ckptimer2=ckpTime2; ckptimerenabled2 = 1; tt2=1; digitalWrite (ckp,1);}
if (ckptimerenabled2) {if (ckpTIMEREXPIRED2){ckptimerenabled2=0; tt2end=1;  }}

if (!tt3&& tt2end) {ckptimer3=ckpTime3; ckptimerenabled3 = 1; tt3=1; digitalWrite (ckp,0);}
if (ckptimerenabled3) {if (ckpTIMEREXPIRED3){ckptimerenabled3=0; tt3end=1;  }}

if (!tt4&& tt3end) {ckptimer4=ckpTime4; ckptimerenabled4 = 1; tt4=1; digitalWrite (ckp,1);}
if (ckptimerenabled4) {if (ckpTIMEREXPIRED4){ckptimerenabled4=0; tt4end=1; }}

if (!tt5&& tt4end) {ckptimer5=ckpTime5; ckptimerenabled5 = 1; tt5=1; digitalWrite (ckp,0);}
if (ckptimerenabled5) {if (ckpTIMEREXPIRED5){ckptimerenabled5=0; tt5end=1;  }}

if (!tt6&& tt5end) {ckptimer6=ckpTime6; ckptimerenabled6 = 1; tt6=1; digitalWrite (ckp,1);}
if (ckptimerenabled6) {if (ckpTIMEREXPIRED6){ckptimerenabled6=0; tt6end=1;  }}

if (!tt7&& tt6end) {ckptimer7=ckpTime7; ckptimerenabled7 = 1; tt7=1; digitalWrite (ckp,0);}
if (ckptimerenabled7) {if (ckpTIMEREXPIRED7){ckptimerenabled7=0; tt7end=1; }}

if (!tt8&& tt7end) {ckptimer8=ckpTime8; ckptimerenabled8 = 1; tt8=1; digitalWrite (ckp,1);}
if (ckptimerenabled8) {if (ckpTIMEREXPIRED8){ckptimerenabled8=0; tt8end=1;  }}

if (!tt9&& tt8end) {ckptimer9=ckpTime9; ckptimerenabled9 = 1; tt9=1; digitalWrite (ckp,0);}
if (ckptimerenabled9) {if (ckpTIMEREXPIRED9){ckptimerenabled9=0; tt9end=1;  }}

if (!tt10&& tt9end) {ckptimer10=ckpTime10; ckptimerenabled10 = 1; tt10=1; digitalWrite (ckp,1);}
if (ckptimerenabled10) {if (ckpTIMEREXPIRED10){ckptimerenabled10=0; tt10end=1; }}

if (!tt11&& tt10end) {ckptimer11=ckpTime11; ckptimerenabled11 = 1; tt11=1; digitalWrite (ckp,0);}
if (ckptimerenabled11) {if (ckpTIMEREXPIRED11){ckptimerenabled11=0; tt11end=1;  }}

if (!tt12&& tt11end) {ckptimer12=ckpTime12; ckptimerenabled12 = 1; tt12=1; digitalWrite (ckp,1);}
if (ckptimerenabled12) {if (ckpTIMEREXPIRED12){ckptimerenabled12=0; tt12end=1;  }}

if (!tt13&& tt12end) {ckptimer13=ckpTime13; ckptimerenabled13 = 1; tt13=1; digitalWrite (ckp,0);}
if (ckptimerenabled13) {if (ckpTIMEREXPIRED13){ckptimerenabled13=0; tt13end=1; }}

if (!tt14&& tt13end) {ckptimer14=ckpTime14; ckptimerenabled14 = 1; tt14=1; digitalWrite (ckp,1);}
if (ckptimerenabled14) {if (ckpTIMEREXPIRED14){ckptimerenabled14=0; tt14end=1;  }}

if (!tt15&& tt14end) {ckptimer15=ckpTime15; ckptimerenabled15 = 1; tt15=1; digitalWrite (ckp,0);}
if (ckptimerenabled15) {if (ckpTIMEREXPIRED15){ckptimerenabled15=0; tt15end=1;  }}

if (!tt16&& tt15end) {ckptimer16=ckpTime16; ckptimerenabled16 = 1; tt16=1; digitalWrite (ckp,1);}
if (ckptimerenabled16) {if (ckpTIMEREXPIRED16){ckptimerenabled16=0; tt16end=1;  }}

if (!tt17&& tt16end) {ckptimer17=ckpTime17; ckptimerenabled17 = 1; tt17=1; digitalWrite (ckp,0);}
if (ckptimerenabled17) {if (ckpTIMEREXPIRED17){ckptimerenabled17=0; tt17end=1;  }}

if (!tt18&& tt17end) {ckptimer18=ckpTime18; ckptimerenabled18 = 1; tt18=1; digitalWrite (ckp,1);}
if (ckptimerenabled18) {if (ckpTIMEREXPIRED18){ckptimerenabled18=0; tt18end=1;  }}

if (!tt19&& tt18end) {ckptimer19=ckpTime19; ckptimerenabled19 = 1; tt19=1; digitalWrite (ckp,0);}
if (ckptimerenabled19) {if (ckpTIMEREXPIRED19){ckptimerenabled19=0; tt19end=1;  }}

if (!tt20&& tt19end) {ckptimer20=ckpTime20; ckptimerenabled20 = 1; tt20=1; digitalWrite (ckp,1);}
if (ckptimerenabled20) {if (ckpTIMEREXPIRED20){ckptimerenabled20=0; tt20end=1;  }}

if (!tt21&& tt20end) {ckptimer21=ckpTime21; ckptimerenabled21 = 1; tt21=1; digitalWrite (ckp,0);}
if (ckptimerenabled21) {if (ckpTIMEREXPIRED21){ckptimerenabled21=0; tt21end=1;  }}

if (!tt22&& tt21end) {ckptimer22=ckpTime22; ckptimerenabled22 = 1; tt22=1; digitalWrite (ckp,1);}
if (ckptimerenabled22) {if (ckpTIMEREXPIRED22){ckptimerenabled22=0; tt22end=1; }}

if (!tt23&& tt22end) {ckptimer23=ckpTime23; ckptimerenabled23 = 1; tt23=1; digitalWrite (ckp,0);}
if (ckptimerenabled23) {if (ckpTIMEREXPIRED23){ckptimerenabled23=0; tt23end=1; }}

if (!tt24&& tt23end) {ckptimer24=ckpTime24; ckptimerenabled24 = 1; tt24=1; digitalWrite (ckp,1);}
if (ckptimerenabled24) {if (ckpTIMEREXPIRED24){ckptimerenabled24=0; tt24end=1; }}

if (!tt25&& tt24end) {ckptimer25=ckpTime25; ckptimerenabled25 = 1; tt25=1; digitalWrite (ckp,0);}
if (ckptimerenabled25) {if (ckpTIMEREXPIRED25){ckptimerenabled25=0; tt25end=1; }}

if (!tt26&& tt25end) {ckptimer26=ckpTime26; ckptimerenabled26 = 1; tt26=1; digitalWrite (ckp,1);}
if (ckptimerenabled26) {if (ckpTIMEREXPIRED26){ckptimerenabled26=0; tt26end=1; }}

if (!tt27&& tt26end) {ckptimer27=ckpTime27; ckptimerenabled27 = 1; tt27=1; digitalWrite (ckp,0);}
if (ckptimerenabled27) {if (ckpTIMEREXPIRED27){ckptimerenabled27=0; tt27end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt28&& tt27end) {ckptimer28=ckpTime28; ckptimerenabled28 = 1; tt28=1; digitalWrite (ckp,1);}
if (ckptimerenabled28) {if (ckpTIMEREXPIRED28){ckptimerenabled28=0; tt28end=1; }}

if (!tt29&& tt28end) {ckptimer29=ckpTime29; ckptimerenabled29 = 1; tt29=1; digitalWrite (ckp,0);}
if (ckptimerenabled29) {if (ckpTIMEREXPIRED29){ckptimerenabled29=0; tt29end=1; }}

if (!tt30&& tt29end) {ckptimer30=ckpTime30; ckptimerenabled30 = 1; tt30=1; digitalWrite (ckp,1);}
if (ckptimerenabled30) {if (ckpTIMEREXPIRED30){ckptimerenabled30=0; tt30end=1; }}

if (!tt31&& tt30end) {ckptimer31=ckpTime31; ckptimerenabled31 = 1; tt31=1; digitalWrite (ckp,0);}
if (ckptimerenabled31) {if (ckpTIMEREXPIRED31){ckptimerenabled31=0; tt31end=1; }}

if (!tt32&& tt31end) {ckptimer32=ckpTime32; ckptimerenabled32 = 1; tt32=1; digitalWrite (ckp,1);}
if (ckptimerenabled32) {if (ckpTIMEREXPIRED32){ckptimerenabled32=0; tt32end=1; }}

if (!tt33&& tt32end) {ckptimer33=ckpTime33; ckptimerenabled33 = 1; tt33=1; digitalWrite (ckp,0);}
if (ckptimerenabled33) {if (ckpTIMEREXPIRED33){ckptimerenabled33=0; tt33end=1; }}

if (!tt34&& tt33end) {ckptimer34=ckpTime34; ckptimerenabled34 = 1; tt34=1; digitalWrite (ckp,1);}
if (ckptimerenabled34) {if (ckpTIMEREXPIRED34){ckptimerenabled34=0; tt34end=1; }}

if (!tt35&& tt34end) {ckptimer35=ckpTime35; ckptimerenabled35 = 1; tt35=1; digitalWrite (ckp,0);}
if (ckptimerenabled35) {if (ckpTIMEREXPIRED35){ckptimerenabled35=0; tt35end=1; }}

if (!tt36&& tt35end) {ckptimer36=ckpTime36; ckptimerenabled36 = 1; tt36=1; digitalWrite (ckp,1);}
if (ckptimerenabled36) {if (ckpTIMEREXPIRED36){ckptimerenabled36=0; tt36end=1; }}

if (!tt37&& tt36end) {ckptimer37=ckpTime37; ckptimerenabled37 = 1; tt37=1; digitalWrite (ckp,0);}
if (ckptimerenabled37) {if (ckpTIMEREXPIRED37){ckptimerenabled37=0; tt37end=1; }}

if (!tt38&& tt37end) {ckptimer38=ckpTime38; ckptimerenabled38 = 1; tt38=1; digitalWrite (ckp,1);}
if (ckptimerenabled38) {if (ckpTIMEREXPIRED38){ckptimerenabled38=0; tt38end=1; }}

if (!tt39&& tt38end) {ckptimer39=ckpTime39; ckptimerenabled39 = 1; tt39=1; digitalWrite (ckp,0);}
if (ckptimerenabled39) {if (ckpTIMEREXPIRED39){ckptimerenabled39=0; tt39end=1; }}

if (!tt40&& tt39end) {ckptimer40=ckpTime40; ckptimerenabled40 = 1; tt40=1; digitalWrite (ckp,1);}
if (ckptimerenabled40) {if (ckpTIMEREXPIRED40){ckptimerenabled40=0; tt40end=1; }}

if (!tt41&& tt40end) {ckptimer41=ckpTime41; ckptimerenabled41 = 1; tt41=1; digitalWrite (ckp,0);}
if (ckptimerenabled41) {if (ckpTIMEREXPIRED41){ckptimerenabled41=0; tt41end=1; }}

if (!tt42&& tt41end) {ckptimer42=ckpTime42; ckptimerenabled42 = 1; tt42=1; digitalWrite (ckp,1);}
if (ckptimerenabled42) {if (ckpTIMEREXPIRED42){ckptimerenabled42=0; tt42end=1; }}

if (!tt43&& tt42end) {ckptimer43=ckpTime43; ckptimerenabled43 = 1; tt43=1; digitalWrite (ckp,0);}
if (ckptimerenabled43) {if (ckpTIMEREXPIRED43){ckptimerenabled43=0; tt43end=1; }}

if (!tt44&& tt43end) {ckptimer44=ckpTime44; ckptimerenabled44 = 1; tt44=1; digitalWrite (ckp,1);}
if (ckptimerenabled44) {if (ckpTIMEREXPIRED44){ckptimerenabled44=0; tt44end=1; }}

if (!tt45&& tt44end) {ckptimer45=ckpTime45; ckptimerenabled45 = 1; tt45=1; digitalWrite (ckp,0);}
if (ckptimerenabled45) {if (ckpTIMEREXPIRED45){ckptimerenabled45=0; tt45end=1; }}

if (!tt46&& tt45end) {ckptimer46=ckpTime46; ckptimerenabled46 = 1; tt46=1; digitalWrite (ckp,1);}
if (ckptimerenabled46) {if (ckpTIMEREXPIRED46){ckptimerenabled46=0; tt46end=1; }}

if (!tt47&& tt46end) {ckptimer47=ckpTime47; ckptimerenabled47 = 1; tt47=1; digitalWrite (ckp,0);}
if (ckptimerenabled47) {if (ckpTIMEREXPIRED47){ckptimerenabled47=0; tt47end=1; }}

if (!tt48&& tt47end) {ckptimer48=ckpTime48; ckptimerenabled48 = 1; tt48=1; digitalWrite (ckp,1);}
if (ckptimerenabled48) {if (ckpTIMEREXPIRED48){ckptimerenabled48=0; tt48end=1; }}

if (!tt49&& tt48end) {ckptimer49=ckpTime49; ckptimerenabled49 = 1; tt49=1; digitalWrite (ckp,0);}
if (ckptimerenabled49) {if (ckpTIMEREXPIRED49){ckptimerenabled49=0; tt49end=1; }}

if (!tt50&& tt49end) {ckptimer50=ckpTime50; ckptimerenabled50 = 1; tt50=1; digitalWrite (ckp,1);}
if (ckptimerenabled50) {if (ckpTIMEREXPIRED50){ckptimerenabled50=0; tt50end=1; }}

if (!tt51&& tt50end) {ckptimer51=ckpTime51; ckptimerenabled51 = 1; tt51=1; digitalWrite (ckp,0);}
if (ckptimerenabled51) {if (ckpTIMEREXPIRED51){ckptimerenabled51=0; tt51end=1; }}

if (!tt52&& tt51end) {ckptimer52=ckpTime52; ckptimerenabled52 = 1; tt52=1; digitalWrite (ckp,1);}
if (ckptimerenabled52) {if (ckpTIMEREXPIRED52){ckptimerenabled52=0; tt52end=1; 


tt1=0; tt2=0; tt3=0; tt4=0; tt5=0; tt6=0; tt7=0; tt8=0; tt9=0; tt10=0; tt11=0; tt12=0; tt13=0; tt14=0; 
tt15=0; tt16=0; tt17=0; tt18=0; tt19=0; tt20=0; tt21=0; tt22=0; tt23=0; tt24=0; tt25=0; tt26=0; 
tt27=0; tt28=0; tt29=0; tt30=0; tt31=0; tt32=0; tt33=0; tt34=0; tt35=0; tt36=0; tt37=0; tt38=0;
tt39=0; tt40=0; tt41=0; tt42=0; tt43=0; tt44=0; tt45=0; tt46=0; tt47=0; tt48=0; tt49=0; tt50=0; tt51=0;tt52=0;   
tt1end=0; tt2end=0; tt3end=0; tt4end=0; tt5end=0; tt6end=0; tt7end=0; tt8end=0; tt9end=0; 
tt10end=0; tt11end=0; tt12end=0; tt13end=0; tt14end=0; tt15end=0; tt16end=0; tt17end=0; tt18end=0; 
tt19end=0; tt20end=0; tt21end=0; tt22end=0; tt23end=0; tt24end=0; tt25end=0;
tt26end=0; tt27end=0; tt28end=0;
tt29end=0; tt30end=0; tt31end=0; tt32end=0; tt33end=0; tt34end=0; tt35end=0;
tt36end=0; tt37end=0; tt38end=0; tt39end=0; tt40end=0; tt41end=0; tt42end=0;
tt43end=0; tt44end=0; tt45end=0; tt46end=0; tt47end=0; tt48end=0; tt49end=0;tt50end=0;tt51end=0;
 }}

CKP ();



}

void CKP (){
  
  Time23 = micros();
  Time156 = micros();
  Time40_1 = micros();
  Time40_2 = micros();
  Time40_3 = micros();
  Time40_4 = micros();
  Time210_1 = micros();
  Time210_2 = micros();
  Time210_3 = micros();
  Time36 = micros();
  
if (!t1){timer23=Time23; timerenabled23 = 1; ckptimer1=ckpTime1; ckptimerenabled1 = 1; t1=1; digitalWrite (CMP,0); digitalWrite (ckp,0);}
if (timerenabled23) {if (TIMEREXPIRED23){timerenabled23=0; t1end=1;}}

if (!t2 && t1end) {timer156=Time156; timerenabled156 = 1; t2=1; digitalWrite (CMP,1);}
if (timerenabled156) {if (TIMEREXPIRED156){timerenabled156=0; t2end=1;}}

if (!t3 && t2end) {timer40_1=Time40_1; timerenabled40_1 = 1; t3=1; digitalWrite (CMP,0);}
if (timerenabled40_1) {if (TIMEREXPIRED40_1){timerenabled40_1=0; t3end=1;}}

if (!t4 && t3end) {timer210_1=Time210_1; timerenabled210_1 = 1; t4=1; digitalWrite (CMP,1);}
if (timerenabled210_1) {if (TIMEREXPIRED210_1){timerenabled210_1=0; t4end=1; }}

if (!t5 && t4end) {timer40_2=Time40_2; timerenabled40_2 = 1; t5=1; digitalWrite (CMP,0);}
if (timerenabled40_2) {if (TIMEREXPIRED40_2){timerenabled40_2=0; t5end=1; }}

if (!t6 && t5end) {timer210_2=Time210_2; timerenabled210_2 = 1; t6=1; digitalWrite (CMP,1);}
if (timerenabled210_2) {if (TIMEREXPIRED210_2){timerenabled210_2=0; t6end=1; }}

if (!t7 && t6end) {timer40_3=Time40_3; timerenabled40_3 = 1; t7=1; digitalWrite (CMP,0);}
if (timerenabled40_3) {if (TIMEREXPIRED40_3){timerenabled40_3=0; t7end=1; }}

if (!t8 && t7end) {timer210_3=Time210_3; timerenabled210_3 = 1; t8=1; digitalWrite (CMP,1);}
if (timerenabled210_3) {if (TIMEREXPIRED210_3){timerenabled210_3=0; t8end=1; }}

if (!t9 && t8end) {timer40_4=Time40_4; timerenabled40_4 = 1; t9=1; digitalWrite (CMP,0);}
if (timerenabled40_4) {if (TIMEREXPIRED40_4){timerenabled40_4=0; t9end=1; }}

if (!t10 && t9end) {timer36=Time36; timerenabled36 = 1; t10=1; digitalWrite (CMP,1);}
if (timerenabled36) {if (TIMEREXPIRED36){timerenabled36=0; t10end=1; 
t1=0; t2=0; t3=0; t4=0; t5=0; t6=0; t7=0; t8=0; t9=0; t10=0; 
t1end=0; t2end=0; t3end=0; t4end=0; t5end=0; t6end=0; t7end=0; t8end=0; t9end=0;}}

}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

вот что получилось с этого скетча на оборотах 1400, но если обороты менять, нижний график уплывает

Я так понимаю нужно делать прямое управление портами через регистры, и аппаратные таймеры использовать, прерывания ещё наверное. Я ещё не дорос до этого. 

 

Logik
Offline
Зарегистрирован: 05.08.2014

1. Получаете тахосигнал, измеряете его период

2. на основе периода расчитываете нужные длительности всех интервалов на диаграме.

3. формируете два сигнала начиная с момента где они совпадают, тем гарантируете их совпадение. Делантся без делеев на класической машинке состояний.

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

ПС. в скетче позаменяйте строки вида

ckpTime1 = micros();
439   ckpTime2 = micros();
440   ckpTime3 = micros();

на

ckpTime1 = micros();
ckpTime2 = ckpTime1;
ckpTime3 = ckpTime1;
 
Может даже и поможет.
А вобще про массивы почитайте, сильно сократится и упростится все.
 
MaksVV
Offline
Зарегистрирован: 06.08.2015

спасибо попробую

MaksVV
Offline
Зарегистрирован: 06.08.2015

Не помогло. Спецы по таймерам, отзовитесь, плиз. Dimax ,как лучший в этом вопросе , прошу помощи.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Logik пишет:

1. Получаете тахосигнал, измеряете его период

2. на основе периода расчитываете нужные длительности всех интервалов на диаграме.

3. формируете два сигнала начиная с момента где они совпадают, тем гарантируете их совпадение. Делантся без делеев на класической машинке состояний.

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

 

я не знаю че такое машинка состояний, но  код немного переделал.

Измеряется частота (ну или период), другой ардуиной кстати.

Передаётся на эту дуню по сериал.

В зависимости от этой частоты формируется (с помощью библиотеки PWM.h) шим сигнал (коленвала) с одной и той же скважностью, но с изменяемой частотой

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

В зависимости от номера зуба коленвала создается второй сигнал - зубья распредавала - на micros()

В зависимости от номера зуба коленвала создается третий сигнал - доп. зуб коленвала - на micros()

первый и третий сигналы хочу соединить на лог элементе "И"  (К555ЛИ1 ?)

PS использовал теперь низкоуровневое управление портами. 

Стало работать гораздо лучше, но всё равно есть нюансы

Код


#include <PWM.h>
#define ckp  9   //пин для генератора сигналов (не менять)
       
//для считываения приёма из сериала частоты taho
#include <SoftwareSerial.h>
SoftwareSerial Serial100(10,11);



unsigned int taho=0;

byte b0;
byte b1;
byte b2;
bool byte1read=0;
bool byte2read=0;
bool byteEnd=0;

//////



bool flag=0;


int PWM = 200;//стартовое значение ШИМ от 0 до 255        
int32_t frequency = 0; //стартовое значение частоты в Гц
float K;



volatile int impulse = 0;

//#include <class_BUTTON.h>
//BUTTON button_plus (3);
//BUTTON button_minus (2);


unsigned long ckpTime1, ckptimer1 = 0;
bool ckptimerenabled1 = 0;
#define ckpTIMEREXPIRED1 (ckpTime1 - ckptimer1)>(1000000L/frequency*0.12)//*0.10) // длина паузы в HIGH до доп зубьев

unsigned long ckpTime2, ckptimer2 = 0;
bool ckptimerenabled2 = 0;
#define ckpTIMEREXPIRED2 (ckpTime2 - ckptimer2)>(1000000L/frequency*0.15)//*0.10)// длина допзуба коленвала

unsigned long cmpTime2, cmptimer2 = 0;
bool cmptimerenabled2 = 0;
#define cmpTIMEREXPIRED2 (cmpTime2 - cmptimer2)>(1000000L*K/frequency*0.4) // длина допзуба распредвала

unsigned long cmpTime3, cmptimer3 = 0;
bool cmptimerenabled3 = 0;
#define cmpTIMEREXPIRED3 (cmpTime3 - cmptimer3)>(1000000L*K/frequency*0.36)// длина паузы в HIGH до зубьев распредвала

unsigned long cmpTime4, cmptimer4 = 0;
bool cmptimerenabled4 = 0;
#define cmpTIMEREXPIRED4 (cmpTime4 - cmptimer4)>(1000000L/frequency*0.94) //длина зуба распредвала


bool ckpT1=0;
bool ckpT1end=0;
bool ckpT2=0;
bool cmpT3=0;
bool cmpT3end=0;
bool cmpT4=0;

bool flag12=0;
bool flag24=0;
bool flag4=0;
bool flag10=0;
bool flag16=0;
bool flag22=0;

bool metka =0;


void IMPULSE (){
  impulse++;
  if (impulse==25) impulse=1; 
}





unsigned long prev = 0;
void setup()
{
Serial100.begin (19200);
Serial.begin(9600);
pinMode (12,OUTPUT);
pinMode (13,OUTPUT);
pinMode (13,1);
DDRD  |= (1 << 7);
DDRD  |= (1 << 6);
DDRD  |= _BV(PD3);

attachInterrupt (0, IMPULSE, FALLING);


 InitTimersSafe(); 
 bool success = SetPinFrequencySafe(ckp, frequency); 

delay (300);
    }   

void loop() {

  while (1){
unsigned long cur = millis();
frequency = taho*4.33;
if (taho>300){K=0.7;PWM=190;}
else {K=1; PWM=200;}
if (taho==0) PWM=0;

SerialREAD();


if (byteEnd) {taho = ( ( unsigned int )b1 << 8 ) | b2; byteEnd=0;}


//if (cur-prev>100) { Serial.print (impulse); Serial.print ("   "); Serial.println (taho); prev=cur;} 

bool success = SetPinFrequencySafe(ckp, frequency);
pwmWrite(ckp, PWM); 

ckpTime1 = micros();
ckpTime2 = ckpTime1;
cmpTime2 = ckpTime1;
cmpTime3 = ckpTime1;
cmpTime4 = ckpTime1;


//если посчитали 4,10,16 или 22 маркер запускаем таймер задержки в HIGH для зубьев распредвала
if (((impulse==4&&!flag4)||(impulse==10&&!flag10)||(impulse==16&&!flag16)||(impulse==22&&!flag22)) && !cmpT3 && PWM!=0)  {cmptimer3=cmpTime3; cmptimerenabled3=1; cmpT3=1; }    
if (impulse!=4)flag4=0; 
if (impulse!=10)flag10=0;
if (impulse!=16)flag16=0; 
if (impulse!=22)flag22=0;

if (cmptimerenabled3) {if (cmpTIMEREXPIRED3) {cmptimerenabled3=0; cmpT3end=1;}}

// когда таймер задержки в HIGH кончился, запускаем таймер зуба распредвала, во время которого выход находится в LOW
if (!cmpT4 && cmpT3end)  { cmptimer4=cmpTime4; cmptimerenabled4=1; cmpT4=1;  PORTD &=~ _BV(PD7); }
// когда таймер зуба распредвала истек, переводим вывод в HIGH
if (cmptimerenabled4) {if (cmpTIMEREXPIRED4) { PORTD |= _BV(PD7); cmptimerenabled4=0;  cmpT3=0; cmpT3end=0; cmpT4=0;}}

// если посчитали 12 маркер запускаем таймер задержки в HIGH, флаг метки ВМТ такт сжатия 1-го ц. (МПЦ) НЕ ТРОГАЕМ
if (impulse==12 && !flag12 && !ckpT1&& PWM!=0) {ckptimer1=ckpTime1; ckptimerenabled1=1; ckpT1=1; flag12=1;}
if (impulse!=12)flag12=0;
if (impulse!=24)flag24=0;

// если посчитали 24 маркер, запускаем таймер задержки в HIGH, флаг метки МПЦ в true
if (impulse==24 && !flag24 && !ckpT1 && PWM!=0)  {ckptimer1=ckpTime1; ckptimerenabled1=1; ckpT1=1; metka=1;flag24=1;}    
if (ckptimerenabled1) {if (ckpTIMEREXPIRED1) {ckptimerenabled1=0; ckpT1end=1;}}

// когда таймер задержки в HIGH кончился, запускаем таймеры, во время которых выходы находятся в LOW
// если сейчас присутствует метка МПЦ, запускаем доболнительный зуб и на коленвале и на распредвале, после чего сбрасываем метку МПЦ
if (!ckpT2 && ckpT1end && metka)  {ckptimer2=ckpTime2; ckptimerenabled2=1; ckpT2=1; cmptimer2=cmpTime2; cmptimerenabled2=1; 
PORTD &=~ _BV(PD7); PORTD &= ~(1 << PD3);   metka=0;}

// если метки МПЦ НЕТ, запускаем доболнительный только на коленвале
if (!ckpT2 && ckpT1end && !metka)  {ckptimer2=ckpTime2; ckptimerenabled2=1; ckpT2=1; PORTD &= ~(1 << PD3);   }

// когда таймеры дополнительных зубов истекли, переводим выводы в HIGH
if (ckptimerenabled2) {if (ckpTIMEREXPIRED2) {    PORTD |= (1 << PD3); ckptimerenabled2=0;  ckpT1=0; ckpT1end=0; ckpT2=0;}}
if (cmptimerenabled2) {if (cmpTIMEREXPIRED2) {PORTD |= _BV(PD7); cmptimerenabled2=0; }}


//byte k; k=PIND;
//if (!((1 << PD4) & k) || !((1 << PD5) & k)) {PORTD  &=~ _BV(PD6);} 
//if (((1 << PD4) & k) && ((1 << PD5) & k)) {PORTD  |= _BV(PD6);} 



}}

void SerialREAD (){
if (!Serial100.available()) return;

 
 b0 = Serial100.read();
if (byte1read){ if (b0!=0x31 && b0!=0x32 && b0!=0x33) {b1=b0; byte1read=0;} }
if (byte2read){ if (b0!=0x31 && b0!=0x32 && b0!=0x33) {b2=b0; byte2read=0;} }

if (b0==0x31) byte1read=1;
if (b0==0x32) byte2read=1;
if (b0==0x33) byteEnd=1;
Serial.println (b0,HEX);
}

 

 

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

получилось настроить таймер 1 ардуино чтобы получить такие сигналы. Работает гораздо более стабильно. Кто нибудь подскажите как сделать дополнительные зубья? можно на других пинах, т.к. К555ЛИ1 хорошо сигналы соединяет, попробовал. 

 



bool high;
volatile bool falsetooth=0; 

int shet=0;
bool flagshet=0;

uint8_t dutyA=83;
uint8_t dutyB=8;
static uint32_t enc = 0;
volatile int impulse;

void IMPULSE (){
  impulse++;
  if (impulse==25) impulse=1; 
  if (impulse==6||impulse==12||impulse==18||impulse==24) falsetooth=1;
  if (impulse==2||impulse==8||impulse==14||impulse==20)falsetooth=0; 
}

void setup() {

pinMode (9,OUTPUT); // выход генератора PB2
pinMode (10,OUTPUT); // выход генератора 
pinMode (4,OUTPUT); //
pinMode (2,INPUT); //
digitalWrite (2,1); // 


TCCR1A=1<<COM1A1|1<<COM1B1; //подключить выход OC1A и OC1Bпервого таймера
TCCR1B=0;//

attachInterrupt (0, IMPULSE, RISING);
}

void loop() {
  while (1){



uint32_t icr=ICR1;
uint16_t divider=1; //переменная коэфф. деления прескалера
enc = 400;
icr = (F_CPU / enc /2 /divider); 
 byte shifts[] = {3,3,2,2};
  for(byte i = 0; i < 4; i++){
      if (icr > 65536) {
          divider <<= shifts[i];
          icr = F_CPU / enc /2 /divider;
         }
    else {  //запись в регистр прескалера
        TCCR1B = (i+1)|(1<<WGM13);  break;
         }
    }
ICR1=icr-1;
 OCR1A=(uint32_t)ICR1*dutyA/100; 
 
 OCR1B=(uint32_t)ICR1*dutyB/100; 
 

if (impulse == 2||impulse == 3||impulse == 4||impulse == 5||impulse == 8||impulse == 9||impulse == 10||impulse == 11||impulse == 14||impulse == 15||impulse == 16||impulse == 17||impulse == 20||impulse == 21||impulse == 22||impulse == 23){ 
  TCCR1A=1<<COM1A1|0<<COM1B1; PORTB = _BV(PB2); high = 1;}
else {TCCR1A=1<<COM1A1|1<<COM1B1; high=0;}
byte k; k=PINB;
 if (falsetooth &&  !flagshet &&  ((1 << PB2) & k))   {shet++; flagshet=1;}
 if (falsetooth && flagshet && !((1 << PB2) & k))   {flagshet=0; }
 if (!falsetooth) shet=0;

 


if (!high && !((1 << PB2) & k) && shet==1) {PORTD  &=~ _BV(PD4);} 
if (((1 << PB2) & k) ) {PORTD  |= _BV(PD4);} 

 
}}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

поспешил, на частоте более 600 лажа потому что измерение в лупе, надо на второе внешнее прерывание вешать

MaksVV
Offline
Зарегистрирован: 06.08.2015

Вот исправил, теперь вроде как до 1400 Гц стабильный сигнал. Вопрос как создать дополнительный зуб у распредвала и коленвала, не используя micros() остаётся открытым.

 

получилось вот так 

Код




 
volatile int tic=0;
volatile int impulse;


uint8_t dutyA=83;
uint8_t dutyB=8;
static uint32_t enc = 0;

//unsigned long prev=0;

void IMPULSE (){
  impulse++;
  if (impulse==25) impulse=1; 
  
}

void TIC (){
 tic++;
  if (tic==13) tic=1; 
}


void setup() {

pinMode (9,OUTPUT); // выход генератора PB2
pinMode (10,OUTPUT); // выход генератора 
pinMode (4,OUTPUT); //
pinMode (2,INPUT); //
digitalWrite (2,1); // 
pinMode (3,INPUT); //
digitalWrite (3,1); // 

Serial.begin(9600);

TCCR1A=1<<COM1A1|1<<COM1B1; //подключить выход OC1A и OC1Bпервого таймера
TCCR1B=0;//

attachInterrupt (0, IMPULSE, RISING);
attachInterrupt (1, TIC, FALLING);
}

void loop() {
  while (1){
//int val = analogRead(0);
//unsigned long cur = millis();
//if (cur - prev>200){Serial.print (val); Serial.print ("   "); Serial.println (enc); prev=cur;}


 // val = map(val, 0, 1023, 0, 1400);
  
  
uint32_t icr=ICR1;
uint16_t divider=1; //переменная коэфф. деления прескалера
enc = 800;
icr = (F_CPU / enc /2 /divider); 
 byte shifts[] = {3,3,2,2};
  for(byte i = 0; i < 4; i++){
      if (icr > 65536) {
          divider <<= shifts[i];
          icr = F_CPU / enc /2 /divider;
         }
    else {  //запись в регистр прескалера
        TCCR1B = (i+1)|(1<<WGM13);  break;
         }
    }
ICR1=icr-1;
 OCR1A=(uint32_t)ICR1*dutyA/100; 
 
 OCR1B=(uint32_t)ICR1*dutyB/100; 
 

if (impulse == 2||impulse == 3||impulse == 4||impulse == 5||impulse == 8||impulse == 9||impulse == 10||impulse == 11||impulse == 14||impulse == 15||impulse == 16||impulse == 17||impulse == 20||impulse == 21||impulse == 22||impulse == 23){ 
  TCCR1A=1<<COM1A1|0<<COM1B1; PORTB = _BV(PB2);}
else {TCCR1A=1<<COM1A1|1<<COM1B1;}

 if (tic==3||tic==6||tic==9||tic==12)PORTD  &=~ _BV(PD4);
 else PORTD  |= _BV(PD4);



 
}}

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

Продолжаю монолог. Всем спасибо за неоценимую "помощь" в освоении таймеров и прерываний. Изначально тахосигнал, с которого нужно было измерять обороты, был такой 

т.е. я сначала пытался измерить частоту тахосигнала, а затем выдать свою частоту на сигнал коленвала (т.е. на три импульса тахосигнала нужно выдать 12 импульсов коленвала). Боролся , боролся, все "помогали". Т.е. сгенерировать сигнал то более менее получилось, но вот адектватно измерить часототу тахосигнала не вышло, т.к. все методы либо медленно мереют, либо при прекращении сигнала показывают предыдуще измеренную частоту, а мне надо ноль. 

Короче вышел из положения. На установленном двигателе кроме тахосигнала нашел сигнал первичного вала АКПП. На нём гораздо больше импульсов на один оборот коленвала.

Плохо только что немного отличается частота вращения, т.к. гидротрансформатор АКПП немного скользит, да и фиг с ним, не сильно как мне кажется. Зато пропала необходимость измерения частоты. Сигнал этот 5В в отличие от тахосигнала (он на 14В) - пропала необходимость в преобразователе напряжения (до этого использовал оптопару).

В прерывании подсчитываю количество импульсов сигнала этого первичного  вала КПП. И в зависимости от номера имульса рулю тупо ногами МК низкоуровнево. Код сократился до нельзя и работает стабильно хоть до 10000 RPM.

Всего одна переменная и луп пустой. 

volatile int impulse=0;

void IMPULSE (void){
impulse++;
if (impulse==85) impulse=1; 
if (impulse == 1||impulse==8||impulse==15||impulse==22||impulse==29||impulse==36||impulse==43||impulse==50||impulse==57||impulse==64||impulse==71||impulse==78)PORTB &=~ _BV(PB2);
else PORTB |= _BV(PB2);
if (impulse == 34||impulse==76) PORTD &=~ _BV(PD7);
if (impulse == 39||impulse==81) PORTD |= _BV(PD7);

}

void setup () {

pinMode (10,OUTPUT); // выход сигнала коленвала 
pinMode (7,OUTPUT); // выход сигнала распредвала 
pinMode (3,INPUT); // вход частоты
digitalWrite (3,1); // 
attachInterrupt (1, IMPULSE, CHANGE);
}

void loop(){}

ПС. Информация будет полезна тем, кто на хонде решил поменять рядный 4 цил двигатель К20 или К24 на V6 J30 или J35

chiptuningnt
chiptuningnt аватар
Offline
Зарегистрирован: 22.01.2018

Привет. Можешь немного пояснить, только пытаюсь вникнуть в МК, архитектуру и язык С. 
 

pinMode (3,INPUT); // вход частоты
digitalWrite (3,1); 
attachInterrupt (1, IMPULSE, CHANGE);

01: назначаем порт 3 на вход
02: устанавливаем на входе 3 значение 1
03: запускаем функцию IMPULSE по изменению состаяния на входе

не могу понять с командой attachInterrupt, а именно с единицей, как понял здесь назначается порт по которому идут прерывания, почему 1? 
 

chiptuningnt
chiptuningnt аватар
Offline
Зарегистрирован: 22.01.2018

И еще вопрос. Этой прогой ты имитируешь работу датчиков КВ и РВ синхранизируясь по датчику входного вала АКП. Зная к-во зубьев за оборот мы имеем один оборот коленчатого вала (не беря в расчет вероятность проскальзывания муфты). Два оборота вала АКП получаем полный цикл, 2 поворота КВ и один РВ. Хорошо, сигналы этих датчиков мы с имитировали. А как выполняется синхранизация по положению КВ? Те начиная считать зубья с вала АКП программе без разницы фактическое поожение КВ, на каком такте работы находится тот или иной цилиндр. Или я не совсем правильно что то понял

MaksVV
Offline
Зарегистрирован: 06.08.2015

chiptuningnt пишет:

Те начиная считать зубья с вала АКП программе без разницы фактическое поожение КВ, на каком такте работы находится тот или иной цилиндр. Или я не совсем правильно что то понял

да без разницы, т.к. устройство задумывалось просто сымитировать работу двигателя (чтобы тахометр работал). 

MaksVV
Offline
Зарегистрирован: 06.08.2015

chiptuningnt пишет:

03: запускаем функцию IMPULSE по изменению состаяния на входе

не могу понять с командой attachInterrupt, а именно с единицей, как понял здесь назначается порт по которому идут прерывания, почему 1? 
 

в ардуино уно, нано, мини есть два аппаратных прерывания (прерывание - это когада МК прекращает выполенени основной программы и переходит в функцию прерывания, она называется обработчик прерывания, в данном случае назвал её IMPULSE. Цифра 1 это номер прерывания, точнее будет int1 , как я сказал их два. То есть первое будет 0. Для прерывания 0 используется 2 пин ардуино, для прерывания 1 - 3 пин. Вообще про это смотрим тут)

oshiman
Offline
Зарегистрирован: 28.01.2018

А зачем такой огород городить ради тахометра. Вам нужно просто знать обороты двигателя. Если датчик коленвала типа Холла - взять сигнал с него, посчитать количество импульсов за оборот. Еще проще взять сигнал управления катушкой зажигания. Можно и с форсунки, но в некоторых режимах форсунки могут отключаться. 

Если приборка действительно CAN-овая, то больше сложностей передать сигнал в шину.

 

MaksVV
Offline
Зарегистрирован: 06.08.2015

oshiman пишет:
Если приборка действительно CAN-овая, то больше сложностей передать сигнал в шину.

В том то и дело, что я на тот момент не умел обращаться с CAN шиной и решено было оставить старый ЭБУ двигателя который будет посылать на панель обороты. Но этот блок оказался капризный и ему нужны были точные сигналы коленвала и распредвала с "родного" двигателя. 

MaksVV
Offline
Зарегистрирован: 06.08.2015

для тех кто набредет на эту тему. Для мотора Honda K20 (24).  Вот спустя 4 года, я наконец смог написать нормальный скетч, который хорошо работает хоть до 15 тыс. об мин.  И никуда сигналы друг от друга не уплывают. Мне уже конечно это не надо, чисто так, для спортивного интереса.

Аппаратный таймер 1 ардуино в соответствии с заданной частотой вращения коленчатого вала постоянно создает прерывания, соответствующие по времени 1 градусу оборота коленвала, в зависимости от нужного количества градусов в обработчике прерывания формируются сигналы датчиков коленчатого и распределительных валов . Луп не участвует в формировании сигналов, в лупе только в терминале настраивается смещение фаз и обороты колена. 

скетч 

//--------------------------------------------
uint16_t rpm_D = 1000;    // по дефолту  1000 об/мин 
int phaseEX_D = 115;      // смещение вып вала по дефолту , градусов 
int phaseIN_D = 10;       // смещение вп вала по дефолту , градусов 

volatile int ExTooths[] =   {20,160,20,160,20,160,20};         // здесь задаем количество зубов вып распреда и их длительность в градусах
volatile int InTooths[] =   {15,110,30,150,30,150,30,150,30};  // здесь задаем количество зубов вп распреда и их длительность в градусах


bool CKPbeginLogic = 1; // логика начала сигнала колена
bool EXbeginLogic =  0; // логика начала сигнала выпуска
bool INbeginLogic =  0; // логика начала сигнала впуска

#define CKPpin PB0      // пин коленвала 
#define EXpin  PB1      // пин вып распредвала 
#define INpin  PB5      // пин вп  распредвала 
//--------------------------------------------


volatile int ExToothsG[sizeof(ExTooths)/2+1];
volatile byte countEX = 0;
volatile byte NumbcountEX = 0;
volatile int InToothsG[sizeof(InTooths)/2+1];
volatile byte countIN = 0;
volatile byte NumbcountIN = 0;
volatile uint16_t countgrad = 1; 
volatile byte countT = 1; 
volatile byte counttooth = 1; 
volatile uint16_t rpm;     
volatile int phaseEX;      
volatile int phaseIN;      
volatile bool tooth_or_hole = 1;

void Default () 
{
rpm = rpm_D;
phaseEX = phaseEX_D;
phaseIN = phaseIN_D;
Serial.println ("Default settings:");
Serial.print (rpm); Serial.println (" rpm");
Serial.print("Ex: ");  Serial.print (phaseEX); Serial.println(" grad"); 
Serial.print("In: ");  Serial.print (phaseIN); Serial.println(" grad"); 
Serial.println();
}

void setup() {
Serial.begin(115200);
 Default () ;
  DDRB|= _BV(CKPpin);
  DDRB|= _BV(EXpin);
  DDRB|= _BV(INpin);
 if (!CKPbeginLogic)PORTB |=_BV(CKPpin);
 if (!EXbeginLogic) PORTB |=_BV(EXpin);
 if (!INbeginLogic) PORTB |=_BV(INpin);
  TCCR1A = 0;
  TCCR1B = 8;
  TCCR1B |= 1;
  OCR1A = 2666666ul/rpm;  
  TIMSK1 |= (1<<OCIE1A);
for (int i=0; i<sizeof(ExToothsG)/2 ; i++) 
      {   if (i==0) ExToothsG[i]= phaseEX;
         else  ExToothsG[i] = ExToothsG[i-1]+ExTooths[i-1];
      }
for (int i=0; i<sizeof(InToothsG)/2 ; i++) 
      {   if (i==0) InToothsG[i]= phaseIN;
         else  InToothsG[i] = InToothsG[i-1]+InTooths[i-1];         
      }
NumbcountEX = sizeof(ExTooths)/2+1;
NumbcountIN = sizeof(InTooths)/2+1;

}


void loop() {
if (Serial.available() )
  {
    static int mode = 0; 
    
    int in = Serial.read();
if (in >='0' && in <='9' && mode ==0)
    {int rpm = (in-'0')*1000;
Serial.print (rpm); Serial.println (" rpm");
OCR1A = 2666666UL/rpm;}

else if (in=='+'&& mode==1) {phaseEX++; Serial.print("Ex: ");  Serial.print (phaseEX); Serial.println(" grad");  }
else if (in=='-'&& mode==1) {phaseEX--; Serial.print("Ex: "); Serial.print (phaseEX); Serial.println(" grad"); }

else if (in=='+'&& mode==2) {phaseIN++; Serial.print("In: ");  Serial.print (phaseIN); Serial.println(" grad");  }
else if (in=='-'&& mode==2) {phaseIN--; Serial.print("In: "); Serial.print (phaseIN); Serial.println(" grad"); }

else if (in=='r'){mode = 0; Serial.println ("RPM input");}           // настройка оборотов ДВС
else if (in=='e'){mode = 1; Serial.println ("EX Phase  input");}     // режим смещения фазы выпуска 
else if (in=='i'){mode = 2; Serial.println ("IN Phase  input");}     // режим смещения фазы впуска 
else if (in=='d'){Default () ; } // настройки по умолчанию



for (int i=0; i<sizeof(ExToothsG)/2 ; i++) 
      {   if (i==0) ExToothsG[i]= phaseEX;
         else  ExToothsG[i] = ExToothsG[i-1]+ExTooths[i-1];
      }
for (int i=0; i<sizeof(InToothsG)/2 ; i++) 
      {   if (i==0) InToothsG[i]= phaseIN;
         else  InToothsG[i] = InToothsG[i-1]+InTooths[i-1];         
      }

     Serial.println();
}

}
ISR (TIMER1_COMPA_vect)

{
  
  countgrad++;
  countT++;
  if ((tooth_or_hole && countT>=4) || (!tooth_or_hole && countT>=26) ) // основные зубья дпкв (зубы 4гр, впадины 26гр.)
  
  {
    tooth_or_hole = !tooth_or_hole;
    countT = 0;
    counttooth++; 
    if (counttooth>24) counttooth =1;
    PORTB ^= _BV(CKPpin);
  }
  if (countgrad>720) countgrad=1;

  if (countgrad==10||countgrad==14||countgrad==370||countgrad==374) PORTB ^= _BV(CKPpin); // доп зуб дпкв
  if (countgrad==ExToothsG[countEX]){ PORTB ^=( _BV(EXpin)); countEX++; if (countEX>=NumbcountEX) countEX=0; }
  if (countgrad==InToothsG[countIN]){ PORTB ^=( _BV(INpin)); countIN++; if (countIN>=NumbcountIN) countIN=0; }
}

 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

MaksVV пишет:

Аппаратный таймер 1 ардуино в соответствии с заданной частотой вращения коленчатого вала постоянно создает прерывания, соответствующие по времени 1 градусу оборота коленвала...

А почему в качестве единицы задается именно 1/360 часть оборота? Почему, скажем, не 1/256, 1/512 или 1/400?

MaksVV
Offline
Зарегистрирован: 06.08.2015

Ну для удобства и чтобы без дробных частей на зуб. Обычно задающие шкивы коленчатого вала 36 или 60 зубьев, иногда 12 как здесь, может и другие есть, но скорее всего кратно либо 3 либо 6. А разрешение смещения фаз в 1 градус я думаю этого достаточно. Мне смещение вообще было не нужно. Смотря для чего кто сигналы хочет сымитировать.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Наименьшее общее кратное 36, 60, 12, 3 и 6 - 180. Значит, достаточно было сделать 180 прерываний на оборот. 360 - явно избыточно.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Ну как сказать. При задающем диске 60 зубьев, зуб имеет 1 градус и впадина 5 градусов. Если взять квант 1/180 то это будет 2 градуса - зуб в 1 градус сделать не получится.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

MaksVV пишет:
Ну как сказать. При задающем диске 60 зубьев, зуб имеет 1 градус и впадина 5 градусов. Если взять квант 1/180 то это будет 2 градуса - зуб в 1 градус сделать не получится.

Что-то я не понял Ваших рассуждений.

А если зуб не 1 градус, а 1.1 градуса, то нам нужно квант до 0.1 градуса уменьшать?

А если там на самом деле вообще периодическая дробь или, не дай Бог, иррациональное число?

MaksVV
Offline
Зарегистрирован: 06.08.2015

andriano пишет:

А если зуб не 1 градус, а 1.1 градуса, то нам нужно квант до 0.1 градуса уменьшать?

мое рассуждение такое,  что если наименьший элемент , в данном случае зуб, размером в 1 градус, то квант должен быть не более 1го градуса. А вы предложили 1/180, что соответствует двум градусам. Имхо, квант в 1 градус необходимо и достаточно, к тому же удобно.  

Я не понял проблемы , что такого случиться, если разрешающую способность увеличить? Я ведь ослом на больших оборотах проверял , картина красивая. Понятное дело, что если разрешение ещё увеличивать, то что нибудь да не успеется на высоких оборотах. Но квант в 1 градус всё красиво до 20тыс. об/мин. 

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

MaksVV пишет:

мое рассуждение такое,  что если наименьший элемент , в данном случае зуб, размером в 1 градус, то квант должен быть не более 1го градуса. А вы предложили 1/180, что соответствует двум градусам. Имхо, квант в 1 градус необходимо и достаточно, к тому же удобно.  

С этим рассуждением я не спорю, просто мне хотелось узнать, почему минимальный квант равен 1/360 оборота. Почему, скажем, если шаг зуба 6 градусов, то сам зуб 1 градус, а не 3?

Но, в принципе, цифры еще ко всему и хорошо укладываются в возможности Atmega328. По моим прикидкам максимальная частота прерываний для недлинных операций с управлением пинами лежит где-то в районе 110 кГц, а тут получается близкая величина в 90 кГц.

MaksVV
Offline
Зарегистрирован: 06.08.2015

andriano пишет:

С этим рассуждением я не спорю, просто мне хотелось узнать, почему минимальный квант равен 1/360 оборота. Почему, скажем, если шаг зуба 6 градусов, то сам зуб 1 градус, а не 3?

Датчики коленвала в большинстве своём бывают либо индуктивные (сигнал синусоида) либо же Холла (прямоугольный сигнал). Дак вот, по моим наблюдениям, в случае с индуктивным, зуб и впадина равны и так бы и было, как вы говорите зуб и впадина по 3градуса. Но речь я вёл про датчик Холла. По какой-то причине автопроизводители зуб при этом делают раз в 5 меньше впадины. Не знаю с чем это связано, но сколько сигналов снимал, всегда так. Вот здесь  в соседней теме я и сначала неправильно сделал сигнал - как индуктивный, с равными зубьями и впадинами, потом смотрю, что то не то. Исправил. Можете там сравнить картинку ТС и которую я сначала неправильно сделал, с равными зубами и впадинами. 

ussr717
Offline
Зарегистрирован: 11.06.2021

Здравствуйте. Ардуино только начал изучать. Ваш скетч практически то что нужно, только можете помочь немного переделать, нужна имитация  работы датчика холла трамблера. По логике просто -принимаем сигнал с ДХ трамблера и выдаем нужный нам сигнал с нужной скважностью. ( 4х цилиндровый мотор ВАЗ 08-09). Грубо говоря я так понимаю вместо зубьев шкива берем в расчет четыре шторки на валу трамблера. И весь код надо значительно упростить)) - в этом проблема, чтобы его упростить его нужно понять, пока сложно это сделать без вашей помощи.

MaksVV
Offline
Зарегистрирован: 06.08.2015

ussr717 пишет:
По логике просто -принимаем сигнал с ДХ трамблера и выдаем нужный нам сигнал с нужной скважностью. ( 4х цилиндровый мотор ВАЗ 08-09). Грубо говоря я так понимаю вместо зубьев шкива берем в расчет четыре шторки на валу трамблера.

Не понятно, что именно вам нужно. Мой скетч  через Serial получает значение оборотов. В зависимости от оборотов формирует сигналы дпкв и дпрв. Опишите задачу более точно. 

ussr717
Offline
Зарегистрирован: 11.06.2021

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

Могу реализовать получение сигнала с ДХ, на пин D2 Ардуино, с прерываниями и рассчитать кол-во оборотов коленчатого вала. -это мы получили обороты. Теперь в зависимости от оборотов надо сформировать новый сигнал, с прерываниями такой частоты и скважности чтобы возникла отсечка, пропуски зажигания.
Скважность и частоту можно подобрать опытным путем. А вот как рассчитать и вывести нужный сигнал на пин Ардуино пока сложно.

MaksVV
Offline
Зарегистрирован: 06.08.2015

Не понял при чем тут скважность. Она всегда одна и та же. Размер прорези и закрытой части задающего диска датчика ведь не меняется.

Не проще ли для организации отсечки измерять обороты,  и в зависимости от их значения либо пропускать сигнал дальше, либо нет? При отсутствии сигнала как раз и прекратится искрообразование. 

ussr717
Offline
Зарегистрирован: 11.06.2021

MaksVV пишет:

Не проще ли для организации отсечки измерять обороты,  и в зависимости от их значения либо пропускать сигнал дальше, либо нет? При отсутствии сигнала как раз и прекратится искрообразование. 


Хорошая идея. Как реализовать пропускание сигнала?

MaksVV
Offline
Зарегистрирован: 06.08.2015

В обработчике внешнего прерывания CHANGE, добавить типа этого:

if (обороты норм)  digitalWrite (нужная нога, digitalRead(2));

Только лучше дергая лапой через регистры

ussr717
Offline
Зарегистрирован: 11.06.2021

MaksVV пишет:

В обработчике внешнего прерывания CHANGE, добавить типа этого:

if (обороты норм)  digitalWrite (нужная нога, digitalRead(2));

Только лучше дергая лапой через регистры

unsigned long RPM_impuls;  // переменная считает импульсы тахометра
int RPM = 0;                // переменная измеренных данных тахометра
unsigned long prev_ms = 0; // переменная для вычисления отрезков времени оборотов

int otsechka = 3000; // обороты на которых будtт отсечка

void setup() {
    pinMode(2, INPUT); //тахометр (D2)
    pinMode(3, OUTPUT); //тахометр (D3)
    digitalWrite(2, HIGH); // включаем подтягивающий резистор на 2 пине
    attachInterrupt(0,RPMmetr,RISING); //задать функцию прерывания на 2 пин
    Serial.begin(9600);
}

void loop() {
  
             // Считаем тахометр
             RPM=((RPM_impuls*30000)/(millis() - prev_ms)); // формула расчета оборотов
             RPM_impuls=0;                    // обнуляем счетчик прерываний
             prev_ms = millis();                // обнуляем отрезок времени
   
             Serial.print(RPM);
             Serial.println(" RPM ");

if (RPM>otsechka){ //если обороты двигателя больше 3000, то подаем искру с задержкой (отсечка)
                 delayMicroseconds(17); //задержка до подачи сигнала на коммутатор
                 //  digitalWrite(3,HIGH); //подача сигнала на коммутатор
                 digitalWrite (3, digitalRead(2));
                 delayMicroseconds(20); //задержка после подачи сигнала на коммутатор
                 //  digitalWrite(3,LOW);    
}else{ //подаем искру как есть
              digitalWrite (3, digitalRead(2));
}
}


// Запуск счетчика прерываний тахометра с нуля
void RPMmetr() {
               RPM_impuls++;
               }