- Katılım
- 17 Eyl 2013
- Mesajlar
- 9,084
- Tepkime puanı
- 23,743
- Yaş
- 62
- Konum
- İstanbul
- Web sitesi
- www.sumeryamaner.com
- İlgi Alanı
- Uçak
Yeni proje: Motor rölanti devri emniyeti ve kill switch kombinasyonu
Bir adım daha ilerledik. Her ne kadar çok turlu trimpotlar kullanılmış olsa da titreşime bağlı sorun riski devam ediyordu. Ben de ayarlamalar için trimpot yerine butonlar kullanmaya karar verdim. Butonlarla ayarlanan alt devir hassasiyeti ve tepki miktarı ise chip üzerindeki EEPROM'a yazılıyor ve oradan okunuyor. Yani elektrik gittiğinde yok olmuyor. Mekanik risk de yok. Tabii şu anki kodda en önemli özellik olan "key debounce" yok. Ona bir çözüm üreteceğim. Yine de test için yeterli bir kod. Tabii binbir hata ve sorun çıkacak ama adım adım debug edeceğiz.
Plaket artık böyle:
[attachimg=1]
Kodun son hali de burada:
Temel mantık yaklaşımını özetlemek istiyorum. Bu şekilde sizlerden gelecek öneri ve eleştiriler ile daha iyi bir şey yapabilirim diye umuyorum.
* İlk çalışmada butonlara pullup dirençleri üzerinden logic HIGH veriliyor. Yani butonlar aktifken LOW değeri veriyorlar.
* Engine kill kanalından gelen sinyal izlenip ignition ON yapılıyor. Burada akıllı kill switch algoritmasına henüz giremedim. O daha ileriki bir versiyonda belki...
* Ana loopta önce devir hesaplanıyor. Bunu yapmak için iki ateşleme arasındaki süreyi mikrosaniye olarak sayıyoruz. Sonra bundan devri hesaplıyoruz. Motorun stop etmiş olma olasılığına karşın bir de timeout var burada. Eğer iki ateşleme arası 60 milisaniyeden uzunsa motorun stop ettiğine karar veriyoruz.
* Loop içinde devir hesaplandıktan sonra bu, butonlarla belirlenmiş ve EEPROM'a yazılmış olan bir değerle karşılaştırılıyor. EEPROM'da toplam iki byte kullanmak istedim. 0 numaralı adreste asgari devir sınırı var. 1 numaralı adreste ise ne kadar tepki verileceği kayıtlı.
* Asgari devrin 1000 - 2000 devir arasında ayarlanmasını uygun gördüm. EEPROM'da bir byte kullanacaksak ancak 0 - 255 arası bir değerimiz olacak. Bu nedenle orada kayıtlı değeri 4 ile çarpıp 1000'e ekliyoruz.
* Aktüel motor devri ayarlanmış olan asgari devrin altında ise ne kadar gaz vereceğimizi belirleyen thrstep değişkeni EEPROM'da 1 numarada kayıtlı. Servo range'i 1000 - 2000 mikrosaniye (ya da 800 - 2200 mikrosaniye) olmalı. Burada bizim ekleyeceğimiz en fazla gaz miktarı da bence en fazla 64 mikrosaniye olmalı Bu nedenle EEPROM'daki 0 - 255 arasındaki değeri dörde bölerek kullanıyorum.
* Ana loop içinde sık sık "throut()" işlevi çağrılarak servoya çıkış sinyali gönderiliyor. Eğer devir düştü ve sistem devreye girdiyse bir saniye boyunca o konumda kalıp sonra normale dönüyor.
* "Throut()" işlevi içinde butonlar kontrol ediliyor. "Mindevir" ve "thrstep" değişkenlerinde değişiklik olursa yeni değerler EEPROM'a yazılıyor.
Bir adım daha ilerledik. Her ne kadar çok turlu trimpotlar kullanılmış olsa da titreşime bağlı sorun riski devam ediyordu. Ben de ayarlamalar için trimpot yerine butonlar kullanmaya karar verdim. Butonlarla ayarlanan alt devir hassasiyeti ve tepki miktarı ise chip üzerindeki EEPROM'a yazılıyor ve oradan okunuyor. Yani elektrik gittiğinde yok olmuyor. Mekanik risk de yok. Tabii şu anki kodda en önemli özellik olan "key debounce" yok. Ona bir çözüm üreteceğim. Yine de test için yeterli bir kod. Tabii binbir hata ve sorun çıkacak ama adım adım debug edeceğiz.
Plaket artık böyle:
[attachimg=1]
Kodun son hali de burada:
Kod:
// Motor devrini sürekli gözleyip belirli bir değerin altına inmeye başladığında gaz verecek program
#include <EEPROM.h>
const int throttlein = 4; // Alıcıdan throttle sinyali girişi
const int ignin = 3; // Alıcıdan kill switch girişi
const int sensorin = 2; // Ateşlemeden gelen sinyal girişi
const int throttleout = 5; // Gaz servosu çıkışı
const int ignLED = 9; // Ateşleme LED göstergesi çıkışı
const int ign = 12; // Ateşleme optokuplör çıkışı
//const int steppin = 0; // Devir düştüğünde gazın ne kadar açılacağını belirleyen trimpot girişi
//const int mindevirpin = 2; // Alt devir sınırını ayarlamak için trimpot girişi
const int sensup = 15; // A01
const int sensdn = 19; // A05
const int respup = 16; // A02
const int respdn = 18; // A04
const int revpin = 6; // Gaz servosu reverse jumper girişi
const int jumper = 7; // Reverse pin jumperi için HIGH level sağlıyor
int motorstop = 0; // Motorun stop etmiş olduğunu gösteren değişken. 0 ise motor çalışıyor 1 ise stop etmiş
unsigned int mindevir;
int devir;
int ignPWM;
int rxPWM;
unsigned int thrstep = 15;
unsigned long timer;
unsigned long frame;
unsigned long timer2;
int n;
int x;
int sensupbuton = 1;
int sensdnbuton = 1;
int respupbuton = 1;
int respdnbuton = 1;
int senschanged = 0;
int respchanged = 0;
void setup()
{
pinMode(throttleout, OUTPUT);
pinMode(ign, OUTPUT);
pinMode(ignLED, OUTPUT);
pinMode(jumper, OUTPUT);
digitalWrite(jumper, HIGH);
pinMode(sensup, INPUT); //Sensitivite + butonu
pinMode(sensdn, INPUT); //Sensitivite - butonu
pinMode(respup, INPUT); //Response + butonu
pinMode(respdn, INPUT); //Response - butonu
digitalWrite(sensup, HIGH); // Pullup direnci aktive ediliyor
digitalWrite(sensdn, HIGH); // Pullup direnci aktive ediliyor
digitalWrite(respup, HIGH); // Pullup direnci aktive ediliyor
digitalWrite(respdn, HIGH); // Pullup direnci aktive ediliyor
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(ignin, HIGH, 25000);
while (ignPWM > 1500)
{
frame = micros();
ignPWM = pulseIn(ignin, HIGH, 25000);
rxPWM = pulseIn(throttlein, HIGH, 25000);
devirhesapla();
if (devir > 0)
{
mindevir = 1000 + 4 * EEPROM.read(0);
thrstep = EEPROM.read(1) / 4;
if (devir < mindevir)
{
if (digitalRead(revpin) == HIGH)
{
rxPWM = rxPWM + thrstep;
}
else
{
rxPWM = rxPWM - thrstep;
}
if (rxPWM > 2200)
{
rxPWM = 2200;
}
if (rxPWM < 800)
{
rxPWM = 800;
}
for (int i = 0; i < 50; i++)
{
throut();
while ((micros() - frame) < 20000)
{
}
frame = micros();
}
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)
{
sensupbuton = digitalRead(sensup);
sensdnbuton = digitalRead(sensdn);
respupbuton = digitalRead(respup);
respdnbuton = digitalRead(respdn);
if (sensupbuton != sensdnbuton)
{
if (sensupbuton == 0)
{
mindevir++;
senschanged = 1;
if (mindevir > 255)
{
mindevir = 255;
senschanged = 0;
}
else
{
mindevir--;
senschanged = 1;
if (mindevir < 1)
{
mindevir = 1;
senschanged = 0;
}
}
}
}
if (senschanged == 1)
{
EEPROM.write(0, mindevir);
senschanged = 0;
}
if (respupbuton != respdnbuton)
{
if (respupbuton == 0);
{
thrstep++;
respchanged = 1;
if (thrstep > 63)
{
thrstep = 63;
respchanged = 0;
}
else
{
thrstep--;
respchanged = 1;
if (thrstep < 1)
{
thrstep = 1;
respchanged = 0;
}
}
}
}
if (respchanged == 1)
{
EEPROM.write(1, thrstep * 4);
respchanged = 0;
}
}
digitalWrite(throttleout, LOW);
}
Temel mantık yaklaşımını özetlemek istiyorum. Bu şekilde sizlerden gelecek öneri ve eleştiriler ile daha iyi bir şey yapabilirim diye umuyorum.
* İlk çalışmada butonlara pullup dirençleri üzerinden logic HIGH veriliyor. Yani butonlar aktifken LOW değeri veriyorlar.
* Engine kill kanalından gelen sinyal izlenip ignition ON yapılıyor. Burada akıllı kill switch algoritmasına henüz giremedim. O daha ileriki bir versiyonda belki...
* Ana loopta önce devir hesaplanıyor. Bunu yapmak için iki ateşleme arasındaki süreyi mikrosaniye olarak sayıyoruz. Sonra bundan devri hesaplıyoruz. Motorun stop etmiş olma olasılığına karşın bir de timeout var burada. Eğer iki ateşleme arası 60 milisaniyeden uzunsa motorun stop ettiğine karar veriyoruz.
* Loop içinde devir hesaplandıktan sonra bu, butonlarla belirlenmiş ve EEPROM'a yazılmış olan bir değerle karşılaştırılıyor. EEPROM'da toplam iki byte kullanmak istedim. 0 numaralı adreste asgari devir sınırı var. 1 numaralı adreste ise ne kadar tepki verileceği kayıtlı.
* Asgari devrin 1000 - 2000 devir arasında ayarlanmasını uygun gördüm. EEPROM'da bir byte kullanacaksak ancak 0 - 255 arası bir değerimiz olacak. Bu nedenle orada kayıtlı değeri 4 ile çarpıp 1000'e ekliyoruz.
* Aktüel motor devri ayarlanmış olan asgari devrin altında ise ne kadar gaz vereceğimizi belirleyen thrstep değişkeni EEPROM'da 1 numarada kayıtlı. Servo range'i 1000 - 2000 mikrosaniye (ya da 800 - 2200 mikrosaniye) olmalı. Burada bizim ekleyeceğimiz en fazla gaz miktarı da bence en fazla 64 mikrosaniye olmalı Bu nedenle EEPROM'daki 0 - 255 arasındaki değeri dörde bölerek kullanıyorum.
* Ana loop içinde sık sık "throut()" işlevi çağrılarak servoya çıkış sinyali gönderiliyor. Eğer devir düştü ve sistem devreye girdiyse bir saniye boyunca o konumda kalıp sonra normale dönüyor.
* "Throut()" işlevi içinde butonlar kontrol ediliyor. "Mindevir" ve "thrstep" değişkenlerinde değişiklik olursa yeni değerler EEPROM'a yazılıyor.