Universal Havya Kontrolcüsü Tasarımı

Süremiz belli abi;
pwm count 1 iken 980 mikro
pwm count full iken 4mikro.

Zaten şöyle büyük bir sorunumuz var.
Aynı pini hem intterupt hem pwm output çalıştırabiliyorum.
Ama kesme içinde hem ortalama almak, hem voltaj hesabı yapmak, hemde sıcaklık hesabı yapmak çok uzun sürüyor yarıda çekip gidiyor kesmeden çünkü pin konum değiştiriyor.
Kesme içinde sadece gerekli ölçümleri yapıp ve hesaplamaları kesme dışında yapmak lazım mesela kesmeye bir güncelleme bayrak değişkeni koyabilirsin adı "T_guncel" olsun misal, bunu ölçüm aldığında kesme içinde 1 yapabilirsin, kesme dışında, döngüde de if döngüsüne aşağıdaki yapıda bir kontrol kullanılabilir.

if(T_guncel){ T_guncel=0;/*ortalama,pid hesaplamaları vb.*/} : sıcaklık güncellendiğinde çalışır sadece, ve döngü için PWM count'u da tayin edebilirsin.
 
Kesme içinde sadece gerekli ölçümleri yapıp ve hesaplamaları kesme dışında yapmak lazım mesela kesmeye bir güncelleme bayrak değişkeni koyabilirsin adı "T_guncel" olsun misal, bunu ölçüm aldığında kesme içinde 1 yapabilirsin, kesme dışında, döngüde de if döngüsüne aşağıdaki yapıda bir kontrol kullanılabilir.

if(T_guncel){ T_guncel=0;/*ortalama,pid hesaplamaları vb.*/} : sıcaklık güncellendiğinde çalışır sadece, ve döngü için PWM count'u da tayin edebilirsin.
C++:
void kesme() {
  detachInterrupt(0);
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(A0);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;

  adc_v = average * (cpu_v / max_adc);
  c = adc_v * 248, 3 - 7, 621;

  Serial.println(c);
  interrupts();

}

Böyle denediğimde ise sona kadar gelebiliyor fakat bu loop içindeyken harika çalıştığı halde kesme içinde ne olursa olsun 35.60 döndürüyor sayı asla değişmiyor.
 
C++:
void kesme() {
  detachInterrupt(0);
  total = total - readings[readIndex];
  readings[readIndex] = analogRead(A0);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;

  adc_v = average * (cpu_v / max_adc);
  c = adc_v * 248, 3 - 7, 621;

  Serial.println(c);
  interrupts();

}

Böyle denediğimde ise sona kadar gelebiliyor fakat bu loop içindeyken harika çalıştığı halde kesme içinde ne olursa olsun 35.60 döndürüyor sayı asla değişmiyor.
Hareketli ortalamayla çalışıyorsun yanlış görmüyorsam. O zaman bukadar hesaplama yapmaya gerek yok. Her döngüde voltaj hesaplamak yerine Tüm birimlerimizi ADC count cinsinden kullanabiliriz. öyle olunca Ortalama almak yerine sadece "total" değişkenini veri olarak kullanabilirsin. Ama bunu yapmak için önce kontrol döngüsünü kararlaştırmak lazım.
Karışıklığa sebep olmak istemiyorum. Şu anda layığıyla da inceleyemeyeceğim ancak akşama zaman ayırabilirim. Bahsettiğin sorunu göremedim. kolay gele.
 
Hareketli ortalamayla çalışıyorsun yanlış görmüyorsam. O zaman bukadar hesaplama yapmaya gerek yok. Her döngüde voltaj hesaplamak yerine Tüm birimlerimizi ADC count cinsinden kullanabiliriz. öyle olunca Ortalama almak yerine sadece "total" değişkenini veri olarak kullanabilirsin. Ama bunu yapmak için önce kontrol döngüsünü kararlaştırmak lazım.
Karışıklığa sebep olmak istemiyorum. Şu anda layığıyla da inceleyemeyeceğim ancak akşama zaman ayırabilirim. Bahsettiğin sorunu göremedim. kolay gele.
sadece pico için çıkaracak olsam zaten 2 çekirdek var 1 çekirdek PID+SICAKLIK OKUMA diğer çekirdek ekran,buton,haberleşme,enkoder'e baksın.

Ama böyle yaparsam diğer 2 denetleyici geçince kilitlenip kalırım ne yapacağım diye.

Şimdi PWM'in 0 konumunu doğru şekilde yakalamaya çalışıyorum ama yanlış ilerliyorum sanırım.
hem intterupt hem pwm output çalışabiliyor ama şekilde asla doğru çalıştıramıyorum, değişken tek değer alıyor.
bayrak set edince bayrak içinde işlemi yapıp bayrağı 0'layana kadar mosfet defalarca açılıp kapanmış oluyor.
 
Artık software'in şanzımanı var 3 vitesli.

C++:
int flag = 0;

void kesme() {

  flag++;
}

  if (flag == 1) {
    total = total - readings[readIndex];
    readings[readIndex] = analogRead(A0);
    total = total + readings[readIndex];
    readIndex = readIndex + 1;
    if (readIndex >= numReadings) {
      readIndex = 0;
    }
    average = total / numReadings;
  }
  if(flag == 2){
    adc_v = average * (cpu_v / max_adc);
  }
  if(flag == 3){
  c = adc_v * 248, 32 - 70, 421;
  Serial.println(c);
  flag = 0;
  }

1. viteste analog ortalama alıyoruz.
2. viteste adc to voltaj yapıyoruz.
3. viteste voltaj to sıcaklık yapıyoruz.

şimdilik güzel çalışıyor.
 
Güzel çalışmadı...
aslında yaparken hoşuma gitmişti, her pulse'de tek işlem.
aslında 3 vitesede gerek yok, sadece 1. viteste yapılan işlem yeterli diğerleri okunduktan 1ms sonra da sonuca ulaşssa yeterli.
biz bunu sadece 1 vitesli yapalım.
 
Öyle flag ile olmaz. Olsaydı ana kodda doğrudan interrupt flag'ını da okuyarak yapabilirdin. Ama şunu yapabilirsin. PWM frekansını 100 Hz e düşürürsün ve maksimum PWM değerini de öyle bir ayarlarsın ki, PWM count sıfıra düştükten sonra bir sonraki PWM palsına yeterince süre kalır sana. PWM count 65535 ile 60000 arasında ısınma anlamında neredeyse hiç fark olmaz.
 
Öyle flag ile olmaz. Olsaydı ana kodda doğrudan interrupt flag'ını da okuyarak yapabilirdin. Ama şunu yapabilirsin. PWM frekansını 100 Hz e düşürürsün ve maksimum PWM değerini de öyle bir ayarlarsın ki, PWM count sıfıra düştükten sonra bir sonraki PWM palsına yeterince süre kalır sana. PWM count 65535 ile 60000 arasında ısınma anlamında neredeyse hiç fark olmaz.
Frekans 100Hz.
pwm count 1.
0'da kalma süresi tam 10ms

Frekans 100Hz
pwm count 60000
0'da kalma süresi 1ms

Frekans 100Hz.
pwm count 65535
0'da kalma süresi 200us
 
Kafam bu hale geldi ama anladım

PWM count değerimiz 2 farklı yere yazılacak.
1.si pwm çıkış komutumuza.
diğeri ise 16bit timer içeriğine.

timerin saymayı bitirip baştan başladığı(0'a düştüğü anda) biz işlemimizi yapacağız.
@taydin abi doğru anlamış mıyım?
 
Kafam bu hale geldi ama anladım
21089 eklentisine bak
PWM count değerimiz 2 farklı yere yazılacak.
1.si pwm çıkış komutumuza.
diğeri ise 16bit timer içeriğine.

timerin saymayı bitirip baştan başladığı(0'a düştüğü anda) biz işlemimizi yapacağız.
@taydin abi doğru anlamış mıyım?

Sen PWM destekleyen bir pine digitalWrite yapınca zaten PWM count registerine değer yazmış oluyorsun. Senin yapman gereken, count 0 a düştüğünde kesme gelmesini sağlamak. Bu pinle alakalı birşey değil. PWM herhangi bir pinden çıkış vermezse bile count 0 interrupt'unu ürettirebilirsin.
 
Sen PWM destekleyen bir pine digitalWrite yapınca zaten PWM count registerine değer yazmış oluyorsun. Senin yapman gereken, count 0 a düştüğünde kesme gelmesini sağlamak. Bu pinle alakalı birşey değil. PWM herhangi bir pinden çıkış vermezse bile count 0 interrupt'unu ürettirebilirsin.
Dün earle abimle ufak bir hasbihal yaptık.
Anlattım durumu dedim abi hem output hem'de kesme almam lazım ama yazınca işlemci boot olmuyor.
abim sadece ufak trikler verdi.
digitalPinToİntettupt kullan direkt numarasını yazma.
hem output hem'de konum belirtirsen kararsızlık olur ara konumları tespit et(yükselen, düşen kenar).

Bu yönergeler ile pin durumunun yükselen düşen anlarını okuyabiliyorum.

Ama şimdi yapmam gereken pwm count registerinin okuyup bu registeri yorumlamak biraz da buna uğraşalım.
yarın akşam 00.00'da projenin %80i bitmiş olacak sözüm var.
 
Eğer piconun arduino paketi senin istediğini yapmıyorsa doğrudan registerlerle çalış. Veya piconun kendi SDK var onu kullan. Neticede Earle abinin kuralları değil önemli olan, bu işi işlemcinin yapıp yapamadığı önemli. Ve benim bildiğim bütün PWM destekleyen işlemcilerden count 0 olduğu zaman interrupt alınabilir.
 
Eğer piconun arduino paketi senin istediğini yapmıyorsa doğrudan registerlerle çalış. Veya piconun kendi SDK var onu kullan. Neticede Earle abinin kuralları değil önemli olan, bu işi işlemcinin yapıp yapamadığı önemli. Ve benim bildiğim bütün PWM destekleyen işlemcilerden count 0 olduğu zaman interrupt alınabilir.
Başlıca kaynağım C/C++ sdk'sı zaten arduino-pico kart dosyası temelinde bu sdk'da verilen komutlar üstüne giydirilmiş hal veya m0 komutları kullanılmamış.

Kurcalıyorum yapamam lazım artıkkkkk
 
Eğer harici pin ile oluyorsa ilerlemek adına o yöntemi kullan. PWM output, interrupt özelliği olan bir pine geri dönsün. Sonra işin aslını öğrenirsin.
 
Eğer harici pin ile oluyorsa ilerlemek adına o yöntemi kullan. PWM output, interrupt özelliği olan bir pine geri dönsün. Sonra işin aslını öğrenirsin.
C++:
void kesme() {

  total = total - readings[readIndex];
  readings[readIndex] = analogRead(A0);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
}
 adc_v = average * (cpu_v / max_adc);
 c = adc_v * 248, 32 - 70, 421;
 Serial.println(c);
}

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  pinMode(A0, INPUT);

  attachInterrupt(digitalPinToInterrupt(0), kesme, FALLING);

  analogWriteResolution(16);
  pinMode(0, OUTPUT_4MA);


  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}



void loop() {


  if (c > 253) {

    analogWrite(0, 0);
  }

  if (c < 255) {
    analogWriteFreq(100);
    analogWrite(0, 60000);
  }


}

Şimdi bununla deneyeceğim.
 
Ben anlamadım pin mi yetmiyor da aynı pini iki kere kullanıyor?
 
C++:
void kesme() {

  total = total - readings[readIndex];
  readings[readIndex] = analogRead(A0);
  total = total + readings[readIndex];
  readIndex = readIndex + 1;
  if (readIndex >= numReadings) {
    readIndex = 0;
  }
  average = total / numReadings;
}
 adc_v = average * (cpu_v / max_adc);
 c = adc_v * 248, 32 - 70, 421;
 Serial.println(c);
}

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  pinMode(A0, INPUT);

  attachInterrupt(digitalPinToInterrupt(0), kesme, FALLING);

  analogWriteResolution(16);
  pinMode(0, OUTPUT_4MA);


  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }
}



void loop() {


  if (c > 253) {

    analogWrite(0, 0);
  }

  if (c < 255) {
    analogWriteFreq(100);
    analogWrite(0, 60000);
  }


}

Şimdi bununla deneyeceğim.
bu yanlış sonuç çıkarıyor bununla 21 dereceyi 3.60 derece olarak ölçüyoruz.
 
@taydin abi bu işlemin sonucunu seri porta yazdırdığımda sonucu 'inf' olarak çıkıyor.
cal_pid = P * error + I * el_time + D * raterr;

cal_pid= double
P = float
I = float
D = float
error = float
el_time = double
raterr = float
 

Çevrimiçi personel

Forum istatistikleri

Konular
6,955
Mesajlar
118,787
Üyeler
2,824
Son üye
selocan32

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Lyewor_ wrote on taydin's profile.
Merhabalar forumda yeniyim! Bir sorum olacaktı lcr meterler hakkında. Hem bobini ölçen hemde bobin direnci ölçen bir lcr meter var mı acaba?
Back
Top