- Katılım
- 17 Eyl 2013
- Mesajlar
- 8,789
- Tepkime puanı
- 23,175
- Yaş
- 61
- Konum
- İstanbul
- Web sitesi
- www.sumeryamaner.com
- İlgi Alanı
- Uçak
Hezarfen ekibinden bir arkadaşım, motor düşük devirlerdeyken stop edecek kadar yavaşlarsa bunu farkedip biraz gaz açacak bir devre istedi.
Tasarladığım devre şöyle:
Alıcıdan gaz servo çıkışı ve kill switch çıkışı devreye giriyor. Benzinli motorun ateşleme sensöründen gelen sinyal de Y kablo ile devreye alınıyor.
Devre üzerinde iki adet trimpot var. Bunlardan birisi sistemin devreye girmesi için gerekecek minimum devri belirliyor. Bu devir yaklaşık olarak 1000 ile 2023 devir arasında. Diğer trimpot ise devir sınırın altına indiğinde gazın ne kadar açılacağını belirliyor. Devrede bir de jumper var. Bu da throttle kanalının normal ya da reverse olmasına göre ya boş kalıyor ya da 0 V'a bağlanıyor.
Çalışma mantığı da şöyle:
Setup kısmında kill switch'in açılması bekleniyor. Ateşleme enerjilendiriliyor.
Loop kısmında öncelikle alıcıdan motor stop komutu gelip gelmediği sürekli izleniyor. Motor stop gelirse ateşleme kapatılıyor (buraya henüz akıllı kill switch işlevi ekleyemedim).
Motor stop gelmiyorsa sürekli devir ölçülüyor ve değerlendiriliyor. Devir trimpot ile belirlenen değerin altında ise gaz kolu değeri diğer trimpot ile belirlenen miktar kadar artırılıyor ya da eksiltiliyor. Bu artırma ya da eksiltme reverse jumper konumuna göre yapılıyor. (Biliyorsunuz gerek uçaktaki geometri gerekse karbüratörün yapısı ve konumu nedeniyle gaz kimi zaman ileriye kimi zaman ise geriye doğru çalışır. Bu reverse jumperi o ayarı sağlıyor bize.)
Peki devir nasıl ölçülüyor? Devir ölçmenin iki farklı yöntemi var. Birincisi belirli bir süre içindeki ateşlemeleri saymak. Bu çok uzun zaman alır ve hassas bir ayara izin vermez. O zaman ikinci yöntemi kullanacağız. Yani peş peşe gelen iki ateşleme sinyalinin arasını ölçüyoruz. Bu süreyi mikrosaniye cinsinden ölçüp 60000000'i bu sayıya böldüğümüzde dakikada devir sayısını elde ediyoruz. Aslında program içinde bu dönüşümü hiç yapmadan sadece süre üzerinden de gitmek mümkün ama daha iyi anlaşılabilirlik açısından ilk aşamada bunu tercih ettim.
Kod aşağıda.
Bu kodun şu an için büyük bir sorunu var. Düşünün, bir ateşleme aralığı ölçüldü ve devir asgari devrin altında çıktı. Servo sinyaline müdahale ettik. Gazı biraz açtık. Bir sonraki çevrimde devir yükselmiş olacak. Yani gaz kolu yine eski konumuna dönecek. Yani sürekli oynayan, kararsız bir rölanti ortaya çıkacak. Buna bir çözüm bulmak gerekiyor.
Aklıma gelen yöntem ise şu: rxPWM değerini her döngüde ayrı bir değişkende depolayıp aktüel rxPWM ile arasında fark varsa (yani bir döngü öncesinde sistem devreye girip gaz açtıysa) gaz servosu çıkışını adım adım aktüel değere getirmek. Bunu, daha çnce yapmış olduğum servo yavaşlatıcıdaki mantık ve algoritmayı uyarlayarak başarabilirim gibime geliyor.
EDİT: Koda ekleme yaptım. Bu şekilde anlattığım sorunun üstesinden gelebilmeyi umuyorum.
Tasarladığım devre şöyle:
Alıcıdan gaz servo çıkışı ve kill switch çıkışı devreye giriyor. Benzinli motorun ateşleme sensöründen gelen sinyal de Y kablo ile devreye alınıyor.
Devre üzerinde iki adet trimpot var. Bunlardan birisi sistemin devreye girmesi için gerekecek minimum devri belirliyor. Bu devir yaklaşık olarak 1000 ile 2023 devir arasında. Diğer trimpot ise devir sınırın altına indiğinde gazın ne kadar açılacağını belirliyor. Devrede bir de jumper var. Bu da throttle kanalının normal ya da reverse olmasına göre ya boş kalıyor ya da 0 V'a bağlanıyor.
Çalışma mantığı da şöyle:
Setup kısmında kill switch'in açılması bekleniyor. Ateşleme enerjilendiriliyor.
Loop kısmında öncelikle alıcıdan motor stop komutu gelip gelmediği sürekli izleniyor. Motor stop gelirse ateşleme kapatılıyor (buraya henüz akıllı kill switch işlevi ekleyemedim).
Motor stop gelmiyorsa sürekli devir ölçülüyor ve değerlendiriliyor. Devir trimpot ile belirlenen değerin altında ise gaz kolu değeri diğer trimpot ile belirlenen miktar kadar artırılıyor ya da eksiltiliyor. Bu artırma ya da eksiltme reverse jumper konumuna göre yapılıyor. (Biliyorsunuz gerek uçaktaki geometri gerekse karbüratörün yapısı ve konumu nedeniyle gaz kimi zaman ileriye kimi zaman ise geriye doğru çalışır. Bu reverse jumperi o ayarı sağlıyor bize.)
Peki devir nasıl ölçülüyor? Devir ölçmenin iki farklı yöntemi var. Birincisi belirli bir süre içindeki ateşlemeleri saymak. Bu çok uzun zaman alır ve hassas bir ayara izin vermez. O zaman ikinci yöntemi kullanacağız. Yani peş peşe gelen iki ateşleme sinyalinin arasını ölçüyoruz. Bu süreyi mikrosaniye cinsinden ölçüp 60000000'i bu sayıya böldüğümüzde dakikada devir sayısını elde ediyoruz. Aslında program içinde bu dönüşümü hiç yapmadan sadece süre üzerinden de gitmek mümkün ama daha iyi anlaşılabilirlik açısından ilk aşamada bunu tercih ettim.
Kod aşağıda.
Kod:
// Motor devrini sürekli gözleyip belirli bir değerin altına inmeye başladığında gaz verecek program
int throttlein = 1; // Alıcıdan throttle sinyali girişi
int sensorin = 3; // Ateşlemeden gelen sinyal girişi
int throttleout = 5; // Gaz servosu çıkışı
int ignLED = 11; // Ateşleme LED göstergesi çıkışı
int ign = 9; // Ateşleme optokuplör çıkışı
int steppin = 0; // Devir düştüğünde gazın ne kadar açılacağını belirleyen trimpot girişi
int revpin = 8; // Gaz servosu reverse jumper girişi
int mindevirpin = 2; // Alt devir sınırını ayarlamak için trimpot girişi
int motorstop = 0; // Motorun stop etmiş olduğunu gösteren değişken. 0 ise motor çalışıyor 1 ise stop etmiş
int mindevir;
int devir;
int ignPWM;
int rxPWM;
int oldrxPWM;
int thrstep = 15;
unsigned long timer;
unsigned long frame;
unsigned long timer2;
int n;
int x;
void setup()
{
pinMode(throttleout, OUTPUT);
pinMode(ign, OUTPUT);
pinMode(ignLED, OUTPUT);
pinMode(revpin, INPUT);
digitalWrite(revpin, HIGH);
ignPWM = pulseIn(ign, HIGH, 25000);
while(ignPWM <= 1500) //Burada ateşlemenin açık komutunu bekliyoruz
{
ignPWM = pulseIn(ign, HIGH, 25000);
}
digitalWrite(ignLED, HIGH);
digitalWrite(ign, HIGH); //Ateşlemeyi açtık
}
void loop()
{
rxPWM = pulseIn(throttlein, HIGH, 25000);
ignPWM = pulseIn(ign, HIGH, 25000);
while(ignPWM > 1500)
{
frame = micros();
ignPWM = pulseIn(ign, HIGH, 25000);
rxPWM = pulseIn(throttlein, HIGH, 25000);
devirhesapla();
if(devir > 0)
{
mindevir = 1000 + analogRead(mindevirpin);
thrstep = analogRead(steppin) / 4;
if(devir < mindevir)
{
if(digitalRead(revpin) == HIGH)
{
rxPWM = rxPWM + thrstep;
}
else
{
rxPWM = rxPWM - thrstep;
}
oldrxPWM = rxPWM;
if(rxPWM > 2200)
{
rxPWM = 2200;
}
if(rxPWM < 800)
{
rxPWM = 800;
}
}
else
{
if(rxPWM > oldrxPWM)
{
rxPWM = rxPWM - ((rxPWM - oldrxPWM)/2);
oldrxPWM = rxPWM;
}
else
{
rxPWM = rxPWM - ((rxPWM + oldrxPWM)/2);
oldrxPWM = rxPWM;
}
}
}
else
{
oldrxPWM = rxPWM;
}
throut();
while((micros() - frame) < 20000)
{
}
}
digitalWrite(ignLED, LOW);
digitalWrite(ign, LOW); //Ateşlemeyi kapattık
}
void devirhesapla()
{
motorstop = 0;
n = digitalRead(sensorin);
timer2 = micros();
while(motorstop == 0)
{
while(n == 0)
{
n = digitalRead(sensorin);
if((micros() - timer2) > 60000)
{
motorstop = 1;
devir = 0;
}
}
timer = micros();
while(n > 0)
{
n = digitalRead(sensorin);
if((micros() - timer2) > 60000)
{
motorstop = 1;
devir = 0;
}
}
while(n == 0)
{
n = digitalRead(sensorin);
if((micros() - timer2) > 60000)
{
motorstop = 1;
devir = 0;
}
}
}
if(motorstop == 0)
{
x = micros();
n = x - timer;
devir = 60000000 / n;
}
else
{
devir = 0;
}
}
void throut()
{
digitalWrite(throttleout, HIGH);
timer = micros();
while((micros() - timer) < rxPWM)
{
}
digitalWrite(throttleout, LOW);
}
Bu kodun şu an için büyük bir sorunu var. Düşünün, bir ateşleme aralığı ölçüldü ve devir asgari devrin altında çıktı. Servo sinyaline müdahale ettik. Gazı biraz açtık. Bir sonraki çevrimde devir yükselmiş olacak. Yani gaz kolu yine eski konumuna dönecek. Yani sürekli oynayan, kararsız bir rölanti ortaya çıkacak. Buna bir çözüm bulmak gerekiyor.
Aklıma gelen yöntem ise şu: rxPWM değerini her döngüde ayrı bir değişkende depolayıp aktüel rxPWM ile arasında fark varsa (yani bir döngü öncesinde sistem devreye girip gaz açtıysa) gaz servosu çıkışını adım adım aktüel değere getirmek. Bunu, daha çnce yapmış olduğum servo yavaşlatıcıdaki mantık ve algoritmayı uyarlayarak başarabilirim gibime geliyor.
EDİT: Koda ekleme yaptım. Bu şekilde anlattığım sorunun üstesinden gelebilmeyi umuyorum.