display tarama süresi

Başlatan Emre MERMİ, 12 Aralık 2015, 16:19:51

Emre MERMİ

merhaba hocalarım.
bir devrede 3 tane 7 segment display kullanıyorum.  En ufaklarından bu sanırm 14mm olandan. Tarama yöntemiyle ekrana birşeyler yazdırmaya çalışıyorum ama bir türlü yapamadım.  Displayler ortak katot. GND bacaklarını uln2003 kullanarak sırayla toprağa çekiyorum. Yaşadığım sorun şu; bir displaydeki görüntü süresini 20ms çıkarmama rağmen rahatsız edecek kadar diğer displaylere yazılacak karakterlerin birbirlerinde görünmesi. yani ekrana 123 yazdıracağım. 1 yazılacak ekranda hem 2 nin hem 3 ün gölgesi rahatsız edecek kadar görünüyor. daha önce 10cm lik display kullanarak 1 ms tarama süresiyle yapmıştım hiçbir sorun olmamıştı.

aklımda olan diğer bir soru ise butonlarla ayar yaparken butona bastığımda ekrandaki görüntü gidiyor. bu da buton okuma esnasında buton sekmesini kaldırmak için eklediğim bekleme süresi yüzünden. eklemesem bu sefer değer çok hızlı artıyor veya buton sekmesi yüzünden işlev yapamıyorum. bu sorunu nasıl aşabilirim ?

yardımcı olursanız çok sevinirim.

kod;
#include <16F628A.h>

#FUSES MCLR //Master Clear pin enabled
#fuses INTRC_IO

#use delay(internal=4MHz)
#include <ds18b20.c>
const char  digit[10]={ 0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C,  0x07, 0x7F, 0x67};
long int sicaklik=0,max=30; 
int a=0,b=0,b1=0,c=0,d=0,e=0,f=0,g=0,h=0,m=0;
int1 z=0;
int k=1,l=21,n=41;
#INT_TIMER0
void  TIMER0_isr(void) 
{

if(m==60){
m=0;
}

m=m+1;

}

void display_yaz()
  {
   if(m==k){
   a=sicaklik/100;
   output_high(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
   output_b(digit[a]);

   }
   if(m==l){

   output_low(pin_a0);  // soldan 1. display toprağı
   output_high(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
   b=sicaklik%100;
   b1=b/10;
   output_b(digit[b1]);


   }
   
   if(m==n){
  
   output_low(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. display toprağı
   output_high(pin_a6);     // soldan 3. display toprağı
   c=sicaklik%10;
   output_b(digit[c]);


   }
  }
  
   void ayar()
  {
  if(m==k){
   output_high(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
  e=max/100;
  output_b(digit[e]);

  }
  
   if(m==l){

   output_low(pin_a0);  // soldan 1. display toprağı
   output_high(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
   f=max%100;
   g=f/10;
   output_b(digit[g]);


   }
   
      if(m==n){
  
   output_low(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. display toprağı
   output_high(pin_a6);     // soldan 3. display toprağı
   h=max%10;
   output_b(digit[h]);
  }
   
  }

void main()
{
   setup_oscillator(osc_4mhz);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_4|RTCC_8_bit);      //1,0 ms overflow
   set_tris_b(0x00);
   delay_ms(50);
   output_b(0x00);
   set_tris_a(0b00111110);
   delay_ms(50);
   output_b(0x00);

   enable_interrupts(INT_TIMER0);
   enable_interrupts(GLOBAL);

   while(TRUE)
   {
        if(input(pin_a2)){
      delay_ms(100);
      z=z+1;

      }
      
      
       if(z==0){
      sicaklik=20;
      display_yaz();
      if(sicaklik>max){
      output_high(pin_b7);
      }
      if(sicaklik<max){
      output_low(pin_b7);
      }
       }
      
         if(z==1){
      ayar();
            if(input(pin_a3)){
      delay_ms(50);
      max=max+1;
      }
            if(input(pin_a4)){
           
      delay_ms(50);
      max=max-1;
            }
      
      
      }
      


   } 

}

şema;

selimkoc

displayin yanık kalma süresini 3-4ms yapabilirsin. her displaye veri gönderdikten sonra 3sn bekleyik ilgili transistörü kesime götür. daha sonra diğer displaye veri gönder ve transistörünü aktif et.

taramayı kesme içine timer kullanarak yap. Blogumda uygulamalar mevcut.

mehmet

Display değer hesaplarını ilk önce yapınız.
Her display seçiminden önce segmentlere sıfır
değeri yollayınız. Sonra display seçip değer
veriniz.
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

Emre MERMİ

Alıntı yapılan: selimkoc - 12 Aralık 2015, 17:06:47
displayin yanık kalma süresini 3-4ms yapabilirsin. her displaye veri gönderdikten sonra 3sn bekleyik ilgili transistörü kesime götür. daha sonra diğer displaye veri gönder ve transistörünü aktif et.

taramayı kesme içine timer kullanarak yap. Blogumda uygulamalar mevcut.

hocam 20 ms ye kadar çıkardım hala aynı ve kesme kullanarak süre oluşturuyorum taramayı da bu süreye göre yapıyorum. şimdi blogunuzu inceleyeceğim. yanıtınız için teşekkürler.

Alıntı yapılan: mehmet - 12 Aralık 2015, 17:14:49
Display değer hesaplarını ilk önce yapınız.
Her display seçiminden önce segmentlere sıfır
değeri yollayınız. Sonra display seçip değer
veriniz.


hocam segmentlere sıfır yollamak dediğiniz tamamen söndürmek mi ?sıfır yollasam da bu sefer sıfır ışığı yanık kalmaz mı ? birde display hesaplaması dediniz nedir ? önerilerinizi birazdan deneyip sonuçları paylaşacağım. Yanıtınız için teşekkür ederim.

selimkoc

kesime götürmek istediğin ilgili transistörün beyzini gndye çek(npn için).

RaMu

Gölge olayı her genç programcının başına gelir,
7 segment a~g bilgi bacaklarına (diyeyim) sıradaki tarama bilgisini göndermeden önce
halihazırda aktif olan (sıradaki display aktif olsun transistörü gibi)
displayin kapatılması gerekiyor, yani
önce tüm displayler pasif yap
sonra gösterilmesi gereken veriyi a~g bacaklarıına gönder, sonra
bu bilgiyi göstermesi gereken sıradaki 7 segment i aktif et.

Bekleme esnasında tarama yapılmadığı için doğal olarak 7seg ler söner,
7 seg tarama kesme ile yapılabilir,
veya bekleme döngüsü + 7 seg tarama şeklinde bekleme döngüsü yazılabilir.

Misal 4 tane 7seg displayi taraman 10ms sürüyor olsun,
100ms beklemek istiyorsan
bir döngü içerisinde 10 defa 7segdisptara fonksiyonunu çağırabilirsin.
Sorularınıza hızlı cevap alın: http://www.picproje.org/index.php/topic,57135.0.html

Emre MERMİ

Yanıtınız için çok teşekkür ederim RaMu hocam dediğinizi deneyeceğim. Yarın buraya yazarım sonucunu.

Emre MERMİ

değerli hocalarım, yardımlarınız için çok teşekkür ederim. Kodları dediğiniz gibi display geçişleri sırasında kapatarak atlattım. Her displaye 2ms bilgi yolluyorum ardından 1 ms displayi kapatıyorum sonuç mükemmel oldu. Kodlar aşşağıdadır.

bu arada 'm' değişkeni 1ms de kesme oluşturduğum timer içinde arttırığım değişken.

void display_yaz()
  {
   if(m==1){
   a=sicaklik/100;
   output_high(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
   output_b(digit[a]);

   }
   if(m==4){

   output_low(pin_a0);  // soldan 1. display toprağı
   output_high(pin_a7);  //  soldan 2. d,splay toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
   b=sicaklik%100;
   b1=b/10;
   output_b(digit[b1]);


   }
   
   if(m==7){
  
   output_low(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. display toprağı
   output_high(pin_a6);     // soldan 3. display toprağı
   c=sicaklik%10;
   output_b(digit[c]);


   }
    if(m==3||m==6||m==9){
    output_b(0x00);
   output_low(pin_a0);  // soldan 1. display toprağı
   output_low(pin_a7);  //  soldan 2. display toprağı
   output_low(pin_a6);     // soldan 3. display toprağı
    
    
    }
  }


Birde sormak istediğim birşey var buton sekleeri için şu kodu kullanıyorum ama bu sefer de bekleme esnasında normal olarak display sönüyor. Bunun için ne yapılabilir timer içinde mi beklemeyi yapayım yoksa başka çözüm var mı ?

          
  if(input(pin_a3)){
      delay_ms(50);
  if(input(pin_a3)){
      max=max+1;
}
}


Tekrardan teşekkür ederim.

MrDarK

7 segment display taramasında en mantıklı yol;
Aktif display süre değeri Örn 5ms için Timer interrupt kurulur. Her 5ms'de bir Timer interrupt anahtarlayacağı 7 segmenti seçerek ana programda karakterlerine böldüğün digitleri porta gönderir. Ana programda istediğin yerde istediğin kadar delay kullan ekranda hiçbir zaman bozulma sönme göremezsin. İnterruptların içine bekleme yazmadığın sürece :)
Picproje Eğitim Gönüllüleri ~ MrDarK

Emre MERMİ

Hocam ama pic delay içindeyken kesme gelirse delay bitiminde kesmeye gider diye biliyorum ?

mehmet

Bence ULN yerine 74HC595 veya akım yüksek ise
TPIC6B595 kullanmak. Böylece mcu display ile uğraşmaz...
Olan olmuştur,
olacak olan da olmuştur.
Olacak bir şey yoktur.
---------------------------------------------
http://www.mehmetbilgi.net.tr
https://creativecommons.org/licenses/by/4.0/deed.tr "CC BY"

Emre MERMİ

Alıntı yapılan: mehmet - 14 Aralık 2015, 19:02:49
Bence ULN yerine 74HC595 veya akım yüksek ise
TPIC6B595 kullanmak. Böylece mcu display ile uğraşmaz...


hocam boşta pin vardı birde displayler en ufağından o yüzden uln2003 kullandım ve pic çıkışlarını kullandım

Emre MERMİ

#12
birde şunu sormak istiyorum hocalarım;


#define ONE_WIRE_PIN PIN_a1


void onewire_reset() 

{
output_low(ONE_WIRE_PIN);
delay_us( 500 ); //1-wire resetleme için sıfıra çekilir
output_float(ONE_WIRE_PIN); //1-wire bir yapılır
delay_us( 500 ); // sensörün hazırlanması için beklenir.
output_float(ONE_WIRE_PIN);
} 

void onewire_write(int data)
{
int count;
for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); // Sensöre yazma işlemine başlamak için  1-wire sıfıra çekilir.
output_bit(ONE_WIRE_PIN, shift_right(&data,1,0)); // yazılacak bilgi 1-wire'da
delay_us( 60 ); // Yazma işlemi zamanı doldurulur.
output_float(ONE_WIRE_PIN); // 1-wire bir yapılır,
delay_us( 2 ); // 1us'den fazla beklenir.
}
} 

int onewire_read()
{
int count, data;
for (count=0; count<8; ++count)
{
output_low(ONE_WIRE_PIN);
delay_us( 2 ); //Sensördem okuma işlemi içinl 1-wire sıfıra çekilir.
output_float(ONE_WIRE_PIN); //1-wire bir yapılır,
delay_us( 8 ); // Sensörün kendine gelmesi beklenir,
shift_right(&data,1,input(ONE_WIRE_PIN)); // sonuc bilgisi alınır.
delay_us( 120 ); //Okuma işlemi zamanı doldurulur.
}
return( data );
} 

float ds1820_read()
{
int8 busy=0, temp1, temp2;
signed int16 temp3;
float result;
onewire_reset();
onewire_write(0xCC);
onewire_write(0x44);
while (busy == 0)
busy = onewire_read();
onewire_reset();
onewire_write(0xCC);
onewire_write(0xBE);
temp1 = onewire_read();
temp2 = onewire_read();
temp3 = make16(temp2, temp1);
result = (float) temp3 / 16.0;
delay_ms(200);
return(result);
}


yukarıda verdiğim kod ds18b20 nin okunmasında kullandığım kütüphane. ben displayleri 2-3 ms ile tarıyorum buna karşı  bu kütüphanede 200 ms den fazla bekleme süresi var. Bu yüzden her sıcaklığı okumaya çalışmamda ekrandaki yazı siliniyor. Ayrıca sürekli okumaya çalıştığımda mcu saçmalıyor, bende şimdilik 5-10 saniyede bir okuyorum. Bu sorun nasıl aşılır ? şimdiden teşekkürler.

mesaj birleştirme:: 15 Aralık 2015, 23:51:07

https://www.picproje.org/index.php?topic=49756.0

şu konudaki gibi yapmaya çalıştım ama bende yemedi yada beceremedim.

MrDarK

Emre neden önerimi hiç dikkate almıyorsun ?

Tekrar tekrar tekrar yazıyorum umarım bu sefer denemeyi denersin. 1 Adet 3ms'ye kurulmuş timer. Timer Interrupt'ta kurulu olacak. Ana programında ne yazdığı önemli değil.

Timer Interrupt'ı içinde şunu yapacaksın

switch(Display_No)
{
	case 0:
		output_high(Display_1);
		output_low(Display_2);
		output_low(Display_3);
		output_low(Display_4);
		output_b(Display_Array[0]);
		Display_No = 1;
	break;

	case 1:
		output_high(Display_2);
		output_low(Display_1);
		output_low(Display_3);
		output_low(Display_4);
		output_b(Display_Array[1]);
		Display_No = 2;
	break;

	case 2:
		output_high(Display_3);
		output_low(Display_1);
		output_low(Display_2);
		output_low(Display_4);
		output_b(Display_Array[2]);
		Display_No = 3;
	break;

	case 3:
		output_high(Display_4);
		output_low(Display_1);
		output_low(Display_2);
		output_low(Display_3);
		output_b(Display_Array[3]);
		Display_No = 0;
	break;
}


Interrupt alt programın içinde yukarıdaki gibi bir kodun olacak. dikkat ettiysen tarama işini timer'a yaptırıyorum. Ana programda Display_Array'yi segmentlerde ne yazdırmak istiyorsan o değerlerle dolduracaksın sadece.
Picproje Eğitim Gönüllüleri ~ MrDarK

Emre MERMİ

Hocam estagfurullah dikkate almamak değil, bugün deneyeceğim. Kusura bakmayın.