- 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
Arduino'dan sonra...
Bugün neler yaptığımı anlatayım...
Önce nette bolca bulunan sayfalardan birinden aldığım bağlantı şemasını Arduino Uno ve bir adet ATTiny85 ile uyguladım. (
Sonra Arduino IDE üzerinden gerekli ayarlamaları yaparak ATTiny85'e 8 MHz internal clock ile çalışması için gereken bootloaderi yazdırdım (ki bu aslında sadece bir registeri değiştiriyor).
Sonra daha önce ATMega328 üzerinde test etmiş ve ATTiny85'e uyarlamış olduğum servo programını Arduino'yu ISP (In System Programmer) olarak kullanıp ATTiny85'e yükledim.
Breadboard üzerinde hemen ekteki şemayı uyguladım ve pili taktım.
Bir butona bastıkça servo bir yöne diğerine bastıkça diğer yöne dönüyor. İkisine birden basarsam hiçbir şey olmuyor. Basit bir servo tester kısaca. Ama bence en önemli nokta interrupt kullanıyor oluşu.
ATTiny85'in TIMER1'ini kullanıyorum. Gerekli ayarlar setup'tan çağrılan initTimerCounter() işlevinde gerekli register bitleri ayarlanarak yapılıyor. 8 MHz sistem saati 1024'e bölüncek şekilde ayarlı. Timer bunu sayıp 156 olduğunda bir interrupt oluşturuyor. Yani ana loopta ne yapıyorsak yapalım (interruptları kapatmadığımız sürece) her 20 milisaniyede bir interrupt geliyor ve bu interrupt sonrası sistem hazırda bekleyen pwm değeri boyutunda bir darbeyi servoya gönderiyor.
Ana loopta ise tuşlar kontrol edilip pwm değeri değiştiriliyor. Interruptta kullanılan tüm değişkenler volatile olarak tanımlı.
Breadboard şeması bu:
[attachimg=1]
Kullanılan kod da bu:
Anlatmaya çalıştığım şey, "bakın ben ne acayip programlar yazıyomm" değil. TCNT1, OCR1A, TIMSK, ACIE1A... Önce Mars dili gibi gelen bu ifadeleri, okuyup deneyerek anlayabiliyor olmanın verdiği keyfi anlatmak istiyorum. Muhtemelen Servo Library benzer bir iş yapıyordur ama bunu kendi ürettiğim çözüm ve kodla başarınca sistemi çok daha yakından tanımış oluyorum. Bütün derdim de bu işte.
Bugün neler yaptığımı anlatayım...
Önce nette bolca bulunan sayfalardan birinden aldığım bağlantı şemasını Arduino Uno ve bir adet ATTiny85 ile uyguladım. (
Bu LİNKİ görmek için izniniz yok. Giriş yap veya üye ol
)Sonra Arduino IDE üzerinden gerekli ayarlamaları yaparak ATTiny85'e 8 MHz internal clock ile çalışması için gereken bootloaderi yazdırdım (ki bu aslında sadece bir registeri değiştiriyor).
Sonra daha önce ATMega328 üzerinde test etmiş ve ATTiny85'e uyarlamış olduğum servo programını Arduino'yu ISP (In System Programmer) olarak kullanıp ATTiny85'e yükledim.
Breadboard üzerinde hemen ekteki şemayı uyguladım ve pili taktım.
Bir butona bastıkça servo bir yöne diğerine bastıkça diğer yöne dönüyor. İkisine birden basarsam hiçbir şey olmuyor. Basit bir servo tester kısaca. Ama bence en önemli nokta interrupt kullanıyor oluşu.
ATTiny85'in TIMER1'ini kullanıyorum. Gerekli ayarlar setup'tan çağrılan initTimerCounter() işlevinde gerekli register bitleri ayarlanarak yapılıyor. 8 MHz sistem saati 1024'e bölüncek şekilde ayarlı. Timer bunu sayıp 156 olduğunda bir interrupt oluşturuyor. Yani ana loopta ne yapıyorsak yapalım (interruptları kapatmadığımız sürece) her 20 milisaniyede bir interrupt geliyor ve bu interrupt sonrası sistem hazırda bekleyen pwm değeri boyutunda bir darbeyi servoya gönderiyor.
Ana loopta ise tuşlar kontrol edilip pwm değeri değiştiriliyor. Interruptta kullanılan tüm değişkenler volatile olarak tanımlı.
Breadboard şeması bu:
[attachimg=1]
Kullanılan kod da bu:
Kod:
const int servopin = 0;
const int uppin = 3;
const int downpin = 4;
int up = 1;
int down = 1;
volatile unsigned int x = 0;
volatile unsigned long timer;
volatile unsigned int pwm = 1500;
void setup()
{
pinMode(servopin, OUTPUT);
initTimerCounter();
}
void loop()
{
up = digitalRead(uppin);
down = digitalRead(downpin);
if (up != down)
{
delay(1);
up = digitalRead(uppin);
down = digitalRead(downpin);
if (up != down)
{
if (up == 0)
{
pwm = pwm + 1;
}
else
{
pwm = pwm - 1;
}
if (pwm < 1000)
{
pwm = 1000;
}
if (pwm > 2000)
{
pwm = 2000;
}
}
}
}
ISR(TIMER1_COMPA_vect)
{
timer = micros();
digitalWrite(servopin, HIGH);
while ((micros() - timer) < pwm)
{
}
digitalWrite(servopin, LOW);
}
void initTimerCounter() { // initialize Timer1
noInterrupts(); // disable global interrupts
PLLCSR = 0; //
TCCR1 = 0; // set all bits in TCCR1 register to 0
TCCR1 |= (1 << CTC1); //CTC Mode enabled
// prescaler 1024
TCCR1 |= (1 << CS10);
TCCR1 |= (1 << CS11);
TCCR1 |= (0 << CS12);
TCCR1 |= (1 << CS13);
GTCCR |= (1 << PSR1); // reset Timer/Counter prescaler
TCNT1 = 0; // Zero (Reset) Timer1 8-bit up counter value
OCR1A = 156; //156 periyot * 128 us = 20 mS
TIMSK |= (1 << OCIE1A); // enable Timer1 compare A interrupt
interrupts(); // enable global interrupts
}
Anlatmaya çalıştığım şey, "bakın ben ne acayip programlar yazıyomm" değil. TCNT1, OCR1A, TIMSK, ACIE1A... Önce Mars dili gibi gelen bu ifadeleri, okuyup deneyerek anlayabiliyor olmanın verdiği keyfi anlatmak istiyorum. Muhtemelen Servo Library benzer bir iş yapıyordur ama bunu kendi ürettiğim çözüm ve kodla başarınca sistemi çok daha yakından tanımış oluyorum. Bütün derdim de bu işte.