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

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

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

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


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


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

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

1

Есть необходимость сделать полуавтономное питание в катере. Суть его такова, пока двигатель работает и напряжение в бортсети больше 25 вольт заряжать аккумулятор на 12 вольт 45 амперчасов максимально допустимым для него током, контролируюя максимальное напряжение и температуру, что бы не закипел. При подходе к кипению "добивать" меньшим током. Цель "забить" как можно больше амперчасов за ограниченное время. Так как ток стабилен, то несложно подсчитать "залитые" амперчасы. Далее, при разряде каждую секунду мерить ток и опять же просчитывать "вылитые" амперчасы, тем самым как то прогнозируя остаток времени работы (- 30 минут вполне устроит ). Одновременно с этим не давать аккумулятору "просесть" ниже 10 вольт на время скажем дольше 5 минут.
mega 328P думаю вполне хватит вместе с бантиками и часами. Программа тоже довольно понятная кроме стабилизатора тока. ШИМ с обратной связью дает неприятные колебания и плохо держит ток. Хочу попробовать ПИД, но я никогда не использовал его. Подскажите, есть ли какой то код примерный?

0

2

Может это поможет?

0

3

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

Может это поможет?

Запускал в симуляторе и не понял сути. :(
Где там обратная связь? Надо функцию свою составить? Pv в моем случае это значение ADC ? 
Cv это значение ШИМ (PWM1A)? К каким единицам их нужно приводить? В общем не понял я, примерчик реализации бы. :)

0

4

Вечером могу выложить пример. Когда то делал ПИД для стабилизации и поддержания скорости.

0

5

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

Вечером могу выложить пример. Когда то делал ПИД для стабилизации и поддержания скорости.

Хорошо бы!

0

6

Добрый вечер!
Выкладываю так как есть.
Код писал по примеру ПИД РЕГУЛЯТОР ДЛЯ КОЛЛЕКТОРНОГО ДВИГАТЕЛЯ .
Все достаточно примитивно , поддерживал  скорость вращения вала двигателя . Управления производилось 4 кнопками   ПУСК, СТОП, +200 оборотов , - 200 оборотов.
В начале измеряем скорость датчиком , затем производим расчет разницы заданной и реальной скорости , вычисляем сигнал коррекции и записываем его в регистр сравнения PWM.
Отвечу на вопросы.

Код:
$regfile = "m8adef.dat"
$crystal = 8000000
$framesize = 32
$hwstack = 40
$swstack = 16

 Config Lcd = 16 * 2
 Config Lcdpin = Pin , Db4 = Portd.6 , Db5 = Portc.1 , Db6 = Portc.0 , Db7 = Portd.2 , E = Portd.1 , Rs = Portd.0


  Config Portb.1 = Output
  Config Pinc.2 = Input
  Config Pinc.3 = Input
  Config Pinc.4 = Input
  Config Pinc.5 = Input
  Config Adc = Single , Prescaler = 8 , Reference = Aref
  Config Timer1 = Pwm , Prescale = 8 , Compare A Pwm = Clear Up

 ' ------------------------------------------[ Переменные ]---------------------------


   Const Kp = .8                                            ' коэффициент пропорциональной корректировки
   Const Ki = .55                                           ' коэффициент интегральной корректировки
   Const Kd = .15                                           ' коэффициент диференциальной корректировки

 Dim Pv As Single                                           ' входное значение (то что получаем от датчиков)
 Dim Cv As Single                                           ' выходное значение с PID (то что отдаем исполнительному устройству)
 Dim Count As Word                                          ' значения регистра сравнения ШИМ
 Dim Error As Single                                        ' разница между входным и установленным значениями
 Dim Pterm As Single                                        ' пропорциональная составляющая
 Dim Sum_error As Single                                    ' значение суммированной ошибки
 Dim Last_pv As Single                                      ' последние входное значение
 Dim D_pv As Single                                         ' ошибка между прошлым входным и входным етого фремени
 Dim Iterm As Single                                        ' интегральная составляющая
 Dim Dterm As Single                                        ' диференсиальная  составляющая
 Dim W As Word                                              'значение АЦП в битах
 Dim M1 As Single                                           'перевод значения АЦП в реальное показание
 Dim Setpoint As Single                                     ' значения установленой скорости
 Dim S As Byte
 Dim Q As Byte                                              ' Флаг для еденичного выключения  таймере
 Dim Q1 As Byte                                             ' Флаг для еденичного включения таймере
 Dim Skor_zad As Word                                       ' скорость заданая  в оборотах на дисплей
 Dim Skor_real As Word                                      ' скорость в оборотах реальная  на диспле
 Config Single = Scientific , Digits = 1

 Sum_error = 0

 Last_pv = 0

  Setpoint = 1

  S = 1

  Q = 0
  Count = 100
  Q1 = 0
 Do

   If Pinc.4 = 0 Then
    Waitms 100

    Setpoint = Setpoint + 0.1

     End If

     If Pinc.5 = 0 Then
      Waitms 100

     Setpoint = Setpoint - 0.1

      End If

     If Setpoint > 7 Then Setpoint = 7
     If Setpoint < 1 Then Setpoint = 1

    If Pinc.2 = 0 Then
     Waitms 100

     S = S + 1

      End If

     If Pinc.3 = 0 Then
      Waitms 100

     S = S - 1

      End If


     If S > 2 Then S = 2
     If S < 1 Then S = 1

 '__________________________Пуск (ВКЛ)  __________________________________________

     If S = 2 Then

  Decr Q

    If Q > 2 Then Q = 2


    If Q = 1 Then

   Config Timer1 = Pwm , Prescale = 8 , Compare A Pwm = Clear Up
   End If

'__________________Вызов функции высчитывания датчиков скорости ______________


    Gosub Speed

'__________________Вызов функции высчитывания ПИД алгоритма ___________________

   Gosub Regulator

'__________________Вызов функции управления нагрузкой  __________________________

    Gosub Object

    End If

'_________________________Остановка (ВЫКЛ)  _________________________

    If S = 1 Then

    Decr Q1

   If Q1 > 2 Then Q1 = 2


    If Q1 = 1 Then

  Config Timer1 = Timer , Prescale = 8 , Compare A = Disconnect , Clear Timer = 0

   Stop Timer1
   Stop Adc
    Sum_error = 0
    Last_pv = 0
    Cv = 0
    Pv = 0
    Q = 0
   Q1 = 0
   Pwm1a = 0

  Skor_real = 0

 End If

 End If


'_________________Вивод на дисплей  _______________________________________

Skor_zad = Setpoint * 214

Skor_real = Pv * 214

   Locate 1 , 1                                             ' позиция курсора
   Lcd "n_z=" ; Skor_zad ; "  "                             ' вызов функции управлеия нагрузкой
   Locate 2 , 1                                             ' позиция курсора
   Lcd "n_r=" ; Skor_real ; " "

 Loop

 End



   ' ---------------------------------------------------------------------------
   ' -----------------------------[ подпрограммы ]-------------------------------
   ' ---------------------------------------------------------------------------


  Object:
   ' -----[ Управление нагрузкой ]--------------------------------

     Start Timer1
    Pwm1a = Count

  Return




  ' -------------------------[ ПИД регулирование]-------------------------------

  Regulator:





' __________________интегральная корректировка________________________________

       Error = Setpoint - Pv

       Sum_error = Sum_error + Error

       Iterm = Ki * Sum_error


'_____________________пропорциональная корректировка __________________________


      Pterm = Kp * Error


'_____________________дифференциальная корректировка___________________________

       D_pv = Last_pv - Pv

       Last_pv = Pv

      Dterm = Kd * D_pv


'_____суммирование пропорциональной/интегральной/пропорциональной частей _____

          Cv = Pterm + Iterm
          Cv = Cv + Dterm


           Count = Cv

           If Count > 254 Then Count = 254
           If Count < 1 Then Count = 1

    Return


   Speed:

' -------------------------Измерение скорости-------------------------------

 Start Adc

 W = Getadc(7)

 M1 = W * 137

M1 = M1 / 10000

 Pv = M1

 Return

0

7

Вот пример с сайта :

Код:
' -----[ 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

Пид-регулятор температуры с польского сайта :

Код:
Config Portc = Output
Config Portd = Input
Config Portb = Output

Sett Alias Pind.7
Minus Alias Pind.6
Plus Alias Pind.5



Config Lcdpin = Pin , Db4 = Portb.5 , Db5 = Portb.4 , Db6 = Portb.3 , Db7 = Portb.2 , E = Portc.0 , Rs = Portc.1

Config Lcd = 16 * 2
Cursor Off

Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Disconnect , Prescale = 64

Config Timer0 = Counter , Edge = Falling


'ds18b20

Config 1wire = Portd.1                                      ' Wr ds18b20
Dim I As Integer                                            'zmienne do odczytu temp.
Dim Tr As Single
Dim T As String * 4
Dim Trold As Single
Dim Licznik As Byte



Dim Tz As Single
'Dim Tot As Single
                                         'temperatura zadana
Dim Tstr As Single , Tstr2 As Single ,

Dim E As Single
'Dim Eczek As Single , Eczekp As Single , Eczekm As Single


                                           'uchyb
Dim Eold As Single

Dim Sp As Single , Sr As Single , Si As Single              ' wspуіczynniki Pid

Dim Kp As Integer , Kd As Integer , Ki As Integer           ' parametry

Dim Ei As Single , Er As Single , Ss As Single

Dim Hist_proc As Byte , H As Single

Dim Tab(9) As Byte , Crc As Byte



'Dim Z As Byte


Dim Menuu As Byte

''''''
'zmiennne
''''''

Dim W As Word , Pwm As Word , Pwm_proc As Single


Deflcdchar 0 , 31 , 31 , 31 , 31 , 31 , 31 , 31 , 31

Deflcdchar 1 , 6 , 9 , 6 , 32 , 32 , 32 , 32 , 32           ' znak stopnia
Deflcdchar 2 , 14 , 14 , 14 , 31 , 31 , 14 , 4 , 32         ' dуі
Deflcdchar 3 , 32 , 4 , 14 , 31 , 14 , 14 , 14 , 32         ' gуra
Deflcdchar 4 , 32 , 4 , 14 , 31 , 31 , 31 , 14 , 4          ' kolko






'''''''''''
'Deklaracje Procedur
''''''''

Declare Sub Pid
Declare Sub Menu
Declare Sub Odczyt
Declare Sub Ustaw_temp
Declare Sub Ustaw_k
Declare Sub Reseteeprom
Declare Sub Dwustan
Declare Sub Wymuszenie
Declare Sub Menu_dwustan



''''''''''


Enable Interrupts
Enable Timer0
Enable Timer1
Enable Int1



Cls


 'zmiana na 9bit'

   1wreset
   1wwrite &HCC
   1wwrite &H4E
   1wwrite 1
   1wwrite 1
   1wwrite 31






Tz = 30
Kp = 10
Kd = 2
Ki = 5
Licznik = 0






Set Portd.7
Set Portd.6
Set Portd.5

Menuu = 1


Cls
Lcd " Regulator  PID"
Wait 3
Cls
Lcd "    Wykonal:"
Wait 1
Cls
Lcd "      Piotr"
Locate 2 , 1
Lcd "   Ludwikowski"
Wait 3
Call Menu



              '''''''''''''''''''''''''''''''''''''''''''''''''




Sub Pid
Ei = 0

Waitms 100
Cls
Do
Reset Portb.0

Odczyt



      E = Tz - Tr









Locate 1 , 1
Lcd "Wr:"
Lcd Tr
Locate 1 , 8
Lcd " "
Locate 2 , 1
Lcd "Wz:"
Lcd Tz
Locate 2 , 8
Lcd " "
Locate 1 , 5

Locate 1 , 9
Lcd "E:"
Lcd E
Lcd "   "

                    'wyliczanie uchybu i czіonуw P I D





E = E * -1                                                  'inwersja



Sp = E * Kp                                                 'proporcjonalny

Er = Eold - E                                               'rуїniczkuj№cy
Sr = Er * Kd

If Si > 0 Or E > 0 Then

If Si < 255 Or E < 0 Then
Ei = Ei + E

End If

End If












Si = Ei * Ki                                                ' caіkuj№cy


If Si > 255 Then
Si = 255
End If

Eold = E

Ss = Sp + Sr
Ss = Ss + Si


If Ss > 255 Then
Ss = 255
End If
If Ss < 0 Then
Ss = 0
End If






 E = E * -1                                                 'aby wyњwietlaіo rzeczywisty



Pwm = Round(ss)
Pwm1a = Pwm

Pwm_proc = Pwm / 2.55
Pwm_proc = Round(pwm_proc)



Locate 2 , 9
Lcd "PWM:"
Lcd Pwm_proc

Shiftcursor Left
Shiftcursor Left
Lcd "%  "





If Sett = 0 Then
Call Menu
End If

If Plus = 0 Then
Cls
Lcd "Si:"
Lcd Si

Locate 2 , 1
Lcd "Sr:"
Lcd Sr

Locate 2 , 9
Lcd "Sp:"
Lcd Sp

Wait 2
End If


If Minus = 0 Then
Si = 0
Ei = 0
End If





Loop

End Sub Pid


           '''''''''''''''''''''''''''''''''''''''''''''''''


Sub Odczyt                                                  'odczyt temp


 '  If Licznik = 0 Then:

   1wreset
   1wwrite &HCC
   1wwrite &H44

'   End If

   Waitms 95

  ' Incr Licznik

  ' If Licznik = 7 Then

   1wreset
   1wwrite &HCC
   1wwrite &HBE
   Tab(1) = 1wread(9)

   If Tab(9) = Crc8(tab(1) , 8) Then

         I = Makeint(tab(1) , Tab(2))
         Tr = I
         Tr = Tr / 16

   T = Fusing(tr , "##.#")
 '  End If
  ' Licznik = 0
   End If




End Sub Odczyt


          '''''''''''''''''''''''''''''''''''''''''''''''''

Sub Menu
Pwm1a = 0


Waitms 200
Cls

'znaki gуra/dуі/ok
Locate 2 , 1
Lcd Chr(3)
Locate 2 , 8
Lcd Chr(2)
Locate 2 , 15
Lcd "OK"



Do
Locate 1 , 1
Select Case Menuu
Case Is = 1
Lcd "1.Ustaw Wz      "
Case Is = 2
Lcd "2.Ustaw Kp,Kd,Ki"
Case Is = 3
Lcd "3.R. Dwustanowa "
Case Is = 4
Lcd "4.R. PID        "
Case Is = 5
Lcd "5.Reset         "
Case Is = 6
Lcd "6.Wym.skokowe   "
End Select

If Plus = 0 And Menuu < 6 Then
Incr Menuu
Waitms 222
End If

If Plus = 0 And Menuu = 6 Then
Menuu = 1
Waitms 222
End If

If Minus = 0 And Menuu > 1 Then
Decr Menuu
Waitms 222
End If

If Minus = 0 And Menuu = 1 Then
Menuu = 6
Waitms 222
End If




If Sett = 0 And Menuu = 4 Then
Call Pid
End If


If Sett = 0 And Menuu = 1 Then
Call Ustaw_temp
End If

If Sett = 0 And Menuu = 2 Then
Call Ustaw_k
End If


If Sett = 0 And Menuu = 5 Then
Call Reseteeprom
End If

If Sett = 0 And Menuu = 3 Then
Call Dwustan
End If

If Sett = 0 And Menuu = 6 Then
Call Wymuszenie
End If

Loop

End Sub Menu


       '''''''''''''''''''''''''''''''''''''''''''''''''

Sub Ustaw_temp
Waitms 200
Cls
Lcd "Wz:"
Locate 2 , 1
Lcd "+       -     OK"

While Sett = 1

Locate 1 , 8
Lcd Tz

If Plus = 0 Then
Tz = Tz + 0.5
Waitms 66
End If

If Minus = 0 Then
Tz = Tz - 0.5
Waitms 66
End If


Wend

Call Menu


End Sub Ustaw_temp



  '''''''''''''''''''''''''''''''''''''''''''''''''



Sub Ustaw_k
                              'ustaw Kp
Cls
Lcd "Kp:"
Locate 2 , 1
Lcd "+       -     OK"
Waitms 200
While Sett = 1
Locate 1 , 8
Lcd Kp
Lcd "   "
If Plus = 0 Then
Incr Kp
Waitms 66
End If
If Minus = 0 And Kp > 0 Then
Decr Kp
Waitms 66
End If
Wend

                              'ustaw Kd
Cls
Lcd "Kd:"
Locate 2 , 1
Lcd "+       -     OK"
Waitms 200
While Sett = 1
Locate 1 , 8
Lcd Kd
Lcd "   "
If Plus = 0 Then
Incr Kd
Waitms 66
End If
If Minus = 0 And Kd > 0 Then
Decr Kd
Waitms 66
End If
Wend

                              'ustaw Ki
Cls
Waitms 200
Lcd "Ki:"
Locate 2 , 1
Lcd "+       -     OK"
Waitms 333
While Sett = 1
Locate 1 , 8
Lcd Ki
Lcd "   "
If Plus = 0 Then
Incr Ki                                                     'Ki = Ki + 0.25
Waitms 66
End If
If Minus = 0 And Ki > 0 Then
Decr Ki                                                     'Ki = Ki - 0.25
Waitms 66
End If
Wend

Call Menu


End Sub Ustaw_temp

        '''''''''''''''''''''''''''''''''''''''''''''''''

Sub Reseteeprom
Cls
Waitms 200
Lcd "Reset?          "
Locate 2 , 1
Lcd "TAK          NIE"

While Plus = 1
If Sett = 0 Then
Call Pid
Waitms 66
End If
Wend

Cls
Lcd "Zapisuje"


Tz = 30
Kp = 10
Kd = 2
Ki = 5



Call Menu

End Sub Reseteeprom

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


Sub Dwustan
Cls
Waitms 222

Do
Odczyt

Locate 1 , 1
Lcd "Wr:"
Lcd T
Lcd "  "
Locate 1 , 10
Lcd "Wz:"
Lcd Tz

Locate 2 , 1
Lcd "+       -      M"

If Plus = 0 Then
Tz = Tz + 0.5
Waitms 66
End If

If Minus = 0 Then
Tz = Tz - 0.5
Waitms 66
End If

If Sett = 0 Then
Call Menu_dwustan
End If

H = Tz * Hist_proc
H = H / 100

Tz = Tz + H

If Tr > Tz Then
Pwm1a = 255
End If


Tz = Tz - H
Tz = Tz - H


If Tr < Tz Then
Pwm1a = 0
End If

Tz = Tz + H




Loop


End Sub Dwustan


''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''


Sub Wymuszenie
Cls



Waitms 333
Lcd "Wr: "
Locate 1 , 9
Lcd "PWM: "
Locate 2 , 12
Lcd "Start"


While Sett = 1
Odczyt

If Plus = 0 And Pwm_proc < 100 Then
Incr Pwm_proc
'Waitms 66
End If

If Minus = 0 And Pwm_proc > 0 Then
Decr Pwm_proc
'Waitms 66
End If



Locate 1 , 13

Lcd Pwm_proc ; "%"

Shiftcursor Left
Shiftcursor Left
Shiftcursor Left
Lcd "%  "

Locate 1 , 4
Lcd Tr

Wend
Pwm = Pwm_proc * 2.55



Pwm1a = Pwm
Locate 2 , 12
Lcd " Stop"
Waitms 333
Do
Odczyt
Locate 1 , 4
Lcd T
If Sett = 0 Then
Call Menu
End If
Loop






End Sub Wymuszenie


'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
Sub Menu_dwustan
Cls
Lcd "Histereza   Menu"
Locate 2 , 2
Lcd Chr(4)
Locate 2 , 15
Lcd Chr(4)
Waitms 333
While Plus = 1
If Sett = 0 Then
Call Menu
End If
Wend

Cls

Waitms 333

Lcd "Histereza: "
Locate 2 , 1
Lcd "+       -     OK"

Do
Locate 1 , 12
Lcd Hist_proc ; "%  "
If Plus = 0 And Hist_proc < 100 Then
Incr Hist_proc
Waitms 66
End If

If Minus = 0 And Hist_proc > 0 Then
Decr Hist_proc
Waitms 66
End If

If Sett = 0 Then
Call Dwustan
End If


Loop


End Sub Menu_dwustan

Общий пример :

Код:
            '
' -----[ 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

Для двух моторов с энкодерами :

Код:
  $regfile = "m32def.dat"
$crystal = 18432000  'over clocked CPU
$baud = 115200
$hwstack = 64
$swstack = 64
$framesize = 64
'-------------------------------------------------------------------------------
Const Si = 1
Const No = 0
Const Vb6 = No 'YES PER USARE LA SERIALE CON Visual Basic 6
' 'NO PER TERMINAL WINDOWS
'-------------------------------------------------------------------------------
'------------------- SUBROUTINE ------------------------------------------------
'-------------------------------------------------------------------------------
Declare Sub Hctl_2032(byval Mot As Byte)
Declare Sub Exe_pid(byval Mot As Byte , Byval Pid_setpoint As Long , Byval Pid_actual As Long)
Declare Sub Configura_pid(byval M As Byte , Byval Mot_kp As Long , Byval Mot_ki As Long , Byval Mot_kd As Long)
Declare Sub Init_parameter(byval M As Byte)
Declare Sub Calcola_trapezio(byval M As Byte)
Declare Sub Make_print(byval Mt As Byte , Byval Stringa As String , Byval Valore As Long)
Declare Sub Set_mode(byval Mode_control As Byte)
'-------------------------------------------------------------------------------
'------------------- CONFIGURAZIONI --------------------------------------------
'-------------------------------------------------------------------------------
'configuriamo il timer1 per pwm a 8 bit a freq = 565 hz con xtal=18mhz e prescale=1
'abbiamo  (18432000 / 256 = 72 Khz) (72 K / presc = 72 K) (72 K/2 pwm = 36 Khz)
'-------------------------------------------------------------------------------
Config Watchdog = 16
Stop Watchdog
Config Int0 = Falling
Config Int1 = Falling
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 1 '36.2 Khz pwm
Config Timer0 = Timer , Prescale = 64 '
On Timer0 Timer_0 '
On Int1 Int_1  '
On Int0 Int_0 '
On Urxc Rs232 '
Enable Timer0 'handler seriale
Enable Urxc  'abilita seriale
Enable Int0 'fine corsa motore 1
Enable Int1 'fine corsa motore 2
Enable Interrupts  'abilita tutti interrupts
'------------------- ALIAS -----------------------------------------------------
 Motor_pwm_1 Alias Pwm1a : Motor_pwm_1 = 0 'pwm out motore x
 Motor_pwm_2 Alias Pwm1b : Motor_pwm_2 = 0 'pwm out motore y
 Ddrd.2 = 0 : Portd.2 = 1 'pullup x int 0
 Ddrd.3 = 0 : Portd.3 = 1 'pullup x int 1
 Fc2_1 Alias Pinb.0 : Ddrb.0 = 0 'limit 1
 Fc2_2 Alias Pinb.1 : Ddrb.1 = 0 'limit 2
 Aux_0 Alias Pinb.2 : Ddrb.2 = 0 : Portb.2 = 1 'pullup aux per indirizzo scheda
 Aux_1 Alias Pinb.3 : Ddrb.3 = 0 : Portb.3 = 1 'pullup aux per indirizzo scheda
 Smt_1 Alias Portb.4 : Ddrb.4 = 1 'stato motore 1
 Smt_2 Alias Portc.6 : Ddrc.6 = 1 'stato motore 2
 Motor_dir_1 Alias Portd.6 : Ddrd.6 = 1 'direzione motore x
 Motor_dir_2 Alias Portd.7 : Ddrd.7 = 1 'direzione motore y
 Motor_led Alias Portc.7 : Ddrc.7 = 1 'led test
 Hctl_xy Alias Portc.0 : Ddrc.0 = 1 'selezione xy hctl2032
 Hctl_sel1 Alias Portc.1 : Ddrc.1 = 1 'selezione byte bit 0
 Hctl_sel2 Alias Portc.2 : Ddrc.2 = 1 'selezione byte bit 1
 Hctl_oe Alias Portc.3 : Ddrc.3 = 1 'selezione oe hctl data
 Hctl_rst_1 Alias Portc.4 : Ddrc.4 = 1 'reset encoder x
 Hctl_rst_2 Alias Portc.5 : Ddrc.5 = 1 'reset encoder y
 Hctl_data Alias Pina : Ddra = &H00 'porta input data encoder
'-------------------------------------------------------------------------------
Hctl_xy = 0 'seleziona encoder x
Hctl_sel1 = 0 'selezione primo byte msb
Hctl_sel2 = 1  'seleziona primo byte msb
Hctl_oe = 1 'no output enable
Hctl_rst_1 = 1 'no reset
Hctl_rst_2 = 1 'no reset
'---------------------------- COSTANTI -----------------------------------------
Const Mode_pos = 0
Const Mode_vel = 1
Const Mode_trp = 2
Const Mode_velp = 3
Const Mode_idle = 4
Const True = 1
Const False = 0
'---------------------- VARIABILI ----------------------------------------------
Dim Pid_kp(2) As Long
Dim Pid_ki(2) As Long
Dim Pid_kd(2) As Long
Dim Pid_scale(2) As Long
Dim Pid_prev_error(2) As Long
Dim Pid_integral_error(2) As Long
Dim Pid_error(2) As Long
Dim Ptemp(2) As Long
Dim Motore_setpoint(2) As Long
Dim Pid_out(2) As Long 'valore da assegnare a pwm
Dim Data_1 As Byte 'hctl used
Dim Data_2 As Byte 'hctl used
Dim Data_3 As Byte 'hctl used
Dim Data_4 As Byte 'hctl used
Dim Timer_pid As Byte 'sample timer pid
Dim Pos_encoder(2) As Long 'encoder position
Dim Old_encoder(2) As Long 'prewius encoder position
Dim New_speed(2) As Long 'velocita in ingresso pid
Dim Act_speed(2) As Long 'velocita attuale
Dim Acc_speed(2) As Long 'velocita accelerazione
Dim Pos_finale(2) As Long 'posizione trapezoidale finale
Dim Temp_enc As Long 'temp encoder position
Dim Comando As String * 30
Dim Comando_old As String * 30
Dim Char(20) As Byte
Dim Idt As Byte : Idt = 1
Dim N_cmd As Byte
Dim Cmd_ar(5) As String * 10
Dim Mode_ctrl As Byte 'mode control
Dim Mot_kp As Long
Dim Mot_ki As Long
Dim Mot_kd As Long
Dim Vel_pos(2) As Long
Dim Vel_neg(2) As Long
Dim Vel_last(2) As Long
Dim Rpwm(2) As Byte
Dim Fattore_acc(2) As Long
Dim Punto_p1(2) As Long
Dim Dir_diff(2) As Byte
Dim Diff_posizione(2) As Long
Dim Trap_1(2) As Long
Dim Trap_2(2) As Long
Dim New_encoder(2) As Long
Dim Deg(2) As Single
Dim Rad(2) As Single
Dim Vel_max(2) As Single
Dim Diff_2(2) As Long
Dim Max_pwm(2) As Byte
Dim Mot As Byte
Dim M As Byte
Dim Start_move As Bit
Dim Tx_enable As Bit
Dim Str_tx_1 As String * 20
Dim Flag_velocita As Bit
Dim Somma As Long
Dim Vmax_pos(2) As Long
Dim Vmax_neg(2) As Long
Dim Fattore_ang(2) As Long 'fattore angolare 0-99
Dim Differenza(2) As Long 'differenza
Dim Acc_speed_p(2) As Long 'accelerazione positiva x controllo velocita
Dim Acc_speed_n(2) As Long 'accelerazione negativa x controllo velocita
Dim Pid_time As Byte 'tempo max pid overflow
Dim Num_smt(2) As Byte 'numero di volte lettura motore fermo
'-------------------------------------------------------------------------------
Call Init_parameter(1)
Call Init_parameter(2)
Call Configura_pid(1 , 500 , 100 , 500) 'configura pid iniziale
Call Configura_pid(2 , 500 , 100 , 500) 'configura pid iniziale
'...................P....I......D
Print "(0 Motor Control by G.De Luca V1.0, 0)"
'-------------------------------------------------------------------------------
'---------------------- MAIN PROGRAM -------------------------------------------
'-------------------------------------------------------------------------------
Main:
Do
 If Tx_enable = 1 Then 'permetti la trasmissione
 Tx_enable = 0
 Print Str_tx_1 'trasmetti la stringa
 End If
 '.....qui controlliamo i fine corsa 2 dei motori
Loop
'-------------------------------------------------------------------------------
End
'-------------------------------------------------------------------------------
Int_0: 'fine corsa 1 motore 1
 Call Configura_pid(1 , 0 , 0 , 0)
 Print "(1 FCM, 1)"
Return
'-------------------------------------------------------------------------------
Int_1: 'fine corsa 1 motore 2
 Call Configura_pid(2 , 0 , 0 , 0)
 Print "(2 FCM, 1)"
Return
'-------------------------------------------------------------------------------
'---------------------- GESTIONE SERIALE ---------------------------------------
'-------------------------------------------------------------------------------
Rs232:
 #if Vb6
 Input Comando Noecho 'se usato con vb6
 #else
 Char(1) = Inkey() 'se usato con terminal
 Char(1) = Ucase(char(1))
 If Char(1) = Chr(13) Then
 Print
 #endif
 '...........................................................................
 If Comando = "" Then Comando = Comando_old
 N_cmd = Split(comando , Cmd_ar(1) , " ")
 M = Val(cmd_ar(2))
 '......................................................................
 Select Case Cmd_ar(1)
 Case "RSTF"
 Print "(0 RST Program, 0)"
 Start Watchdog
 '..........................................................
 Case "MADE"
 Print "(0 De Luca Giovanni, 0)"
 '..........................................................
 Case "VER"
 Print "(0 Ver 2.0 DEL 22-05-07, 0)"
 '..........................................................
 Case "SKP"
 Pid_kp(m) = Val(cmd_ar(3))
 Print "(" ; M ; " SKP, " ; Pid_kp(m) ; ")"
 '..........................................................
 Case "SKI"
 Pid_ki(m) = Val(cmd_ar(3))
 Print "(" ; M ; " SKI, " ; Pid_ki(m) ; ")"
 '..........................................................
 Case "SKD"
 Pid_kd(m) = Val(cmd_ar(3))
 Print "(" ; M ; " SKD, " ; Pid_kd(m) ; ")"
 '..........................................................
 Case "GO" 'vai in controllo posizione
 If Mode_ctrl <> Mode_pos Then 'se mode <> da pos
 Call Set_mode(mode_pos) 'setta a pos
 End If
 M = Val(cmd_ar(2))
 Pos_finale(m) = Val(cmd_ar(3))
 Print "(" ; M ; " GO, " ; Pos_finale(m) ; ")"
 '..........................................................
 Case "VMAX"
 Vmax_pos(m) = Val(cmd_ar(3))
 Vmax_neg(m) = -vmax_pos(m)
 Print "(" ; M ; " VMAX, " ; Vmax_pos(m) ; ")"
 '..........................................................
 Case "GMAX"
 Print "(" ; M ; " GMAX, " ; Vmax_pos(m) ; ")"

 '..........................................................
 Case "SVM" 'set max velocita in trp
 Vel_pos(m) = Val(cmd_ar(3))
 Vel_last(m) = Vel_pos(m)
 Vel_neg(m) = -vel_pos(m)
 Print "(" ; M ; " SVM, " ; Vel_pos(m) ; ")"
 '..........................................................
 Case "GVM"
 Print "(" ; M ; " GVM, " ; Vel_pos(m) ; ")" 'get max velocita impostata
 '..........................................................
 Case "GVE"
 Tx_enable = 1
 Call Make_print(m , Cmd_ar(1) , Act_speed(m))
 '..........................................................
 Case "ENC"
 Tx_enable = 1
 Call Make_print(m , Cmd_ar(1) , Pos_encoder(m))
 '..........................................................
 Case "SPID" 'set pid parameter
 Pid_kp(m) = Val(cmd_ar(3))
 Pid_ki(m) = Val(cmd_ar(4))
 Pid_kd(m) = Val(cmd_ar(5))
 Print "(" ; M ; " SPID, " ; Pid_kp(m) ; " " ; Pid_ki(m) ; " " ; Pid_kd(m) ; ")"
 '..........................................................
 Case "GPID" 'get pid parameter
 Print "(" ; M ; " GPID, " ; Pid_kp(m) ; " " ; Pid_ki(m) ; " " ; Pid_kd(m) ; ")" 'get pid parameter
 '..........................................................
 Case "STIME"
 Pid_time = Val(cmd_ar(2))
 Print "(" ; 0 ; " STIME, " ; Pid_time ; ")"
 '..........................................................
 Case "GTIME"
 Print "(" ; 0 ; " GTIME, " ; Pid_time ; ")"
 '..........................................................
 Case "SZP" 'set zero position
 Select Case M
 Case 1
 Hctl_rst_1 = 0
  Waitms 1
 Hctl_rst_1 = 1

 Case 2
 Hctl_rst_2 = 0
 Waitms 1
 Hctl_rst_2 = 1
 End Select
 Pos_encoder(m) = 0
 Old_encoder(m) = 0
 Motore_setpoint(m) = 0
 Pos_finale(m) = 0
 New_speed(m) = 0
 Call Hctl_2032(m)
 Print "(" ; M ; " SZP, " ; Pos_encoder(m) ; ")"
 '..........................................................
 Case "IDLE" 'metti in idle e disalimenta
 Call Configura_pid(m , 0 , 0 , 0)
 Print "(" ; M ; " IDLE, )"
 '..........................................................
 Case "GSM" 'get stato motore
 If Act_speed(m) > 3 Or Act_speed(m) < -3 Then
 Tx_enable = 1
 Call Make_print(m , Cmd_ar(m) , 1) 'qui si muove
 Else
 Tx_enable = 1
 Call Make_print(m , Cmd_ar(m) , 0) 'qui č fermo
 End If
 '..........................................................
 Case "SMODE" 'set mode control
 Mode_ctrl = Val(cmd_ar(3))

 Select Case Mode_ctrl
 Case Mode_pos
 Call Configura_pid(m , 200 , 0 , 200) 'POSIZIONE 0
  Motore_setpoint(m) = Pos_encoder(m)

 Case Mode_vel
 Call Configura_pid(m , 700 , 100 , 700) 'VELOCITA integrale 1

 Case Mode_trp
 Call Configura_pid(m , 500 , 100 , 500) 'TRAPEZOIDALE 2
 Pos_finale(m) = Pos_encoder(m)

 Case Mode_velp
 Call Configura_pid(m , 100 , 10 , 100) 'VELOCITA proporzionale 3

 Case Mode_idle
 Call Configura_pid(m , 0 , 0 , 0) 'IDLE 4
 End Select
 Print "(0 MODE, " ; Mode_ctrl ; ")"
 '..........................................................
 Case "MODE"
 Mode_ctrl = Val(cmd_ar(2)) 'tipo di controllo
 Call Set_mode(mode_ctrl)
  Print "(0 MODE, " ; Mode_ctrl ; ")"
 '..........................................................
 Case "GMODE" 'get mode control
 Print "(0 GMODE, " ; Mode_ctrl ; ")"
 '..........................................................
 Case "SVEL" 'set velocita in vel mode
 If Mode_ctrl <> Mode_vel Then 'se mode <> da trapezoidale
 Call Set_mode(mode_vel)
 End If
 Motore_setpoint(m) = Val(cmd_ar(3)) 'valori -127 +127
 Print "(" ; M ; " SVEL, " ; Motore_setpoint(m) ; ")"
 '..........................................................
 Case "VELO"
 If Mode_ctrl <> Mode_vel Then 'se mode <> da trapezoidale
 Call Set_mode(mode_vel)
 End If
 Motore_setpoint(1) = Val(cmd_ar(2)) 'valori -127 +127
 Motore_setpoint(2) = Val(cmd_ar(3))
 '..........................................................
  Case "SPWM" 'max pwm per regolare la coppia massima
 Max_pwm(m) = Val(cmd_ar(3))
 Print "(" ; M ; " SPWM, " ; Max_pwm(m) ; ")"
 '..........................................................
 Case "GPWM" 'get pwm massimo
 Print "(" ; M ; " GPWM, " ; Max_pwm(m) ; ")"
 '..........................................................
 Case "RPWM" 'get valore pwm uscita
 Print "(" ; M ; " RPWM, " ; Rpwm(m) ; ")"
 '..........................................................
  Case "SACC"
 Deg(m) = Val(cmd_ar(3))
 Rad(m) = Deg2rad(deg(m))
 Rad(m) = Tan(rad(m))
 Vel_max(m) = Vel_pos(m) * 10
 Punto_p1(m) = Vel_max(m) / Rad(m)
 Punto_p1(m) = Punto_p1(m) * 10
 Print "(" ; M ; " SACC, " ; Deg(m) ; ")"
 '... Print "P1: " ; Punto_p1(m)
 '..........................................................
 Case "GACC" 'calcola pendenza accelerazione
 Print "(" ; M ; " GACC, " ; Deg(m) ; ")"
 '..........................................................
 Case "SANG" 'imposta fattore angolare
 Fattore_acc(m) = Val(cmd_ar(3))
 Print "(" ; M ; " SANG, " ; Fattore_acc(m) ; ")"
 '..........................................................
 Case "GANG" 'leggi fattore angolare
 Print "(" ; M ; " GANG, " ; Fattore_acc(m) ; ")"
 '..........................................................
 Case "POS"
 If Mode_ctrl <> Mode_trp Then 'se mode <> da trapezoidale
 Call Set_mode(mode_trp)
 End If
  Pos_finale(m) = Val(cmd_ar(3))
 Vel_pos(m) = Val(cmd_ar(4))
 Call Calcola_trapezio(m)
 Start_move = True
 '..........................................................
 Case "MOVE"
 If Mode_ctrl <> Mode_trp Then 'se mode <> da trapezoidale
 Call Set_mode(mode_trp)
 End If
  Pos_finale(1) = Val(cmd_ar(2))
 Pos_finale(2) = Val(cmd_ar(3))
 Vel_pos(1) = Val(cmd_ar(4))
 Vel_pos(2) = Val(cmd_ar(4))
 Call Calcola_trapezio(1)
 Call Calcola_trapezio(2)
 Print "(0 MOVE, " ; Pos_finale(1) ; " " ; Pos_finale(2) ; ")"
 'Start_move = False 'se si vuole avviare con start
 '..........................................................
 Case "VELP"
 If Mode_ctrl <> Mode_velp Then 'se mode <> da velocita
 Call Set_mode(mode_velp)
 End If
  Acc_speed_p(1) = Vmax_pos(1)
 Acc_speed_p(2) = Vmax_pos(2)
 Acc_speed_n(1) = Vmax_neg(1)
 Acc_speed_n(2) = Vmax_neg(2)
 Fattore_ang(1) = Fattore_acc(1)
 Fattore_ang(2) = Fattore_acc(2)
 Pos_finale(1) = Val(cmd_ar(2))
 Pos_finale(2) = Val(cmd_ar(3))
 '..........................................................
 Case "SUM"
 Somma = Val(cmd_ar(2))
 '..........................................................
 Case "START"
 Start_move = True
 Print "(0 START, 0)"
  '..........................................................
 Case "STOP"
 Mode_ctrl = Mode_idle
 Print "(0 STOP, 0)"
 '..........................................................
 Case "RST"
 If M = 1 Then
 Hctl_rst_1 = 0
 Waitms 1
 Hctl_rst_1 = 1
 End If
 If M = 2 Then
 Hctl_rst_2 = 0
 Waitms 1
 Hctl_rst_2 = 1
 End If
 Call Hctl_2032(m)
 Print "(" ; M ; " RST, " ; Pos_encoder(m) ; ")"
 '..........................................................
 Case Else
 If Mode_ctrl <> Mode_velp Then 'se mode <> da trapezoidale
 Call Set_mode(mode_velp)
 End If
 Pos_finale(1) = Pos_finale(1) + Somma
 Pos_finale(2) = Pos_finale(2) + Somma
 '..........................................................
  End Select
 Comando_old = Comando
 Comando = ""
 '......................................................................
 #if Vb6
 #else
 Else
 Comando = Comando + Chr(char(1))
 Print Comando ; Chr(13);
 End If
 #endif
Return
'-------------------------------------------------------------------------------
'----------------------- esecuzione PID ----------------------------------------
'-------------------------------------------------------------------------------
'la routine seguente viene eseguita per i due motori in 500 uSec ad una freq di 280 hz
'il periodo di intervento PID č di 3.5 msec con timer_pid = 4
Timer_0:
 If Timer_pid = Pid_time Then
 Timer_pid = 0
 For Mot = 1 To 2
  Motor_led = True
 Call Hctl_2032(mot) 'LEGGI IL VALORE DALL'ENCODER
 Act_speed(mot) = Pos_encoder(mot) - Old_encoder(mot) 'con 12 Volt ed encoder HEDS-5540
 Old_encoder(mot) = Pos_encoder(mot) 'se Pos_encoder(1)=10000 abbiamo trap_1(1)=30000
 New_speed(mot) = Pos_finale(mot) - Pos_encoder(mot) 'differenza per ogni campionamento
 Differenza(mot) = Pos_finale(mot) - Pos_encoder(mot) 'questo calcolo serve x controllo continuo velocita
 '------------------------------------------------------------------------
 '///// se si cambia di segno prima togli velocita e poi accelera \
 '------------------------------------------------------------------------
 If Flag_velocita = True Then
 '.....................................................................
 If Pos_finale(mot) => Pos_encoder(mot) Then Dir_diff(mot) = True '--->
 If Pos_finale(mot) < Pos_encoder(mot) Then Dir_diff(mot) = False '<---
 '.....................................................................
 If Dir_diff(mot) = True Then ' 99 / 100 = 0 'qui si ferma prima ma abbiamo la decellerazione
 If Differenza(mot) <= 10000 Then Acc_speed_p(mot) = New_speed(mot) / Fattore_acc(mot) 'decellera
 If Acc_speed_p(mot) <= 1 Then Acc_speed_p(mot) = 1
 If New_speed(mot) => Vmax_pos(mot) Then New_speed(mot) = Vmax_pos(mot)
 If New_speed(mot) => Acc_speed_p(mot) Then New_speed(mot) = Acc_speed_p(mot)
 End If
 '.....................................................................
 If Dir_diff(mot) = False Then
 If Differenza(mot) => -10000 Then Acc_speed_n(mot) = New_speed(mot) / Fattore_acc(mot) 'decellera
 If Acc_speed_n(mot) => -1 Then Acc_speed_n(mot) = -1
 If New_speed(mot) <= Vmax_neg(mot) Then New_speed(mot) = Vmax_neg(mot)
 If New_speed(mot) <= Acc_speed_n(mot) Then New_speed(mot) = Acc_speed_n(mot)
 End If
 '.....................................................................
 End If
 '------------------------------------------------------------------------
 If Flag_velocita = False Then
 If Dir_diff(mot) = True Then
 New_encoder(mot) = Trap_1(mot) - Pos_encoder(mot) '30000 - 10000 = 20000
 New_encoder(mot) = Punto_p1(mot) - New_encoder(mot) '20000 - 20000 = 0
 If Pos_encoder(mot) < Trap_1(mot) Then Acc_speed(mot) = New_encoder(mot) / Fattore_acc(mot) 'accelerazione prima di trap_1 -->
 If Pos_encoder(mot) => Trap_2(mot) Then Acc_speed(mot) = New_speed(mot) / Fattore_acc(mot) 'decelerazione dopo trap_2 -->
 If Acc_speed(mot) <= 1 Then Acc_speed(mot) = 1
 If New_speed(mot) => Vel_pos(mot) Then New_speed(mot) = Vel_pos(mot) 'ferma su velocita massima
 If New_speed(mot) => Acc_speed(mot) Then New_speed(mot) = Acc_speed(mot) 'riduci la velocita
 End If 'mentre viene ridotta l'accelerazione
 '........................................................................
 If Dir_diff(mot) = False Then
 New_encoder(mot) = Trap_1(mot) - Pos_encoder(mot) '80000 - 99000 = -20000
 New_encoder(mot) = New_encoder(mot) + Punto_p1(mot) '21000 - 20000) = -1000
 New_encoder(mot) = -new_encoder(mot) 'inverti di segno. qui new_encoder č negativo
 If Pos_encoder(mot) => Trap_1(mot) Then Acc_speed(mot) = New_encoder(mot) / Fattore_acc(mot) 'accelerazione prima di trap_1 <--
 If Pos_encoder(mot) < Trap_2(mot) Then Acc_speed(mot) = New_speed(mot) / Fattore_acc(mot) 'decelerazione dopo di trap_2 <--
 If Acc_speed(mot) => -1 Then Acc_speed(mot) = -1
 If New_speed(mot) <= Vel_neg(mot) Then New_speed(mot) = Vel_neg(mot) 'ferma su velocita negativa
 If New_speed(mot) <= Acc_speed(mot) Then New_speed(mot) = Acc_speed(mot) 'riduci la velocita
 End If
 End If
 '------------------------------------------------------------------------
 Select Case Mode_ctrl
 Case Mode_pos
 Call Exe_pid(mot , Pos_finale(mot) , Pos_encoder(mot))
 '...........................................................
 Case Mode_vel
 Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 '...........................................................
 Case Mode_trp
 Motore_setpoint(mot) = New_speed(mot)
 If Start_move = 0 Then Motore_setpoint(mot) = 0
 Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 '...........................................................
 Case Mode_velp
 Motore_setpoint(mot) = New_speed(mot)
 Call Exe_pid(mot , Motore_setpoint(mot) , Act_speed(mot))
 '...........................................................
 Case Mode_idle
 Call Configura_pid(mot , 0 , 0 , 0)
 '..Pos_encoder(mot) = 0
 '..Old_encoder(mot) = 0
 '..Motore_setpoint(mot) = 0
 '..Pos_finale(mot) = 0
 '..New_speed(mot) = 0
 If Mot = 1 Then Motor_pwm_1 = 0
 If Mot = 2 Then Motor_pwm_2 = 0
 End Select
 '........................................................................
 If Act_speed(1) > 2 Or Act_speed(1) < -2 Then 'se quasi fermo
 Num_smt(1) = 0 'controlla se in movimento
 Else
 Incr Num_smt(1) 'se fermo, vedi x quanto tempo
 End If

  If Act_speed(2) > 2 Or Act_speed(2) < -2 Then 'se quasi fermo
 Num_smt(2) = 0
 Else
 Incr Num_smt(2)
 End If
 '..........................................................................
 If Num_smt(1) > 200 Then Num_smt(1) = 200 'non azzerra a 255
 If Num_smt(2) > 200 Then Num_smt(2) = 200 'non azzerra a 255
  If Num_smt(1) > 150 Then Smt_1 = 0 Else Smt_1 = 1
 If Num_smt(2) > 150 Then Smt_2 = 0 Else Smt_2 = 1
 '..........................................................................
 Next Mot
End If
 Incr Timer_pid
 Motor_led = False
Return
'-------------------------------------------------------------------------------
'----------------------- CALCOLO DEL PID ---------------------------------------
'----------------------- tempo PER PID = 90 uSecondi ---------------------------
'-------------------------------------------------------------------------------
Sub Exe_pid(mot , Pid_setpoint , Pid_actual) '90 microsecondi

'.. Motor_led = True
 Pid_error(mot) = Pid_setpoint - Pid_actual
 Pid_out(mot) = Pid_error(mot) * Pid_kp(mot)
 Ptemp(mot) = Pid_error(mot) - Pid_prev_error(mot)
 Pid_prev_error(mot) = Pid_error(mot)
 Ptemp(mot) = Ptemp(mot) * Pid_kd(mot)
 Pid_out(mot) = Pid_out(mot) + Ptemp(mot)
 Ptemp(mot) = Pid_integral_error(mot) * Pid_ki(mot)
 Pid_out(mot) = Pid_out(mot) + Ptemp(mot)
 Pid_out(mot) = Pid_out(mot) / Pid_scale(mot)

 If Pid_out(mot) > 255 Then 'limita il valore a 8 bit
 Pid_out(mot) = 255
 Elseif Pid_out(mot) < -255 Then
 Pid_out(mot) = -255
 Else
 Pid_error(mot) = Pid_error(mot) + Pid_integral_error(mot)
 If Pid_error(mot) > 255 Then
 Pid_error(mot) = 255
 Elseif Pid_error(mot) < -255 Then
 Pid_error(mot) = -255
 End If
 Pid_integral_error(mot) = Pid_error(mot)
 End If

 If Mot = 1 Then
 If Pid_out(mot) => 0 Then Motor_dir_1 = 0 'setta la direzione del motore
 If Pid_out(mot) < 0 Then Motor_dir_1 = 1
 Pid_out(mot) = Abs(pid_out(mot)) 'calcola il valore assoluto
 If Pid_out(mot) => Max_pwm(mot) Then Pid_out(mot) = Max_pwm(mot)
 Motor_pwm_1 = Pid_out(mot) 'imposta il pwm
 Rpwm(mot) = Pid_out(mot) 'segnale uscita test
 End If

 If Mot = 2 Then
 If Pid_out(mot) => 0 Then Motor_dir_2 = 0 'setta la direzione del motore
 If Pid_out(mot) < 0 Then Motor_dir_2 = 1
 Pid_out(mot) = Abs(pid_out(mot)) 'calcola il valore assoluto
 If Pid_out(mot) => Max_pwm(mot) Then Pid_out(mot) = Max_pwm(mot)
 Motor_pwm_2 = Pid_out(mot) 'imposta il pwm
 Rpwm(mot) = Pid_out(mot)  'segnale uscita test
 End If
'.. Motor_led = False
End Sub
'-------------------------------------------------------------------------------
'---------------------- Configurazione pid -------------------------------------
'-------------------------------------------------------------------------------
Sub Configura_pid(m , Mot_kp , Mot_ki , Mot_kd)
 Pid_kp(m) = Mot_kp
 Pid_ki(m) = Mot_ki
 Pid_kd(m) = Mot_kd
 Pid_scale(m) = 100
End Sub
'-------------------------------------------------------------------------------
'----------------------- LETTURA HCTL 2032 -------------------------------------
'-------------------------------------------------------------------------------
Sub Hctl_2032(mot)
 If Mot = 1 Then Hctl_xy = 0
 If Mot = 2 Then Hctl_xy = 1

 Hctl_oe = 0 'oe
 Hctl_sel1 = 0 'selezione primo byte msb
 Hctl_sel2 = 1 'seleziona primo byte msb
 Data_4 = Hctl_data 'msb byte

 Hctl_sel1 = 1
 Hctl_sel2 = 1
 Data_3 = Hctl_data '2nd byte

 Hctl_sel1 = 0
 Hctl_sel2 = 0
 Data_2 = Hctl_data '3rd byte

 Hctl_sel1 = 1
 Hctl_sel2 = 0
 Data_1 = Hctl_data 'lsb byte
 Hctl_oe = 1

 Pos_encoder(mot) = Data_1
 Temp_enc = Data_2 * 256
 Pos_encoder(mot) = Pos_encoder(mot) + Temp_enc
 Temp_enc = Data_3 * 65536
 Pos_encoder(mot) = Pos_encoder(mot) + Temp_enc
 Temp_enc = Data_4 * 16777216
 Pos_encoder(mot) = Pos_encoder(mot) + Temp_enc
End Sub
'-------------------------------------------------------------------------------
'------------------------- inizializza parametri -------------------------------
'-------------------------------------------------------------------------------
Sub Init_parameter(m)
 Pid_time = 4 'tempo di pid
 Somma = 1000
 Vmax_pos(m) = 126
 Vmax_neg(m) = -vmax_pos(m)
 Vel_pos(m) = 126 'velocita iniziale
 Vel_last(m) = Vel_pos(m) 'salva il valore last
 Vel_neg(m) = -vel_pos(m) 'velocita negativa iniziale
 Flag_velocita = False
 Start_move = True 'start move attivo
 Max_pwm(m) = 250 'massimo valore pwm in uscita
 Deg(m) = 45 'pendenza accelerazione in grad(1)i
 Fattore_acc(m) = 100
 Punto_p1(m) = 20000  'punto 1
 Motore_setpoint(m) = 0 'posizione iniziale = 0
 If M = 1 Then Motor_pwm_1 = 0 'pwm x uscita = 0
 If M = 2 Then Motor_pwm_2 = 0 'pwm y uscita = 0
 Mode_ctrl = Mode_trp 'controllo trapezoidale
End Sub
'-------------------------------------------------------------------------------
'------------------------- CALCOLO DEL PROFILO TRAPEZIOIDALE -------------------
'-------------------------------------------------------------------------------
Sub Calcola_trapezio(m)
 If Vel_pos(m) = 0 Then Vel_pos(m) = Vel_last(m)

 Rad(m) = Deg2rad(deg(m)) 'trasforma in radianti i gradi pendenza
 Rad(m) = Tan(rad(m)) 'calcola la tangente dell'angolo
 Vel_max(m) = Vel_pos(m) * 10 'per calcolare la distanza del punto p1
 Punto_p1(m) = Vel_max(m) / Rad(m)
 Punto_p1(m) = Punto_p1(m) * 10

 '.....Print "P1: " ; Punto_p1(m)

 Vel_neg(m) = -vel_pos(m)
 Vel_last(m) = Vel_pos(m)

 Call Hctl_2032(m)

 Diff_posizione(m) = Pos_finale(m) - Pos_encoder(m)
 Diff_posizione(m) = Abs(diff_posizione(m))

 Fattore_acc(m) = Punto_p1(m) / Vel_pos(m) 'messo qui ma prima era giu prima di print
 '..........................................................aggiunto con ACC command
 Diff_2(m) = Diff_posizione(m) / 2
 If Punto_p1(m) > Diff_2(m) Then
 Punto_p1(m) = Diff_2(m)
 Punto_p1(m) = Punto_p1(m) / 2
 End If
 '..........................................................
 If Pos_finale(m) => Pos_encoder(m) Then Dir_diff(m) = True '--->
 If Pos_finale(m) < Pos_encoder(m) Then Dir_diff(m) = False '<---
 '..........................................................
 If Dir_diff(m) = True Then
 Trap_1(m) = Pos_encoder(m) + Punto_p1(m)
 Trap_2(m) = Pos_finale(m) - Punto_p1(m)
 End If
 '..........................................................
 If Dir_diff(m) = False Then
 Trap_1(m) = Pos_encoder(m) - Punto_p1(m)
 Trap_2(m) = Pos_finale(m) + Punto_p1(m)
 End If
 '..........................................................
 Print "(" ; M ; " POS, " ; Pos_finale(m) ; ")"
 '...Print "Trapezio: " ; Trap_1(m) ; ", " ; Trap_2(m)
 '...Print "Fatt ang: " ; Fattore_acc(m)
End Sub
'-------------------------------------------------------------------------------
Sub Make_print(mt , Stringa , Valore)
 Str_tx_1 = "(" + Str(mt) + " " + Stringa + ", " + Str(valore) + ")"
End Sub
'-------------------------------------------------------------------------------
Sub Set_mode(mode_control)
 Select Case Mode_control
 Case Mode_pos 'POSIZIONE 0
 Flag_velocita = False
 Call Configura_pid(1 , 200 , 0 , 200)
 Call Configura_pid(2 , 200 , 0 , 200)
 Pos_finale(1) = Pos_encoder(1)
 Pos_finale(2) = Pos_encoder(2)

 Case Mode_vel 'VELOCITA 1
 Flag_velocita = False
 Call Configura_pid(1 , 700 , 100 , 700)
 Call Configura_pid(2 , 700 , 100 , 700)
  Motore_setpoint(1) = 0
 Motore_setpoint(2) = 0

 Case Mode_trp 'TRAPEZOIDALE 2
 Flag_velocita = False
  Call Configura_pid(1 , 500 , 100 , 500)
 Call Configura_pid(2 , 500 , 100 , 500)
 Pos_finale(1) = Pos_encoder(1)
 Pos_finale(2) = Pos_encoder(2)

 Case Mode_velp 'VELOCITA PID 3
 Flag_velocita = True
 Call Configura_pid(1 , 400 , 100 , 400)
 Call Configura_pid(2 , 400 , 100 , 400)
 Pos_finale(1) = Pos_encoder(1)
 Pos_finale(2) = Pos_encoder(2)

 Case Mode_idle 'IDLE 4
 Flag_velocita = False
 Call Configura_pid(1 , 0 , 0 , 0)
 Call Configura_pid(2 , 0 , 0 , 0)
 End Select
 Mode_ctrl = Mode_control
End Sub
'-------------------------------------------------------------------------------
'-------------------------------------------------------------------------------

+1

8

Спасибо всем! Вроде понял, в выходные буду мучить аккумулятор. :)
Вот эта статья прояснила как влияют составляющие и на что. http://habrahabr.ru/post/145991/

Отредактировано IgorL (2014-04-24 13:07:18)

0

9

Я не фанат сложных расчётов я не понимаю для чего они нужны так вот. Уже давно юзаю ПИ регулятор всё отлично не какой колбасы даже в сложных условиях, алгоритм придумывал ясно дело сам как полагается, пара фильтров что бы избежать перескоков и переключения между пропорциональным и интегральным и всё. Для так же используется релейная подрегулировка для увлечения разрядности если частота низкая и надо лучше ШИМ отфильтровать. Формируется небольшой шум в пределах 1-2 шагов входящего значения, значение перескока пропорционально разнице так что шум будет минимален а реакция максимальна. Гистерезиса нет перескока соответственно тоже почти как аналоговый только цифровой аналогично аналоговому с идеальной стабильностью, аналоговый с идеальной стабильностью тоже бы шумел так же.
У меня всё просто. Для грубой и быстрой настройки управление отдаётся пропорциональному, когда он "закончил" это определяется фильтрами, управление берёт интегральный и держит значение на уровне. Если фильтры выставлены правильно то не какой колбасы быть не может.
А вот по ссылке косяк в описании и очень крутой.

ЗЫ
"пропорционально-дифференциальный начинает снижать подаваемую мощность раньше, чем догрелся до нужной точки" как раз это пропорциональный.
" Просто пропорциональный регулятор даёт мощность всё время, пока температура не достигнет нужной точки" а так делает только релейный.

А вот про заряд АКБ есть динамический метод заряжает максимально быстро я его давно юзаю, самый лучший если на АКБ не висит нагрузка альтернативы ему просто нет! Алгоритм релейный: даёт ток потом меряет напругу, когда достигло прекращает давать. Преимущества точное определение уровня заряда, потерь в линии не боится. Я заряжаю так все, а мелкие АКБ через резюк на проводе без данного метода определить уровень заряда в такой конфигурации было бы не возможно.
Просьба не путать этот метод с другими и не говорить что он может не дозарядить такого быть не может! После выставления статус готово напруга на АКБ будет = напруге окончания заряда. Если интересно могу выложить прошику для ЗУ, это метод работает с тем что может вкл/выкл подачу тока на АКБ в принципе на стабилизатор алгоритму плевать он работает чисто с напругой АКБ. Статус готово ставится когда нагруга на АКБ не снижается до возобновления заряда в течении n времени, статус заряд ставится если заряд идёт n2 время или сразу после подключения АКБ, метод несёт в себе захват по напруге и не подаёт ток при отключенном АКБ (но форсирование ясно дело есть), авто определение АКБ по напруге что очень полезно скажем 1 или 2 лития, или линий и никель, или 6, 12, 24В акб, можно сделать переключение тока в зависимости от заряда и прочую фигню, у меня на данном этапе при увеличение заряда уменьшает время подачи тока, время на замер фиксировано, в случае низкого заряда АКБ подаёт короткие импульсы.
Для лития этот метод вообще идеален но опять таки только если на АКБ не висит нагрузка иначе получится перезаряд. А свой ПИ регулятор я юзаю в ЗУ в девайсах обеспечивает точное напряжения для заряда в статическом режиме, в БП и стабах тока всё идеально.

А вообще тут просится проект универсального БП в котором есть всё что АКБ не переразрядить и возобновление работы при появления питания правда не как не допилю интерфейс, доступ почти ко всем настройкам и параметрам только по UART.

Отредактировано Rotgar (2014-04-27 10:30:45)

-1

10

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

0

11

Вот или читать люди не не умеют либо еще чего я же написал что недозаряда быть не может, это исключено. Если данный метод мог не дозарядить мы бы его не юзали. Если этот метод и способен не дозарядить то это значение будет самым меньшим из всех других методов!!! Да и ток заряда вообще не имеет отношения к данному методу он работает с напряжением а не током на ток ему плевать!!! Если не понимаете физику процессов не говорите. Вы не юзали данный метод просто, на сопротивление ему тоже плевать он работает с напряжением!

Самым точным показателем заряда АКБ может быть лишь напруга именно с ней и работаем, она не зависит от тока заряда и от внутреннего сопротивления, немного зависит от температуры но можно ввести зависимость хотя в случае SLA и данного метода оно не требуется хотя и не будет лишним.
А как вам заряд АКБ через резюк это типа не страшно увеличенное сопротивление а? ЗУ на 1.6А заряжает через резюк 51Ок акб на 50мА, результат что заряд АКБ на 3.4А без резюка что этот, время заряда пропорционально току, конец заряда на АКБ 4.11В то есть = напруги окончания заряда/напруге полного заряда.

Еще раз скажу данный метод идеален если на АКБ не висит нагрузка недозаряда быть не может, если на АКБ висит нагрузка то будет перезаряд потому это делать запрещено, только без нагрузки.
На сильно старых АКБ с увеличенным внутренним сопротивлением наблюдается повышенный нагрев из-за завышенной напруги, так же в случае если АКБ будет убит и иметь огромную утечку то может случиться перезаряд, можно ввести контроль роста напруги что бы в случае если она не растёт в течении 5-10мин заряд прекратить с ошибкой.
Недозаряд и данный метод этот как твёрдая жидкость, в случае нарушения условий есть склонность к перезаряду.

Отредактировано Rotgar (2014-04-27 22:56:42)

0

12

Сколько экспрессии!
Люди умеют не только читать, но и понимать прочитанное. Нетрудно видеть, что Ваш метод не применяется в промышленных зарядный устройствах за исключением примитивных трансформаторных ЗУ времен Брежнева.
Людям, которые умеют работать с микроконтроллерами не составит труда собрать простейший стенд подсчета отданных амперчасов и убедиться, что тот же iMax заряжает куда полнее, чем до "напруги". Особенно если важен временной фактор при заряде, заряд током в три этапа и особенно окончательный этап "добивки" дают прирост отданных амперчасов минимум на 25%. В полном соответствии, кстати, с физикой процессов, происходящих в ионных средах и объемных электродах.

0

13

"что Ваш метод не применяется в промышленных зарядный устройствах за исключением примитивных трансформаторных ЗУ времен Брежнева. "
Если это вы мне то возможно и да, а возможно и его применяют знаю много девайсов где применят, часто применяют в сотовых при правильной напруги АКБ живу лет по 7 литивые.
iMAx говно фирменно фирменно не говна быть не может чисто по определению. Подключите к своему любимому iMax АКБ через резюк ёмкость скажем 50мА и посмотрите как он будет показывать заряд и сколько заряжать.
Мне очень интересно с чем же iMax рабоатет если он лучше этого метода. Хотите прикол ща всех положу: все метода работают с напругой CV работает с НАПРУГОЙ, динамический метод работает с напругой только он вобрал всё лучшее от всех методов быстрый заряд и точность заряда. В природе не существует естественных условий что бы он недозарядил, когда начал прогить МК ЗУ было 1 девайсом после этого только я понял что заряд АКБ имеет такой простой и быстрый характер, сейчас у меня ЗУ умеют заряжать разными методами но для разяда чистого АКБ я юзаю только его. Все литивые АКБ теперь заряжаю за 1 час макс 1.5, а Li-Mn за 40мин силовые Li-Po за 30мин быстрее просто АКБ не хочу мучить не один другой бы метод так быстро и так безопасно для АКБ не зарядит, в девайсах где АКБ под нагрузкой заряд идёт напругой с цифровой регулировкой напруги для обеспечения 100% точности напруги, в некоторых где есть микшер напряжения для запитки девайса для снятия нагрузки с АКБ заряд идёт в динамическом режиме.

Отредактировано Rotgar (2014-04-28 11:48:47)

0

14

Вам, сударь, нужно в Нобелевский комитет.
Я, к сожалению не знаю и половины слов, что  Вы употребили.
На сим прощаюсь с Вами, искренне желаю успехов!

0

15

Но да вы правы то, только вот доказать мне что то невозможно, и моему мини ЗУ тоже, мне нужна меленькая плата что бы могла заряжать любые АКБ и 10А и 50мА и максимально быстро. Много лет заряжаю CR2025 литий через резюк за 1.5ч быстрее АКБ жалко. Сорри если кого то обидел, просто предложил но видимо еще не доросли просто до такого.

Отредактировано Rotgar (2014-05-01 19:13:58)

-1

16

Схему в студию, и весь спор будет понятен с точки зрения физики.

0

17

Пипец, вроде взрослые люди, а общий язык не можете найти!

0

18

Саша, дело не в общем языке совсем. Человек пришел на форум, рассказал нам всем, что все совсем не так как мы думаем. И вместо того, чтобы представить нам схему и алгоритм заряда, который заставил бы меня пересмотреть весь свой 25-летний опыт занятий электроникой просто рассказал нам, что мы тут до чего-то не доросли. Ну, не доросли- просвети, открой нам глаза- мы мальчики неглупые, как-то втыкнем в новое и неизведанное. Логично ?
Поэтому предоставленная схема тихо решила бы возникшее разногласие, и совершенно точно было бы понятно кто прав, а кто не очень...
Но ведь не выкладывает схему.....

+1

19

sasha_1973 , Skull    да, не заморачивайтесь, это тролинг ... нельзя фанатика убедить и переспорить )))

Отредактировано Aleks (2014-05-03 01:02:28)

0

20

Кстати, о схеме. Сегодня выгорели пара IRF 4905. Я совсем забыл, что напряжения пробоя где то 20 вольт и обычный ключ, коммутирующий затвор на землю успешно выжег транзисторы при 27 вольтах заведенного катера :(   Что то туплю, как там стабилитрон поставить так, что бы на затворе  P-канального MOSFET было не больше 9...10 вольт и при этом фронты бы не завалились? С N-канальниками просто, а тут что то не могу никак додуматься. Кстати, еще проблемка вылезла - если отключают массу на 24 вольтовом аккумуляторе, запертый IRF 4905 начинает пропускать ток диодом в обратном направлении, питая 12 вольтами 24 вольтовую схему электрооборудования катера.   :( 
Поставил диод, проблема решилась, но греется он. Поставить два 4905, включенные встречно, исток/сток? Кто нибудь так делал в ШИМ ключе?

0

21

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

как там стабилитрон поставить так, что бы на затворе  P-канального MOSFET было не больше 9...10 вольт и при этом фронты бы не завалились? С N-канальниками просто, а тут что то не могу никак додуматься.

Поставьте двуханодный стабилитрон.

0

22

Питайте 12-15В схему раскачки полевиков. питание нужно отключать одновременно. двуханодный стабилитрон возьмет на себя большой ток, если гасящий резистор мал, и будет завал фронтов, если большой.
Выложите схему силовой части, подумаю что можно сделать.

Отредактировано Skull (2014-05-03 23:51:41)

0

23

А вот по поводу CR2025 теперь я Вам покажу насколько Вы неграмотно пишите!!! Да я назвал CR2025 как такой же форм фактор более привычный это как АКБ АА и ААА.
http://www.ebay.com/itm/2-Rechargeable- … 337b8d27da
Но вообще это метод а не схема, важна программная часть а не аппаратная я об этом писал не раз. А вот это мини ЗУ уже давно прекрасно заряжает разные АКБ в том числе и никель ясно дело автоматически отличает его от лития.
И еще раз скажу вот схема алгоритм я уже представил словестно в коде его полная реализация. Алгоритм просто заряжать пока напруга не достигнет и не будет держаться установленное время потом поставить статус готово в случае если напругу не удаётся держать на установленном уровне заданное время поставить статус заряд, и еще для всех данный метод применим лишь для заряда голого АКБ без нагрузки (плата защиты и спящий режим режим девайса не счёт, чтобы АКБ не навредить допускается около 2-4мА нагрузка для 18650 ёмкостью 3100мА) иначе перезарядит как напруга не будет ниже требуемой!!!
В общем это CC-CV сразу вместе взятые без потери в линии, только

Стыдно батенька - мой внук грамотнее пишет.

Но я же не ваш внук логично да, а вообще что такое стыд мне не чего не стыдно.

Отредактировано Rotgar (2014-05-04 17:29:51)

-1

24

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

А вот по поводу CR2025 теперь я Вам покажу на сколько Вы неграмотно пишите!!!
http://www.ebay.com/itm/2-Rechargeable- … 337b8d27da

Там четко написано:

Li-ion Rechargeable Button Cell LIR2025

А CR2025 - это батарейка. Запомните, чтобы больше не путать и быть более грамотным.

0

25

"пишете" пишется через "е"

А это надо бы сказать разработчикам мозилы и их словарю что он не находит ошибки в написанном. Странно конечно как вы исправить смогли значит поняли? А зачем тогда исправлять раз поняли? Вот этого я точно не понимаю.
А по поводу метода я не знаю другого который бы смог довести напругу до требуемой так эффективно игнорирую потери в линии, может кто то представит который так может делать, но CC-CV не чего подобного не может сделать и от потери в линии увеличат время заряда так и еще и слишком малый ток поставит статус готово тип начнётся CV а ток не показатель вообще если ёмкость АКБ не известна и потери.

Отредактировано Rotgar (2014-05-04 17:41:55)

-1

26

Интересно, кто будет умнее и прекратит пустой спор?

Прям, как неразумные малолетки!

0

27

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

Питайте 12-15В схему раскачки полевиков. питание нужно отключать одновременно. двуханодный стабилитрон возьмет на себя большой ток, если гасящий резистор мал, и будет завал фронтов, если большой.
Выложите схему силовой части, подумаю что можно сделать.

Отредактировано Skull (Сегодня 00:51:41)

Вот такой вариант сегодня набросал. С защитой стабилитронами и парой транзисторов для устранения обратного тока.
http://s019.radikal.ru/i624/1405/c8/0f8aeb1ca35ft.jpg

PS получается что то подобное контроллера  заряда от солнечной батареи, только к меня источник имеет очень низкое сопротивление и соотвественно ток заряда 12 вольтовой батареи может быть очень приличным.
PPS Может куда в другое место написать?

0

28

Брррр... Завязывайте фигней страдать.
Человек начал отвечать на поставленные вопросы. С грамматикой будете к детям и внукам приставать ) Можете даже с ремнем ))
Я тут еще ни одного гения правописания не встречал.

Я немного недопонял алгоритм заряда. Т.е. Вы даете ток и смотрите пока напряжение не станет удерживаться какое-то время ?

Отредактировано Skull (2014-05-04 22:33:17)

0

29

Пока напряжение на банке не будет держаться заданное время на заданном уровне. При заряде большим тока идёт быстрый спад напруги (небольшой ясно дело) и статус будет прыгать нужно выждать. Под конец идёт дозаряд частота подучи тока падает, гистерезис небольшой. Например для заряда АКБ до 4.5В (но это все типы АКБ 1 банка) выбрано 2.5мВ, скажем при достижении 4100мВ прекратить, 4095мВ возобновить заряд. Для АКБ которые частично быстро сбрасывают напругу lifepo4 порог начала понижается на 20мВ после установки статуса готово что бы АКБ не пичкать постоянно. По напряжению на банке устанавливается время подачи тока, начале оно выше, в конце оно меньше. Вот специфика коммутации с ИИП должна быть что бы сам ИИП выключался а тупо отдельным ключом нельзя будут импульсы лететь с заряженных кондёров. Осложняет диодом изоляции АКБ (можно ключ нужно мёртвое время что бы ключ вкл/выкл при погашенном ИИП), так же "переменное" напряжение на ключе. Хотя все эти заморочки для обеспечения изоляции АКБ и невозможности разряда через ЗУ. В данной схему ток через ЗУ 20мкА при полностью заряженном литии.
Следует учитывать средний ток получается ниже на время замера, время замера тут еще пара вещей которые могут поджидать: это падение напруги за время до значение ниже значение захвата иначе при отключении АКБ будет "глюк", в силу специфики метода контроля тока нет и при снятии АКБ в момент подачи тока статус отключения АКБ поставится с задержкой, контроль тока тут не даст результата на очень малом тока потому об нём в таком решении я не думал.

Задержка на смену статуса нужна как напруга на АКБ падает и периодически заряд возобновляется ясно дело что поднять напругу до окончания требуется меньше времени чем при заряда и статус не прыгает.
При подключении АКБ устанавливается состояние заряд в любом случае.

В данном случае у меня 30сек на оценку готово. Но если поставить неправильную напругу окончания то пипец скажу сразу если АКБ такую напругу держать не будет он будет "пичкаться" до смерти можно ввести контроль кончено, аналогичный эффект будет если АКБ нагрузить. Но время и точность на высоте конечно. В принципе это умный CC за место CV замер и окончание при 0 токе типа, хотя можно интерпретировать как угодно.
Другой метод врятли бы смог зарядить 3.1А АКБ через провод 0.8Ом за <2 часа при тока всего то 2А.

Отредактировано Rotgar (2014-05-06 14:35:37)

-1

30

Rotgar Скажи, зачем ты пишешь этот бред в ветке "ПИД регулятор тока."????
Чукча не читатель?
Модераторы здесь есть? Оффтоп сплошной.

0


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