STM32, PWM ve H-Bridge

TunahanC

SbX
Katılım
31 Mayıs 2024
Mesajlar
178
Aslında sorunun cevabını biliyorum fakat emin olmak size danışmak istedim. STM32 ile BLDC motor için H köprü sürmek istersek. STM32 üzerinden PWM ve PWMN göndermek gerekli bunu zaten biliyorum. Sorun şurada faz kaydırmayı aynı timerın farklı kanalları üzerinde yapabilir miyim? Yoksa 3 farklı timer kurup slave olarak birbirlerini mi tetikletmeliyim?
 
Son düzenleme:
Eğer clock hızı yeterince yüksek ise, kesmeleri kapatıp bütün timer'ları peş peşe resetten çıkarabilirsin. 100 MHz MCU clock'ta aralarında 10 ns faz farkı olur, bu da önemli olmaz.
 
Tam olarak nasıl bir yol izlemek istediğinizi anlamadım, ama STM32 ile kanallar arası faz farkı için anahtar kelime Asimetrik PWM
 
Tam olarak nasıl bir yol izlemek istediğinizi anlamadım, ama STM32 ile kanallar arası faz farkı için anahtar kelime Asimetrik PWM
Faz farkı oluşturmak istiyorum işte ama bu tek bir timer üzerinden yapılabilir mi onu sorgulamaya çalıştım.
 
Cogu STM nin 1 tane advanced PWM modulu olur. Dolayisi ile elinde faz farki olusturtacagin birden fazla timer modulun olmayacak.

Bahsettigin faz farki, PWM ler arasindaki faz farki degil. Bu genellikle yanlis anlasiliyor.

PWM sinyal sadece bir tasiyici. Sen module edecegin sinyaller uzerinde faz farki olusturacaksin.

Asagida kirmizi grafik iki ayri sinyal ve aralarinda faz farki var.

1735986484324.png

Bu sinyalleri hemen altindaki siyah pwm ile olusturdum. Dikkat edersen pwm sinyalleri ayni fazda, Fakat pwm sinyallerin tanimladigi sinyaller arasinda belirgin bir faz farki var.

Sen sadece pwm sinyalin ne zaman on ne zaman of olacagini belirleyerek faz farklari olusturacaksin.

F, senin uretmek istedigin sinyalin frekansi olacaksa Fpwm >> F olmak zorunda.
 
TIM1 özelliklerine bakıyorum, elimizde ne var, edge ve center-aligned (orta hizalı) mode ve bunların negatifi. Edge dediği normal çalışma biçimi. Bir periyodu 3 eşit parçaya böl. İlk modül ilk parçayı normal edge modunda, 2. modül 2. parçayı center-aligned ve 3. modül 3. parçayı negatif edge modunda sürsün, bu kadar.

not: Modül dediğim zamanlayıcı kanalı, yani tek bir zamanlayıcıdan bahsediyorum.
 
Son düzenleme:
Hoverboard yazılımlarını incele genelde bir cogu stm32f103 ile yapılmıştır. Nette de kaynak kodları mevcut. Linki P. tesi verebilirim şehir dışında ve pc den uzagım
 
Motoru kontrol etmek için PWM kanalları arasında faz farkı oluşturmanıza gerek yok. High Side anahtar PWM yapacak, Low Side anahtar On/Off çalışacak. Hall Effect Sensör'lerden gelen bilgiye göre rotor pozisyonuna karar verip ilgili durum için hangi High Side ve Low Side anahtarların aktif edileceğine karar veren bir kesme alt rutininiz olacak. Bu kesme alt rutini hall sinyallerinin herhangi birinde değişim olduğunda aktif olacak. Bunu STM otomatik olarak yapabiliyor, Commutation Callback gibi bir ismi vardı sanırım.
İyi çalışmalar.
 
Kod:
  HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim1, TIM_CHANNEL_2);

  HAL_TIM_PWM_Start(&htim2, TIM_CHANNEL_1);
  HAL_TIM_OC_Start(&htim2, TIM_CHANNEL_2);

  HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);

Yukarıdaki kodları ile aşağıdaki gibi ayarlanmış timerlar kullanıldığı zaman aslında araların 120 derece olan 3 adet PWM sinyali üretebiliyorum. Ben bunu tek bir timer üzerinden yapabilir miyim diye sormuştum. @elektorronikci'nin dediğini gün içinde deneyeceğim.

Kod:
static void MX_TIM1_Init(void)
{

  /* USER CODE BEGIN TIM1_Init 0 */

  /* USER CODE END TIM1_Init 0 */

  TIM_ClockConfigTypeDef sClockSourceConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};
  TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};

  /* USER CODE BEGIN TIM1_Init 1 */

  /* USER CODE END TIM1_Init 1 */
  htim1.Instance = TIM1;
  htim1.Init.Prescaler = 168-1;
  htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim1.Init.Period = 33-1;
  htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim1.Init.RepetitionCounter = 0;
  htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
  if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim1) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 11;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
  sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
  if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
  if (HAL_TIM_OC_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
  sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
  sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
  sBreakDeadTimeConfig.DeadTime = 0;
  sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
  sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
  sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
  if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM1_Init 2 */

  /* USER CODE END TIM1_Init 2 */
  HAL_TIM_MspPostInit(&htim1);

}

/**
  * @brief TIM2 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM2_Init(void)
{

  /* USER CODE BEGIN TIM2_Init 0 */

  /* USER CODE END TIM2_Init 0 */

  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM2_Init 1 */

  /* USER CODE END TIM2_Init 1 */
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 84-1;
  htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim2.Init.Period = 33-1;
  htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_OC_Init(&htim2) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_ITR0;
  if (HAL_TIM_SlaveConfigSynchro(&htim2, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_OC2REF;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 11;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_ACTIVE;
  if (HAL_TIM_OC_ConfigChannel(&htim2, &sConfigOC, TIM_CHANNEL_2) != HAL_OK)
  {
    Error_Handler();
  }
  __HAL_TIM_ENABLE_OCxPRELOAD(&htim2, TIM_CHANNEL_2);
  /* USER CODE BEGIN TIM2_Init 2 */

  /* USER CODE END TIM2_Init 2 */
  HAL_TIM_MspPostInit(&htim2);

}

/**
  * @brief TIM3 Initialization Function
  * @param None
  * @retval None
  */
static void MX_TIM3_Init(void)
{

  /* USER CODE BEGIN TIM3_Init 0 */

  /* USER CODE END TIM3_Init 0 */

  TIM_SlaveConfigTypeDef sSlaveConfig = {0};
  TIM_MasterConfigTypeDef sMasterConfig = {0};
  TIM_OC_InitTypeDef sConfigOC = {0};

  /* USER CODE BEGIN TIM3_Init 1 */

  /* USER CODE END TIM3_Init 1 */
  htim3.Instance = TIM3;
  htim3.Init.Prescaler = 84-1;
  htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
  htim3.Init.Period = 33-1;
  htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
  htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
  if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
  {
    Error_Handler();
  }
  sSlaveConfig.SlaveMode = TIM_SLAVEMODE_TRIGGER;
  sSlaveConfig.InputTrigger = TIM_TS_ITR1;
  if (HAL_TIM_SlaveConfigSynchro(&htim3, &sSlaveConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
  sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
  if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
  {
    Error_Handler();
  }
  sConfigOC.OCMode = TIM_OCMODE_PWM1;
  sConfigOC.Pulse = 11;
  sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
  sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
  if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN TIM3_Init 2 */

  /* USER CODE END TIM3_Init 2 */
  HAL_TIM_MspPostInit(&htim3);

}
 
Tek bir timer ile yapmaya çalışıyorum fakat neden PWNM dalgaları ters geliyor. Polarizasyonu low olarak denediğim zaman hiç çıkış vermiyor. Bir tavsiyesi olan var mı?
WhyNUNUWhy.JPG


kod biraz uzun ama aşağıdaki kod ile yapmaya çalışıyorum.

Kod:
void PMSM_Phase_Control(PMSM_Phase_Control_t *control) {
    TIM1->CCER &= ~(TIM_CCER_CC1E | TIM_CCER_CC1NE |
                    TIM_CCER_CC2E | TIM_CCER_CC2NE |
                    TIM_CCER_CC3E | TIM_CCER_CC3NE);

    TIM1->CCR1 = control->a_high ? control->pwm_duty : 0;
    TIM1->CCR2 = control->b_high ? control->pwm_duty : 0;
    TIM1->CCR3 = control->c_high ? control->pwm_duty : 0;

    uint32_t ccer_val = 0;

    if(control->a_high) {
        ccer_val |= TIM_CCER_CC1E;
    } else {
        ccer_val &= ~TIM_CCER_CC1E;
    }
    if(control->a_low) {
        ccer_val |= TIM_CCER_CC1NE;
    } else {
        ccer_val &= ~TIM_CCER_CC1NE;
    }

    // B Fazı kontrol
    if(control->b_high) {
        ccer_val |= TIM_CCER_CC2E;
    } else {
        ccer_val &= ~TIM_CCER_CC2E;
    }
    if(control->b_low) {
        ccer_val |= TIM_CCER_CC2NE;
    } else {
        ccer_val &= ~TIM_CCER_CC2NE;
    }

    // C Fazı kontrol
    if(control->c_high) {
        ccer_val |= TIM_CCER_CC3E;
    } else {
        ccer_val &= ~TIM_CCER_CC3E;
    }
    if(control->c_low) {
        ccer_val |= TIM_CCER_CC3NE;
    } else {
        ccer_val &= ~TIM_CCER_CC3NE;
    }

    TIM1->CCER |= ccer_val;
}

void PMSM_Commutation_Step(uint8_t step, uint16_t pwm_duty) {
    PMSM_Phase_Control_t control;
    control.pwm_duty = pwm_duty;

    switch(step) {
        case 1:
            control.a_high = 1;
            control.a_low = 0;
            control.b_high = 0;
            control.b_low = 1;
            control.c_high = 0;
            control.c_low = 0;
            break;
        case 2:
            control.a_high = 0;
            control.a_low = 0;
            control.b_high = 0;
            control.b_low = 1;
            control.c_high = 1;
            control.c_low = 0;
            break;
        case 3:
            control.a_high = 0;
            control.a_low = 1;
            control.b_high = 0;
            control.b_low = 0;
            control.c_high = 1;
            control.c_low = 0;
            break;
        case 4:
            control.a_high = 0; 
            control.a_low = 1; 
            control.b_high = 1;
            control.b_low = 0;
            control.c_high = 0;
            control.c_low = 0;
            break;
        case 5:
            control.a_high = 0;
            control.a_low = 0;
            control.b_high = 1;
            control.b_low = 0;
            control.c_high = 0;
            control.c_low = 1;
            break;
        case 6:
            control.a_high = 1;
            control.a_low = 0;
            control.b_high = 0;
            control.b_low = 0;
            control.c_high = 0;
            control.c_low = 1;
            break;
    }

    PMSM_Phase_Control(&control);
}

void PMSM_Init(void) {

    TIM1->BDTR &= ~TIM_BDTR_DTG;
    TIM1->BDTR |= 2;

    TIM1->BDTR |= TIM_BDTR_MOE;

    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_3);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_1);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_2);
    HAL_TIMEx_PWMN_Start(&htim1, TIM_CHANNEL_3);
}
 
Şimdi kılavuzu biraz karıştırdım, malesef o dediğim olmazmış. Çünkü zamanlayıcı kanalları ayrı ayrı bu modlarda çalışamıyor, hepsini etkiliyor.
Herneyse, bu iş pratikte kesinlikle toggle mode ile yapılıyordur, bunun farkına vardım. Her periyotta CCR'deki değerde çıkış durum değiştiriyor. Böylece faz farkı yaratmak çok kolay. Her kanalın CCR'sini 0, 1/3*ARR (auto reload register), 2/3*ARR yaparsın ve fıstık gibi çalışır.

Aslında PWM ile işimiz yoktu, sadece faz farkı yaratmak için PWM fikrini işe yarar hale getirmek istemiştim. Bu aşamada amaç komutasyonu yazılım yerine donanımla yapmak. Bu yüzden arkadaşların itirazını haklı bulmadım.

Gücü ayarlayacak PWM için başka bir zamanlayıcı kullanmak zorundasın. Gerekirse H köprüsünün üst kısmında 1. ve 2. zamanlayıcı çıkışlarını VE kapısından geçirip transistörleri sürersin, ya da fazladan bir transistöre uygularsın.
 
İşi ilerlettim buradan nereye gidebilirim dedim ve her motor kontrolcüsünün önüne dikilen 2 tane temel algoritma ile karşılaştım, 6step ve FOC. 6step algoritmasını boş verip FOC algoritmasına yöneldim ve oda bana, düzgün bir IGBT ya da düzgün bir H-Bridge ile PMSM motor kontrol etmenin yolunu açtı.

Aşağıdaki görsel ve incelediğim kaynaklar ile FOC oluşturmaya başladım ve belirli bir aşamayı aştım.
FOC1.JPG

Clarke dönüşümü 3 boyutlu olan bileşenleri 2 boyutlu bileşenlere çeviriyor.
Park dönüşümü ise bu 2 boyutlu bileşenleri döner bir referans sistemine yerleştirir.


Başlangıç noktan PMSM geri beslemesi oldu. Buradan elde edilen Ia, Ib ve Ic akımlarını ADC yardımıyla elde edip Clarke ile dönüştürdüm, Clarke dönüşümü ile de Park dönüşümü (referans değerlerle karşılaştırarak) yaptım. Ardından PI ile yeni değerler elde edip bunu Reverse/Inverse Park ile tekrar dönüştürdüm. SVPWM olarak kullanmak istemezsem diye de son olarak ters Clarke dönüşümü yaptım.

Bunun sonucu olarak ise aşağıdaki gibi bir source ve header dosyası ortaya çıkardım. Lookup_table.h'da bulunan kosinüs tablosunu aslında sinüs formatı üzerinden bulabilirdim fakat daha basit olsun diye böyle yaptım. Daha önce PMSM için motor kontrolcüsü yazmamıştım. Kontrolcü tamamlanmadı tabi ki ama bu kısma kadar olan yerlerde varsa şurası hatalı ya da şurası fazla olmuş diyebileceğiniz bir yer makbule geçer.

Edit: Tabiki sürücü kartı hazırlanmadan yazılan kod biraz havada kalıyor fakat en azından kart tasarımı sonrası için "neyi nasıl yapıyordum" demenin önüne geçmeyi hedefliyorum.
 

Ekler

Son düzenleme:
Eğer motor çok hızlı dönecekse coupling control yapman önem arz edebilir özellikle motor bobini büyükse.

Proposed-vector-control-a-Block-diagram-of-vector-control-with-decoupling-and-3D-i.png
 
Şimdilik FOC kısmını kaba olarak tamamladığımı düşündüğüm için motoru nasıl sürecek donanım nasıl olacak (geri beslemelerden bahsetmiyorum) şeklinde düşünürken biraz araştırarak biraz da mantık yürüterek şöyle bir şema çıkardım. 3x şeklinde bunu yaptığım zaman H-bridge işi tamamlanmış olacak diye düşünüyorum.
H-Bridge.JPG


Fakat burada kafama karıştıran bir şey oldu. Burada octocupler (PC817) inverter şeklinde mi davranacak? Yani aslında PWM1 ve PWMN1 yer mi değişmeli? Bu arada R3, R4 değerlerini yazmamışım ama değerleri 100ohm .
 
Optolar pwm sinyalinin tersini alır bu devre şamasına göre.

Normal hale getirmek için R1 ve R2 yi optonun emiterine bağlayın.
 
Optolar pwm sinyalinin tersini alır bu devre şamasına göre.

Normal hale getirmek için R1 ve R2 yi optonun emiterine bağlayın.
Bu bana biraz sakat bir yöntem gibi geldi sonuçta PWM sinyal ve 20kHz gibi seviyelerde çalışacak. Bunun yerine eğer tersliyorsa PWMN ile PWM'i ters düşünürek çalıştırmak daha az yorar gibi ama kaçırdığım bir nokta varsa açıklarsan sevinirim.
H-Bridge 2.jpg


sanırım bu şekilde bağlamam lazım dediğinize göre.
 
Son düzenleme:
ST Microelectrinics'in STM32 Econsystem for Motor Control sayfası var. Mühtemelen orada hazır çözümler bulunabilir.
Bu arada PC817 biraz yavaş. Eğer optokuplerin tepki zamanı önemliyse (örneğin switch esnasında dead time mikrosaniyeler civarında) datasheete göre R19 ve R2 değerleri gözden geçirmek gerekebilir.

 
ST Microelectrinics'in STM32 Econsystem for Motor Control sayfası var. Mühtemelen orada hazır çözümler bulunabilir.
Bu arada PC817 biraz yavaş. Eğer optokuplerin tepki zamanı önemliyse (örneğin switch esnasında dead time mikrosaniyeler civarında) datasheete göre R19 ve R2 değerleri gözden geçirmek gerekebilir.

Ben bu ST'nin motor control workbenchini de indirdim hatta uğruna bilgisayarın dilini ingilizce (ST motor control workbench Türkçe olan bazı bilgisayalara kurulduğunda CubeMX'i görmüyor) bile yaptım. Ama programı anlayamadım pek. Dediğinize de bakayım yarın müsait olduğumda.
 
Opto ile ilgili tavsiyeyi dikkate almazsan, MCU initilize olurken iki çıkışını da 0 yaptığı zaman cross conduction a sebep olursun(2101 in böyle bir koruması yoktu diye hatırlıyorum)
 
Opto ile ilgili tavsiyeyi dikkate almazsan, MCU initilize olurken iki çıkışını da 0 yaptığı zaman cross conduction a sebep olursun(2101 in böyle bir koruması yoktu diye hatırlıyorum)
6N137 ile değiştireyim o zaman. Low ve High seviyeler için max değeri 100nS civarı.
 
Son düzenleme:

Forum istatistikleri

Konular
7,299
Mesajlar
123,393
Üyeler
2,949
Son üye
dündenbiri

Son kaynaklar

Son profil mesajları

Freemont2.0 herbokolog Freemont2.0 wrote on herbokolog's profile.
nick iniz yakıyor
:D
Freemont2.0 posta Freemont2.0 wrote on posta's profile.
Merhabalar :)
az bilgili çok meraklı
Prooffy semih_s Prooffy wrote on semih_s's profile.
Merhaba, sizden DSO2C10 hakkında bilgi rica ettim. Yanıtlarsanız sevinirim...
Unal taydin Unal wrote on taydin's profile.
Timur Bey, Arduino kontrollü bir akü şarj cihazı yapmaya çalışıyorum. Aklımdaki fikri basit bir çizim olarak konu açmıştım. Özellikle sizin fikirlerinizi çok önemsiyorum.
Back
Top