Администрация форума не несёт ответственности за достоверность информации и оставляет за собой право редактировать или в особых случаях даже удалять посты без предупреждения. Спасибо за понимание.

Программирование ATMEL в BASCOM.

Информация о пользователе

Привет, Гость! Войдите или зарегистрируйтесь.


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » ПИД регулятор тока.


ПИД регулятор тока.

Сообщений 31 страница 40 из 40

31

По теме.
Проверил сейчас схему http://s019.radikal.ru/i624/1405/c8/0f8aeb1ca35ft.jpg в железе. До 15 ампер разогнал, транзистор Q1 греется больше Q1, причем прилично больше.
ШИМ около 250 герц. ПИД регулирование тока я либо я не понял, либо оно не дает преимуществ в быстрых процессах - менял напряжение источника, ток выдерживает как при простом алгоритме усреднения, так и при ПИД. НО я облажался с контроллером, распаял mega328P а когда начал программировать выяснил, что у нее АЦП не может работать в дифференциальном режиме и отрицательные значения тока в контроллере аккумулятора при разряде я не получаю. :( Пришлось воткнуть отдельно ACS712 и грубо (+- 0,1А) мерить ей. В принципе для заряда 120 Ампер/часового 12 вольтового аккумулятора точнее и не надо. :)
PS В окончательной схеме решил вывести из ШИМ транзистор Q1 или вообще реле поставить, такое включение медленное. Стабилитроны отрабатывают нормально, поднимал входное напряжение до 35 вольт, ничего не вылетело!

0

32

Но в я хз что даёт ПИД я юзаю придуманный алгоритм регулятора даёт хороший рзультат.

Код:
Dim Pgravrds(5) As Long
Dim Pgravr(17) As Integer       'дял програмного стабилизатора
Dim Pgravr1 As Bit       'сюда данные обновления напруги
Dim Pgravr2 As Bit       'сжижать коэффицент при приблежении к заданному

Dim Pgravr3 As Bit
Dim Pgravr5 As Bit
Dim Pgravr4 As Bit       'статус регулятора
Dim Pgravr6 As Bit       'плавное приблежение
Dim Pgravr7 As Bit       'использовнание быстрой стабилизации
Dim Pgravr15 As Bit
Dim Pgravr14 As Bit
Dim Pgravr13 As Bit
Dim Pgravr12 As Bit

Dim Pgravr20 As Bit
Dim Pgravr21 As Bit

Dim Pgravr23 As Bit

Dim Pgravr8 As Byte
Dim Pgravr9 As Byte
'Dim Pgravrdk(1) As Integer
Dim Pgravrd(25) As Byte       '0 стоять ан месте, 1 повышать медленно, 2 понижать медленно (доводка), 3 быстро повышать, 4 быстро понижать

'Pgravr7 = 0  Pgravr(11)
Pgravrd(19) = 255       'разрядной линейной перестройки (дискретность перестройки)

do
   If Pgravr2 = 0 Then
        Pgravr(5) = Getadc(6)       '/ 4
   Else
        Pgravr(5) = Getadc(0)
   End If
   Gosub Pgravrsub:
loop

end

Pgravrsub:
    'тут расчёт отклонения напруги



 If Pgravr4 = 1 Then
    If Pgravr5 = 0 Then
       Pgravr5 = 1

        Config Timer0 = Pwm , Compare A = Clear , Compare B = Clear , Prescale = 1 , Clear Timer = 1 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down
        'Config Timer0 = Pwm , Compare A = Clear , Prescale = 1 , Clear Timer = 1 , Compare A Pwm = Clear Down
        Start Timer0
        Pgravr1 = 1
    End If

           Pgravr23 = 0

           Pgravrd(7) = 0       'если значение вошло в пределы то счётчик уже считает на возврат управление интегральному регулятору
           If Pgravr(6) < Pgravr(5) Then       'знаечние вышла за переделы диапазона вниз
                 Pgravrd(7) = 1

           Elseif Pgravr(3) > Pgravr(5) Then       'знаечние вышла за переделы диапазона вверх
                 Pgravrd(7) = 2

           End If


           Pgravrds(3) = 0       'в любых других случаях заполнение 0

           If Pgravr(5) > Pgravr(1) Then       'напруга выше медленно понижать
               Pgravrd(12) = 6
               'If Pgravrd(20) > Pgravrd(24) Then Pgravrd(20) = Pgravrd(20) - 3
               Pgravr(16) = Pgravr(5) - Pgravr(1)

           Elseif Pgravr(5) < Pgravr(1) Then       'напруга ниже медленно повышать
           '  If Pgravrd(20) < Pgravrd(25) Then Pgravrd(20) = Pgravrd(20) + 3

             Pgravrd(12) = 5

             Pgravr(16) = Pgravr(1) - Pgravr(5)

             If Pgravr(3) <= Pgravr(5) Then

                   Pgravrds(3) = Pgravr(1) - Pgravr(5)       'Pgravr(5) - Pgravr(3)       'разница между текущем и заданным
                   Pgravrds(3) = Pgravrds(3) * Pgravrd(19)       'умножаемем на макс шаг промежуточный шаг

                   Pgravrds(3) = Pgravrds(3) / Pgravr(2)

             Else       'дасть полную тягу как выше диапазона
                  Pgravrds(3) = Pgravrd(19)
             End If

           Elseif Pgravr(5) = Pgravr(1) Then
              Pgravrd(12) = 0
           '   If Pgravrd(20) > 100 Then Pgravrd(20) = Pgravrd(20) - 1
             ' If Pgravrd(20) < 100 Then Pgravrd(20) = Pgravrd(20) + 1
              Pgravr8 = 0
           End If

      If Pgravr7 = 1 Then       'установлено 0 значение стабилизации не подлежит просто снизить тягу
          Pgravr23 = 0
          Pgravrd(7) = 0
         ' Pgravrd(14) = 0
          Pgravrd(12) = 0
          Pgravr3 = 1
          Pgravrds(1) = 0
          Pgravr(7) = 0
      End If


     If Pgravr(13) > Pgravrds(3) Then
         Pgravr(13) = Pgravr(13) - Pgravrd(18)
         If Pgravr(13) < Pgravrds(3) Then Pgravr(13) = Pgravrds(3)

     Elseif Pgravr(13) < Pgravrds(3) Then
        Pgravr(13) = Pgravr(13) + Pgravrd(2)

        If Pgravr(13) > Pgravrds(3) Then Pgravr(13) = Pgravrds(3)

     End If

     'если колбасит дольше опеределённого то отдать упарвление интегральному
     If Pgravrd(7) <> Pgravr9 Then       ' при смене статуса фильтр считает вниз к возврату на интегральный
         Pgravr9 = Pgravrd(7)

         If Pgravr(7) > 0 Then Pgravr(7) = Pgravr(7) - Pgravrd(10) Else Pgravr12 = 0       'отдать управление интегральному регулятору
         Pgravr13 = 1

     Else

        If Pgravr9 <> 0 Then       'когда состояние установилось он считает вверх к передаче управления пропорциональному
           If Pgravr(7) < Pgravrd(6) Then Pgravr(7) = Pgravr(7) + 1 Else Pgravr12 = 1       'отдать управление пропорциаональному регулятору

        Else       'если знаечние в норме он снова стремиться к возврату управления интегральному
           If Pgravr(7) > 0 Then Pgravr(7) = Pgravr(7) - Pgravrd(10) Else Pgravr12 = 0       'отдать управление интегральному регулятору

        End If

     End If


    If Pgravr6 = 0 And Pgravr15 = 0 Then       'защита если вдруг скачки в обе стороны окажутся запрещены
       Pgravr6 = 1
       Pgravr15 = 1
    End If



    If Pgravr7 = 0 And Pgravr12 = 0 Then       'перестрйка при малом отклонении

       If Pgravrds(1) < Pgravrd(19) And Pgravrd(11) >= Pgravrd(4) Then

            Pgravrds(1) = Pgravrds(1) + Pgravr(11)
            Pgravrd(11) = Pgravrd(14)
            Pgravr3 = 1
            Pgravr6 = 1

       End If


       If Pgravrds(1) > 0 And Pgravrd(11) <= Pgravrd(3) Then
           Pgravrd(11) = Pgravrd(9)
           Pgravrds(1) = Pgravrds(1) - Pgravr(11)
           Pgravr3 = 1

           Pgravr15 = 1

       End If

       If Pgravr14 = 1 Then

          Pgravrds(4) = Pgravrds(4) + Pgravr(5)
          Pgravrd(20) = Pgravrd(20) + 1
          If Pgravrd(20) >= Pgravrd(22) Then

             If Pgravrds(5) < Pgravrds(4) Then       'корректировка по ошибки за время аналазиа
                 If Pgravrds(1) > 0 Then Pgravrds(1) = Pgravrds(1) - 1
                 Pgravr15 = 1
             Elseif Pgravrds(4) < Pgravrds(5) Then
                 If Pgravrds(1) < Pgravrd(19) Then Pgravrds(1) = Pgravrds(1) + 1
                 Pgravr6 = 1
             End If

             Pgravrds(4) = 0
             Pgravrd(20) = 0
          End If

       End If

    Elseif Pgravr12 = 1 And Pgravr7 = 0 Then       'принять заполнеине от пропорционального
        Pgravrd(12) = 0
        Pgravrds(1) = Pgravr(13)
        Pgravr3 = 1
        Pgravr6 = 1
        Pgravr15 = 1
    End If


    Select Case Pgravrd(12)       'релейный регулятор скачкообразная подстрйока быстрая
            Case 6
               If Pgravrd(11) > 0 Then Pgravrd(11) = Pgravrd(11) - 1

               If Pgravr6 = 1 Then

               If Pgravr(16) > Pgravrd(13) Then Pgravr(16) = Pgravrd(13)

                     Pgravr(15) = Pgravr(16) * 100
                     Pgravr(15) = Pgravr(15) / Pgravrd(13)       'разница в процентах
                     Pgravr(15) = Pgravr(15) * Pgravrd(17)
                     Pgravr(15) = Pgravr(15) / 100
                     Pgravr(15) = Pgravr(15) + Pgravrd(16)

                     Pgravr(12) = Pgravr(15) * -1
                     Pgravr6 = 0
                     Pgravr15 = 1
                     Pgravr3 = 1
                     Pgravr13 = 1
                     Pgravrd(11) = 100
               End If

            Case 5
               If Pgravrd(11) < 200 Then Pgravrd(11) = Pgravrd(11) + 1

               If Pgravr15 = 1 Then


               If Pgravr(16) > Pgravrd(13) Then Pgravr(16) = Pgravrd(13)

                    Pgravr(15) = Pgravr(16) * 100
                    Pgravr(15) = Pgravr(15) / Pgravrd(13)       'разница в процентах
                    Pgravr(15) = Pgravr(15) * Pgravrd(17)
                    Pgravr(15) = Pgravr(15) / 100
                    Pgravr(15) = Pgravr(15) + Pgravrd(16)

                    Pgravr15 = 0
                    Pgravr(12) = Pgravr(15)
                    Pgravr6 = 1
                    Pgravr3 = 1
                    Pgravr13 = 1
                    Pgravrd(11) = 100
               End If
           '   Pgravr3 = 1
            'End If
         '
            Case 0
               Pgravr(12) = 0

               Pgravrd(11) = 100

    End Select

    'End If


  Else
     If Pgravr5 = 1 Then
         Pgravrds(1) = 0
         Pgravr5 = 0
         Pgravr3 = 1
        ' Compare0a = 50       'сброс мощи инверсный режим
        ' Pgravr(9) = 50
          Stop Timer0
          Config Timer0 = Timer
          Portd.6 = 0
          Portd.5 = 1
     End If
  End If




    If Pgravr3 = 1 Then       'тут установка коэффицента заполнения если он изменился

       If Pgravrds(1) < 0 Then Pgravrds(1) = 0
       If Pgravrds(1) > Pgravrd(19) Then Pgravrds(1) = Pgravrd(19)

       Pgravrds(2) = Pgravrds(1) + Pgravr(12)

       Pgravr3 = 0


       If Pgravrds(2) > Pgravrd(19) Then Pgravrds(2) = Pgravrd(19)
       If Pgravrds(2) < 0 Then Pgravrds(2) = 0

       If Pgravrds(2) <> Pgravr(9) Or Pgravr13 = 1 Then

           Pgravr(9) = Pgravrds(2)
           Pgravr13 = 0

          If Pgravr2 = 0 Then Compare0a = Pgravr(9) Else Compare0b = 255 - Pgravr(9)

       End If



    End If


Return


Prgavrsubconf:


  If Pgravr(1) = 0 Then
     Pgravr7 = 1
  Else
     If Pgravr7 = 1 Then
       ' Gosub Pvrres:
     End If
     Pgravr7 = 0

  End If
  Pgravrds(2) = Pgravr(1) * Pgravrd(1)       'Pgravrd(1)

  Pgravr(4) = Pgravrds(2) / 100       'тут абсалютная разница

  Pgravr(3) = Pgravr(1) - Pgravr(4)       'абсалютное значения отклонения вниз и для пропорцианального регулятора

  Pgravr(6) = Pgravr(1) + Pgravr(4)       'тут абсалютное значение отклонения вверх

  Pgravr(2) = Pgravr(4)       'тут разница
 ' Pgravr(10) = Pgravrd(2) * 1       'шаг с увеличенной разрядностью
 Pgravrd(3) = 100 - Pgravrd(5)       'шагов вниз
 Pgravrd(4) = 100 + Pgravrd(5)       'шагов вверх

 Pgravrd(14) = Pgravrd(4) - Pgravrd(8)       'значене ожидание для отимизации вычисления пристаивается фильтру при интегральной перейстройки

 Pgravrd(9) = Pgravrd(3) + Pgravrd(8)       'значене ожидание для отимизации вычисления пристаивается фильтру при интегральной перейстройки


 Pgravrd(17) = Pgravrd(15) - Pgravrd(16)       'промежуточный шаг


 Pgravrd(24) = 100 - Pgravrd(23)
 Pgravrd(25) = 100 + Pgravrd(23)

 Pgravrds(5) = Pgravr(1) * Pgravrd(22)

Return


Firstconavr:'тут переконфигарация работы с разными параметрами

If Pgravr1 = 0 Then
  Pgravrd(10) = 5       'фильтр НЧ колебаний для возврата к интегральному уровень ассиметрии, при смене знака ошибки и при входе в заданную погрешность ускоряет возврат к интегральному
  Pgravrd(6) = 9       'НЧ фильтр компенсация задержки обратной связи ждать (не действует на шумовую стабилизацию) максимально значение фильтра, замедляет переход в пропрциональный режим

  Pgravrd(1) = 15       '% отоклонение для выхода на подводку
  Pgravrd(2) = 1       'максимальная скорость нарастания заполнения для пропорционального регулятора, фактически компенсация разорванной петли
  Pgravrd(18) = 4       'скорость сброса тяги для пропорционального регулятора

  Pgravr14 = 1       'высокая стабильность на основе усредениея по буферу
  Pgravrd(22) = 40       'размер буфера анализа симметрии чем больше тем выше мгновенная не симметрия но если слишком убавить появится низкочастотные плавания ассиметрии

  Pgravrd(8) = 2       'пропус шагов при интегральной перейтройки
  Pgravrd(5) = 8       'фильтр нтегрально стабищизатора ждёт шагов для начала перестройки
  Pgravr(11) = 1       'скорость медленной перестройки интегрального регулятора
  Pgravrd(13) = 50       'верхнее значение отсройки для релейной стабилизации
  Pgravrd(16) = 3       'мин значение пересковов релейной стаьилизации
  Pgravrd(15) = 30       ''макс значение пересковов дял релейной стабилизации

Else
  Pgravrd(2) = 1       'максимальная скорость нарастания заполнения для пропорционального регулятора, фактически компенсация разорванной петли
  Pgravrd(18) = 7       'скорость сброса тяги для пропорционального регулятора
  Pgravrd(22) = 15       'размер буфера анализа симметрии чем больше тем выше мгновенная не симметрия но если слишком убавить появится низкочастотные плавания ассиметрии

  Pgravrd(8) = 2       'пропус шагов при интегральной перейтройки
  Pgravrd(5) = 3       'фильтр нтегрально стабищизатора ждёт шагов для начала перестройки
  Pgravrd(1) = 15       '% отоклонение для выхода на подводку
  Pgravrd(16) = 6       'мин значение пересковов релейной стаьилизации
  Pgravrd(15) = 40       ''макс значение пересковов дял релейной стабилизации
End If

Return

Короче вот функция стабилизации которая юзаю в качестве регулятора напряжения. Мог что то пропустить тогда выложу всё.

Да и вылетать будет только у горе разработчиков которые не учитывают быстрые процессы или выбросы индукции, вообще следует учесть что МК не справится с быстрыми процессами с которыми работают ШИМ контроллеры это нужно учитывать, например превышение тока через транзистор МК не поймает во время.

Отредактировано Rotgar (2014-05-09 12:45:13)

0

33

Размещайте код под спойлером.

0

34

Хорошо!

0

35

Rotgar написал(а):

Хорошо!


Не совсем так, но всё-таки короче.

Есть рисунок в виде книги (свёрнутый тест)

0

36

Вот еще немецкий сайт с ПИД-темой СЮДА

0

37

Как раз то, что нужно.

0

38

Курю ПИД. В этом сообщении потихоньку буду делится накопанным материалом по ПИД.
AN #109 - PID Controller

AN #109
Код:
'
' -----[ Program Description ]--------------------------------------------------
'
' This program implements an PID algorithm in BASCOM
'
' This File is partialy based on a program from ?????? and
' I do not intent to touch any of his rights !!!
' So for correct use of his copyrights please inform as marked below!
' ?????????
'
'
' -----[ Disclaimer ]-----------------------------------------------------------
'
' This example is offered on an "AS IS" basis, no warranty expressed or implied.
' The programers disclaim liability of any damages associated with the use of
' the hardware or software described herein. You use it on your own risk.
' I'm not able to provide any free support.
'
' Copyright (c) 2001 Mike Eitel all rights reserved
'
' -----[ Revision History ]-----------------------------------------------------
'
' 060529 - Version AVRPID Ver .95 Basic PID functionality Mike Eitel
'
' -----[ Aliases ]--------------------------------------------------------------
$sim ' Helps testing in a simulation
' -----[ Constant ]-------------------------------------------------------------

' -----[ Variables ]------------------------------------------------------------
 Dim Auto_mode As Bit ' Regulator on ?
 Dim Manual_value As Single ' Output if not regulating

 Dim Sp As Single ' Setpoint
 Dim Pv As Single  ' Process Value
 Dim Cv As Single ' PID output

 Dim First_execution As Byte ' First start recognition
 Dim Initial_error As Single ' Startup difference

 Dim A As Byte ' Tmp for random
 Dim B As Single ' Tmp for random

' -----[ Start of program ]-----------------------------------------------------
' -----[ Start of program ]-----------------------------------------------------
' -----[ Start of program ]-----------------------------------------------------

 Auto_mode = 1 ' Permanent running choosen
 First_execution = 0 ' Set permanent running algorithm
 Manual_value = 40 ' Output if not regulating = on
 Sp = 37 ' Value to aim to

Cyclic:
' -----[ Start of endless running program ]-------------------------------------
 Waitms 50 ' PID must run deterministic
 ' time slices
 Gosub Regulator ' Call the PID allgorithm
 Gosub Object ' Call the simulated outer loop
Goto Cyclic

 ' -----[ End of endless running program ]------------------------------------
 ' -----[ End of endless running program ]------------------------------------
 ' -----[ End of endless running program ]------------------------------------

 ' ---------------------------------------------------------------------------
 ' -----------------------------[ Subroutines ]-------------------------------
 ' ---------------------------------------------------------------------------
Object:
 ' -----[ Start of simulated regulation loop ]--------------------------------
 Pv = Pv + Cv ' linear function used

 If Pv = Sp Then  ' When PV=SP then make a
 A = Rnd(100) ' random SP jump
 Sp = 1 * A
 End If
Return

Regulator:
 ' -----[ Start of PID Regulator]---------------------------------------------
 ' -----[ Constant ]----------------------------------------------------------
 Const Kp = .85 ' Proportional factor
 Const Ki = .67 ' Integration factor
 Const Kd = .15 ' Derivation factor
 ' -----[ Variables ]---------------------------------------------------------
 'Dim Sp As Single ' Setpoint
 'Dim Pv As Single ' Process Value
 'Dim Cv As Single ' PID output
 '
 'Dim First_execution As Byte ' First start recognition
 'Dim Initial_error As Single ' Startup difference
 Dim Last_pv As Single  ' Last PV
 Dim Last_sp As Single ' Last SP
 Dim Sum_error As Single ' Summed error value
 Dim D_pv As Single ' Derrivated delta PV

 Dim Error As Single ' Difference between SP and PV
 Dim Pterm As Single ' Proportional calculated part
 Dim Iterm As Single ' Integrated calculated part
 Dim Dterm As Single ' Derivated calculated part
 ' -----[ Code ]--------------------------------------------------------------

 If Auto_mode = 1 Then
 ' -------- Regulating modus
 Error = Sp - Pv
 Sum_error = Sum_error + Error
  Iterm = Ki * Sum_error ' Integrated CV part

 ' -------- First time startup
 If First_execution < 2 Then
 If First_execution = 0 Then
 Sum_error = Manual_value / Ki
 First_execution = 1
  Initial_error = Error
 End If
 Pterm = 0
 Dterm = 0
 If Initial_error > 0 And Error < 0 Then
 First_execution = 2
 Last_pv = Pv
 End If
 If Initial_error < 0 And Error > 0 Then
 First_execution = 2
 Last_pv = Pv
 End If
 Last_sp = Sp

 ' -------- Normal calculation loop
 Else
 D_pv = Last_pv - Pv
 Last_pv = Pv
 Dterm = Kd * D_pv ' Derivated CV part
 If Sp = Last_sp Then
 ' -------- Normal loop when setpoint not changed
 Pterm = Kp * Error ' Proportional CV part
 ' -------- Loop when setpoint changed
 Else
 Pterm = 0
 Dterm = 0
 If Sp > Last_sp And Pv > Sp Then
 Last_sp = Sp
 Last_pv = Pv
 End If
 If Sp < Last_sp And Pv < Sp Then
 Last_sp = Sp
 Last_pv = Pv
 End If
 End If ' Enf of SP change seperation '
 End If ' Enf of first time running seperation  '

 Cv = Pterm + Iterm ' Summing of the tree
 Cv = Cv + Dterm ' calculated terms

 ' -------- Forced modus
 Else ' When running in non regulationg modus
 Cv = Manual_value ' Set output to predefined value
 First_execution = 0 ' restart bumpless
 End If
Return
Переделанный AN #109 c русскими комментариями
Код:
$regfile = "m8def.dat" 
$sim 

' -----[ Переменные ]------------------------------------------------------------ 
Dim Auto_mode As Bit                    ' регулировка вкл/выкл 
Dim Manual_value As Single                    ' значение без регулировки 

Dim Setpoint As Single                    ' выбранное значение 
Dim Pv As Single                    ' входное значение (то что получаем от датчиков) 
Dim Cv As Single                    ' выходное значение с PID (то что отдаем исполнительному устройству) 

Dim First_execution As Byte 
Dim Initial_error As Single 

Auto_mode = 1                    ' регулировка включена 
First_execution = 0                    ' начинает с нулевого шага 
Manual_value = 40                    ' выходное значение по умолчанию 
Setpoint = 37                    ' установкленное значение 

Do 
   Waitms 50 
   Gosub Regulator                    ' Вызов функции высчитывания ПИД алгоритма 
   Gosub Object                    ' вызов функции управлеия нагрузкой 
Loop 

End 

   ' --------------------------------------------------------------------------- 
   ' -----------------------------[ подпрограммы ]------------------------------- 
   ' --------------------------------------------------------------------------- 
Object: 
   ' -----[ Управление нагрузкой ]-------------------------------- 
   'печатаем значения переменных 
   Print "Setpoint " ; Setpoint 
   Print "Input value " ; Pv 
   Print "PID output " ; Cv 

Return 

Regulator: 
   ' -----[ ПИД регулирование]--------------------------------------------- 
   ' -----[ переменные и константы ]---------------------------------------------------------- 
   Const Kp = .85                    ' коэффициент пропорциональной корректировки 
   Const Ki = .67                    ' коэффициент интегральной корректировки 
   Const Kd = .15                    ' коэффициент дифференциальной корректировки 

   Dim Last_pv As Single 
   Dim Last_sp As Single 
   Dim Sum_error As Single                    ' значение суммированной ошибки 
   Dim D_pv As Single 

   Dim Error As Single                    ' разница между входным и установленным значениями 
   Dim Pterm As Single                    ' пропорциональная составляющая 
   Dim Iterm As Single                    ' интегральная составляющая 
   Dim Dterm As Single                    ' дифференциальная составляющая 
   ' -----[ код ]-------------------------------------------------------------- 

    If Auto_mode = 1 Then 

      Error = Setpoint - Pv 
      Sum_error = Sum_error + Error 
      Iterm = Ki * Sum_error                    ' интегральная корректировка 

            If First_execution < 2 Then 
                  If First_execution = 0 Then 
                     Sum_error = Manual_value / Ki 
                     First_execution = 1 
                     Initial_error = Error 
                  End If 
            Pterm = 0 
            Dterm = 0 
                 If Initial_error > 0 And Error < 0 Then 
                     First_execution = 2 
                     Last_pv = Pv 
                 End If 
                 If Initial_error < 0 And Error > 0 Then 
                     First_execution = 2 
                     Last_pv = Pv 
                 End If 
            Last_sp = Setpoint 

           Else 
             D_pv = Last_pv - Pv 
             Last_pv = Pv 
             Dterm = Kd * D_pv                    ' дифференциальная корректировка 
                If Setpoint = Last_sp Then 

                   Pterm = Kp * Error                         ' пропорциональная корректировка 

                 Else 
                   Pterm = 0 
                   Dterm = 0 
                     If Setpoint > Last_sp And Pv > Setpoint Then 
                        Last_sp = Setpoint 
                        Last_pv = Pv 
                     End If 
                     If Setpoint < Last_sp And Pv < Setpoint Then 
                        Last_sp = Setpoint 
                        Last_pv = Pv 
                     End If 
                End If 
            End If 

         Cv = Pterm + Iterm                    ' суммирование пропорциональной/интегральной/пропорциональной частей 
         Cv = Cv + Dterm 

        Else                    ' если регулировка отключена 
         Cv = Manual_value                    ' выставляем выходное значение по умолчанию 
         First_execution = 0 
      End If 
Return

Подробное описание ПИД

На С
Код:
// Параметры пропорционального звена
float kp = 10; // Коэффициент пропорционального звена
// Параметры интегратора
float ki = 0.001; // Коэффициент интегрального звена
#define iMin -0.2 // Минимальное значение интегратора
#define iMax 0.2 // Максимальное значение интегратора
float iSum = 0; // Сумма ошибок (значение, накопленное в интеграторе)
// Параметры дифференциатора
float kd = 1; // Коэффициент дифференциального звена
float old_y = 0; // Предыдущее значение сигнала
float PIDctl(float error, float y)
{ float up, ui, ud;
 // Пропорциональная компонента
 up = kp*error;
 // Интегральная компонента
 iSum = iSum+error; // Накапливаем (суммируем)
 if(iSum<iMin) iSum = iMin; // Проверяем граничные значение
 if(iSum>iMax) iSum = iMax;
 ui = ki*iSum;
 // Дифференциальная компонента
 ud = kd*(y-old_y);
 old_y = y;
 return up+ui+ud;
}

Статья

Вот что получается
Код:
 $regfile = "m8def.dat"
 Dim Manual_value As Single                                 ' Output if not regulating
 Dim Уставка As Single                                      ' Значение которого нужно достигнуть и поддерживать
 Dim Входная_величина_пид As Single                         ' Process Value
 Dim Выход_пид As Single                                    ' PID output
 Dim First_execution As Byte                                ' First start recognition
 Dim Initial_error As Single                                ' Startup difference
 Dim Посл_входное_знач As Single                            ' Last PV
 Dim Last_sp As Single                                      ' Last SP
 Dim Sum_error As Single                                    ' Summed error value
 Dim D_pv As Single                                         ' Derrivated delta PV
 Dim Error As Single                                        ' Difference between SP and PV
 Dim Пропорциональная_часть As Single                       ' Proportional calculated part
 Dim Интегральная_часть As Single                           ' Integrated calculated part
 Dim Диференциальная_часть As Single                        ' Derivated calculated part
DIM ШИМ as Single ' управляемый орган, например нагреватель.
 Const Kp = .1                                              ' коэффициент пропорциональной корректировки
 Const Ki = .1                                              ' коэффициент интегральной корректировки
 Const Kd = .1                                              ' коэффициент дифференциальной корректировки
'=======================Настройка ПИД===========================================
 First_execution = 0                                        ' Set permanent running algorithm
 Manual_value = 40                                          ' Output if not regulating = on
 Setpoint = 375                                              ' Значение которое должно быть достигнуто в процессе регулирования например температура
=============================================================================
do
'получаем значение к примеру температуры
Входная_величина_пид = температура
Gosub Расчитать_регулировку_пид
'выполняем регулировку в соответствии с величиной Выход_пид
ШИМ=Выход_пид
loop
'===========================ПИД регулирование===================================
Расчитать_регулировку_пид:

      Error = Уставка - Входная_величина_пид                ' разница между заданным и измеренным значением
      Sum_error = Sum_error + Error
      Интегральная_часть = Ki * Sum_error                   ' интегральная корректировка

            If First_execution < 2 Then
                  If First_execution = 0 Then
                     Sum_error = Manual_value / Ki
                     First_execution = 1
                     Initial_error = Error
                  End If
            Пропорциональная_часть = 0
            Диференциальная_часть = 0
                 If Initial_error > 0 And Error < 0 Then
                     First_execution = 2
                     Посл_входное_знач = Входная_величина_пид
                 End If
                 If Initial_error < 0 And Error > 0 Then
                     First_execution = 2
                     Посл_входное_знач = Входная_величина_пид
                 End If
            Last_sp = Уставка

           Else
             D_pv = Посл_входное_знач - Входная_величина_пид
             Посл_входное_знач = Входная_величина_пид
             Диференциальная_часть = Kd * D_pv              ' дифференциальная корректировка
                If Уставка = Last_sp Then

                   Пропорциональная_часть = Kp * Error      ' пропорциональная корректировка

                 Else
                   Пропорциональная_часть = 0
                   Диференциальная_часть = 0
                     If Уставка > Last_sp And Входная_величина_пид > Уставка Then
                        Last_sp = Уставка
                        Посл_входное_знач = Входная_величина_пид
                     End If
                     If Уставка < Last_sp And Входная_величина_пид < Уставка Then
                        Last_sp = Уставка
                        Посл_входное_знач = Входная_величина_пид
                     End If
                End If
            End If

         Выход_пид = Пропорциональная_часть + Интегральная_часть       ' суммирование пропорциональной/интегральной/пропорциональной частей
         Выход_пид = Выход_пид + Диференциальная_часть
Return
Код пропорционального регулятора
Код:
' все переменные типа single
' Kp - коэффициент пропорциональной регулировки.  подбирается для конкретной системы таким образом, чтобы заданная величина немного не достигалась. После первого разгона будет заброс после нескольких колебаний величина стабилизируется и станет чуть меньше заданной. 
Error = Уставка - Входная_величина                      'разница между заданным и измеренным значением
Выход = Kp * Error

Отредактировано Pasha (2016-05-18 12:12:41)

0

39

http://roboforum.ru/wiki/Перевод_статьи … оритмах%22

0

40

IgorL написал(а):

По теме.
Проверил сейчас схему  в железе. До 15 ампер разогнал, транзистор Q1 греется больше Q1, причем прилично больше.
ШИМ около 250 герц. ПИД регулирование тока я либо я не понял, либо оно не дает преимуществ в быстрых процессах - менял напряжение источника, ток выдерживает как при простом алгоритме усреднения, так и при ПИД. НО я облажался с контроллером, распаял mega328P а когда начал программировать выяснил, что у нее АЦП не может работать в дифференциальном режиме и отрицательные значения тока в контроллере аккумулятора при разряде я не получаю.  Пришлось воткнуть отдельно ACS712 и грубо (+- 0,1А) мерить ей. В принципе для заряда 120 Ампер/часового 12 вольтового аккумулятора точнее и не надо. 
PS В окончательной схеме решил вывести из ШИМ транзистор Q1 или вообще реле поставить, такое включение медленное. Стабилитроны отрабатывают нормально, поднимал входное напряжение до 35 вольт, ничего не вылетело!


( транзистор Q1 греется больше Q1, причем прилично больше)
Без индуктивности кпд сильно уменьшиться

0


Вы здесь » Программирование ATMEL в BASCOM. » Вопросы - ответы » ПИД регулятор тока.