Всем привет!
Увидел одно решение на ардуино, и мне очень понравилась эта идея. https://www.youtube.com/watch?v=XP1SUmiTKZY
Сейчас в работе следующая задача:
Для мотоцикла необходимо реализовать электронное опережение момента, когда искра воспламеняет топливную смесь.
В зависимости от оборотов двигателя необходимо успеть зажечь смесь, чтобы она выдавала наибольшее усилие при взрыве, и обратная ситуация, чтобы не поджечь раньше - тогда сила от воспламенения сыграет в обратную сторону.
С программированием не сильно знаком, но разобраться получается, как прописать диапазоны по оборотам понял, и формулы расчетов углов.
Вопросы, с которыми столкнулся, и хотелось бы найти решение:
По первым двум вопросам прошу совета: стоят ли свеч эти предложения, т.к. для меня это долгий процесс, хотя понимаю, что операции наверно одни из типичных. Если смысл в этом есть прошу помочь сделать или сказать как.
По третьему вопросу интересует как сделать и какой выход задействовать.
Плата digispark attiny85
Вот что получилось на текущий момент:
Увидел одно решение на ардуино, и мне очень понравилась эта идея. https://www.youtube.com/watch?v=XP1SUmiTKZY
Сейчас в работе следующая задача:
Для мотоцикла необходимо реализовать электронное опережение момента, когда искра воспламеняет топливную смесь.
В зависимости от оборотов двигателя необходимо успеть зажечь смесь, чтобы она выдавала наибольшее усилие при взрыве, и обратная ситуация, чтобы не поджечь раньше - тогда сила от воспламенения сыграет в обратную сторону.
С программированием не сильно знаком, но разобраться получается, как прописать диапазоны по оборотам понял, и формулы расчетов углов.
Вопросы, с которыми столкнулся, и хотелось бы найти решение:
- посоветовали операторы if else заменить на switch case т.к. вторые тратят меньше ресурсов при расчете - так ли в моем конкретном случае или нет разницы?
- для вычислений угла поворота возможно ли перевести в uint16 / unsigned int (0...65535), а угол опережения - в uint8 / byte (0...255) вместо текущих расчетов, способствует ли это сокращению расходования ресурсов?
- в текущей реализации используется один выход pinMode(1, OUTPUT), мне необходимо задействовать второй выход, полагаю, что можно использовать "4" и прописать для него сигнал либо в формате через n градусов угла оборота после сигнала из выхода "1" либо в постоянный % который будет применяться на всем диапазоне оборотов коленчатого вала.
По первым двум вопросам прошу совета: стоят ли свеч эти предложения, т.к. для меня это долгий процесс, хотя понимаю, что операции наверно одни из типичных. Если смысл в этом есть прошу помочь сделать или сказать как.
По третьему вопросу интересует как сделать и какой выход задействовать.
Плата digispark attiny85
Вот что получилось на текущий момент:
igntionsystem:
unsigned long newtime;
unsigned long oldtime;
unsigned long diffTime;
unsigned long VMTtime;
unsigned long nextIgnition = 0;
long int rpm;
bool modulator;
bool ignitionWasFired;
bool ignitionFlag;
bool ignitionFlagWithOffset;
bool oldModulator;
float ignitionDegree;
void setup()
{
newtime=micros();
oldtime=micros();
// Serial.begin(115200); //Default Baudrate
pinMode(1, OUTPUT);
pinMode(0, INPUT);
// Serial.print("LOADED");
}
void readrpm()
{
newtime=micros();
diffTime = newtime-oldtime;
rpm = 60000000/diffTime;
// Serial.print("RPM");
// Serial.print(rpm);
}
void countIgnitionTime() {
nextIgnition = (500000 * (360 - ignitionDegree)) / (3 * rpm) + VMTtime;
ignitionFlagWithOffset = true;
}
void loop() {
modulator = digitalRead(0);
if (micros() >= nextIgnition && ignitionFlagWithOffset == true) {
digitalWrite(1, HIGH);
ignitionFlagWithOffset = false;
}
// if (ignitionFlag == false) {
// digitalWrite(1, LOW);
// }
if (ignitionFlag == true) {
digitalWrite(1, HIGH);
ignitionFlag = false;
}
if (modulator != oldModulator) {
oldModulator = modulator;
if(modulator == LOW) {
digitalWrite(1, LOW);
return;
}
VMTtime = micros();
// 1000-20.8; 2000-17; 3000-19.8; 4000-20.1; 5000-22.4; 6000-25
readrpm();
ignitionFlag = true;
if (rpm >= 0 && rpm <= 600) {
oldtime=micros();
ignitionFlag = true;
return;
}
if (rpm >= 600 && rpm <= 800) { // 0 - 10.8
ignitionDegree = 0.0540 * rpm + (-32.400);
}
if (rpm >= 800 && rpm <= 1000) { // 10.8 - 20.8
ignitionDegree = 0.0500 * rpm + (-29.200);
}
if (rpm >= 1000 && rpm <= 1500) { // 20.8 - 18.6
ignitionDegree = 0.0044 * rpm + (-25.200);
}
if (rpm >= 1500 && rpm <= 2000) { // 18.6 - 17
ignitionDegree = 0.0032 * rpm + (-23.400);
}
if (rpm >= 2000 && rpm <= 2500) { // 17 - 18.4
ignitionDegree = 0.0028 * rpm + (11.400);
}
if (rpm >= 2500 && rpm <= 3000) {// 18.4 - 19.8
ignitionDegree = 0.0028 * rpm + (11.400);
}
if (rpm >= 3000 && rpm <= 3500) { // 19.8 - 21.4
ignitionDegree = 0.0032 * rpm + (10.200);
}
if (rpm >= 3500 && rpm <= 4000) { // 21.4 - 20.1
ignitionDegree = 0.0026 * rpm + (-30.500);
}
if (rpm >= 4000 && rpm <= 4500) { // 20.1 - 21.4
ignitionDegree = 0.0026 * rpm + (9.700);
}
if (rpm >= 4500 && rpm <= 5000) { // 21.4 - 22.4
ignitionDegree = 0.0020 * rpm + (12.400);
}
if (rpm >= 5000 && rpm <= 5500) { // 22.4 - 23.9
ignitionDegree = 0.0030 * rpm + (7.400);
}
if (rpm >= 5500 && rpm <= 6000) { // 23.9 - 25
ignitionDegree = 0.0022 * rpm + (11.800);
}
if (rpm >= 6000 && rpm <= 6500) { // 25 - 26.7
ignitionDegree = 0.0034 * rpm + (4.600);
}
if (rpm > 6500) {
ignitionDegree = 26.7;
}
if (ignitionDegree > 0){
countIgnitionTime();
}
oldtime=micros();
}
}