Ты знаешь мою искреннюю "любовь" к пассажиру ;)), но код вполне изящный. Если "доё..ываться" , то до diginalWrite(!digitelRRead(xxx)). И то в тестах все так пишут, из продакшн, конечно убрать надо, но пассажир про продакшн и не говорил.
Если "доё..ываться" , то до diginalWrite(!digitelRRead(xxx)).
Да, ладно! К чему тут? Вот сюда посмотри. Во втором коде используется недокументированное значение второго параметра pinMode, загоняющее светодиод в очень интересный режим :-)))
ТС - задача твоя решается очень просто. Делаешь процедуру, которая берёт из массива булевы данные с датчиков ( 0 или 1) Это будет единичный квант времени, 360 квантов = одному обороту коленвала. А управлять фазой по распредвалам уже будешь смещением счётчика, бегающего по массива распредвала. Подобная задача уже решалась здесь, несколько месяцев назад. Единственная проблема - не хватает скорости проца, больше 1500 об/мин у меня не получилось сделать. Выход - переход на стм32.
было время на работе, решил по упражняться. Вот что получилось. Луп в формировании сигнала не участвует, всё на таймере 1 и низкоуровневое руление ногами. 9000 об/мин (можно и выше) - картинка вроде красивая. Так что 328 мега вполне себе... Фазы распредвалов двигаются с шагом 1 градус. В лупе принимаются настройки по оборотам и смещению фаз.
скетч
//--------------------------------------------
uint16_t rpm_D = 1000; // по дефолту 1000 об/мин
int phaseEX_D = 75; // смещение вып вала по дефолту , градусов
int phaseIN_D = 75; // смещение вп вала по дефолту , градусов
volatile int ExTooths[] = {3}; // здесь задаем количество зубов вып распреда и их длительность (соответствующую зубам колена)
volatile int InTooths[] = {8,6,24,6,24,22,8}; // здесь задаем количество зубов вп распреда и их длительность (соответствующую зубам колена)
bool CKPbeginLogic = 1; // логика начала сигнала колена
bool EXbeginLogic = 1; // логика начала сигнала выпуска
bool INbeginLogic = 1; // логика начала сигнала впуска
#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;
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]+ (6*ExTooths[i-1]);
}
for (int i=0; i<sizeof(InToothsG)/2 ; i++)
{ if (i==0) InToothsG[i]= phaseIN;
else InToothsG[i] = InToothsG[i-1]+ (6*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]+ (6*ExTooths[i-1]);
}
for (int i=0; i<sizeof(InToothsG)/2 ; i++)
{ if (i==0) InToothsG[i]= phaseIN;
else InToothsG[i] = InToothsG[i-1]+ (6*InTooths[i-1]);
}
Serial.println();
}
}
ISR (TIMER1_COMPA_vect)
{
countgrad++;
countT++;
if (countT>=3){
countT = 0;
counttooth++;
if (counttooth>120) counttooth =1;
if (counttooth!=117 && counttooth!=118 && counttooth!=119 && counttooth!=120) PORTB ^= _BV(CKPpin);
}
if (countgrad>720) countgrad=1;
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; }
}
15 строчку заменить на if ((uint16_t)millis() - phase_start + phase_shift > data[data_pos]) {
А как же
Приведенный мной код корректно обрабатывает переполнение переменных
Перестал отрабатывать? :-)
Да ладно Женя, мелкие придирки.
Ты знаешь мою искреннюю "любовь" к пассажиру ;)), но код вполне изящный. Если "доё..ываться" , то до diginalWrite(!digitelRRead(xxx)). И то в тестах все так пишут, из продакшн, конечно убрать надо, но пассажир про продакшн и не говорил.
Сколько оборотов/мин получилось в итоге???
Сколько оборотов/мин получилось в итоге???
+1 на миллис и дигиталврайт будет коряво работать на больших скоростях. только на таймерах, луп должен быть пустой
Я тоже когда то пытался такую задачу решить, но тогда ещё знаний не было((
было время на работе, решил по упражняться. Вот что получилось. Луп в формировании сигнала не участвует, всё на таймере 1 и низкоуровневое руление ногами. 9000 об/мин (можно и выше) - картинка вроде красивая. Так что 328 мега вполне себе... Фазы распредвалов двигаются с шагом 1 градус. В лупе принимаются настройки по оборотам и смещению фаз.
скетч
9000rpm крупно
9000rpm
2000rpm
ну и ТСа картинка для сравнения
постом выше скетч немного неточен в плане сигнала датчика коленвала. Вот более правильный скетч.