DIY Devir Sayaci

DIY Devir Sayaci

Sümer abi, o zaman 3D printer'larda kullanılan termistörler belki işine yarayabilir. 0 - 250 derece arası sıcaklıkları yeterince düzgün olarak okuyabiliyorlar ama biraz kalibrasyon gerekebilir ...

Resistance: 100Kohm + / -1%
B value: 3950 + / -1%
Accuracy: + / -1%
Glass packaging: 2.0 + / -0.2mm
Lead length: 32 + / -5mm
Operating temperature range:-50 to +260°C
Thermal time constant (τ): τ=10 - 17 s ( in still air)
Thermal dissipation constant (δ): δ=1.1 - 1.6mW / °C
Insulation resistance 50MΩ or over by DC500V megge (between glass and lead wire)
Şimdilik yurtiçinden link bulamadım ama olmamasına imkan yok...
 
DIY Devir Sayaci

Küçük fontlarda "V"'yi de kaldırdım. Sonuçta voltaj olduğu soldaki ana göstergeden belli. Altta da ana göstergeye "C" ekledim. Sağdaki min max değerleri için derece sembolü yeterli. Sonuçta ana gösterge Santigrad olup min max değerler Fahrenheit olacak değil. :)

[attachimg=1]
 

Ekli dosyalar

  • pic0001.jpg
    pic0001.jpg
    65.3 KB · Görülme: 131
DIY Devir Sayaci

Voltaj ile sıcaklık arasına enine boydan boya çizgi olsa nasıl olur acaba ?

Sent from my iPhone using Tapatalk
 
DIY Devir Sayaci

Sümer Yamaner' Alıntı:
LM35 azami sıcaklık 150 dereceymiş. :(
Sümer abi benim açımdan 150 derece çok ideal. Temelde hedefim glow motor sıcaklığında 100 dereceyi geçmemek oluyor, geçerse motoru zenginleştiriyorum zaten. :laugh:

Ama benzin motorlarını bilemiyorum, sıcaklık oralara kadar geliyorsa bu durumda söylediğin gibi 200 dereceye kadar olması mantıklı...
 
DIY Devir Sayaci

Ekran kontrolü zordu. Onu halletim sayılır. Gerçi patron ek çizgi istiyor ama bakıcaz artık. :D
Herhangi bir sensörü adapte etmek nispeten kolay olacak. Araştırmaya devam...

SM-N910C cihazımdan Tapatalk kullanılarak gönderildi
 
DIY Devir Sayaci

Sümer abi Pazartesi maaş alıyorum, bilgin olsun. :laugh: ;D
 
DIY Devir Sayaci

Yahu bi cowling söküp aleti test edemedik kiii...

SM-N910C cihazımdan Tapatalk kullanılarak gönderildi
 
DIY Devir Sayaci

Devir göstergesine dönecek olursak...

Hafta sonu gerçek kullanım koşullarındaki ilk testi yapabildik. Sonuç kısmen fiyasko. Gayet güzel çalışırken birden kilitleniyor.
Test ettiğimiz ünitenin devir algoritması birbirini izleyen iki ateşleme darbesi arasındaki sürenin ölçülerek devrin hesaplanması ve peş peşe ölçülen beş değerin sürekli kaydırılarak yenilenmesi sonucu ortalamanın alınmasına dayanıyordu.
Pazar gecesi ve dün buna kafa yordum.
Genel olarak devir ölçmede üç farklı algoritma kullanılıyor. Birisi benim yaptığım şekilde. Diğeri belirli bir zaman aralığında gelen darbelerin sayılması şeklinde. İlki düşük devirler için ikincisi yüksek devirler için ideal. Üçüncü yaklaşım belirli bir devrin altında ilk yöntemi belirli bir devrin üstünde ikinci yöntemi kullanmak.
Bizim motorlar zaten bin devrin altında çalışmıyorlar. En baba motorun rölantisi 1500 devir civarında. Şöyle düşündüm:
600 devir/dakika için saniyede 10 pulse geliyor. Yarım saniye saysak 5 pulse ediyor. Yani yarım saniyede sayılan pulse sayısını 120 ile çarparsak çıkışta 600 elde ederiz.

Hemen Attiny satasheetine daldım. Timer1'i kullanmaya karar verdim. Timer1 ve 8 MHz clock ile 16384 prescaler değerini seçtim. 8000000 / 16384 = 488.28 Hz. Timer 8 bit. Yani 0'dan 255'e kadar sayıp tekrar sıfırlanıyor. Kısaca overflow interrupt kullandığımda bu 488 Hz'i bir de 256'ya bölmüş oluyorum. Ne etti? 1.907 Hz. Yani periyot olarak 1 / 1.907 = 0.524 saniye.

Diğer yandan pulse saymanın en iyi yolu pin change interrupt kullanmak. Ben de öyle yaptım. Hatta burada küçük bir numara daha yaptım. Pin change interrupt ilgili pinin durum değiştirmesi ile tetikleniyor. Yani HIGH ya da LOW pulse ayrımı yok. Ateşleme darbesinde bir yükselen bir de inen kenar var. Ben bu ikisini ayrı ayrı sayarsam çözünürlüğümü iki katına çıkarmış oluyorum. Büyük avantaj.

Yeni kodda temel işlevi, iki ayrı interrupt servis rutini yapıyor. Pin change interrupt geldiğinde tek yapılan iş bir sayaç değişkenini bir artırmak.
Timer overflow interrupt geldiğinde yani 0.524 saniyelik süre dolduğunda ise sayaçtaki değeri başka bir değişkene aktarıp sayacı sıfırlıyoruz. Program bir sayımın tamamlandığını anlasın diye de bir flag set ediyoruz.

Programın ana loop'unda flag'ın set edilmesi bekleniyor. Sayaç değeri alınıp hesap yapılıyor. Yani 0.524 saniyede bu kadar darbe geldiyse 60 saniyede kaç darbe gelir? Yani okunan değeri 114.44 ile çarpmak gerekiyor. Ama biz her devir için iki darbe saydığımıza göre 57.22 ile çarpacağız. Bu çarpımı yaptıktan sonra elde edilen devir değerini de OLED ekrana yazıyoruz. Flag'ı sıfırlayıp yeni sayım sonucunu bekliyoruz.

Kodun ana gövdesi küçücük ama Attiny85 ile OLED ekran kontrolü için gereken kod oldukça hacimli. Sistem RAM'inin neredeyse tamamı kullanılıyor.

Bu yeni kodu işlemciye yükledim. Bir de girişe işlemciyi korumak için tek transistörlü bir ek devre koydum. Hem her çeşit sinyal girişi ile çalışsın hem de işlemciye olası bir yüksek voltaj ulaşmasın diye. Sinyal jeneratörü ile tam olması gerektiği gibi çalıştı. Uçakta da aynen bu şekilde çalışmaması için bir sebep yok. Hafta sonu göreceğiz.

Kod:
// Copyright Sümer Yamaner 2015
// Devir pulse girişi PB3, PCI3, Attiny85 pin 2
// Attiny85 @ 8 MHz internal
// Timer1 Prescaler 16384 ==> 256 sayıp overflow olduğunda
// Period 524 mS oluyor
// 60 / 0.524 = 114.44 oluyor
// Yani 0.524 mS içinde kaç pulse geldiyse onu 114.44 ile çarparak
// Dakikadaki devir sayısını buluyoruz
// PCI ile inen ve çıkan darbe kenarları sayıldığı için iki kat fazla okuma yapılıyor
// O nedenle sayım sonucu 114.44 ile değil 57.22 ile çarpılıyor

#include "SSD1306_minimal.h"

SSD1306_Mini oled;

const byte bitmapUpper1[88] =
{
  0, 240, 60, 15, 15, 15, 60, 240,
  0, 0, 240, 252, 255, 0, 0, 0,
  0, 240, 60, 15, 15, 15, 60, 240,
  0, 240, 60, 15, 15, 15, 60, 240,
  0, 0, 0, 0, 192, 252, 255, 0,
  0, 255, 15, 15, 15, 15, 15, 15,
  0, 240, 60, 15, 15, 15, 60, 240,
  0, 15, 15, 15, 15, 15, 15, 255,
  0, 240, 60, 15, 15, 15, 60, 240,
  0, 240, 60, 15, 15, 15, 60, 240,
  240, 12, 12, 48, 0, 0, 0, 0,
};
const byte bitmapUpper2[88] =
{
  0, 255, 0, 0, 0, 0, 0, 255,
  0, 0, 0, 0, 255, 0, 0, 0,
  0, 0, 0, 192, 192, 192, 240, 63,
  0, 0, 0, 192, 192, 192, 192, 63,
  0, 0, 192, 252, 15, 0, 255, 0,
  0, 63, 60, 60, 60, 252, 240, 192,
  0, 255, 240, 240, 240, 240, 192, 0,
  0, 0, 0, 0, 0, 240, 63, 3,
  0, 15, 252, 240, 240, 240, 252, 15,
  0, 63, 240, 192, 192, 192, 192, 255,
  15, 48, 192, 0, 0, 252, 12, 12,
};
const byte bitmapLower1[88] =
{
  0, 255, 0, 0, 0, 0, 0, 255,
  0, 0, 0, 0, 255, 0, 0, 0,
  0, 252, 15, 3, 3, 3, 0, 0,
  0, 0, 0, 3, 3, 3, 3, 240,
  0, 252, 255, 240, 240, 240, 255, 240,
  0, 0, 0, 0, 0, 0, 3, 255,
  0, 255, 0, 0, 0, 0, 3, 255,
  0, 0, 0, 240, 63, 3, 0, 0,
  0, 255, 3, 0, 0, 0, 3, 255,
  0, 0, 0, 3, 3, 3, 3, 255,
  192, 0, 0, 255, 0, 255, 48, 0,
};
const byte bitmapLower2[88] =
{
  0, 15, 60, 240, 240, 240, 60, 15,
  0, 0, 240, 240, 255, 240, 240, 0,
  0, 255, 240, 240, 240, 240, 240, 240,
  0, 15, 60, 240, 240, 240, 60, 63,
  0, 0, 0, 0, 0, 0, 255, 0,
  0, 63, 240, 240, 240, 252, 63, 15,
  0, 15, 60, 240, 240, 240, 60, 15,
  0, 0, 0, 255, 0, 0, 0, 0,
  0, 15, 60, 240, 240, 240, 60, 15,
  0, 15, 60, 240, 240, 240, 60, 15,
  0, 3, 3, 0, 0, 255, 192, 192,
};
const byte rpmbmpUpper2[20] =
{ 0, 252, 48, 12, 12, 48, 0, 252, 48, 12, 12, 240, 0, 252, 48, 12, 252, 48, 12, 252};
const byte rpmbmpLower1[20] =
{ 0, 255, 0, 0, 0, 0, 0, 255, 12, 48, 48, 15, 0, 255, 0, 0, 255, 0, 0, 255};
const byte rpmbmpLower2[20] =
{ 0, 15, 0, 0, 0, 0, 0, 255, 0, 0, 0, 0, 0, 15, 0, 0, 15, 0, 0, 15};

int b[5];
volatile byte cntr; // pulse counter
volatile byte cntr_result; // tamamlanmış pulse count
volatile boolean flag; // sayım sonucu hazır
int rpm;
float frpm;

ISR(TIMER1_OVF_vect)
{
  cntr_result = cntr;
  cntr = 0;
  flag = 1;
}

ISR(PCINT0_vect)
{
  cntr++;
}

void setup() 
{
//  pinMode(4, OUTPUT);
  oled.init(SlaveAddress);
  oled.clear();
  oled.sendCommand(0xA4); // Resume to RAM content
  oled.sendCommand(0xA6); // Normal display
  oled.sendCommand(0xAF); // Normal mode
  oled.sendCommand(0x81); // Contrast
  oled.sendCommand(0xFF); // Max
  oled.sendCommand(0x20); // Memory addressing mode
  oled.sendCommand(0x02); // Page addressing
  oled.sendCommand(0x00); // Column Address Set Low Nibble
  oled.sendCommand(0x10); // Column Address Set High Nibble
  oled.sendCommand(0xB0); // Page Address Set

  TCCR1 = 15; // Timer1 Prescaler 16384
  TIMSK = 4; // Timer1 Overflow Interrupt Enable
  GIMSK = 32; // Pin Change Interrupt Enable
  PCMSK = 8; // PCI on PB3
}

void loop() 
{
  while(!flag);
  frpm = cntr_result * 57.22;
  rpm = frpm;
  printoled(rpm);
  flag = 0;
}

void printoled(int p)
{
  // int p beş haneli string'e dönüştürülecek
  // digit[5] leftmost, digit[0] rightmost
  p = constrain(p, 0, 99999);
  b[0] = p / 10000;
  p = p - b[0] * 10000;
  b[1] = p / 1000;
  p = p - b[1] * 1000;
  b[2] = p / 100;
  p = p - b[2] * 100;
  b[3] = p / 10;
//  p = p - b[3] * 10;
  b[4] = p % 10;

  if (b[0] == 0) b[0] = 255;
  if ((b[1] == 0) && (b[0] == 255)) b[1] = 255;
  if ((b[2] == 0) && (b[1] == 255)) b[2] = 255;
  if ((b[3] == 0) && (b[2] == 255)) b[3] = 255;

  oled.sendCommand(0x04); // Column 4
  oled.sendCommand(0x10); // Column 4
  oled.sendCommand(0xB0); // Page 0
  for (int m = 0; m < 5; m++)
  {
    Wire.beginTransmission(SlaveAddress);
    Wire.send(GOFi2cOLED_Data_Mode);            // data mode
    for (int i = 0; i < 8; i++)
    {
      if (b[m] != 255)
      {
        oled.sendData(bitmapUpper1[8 * b[m] + i]);
        oled.sendData(bitmapUpper1[8 * b[m] + i]);
      }
      else
      {
        oled.sendData(0);
        oled.sendData(0);
      }
    }
    Wire.endTransmission();
  }

  oled.sendCommand(0x04); // Column 4
  oled.sendCommand(0x10); // Column 4
  oled.sendCommand(0xB1); // Page 1
  for (int m = 0; m < 5; m++)
  {
    Wire.beginTransmission(SlaveAddress);
    Wire.send(GOFi2cOLED_Data_Mode);            // data mode
    for (int i = 0; i < 8; i++)
    {
      if (b[m] != 255)
      {
        oled.sendData(bitmapUpper2[8 * b[m] + i]);
        oled.sendData(bitmapUpper2[8 * b[m] + i]);
      }
      else
      {
        oled.sendData(0);
        oled.sendData(0);
      }
    }

    Wire.endTransmission();
  }

  oled.sendCommand(0x06); // Column 
  oled.sendCommand(0x15); // Column 
  oled.sendCommand(0xB1); // Page 1
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 20; i++)
  {
    oled.sendData(rpmbmpUpper2[i]);
    oled.sendData(rpmbmpUpper2[i]);
  }
  Wire.endTransmission();

  oled.sendCommand(0x04); // Column 4
  oled.sendCommand(0x10); // Column 4
  oled.sendCommand(0xB2); // Page 2
  for (int m = 0; m < 5; m++)
  {
    Wire.beginTransmission(SlaveAddress);
    Wire.send(GOFi2cOLED_Data_Mode);            // data mode
    for (int i = 0; i < 8; i++)
    {
      if (b[m] != 255)
      {
        oled.sendData(bitmapLower1[8 * b[m] + i]);
        oled.sendData(bitmapLower1[8 * b[m] + i]);
      }
      else
      {
        oled.sendData(0);
        oled.sendData(0);
      }
    }
    Wire.endTransmission();
  }

  oled.sendCommand(0x06); // Column 
  oled.sendCommand(0x15); // Column 
  oled.sendCommand(0xB2); // Page 1
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 20; i++)
  {
    oled.sendData(rpmbmpLower1[i]);
    oled.sendData(rpmbmpLower1[i]);
  }
  Wire.endTransmission();

  oled.sendCommand(0x04); // Column 4
  oled.sendCommand(0x10); // Column 4
  oled.sendCommand(0xB3); // Page 3
  for (int m = 0; m < 5; m++)
  {
    Wire.beginTransmission(SlaveAddress);
    Wire.send(GOFi2cOLED_Data_Mode);            // data mode
    for (int i = 0; i < 8; i++)
    {
      if (b[m] != 255)
      {
        oled.sendData(bitmapLower2 [8 * b[m] + i]);
        oled.sendData(bitmapLower2[8 * b[m] + i]);
      }
      else
      {
        oled.sendData(0);
        oled.sendData(0);
      }
    }
    Wire.endTransmission();
  }

  oled.sendCommand(0x06); // Column 
  oled.sendCommand(0x15); // Column 
  oled.sendCommand(0xB3); // Page 3
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 20; i++)
  {
    oled.sendData(rpmbmpLower2[i]);
    oled.sendData(rpmbmpLower2[i]);
  }
  Wire.endTransmission();

//  delay(50);

  // Aşağıya da logomuzu yazalım
  oled.sendCommand(0x0:coolxf:; // Column
  oled.sendCommand(0x13); // Column
  oled.sendCommand(0xB4); // Page 4
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 8; i++)
  {
    oled.sendData(bitmapUpper1[80 + i]);
    oled.sendData(bitmapUpper1[80 + i]);
  }
  Wire.endTransmission();
  oled.sendCommand(0x0:coolxf:; // Column
  oled.sendCommand(0x13); // Column
  oled.sendCommand(0xB5); // Page 5
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 8; i++)
  {
    oled.sendData(bitmapUpper2[80 + i]);
    oled.sendData(bitmapUpper2[80 + i]);
  }
  Wire.endTransmission();
  oled.sendCommand(0x0:coolxf:; // Column
  oled.sendCommand(0x13); // Column
  oled.sendCommand(0xB6); // Page 6
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 8; i++)
  {
    oled.sendData(bitmapLower1[80 + i]);
    oled.sendData(bitmapLower1[80 + i]);
  }
  Wire.endTransmission();
  oled.sendCommand(0x0:coolxf:; // Column
  oled.sendCommand(0x13); // Column
  oled.sendCommand(0xB7); // Page 7
  Wire.beginTransmission(SlaveAddress);
  Wire.send(GOFi2cOLED_Data_Mode);            // data mode
  for (int i = 0; i < 8; i++)
  {
    oled.sendData(bitmapLower2[80 + i]);
    oled.sendData(bitmapLower2[80 + i]);
  }
  Wire.endTransmission();
}
 
DIY Devir Sayaci

Sümer Yamaner' Alıntı:
Devir göstergesine dönecek olursak...

Hafta sonu gerçek kullanım koşullarındaki ilk testi yapabildik. Sonuç kısmen fiyasko. Gayet güzel çalışırken birden kilitleniyor.
Abi sonuca biraz şaşırdık doğrusu ?? Bakalım yeni çözüm haftaya çalışacak mı ;)
 
DIY Devir Sayaci

Yahu neye şaşırdın. Koskoca Microsoft yeni Windows sürümü çıkarıyor. Aradan altı ay geçmeden SP1 yayımlanıyor. :D :p Bende de o kadarcık kusur olsun... :)
 
DIY Devir Sayaci

Sümer Yamaner' Alıntı:
Yahu neye şaşırdın. Koskoca Microsoft yeni Windows sürümü çıkarıyor. Aradan altı ay geçmeden SP1 yayımlanıyor. :D :p Bende de o kadarcık kusur olsun... :)

:lollol: :lollol: Tek rakibimiz Microsoft , siz bizi hafife mi alıyorsunuz arkadaşlar........ ;D
 
DIY Devir Sayaci

Övünmek gibi olmasın ama ben ZX Spectrum ile multitasking yapmış adamım. Microsoft'u seviyemde görmüyorum! :lol:
 
DIY Devir Sayaci

Sümer Yamaner' Alıntı:
Övünmek gibi olmasın ama ben ZX Spectrum ile multitasking yapmış adamım. Microsoft'u seviyemde görmüyorum! :lol:

Aynen Sümer abi , bende görmüyorum , sen ne yapar eder mutlaka yaparsın , senin onca işin arasında bir de bunları yapman bile bana göre mucize :thumbup: ...Bill gelsin de bir uçak uçursun görelim , de ki elektroniği için falan uğraşmaya vakti kalsın ne var paket program yapmaya demi...... :halay:
 
DIY Devir Sayaci

Yalnız Bill'in uzmanlık alanı başka arkadaşlar. Devir saymıyor kendisi para sayıyor. :lollol: :lollol: :lol:

Adam esnaf, Sümer abi cerrah. :laugh: