Przetwornik DAC do zasilacza

Pytania, kody i porady dotyczące nie tylko Bascom.
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Przetwornik DAC do zasilacza

Post autor: Michał6201 » 03 kwie 2021, 23:55

Witam

Pomiar napięcia i natężenia (dwa przetworniki ADC ADS1110) w moim zasilaczu ogarnąłem dzięki pomocy Bartka, wszystko działa tak jak chciałem.
Ogólnie cały zasilacz już działa.
Teraz regulacja napięcia i prądu odbywa się w tym zasilaczu za pomocą 2 potencjometrów wieloobrotowych.

I tak sobie pomyślałem, że mógłbym spróbować zrobić regulację za pomocą dwóch enkoderów i przetwornika cyfrowo analogowego.

Wstępnie znalazłem dwa przetworniki DAC:

jeden 12 bitowy MCP4822 (dwa kanały, bo tyle potrzeba), komunikacja przez SPI
https://ww1.microchip.com/downloads/en/ ... 02249B.pdf
drugi 16 bitowy AD5667 (dwa kanały) komunikacja przez I2C
https://www.analog.com/media/en/technic ... 7_5667.pdf

I teraz mam pytanie który będzie lepszy? Jeśli użyję tego z komunikacją po I2C, to czy procek wyrobi się obsługą tego wszystkiego na raz?

Da się to jakoś w miarę prosto ogarnąć programowo w bascomie?

I drugie pytanie pojawiło mi się - czy takie napięcie na wyjściu tego DAC muszę mierzyć dodatkowo cały czas osobnym przetwornikiem adc, a czy to programowo wędzie widoczna cały czas ta wartość (U_SET)?
Awatar użytkownika
niveasoft
Posty: 1216
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przetwornik DAC do zasilacza

Post autor: niveasoft » 05 kwie 2021, 9:51

Chyba bym tych wszystkich interfejsów nie mieszał bo szkoda pinów uC/ścieżek. Skoro masz I2C a została stworzona by adresować wiele układów w jednym urządzeniu to weź I2C.
Osobiście tego Twojego nie znam, ale to chyba nie problem. W swoim urządzeniu wykorzystuję pojedynczy 12bit MCP4726.
Taki DAC ma od 0 do 5V na wyjściu (albo max tyle czym go zasilisz) Nie trzeba tego mierzyć. Bierzesz 5V i dzielisz przez 4096. Wychodzi 0,001220703125 na krok.
Teraz chcesz mieć 2V na wyjściu. Jak 2 podzielisz przez 0,001220703125 to wyjdzie chyba 1638,4. Chyba, że może jeszcze śpię po wczorajszej nocce przy kompie ;)
Wbijasz te 1638 i powinno być 2V.

To Ciebie może jednak nie urządzać tak jak mnie bo potrzebowałem 0V-20V. Dlatego za DAC wsadziłem OP-AMP. Stary, poczciwy, LM358 z przekładnią 1/4.
Z 2V na DAC zrobi 8V a z 5V powinno wyjść 20V. Sprzężenie z ADC i powinno grać.
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Re: Przetwornik DAC do zasilacza

Post autor: Michał6201 » 06 kwie 2021, 1:08

Wybrałem przetwornik DAC AD5667R

U mnie wygląda to tak:
Regulacja napięcia wyjściowego, to: 0 - 5V, co mi daje na wyjściu zasilacza napięcie: 0 - 20V
Regulacja ograniczenia prądowego, to 0 - 150mV, co mi daje na wyjściu zasilacza 0 - 3A

Przetwornik AD5667R daje na wyjściu 0 - 5V przy napięciu referencyjnym wewnętrznym 2,5V

Więc pasuje to idealnie do sterowania napięciem wyjściowym, jak i ograniczeniem prądowym

Znalazłem w necie program do obsługi tego przetwornika DAC AD5667:
  1. ' Obsługa przetwornika cyfrowo analogowego AD5667R
  2. ' Wersja testowa
  3.  
  4. $regfile = "m32def.dat"
  5. $crystal = 11059200
  6.  
  7. ' Konfiguracja LCD 2X16
  8.     Config Lcdpin = Pin , E = PortA.3 , Rs = PortA.2 , Db7 = PortA.7 , Db6 = PortA.6 , Db5 = PortA.5 , Db4 = PortA.4
  9.     Config Lcd = 16x2
  10.     Cursor Off
  11.     Cls
  12.  
  13. ' Konfiguracja I2C
  14. $lib "i2c_twi.lbx"
  15. Config Scl = Portc.0
  16. Config Sda = Portc.1
  17. I2cinit
  18. Config Twi = 100000
  19. '-------------------------------------------------------------------------------
  20.  
  21.  
  22. '-------------------------------------------------------------------------------
  23. ' 2 Channel AD5667R 16 Bit I2c DAC
  24. '-------------------------------------------------------------------------------
  25. ' 2-kanałowy przetwornik cyfrowo-analogowy AD5667 16-bitowy I2c z wbudowanym precyzyjnym napięciem odniesienia
  26. ' do sterowania zasilaczem z analogowymi portami zdalnego sterowania 0-5 V
  27.  
  28. ' Opis interfejsu I2C
  29.  
  30. ' AD5667R wymaga dwóch bajtów danych dla DAC i bajtu polecenia, który kontroluje różne funkcje DAC.
  31. ' Dlatego w przetworniku cyfrowo-analogowym muszą zostać zapisane trzy bajty danych,
  32. ' bajt polecenia, po którym następuje najbardziej znaczący bajt danych i najmniej znaczący bajt danych.
  33.  
  34. ' Opis Bajtu
  35. '
  36. ' 1 [Command Data Byte ]
  37. ' 2 [Most Significant Data Byte ]
  38. ' 3 [Least Significant Data Byte]
  39.  
  40. ' [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  41.  
  42. ' [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  43.  
  44. ' Inicjalizacja DAC
  45.  
  46. ' [0 0 1 0 1 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0] SOFTWARE RESET
  47. ' [0 0 1 1 1 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 1] INTERNAL REFERENCE ON
  48. ' [0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 1 1] POWER UP BOTH DACS
  49.  
  50. ' SET DACS
  51.  
  52. ' [0 0 0 1 1 0 0 0] [ X X X X X X X X] [X X X X X X X X] SET DAC A
  53. ' [0 0 0 1 1 0 0 1] [ X X X X X X X X] [X X X X X X X X] SET DAC B
  54.  
  55. 'Implemet each I2c command
  56.  
  57. Declare Sub Dac_reset()
  58. Declare Sub Dac_ref_on()
  59. Declare Sub Dac_ldac_async()
  60. Declare Sub Dac_power_on()
  61. Declare Sub Dac_set_a(value As Word)
  62. Declare Sub Dac_set_b(value As Word)
  63. Declare Sub Init_dac()
  64.  
  65. 'Define the Hardware SCL and SDA port pins
  66. $lib "i2c_twi.lbx"
  67. Config Scl = Portc.0
  68. Config Sda = Portc.1
  69. I2cinit
  70. Config Twi = 100000
  71.  
  72. 'Define the DAC address
  73. Dim Dac_addr As Byte
  74. Dac_addr = &B00011110 ' shift left 1 for hardware i2c (DONT KNOW WHY!)
  75.  
  76.  
  77.  'xxxxxxxxxxxx
  78.  Dim Napiecie As Single
  79.  Dim Voltages As String * 10
  80.  'xxxxxxxxxxxxxxxxxx
  81.  
  82. Dim Dachigh As Byte
  83. Dim Daclow As Byte
  84.  
  85. Dim Daccommand(3) As Byte
  86. Dim Length As Byte
  87.  
  88. Dim Ia As Word
  89. Dim Ib As Word
  90.  
  91. Dim Amp as Single
  92. Dim Ampi As Single
  93.  
  94.  
  95. Enable Interrupts
  96.  
  97. Call Dac_reset()
  98. Call Dac_ref_on()
  99. Call Dac_ldac_async()
  100. Call Dac_power_on()
  101.  
  102.  
  103. Do
  104.  
  105. For Ia = 0 To 65535 ' Na wyjściu DAC VOUTA napięcie 0 - 5V
  106. ' Ib = 32768          ' Na wyjściu DAC VOUTB ustawiłem na sztywno wartość 32768 = 2,5V
  107.  
  108. Amp = 2.5
  109. Ampi = Amp / 5
  110. Ampi = Ampi * 65536
  111.  
  112. Ib = Ampi
  113.  
  114. Call Dac_set_a(ia)
  115. Call Dac_set_b(ib)
  116. Next Ia
  117.  
  118. Loop
  119.  
  120. End
  121.  
  122. 'Reset DAC
  123.  
  124. Sub Dac_reset
  125.  
  126. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  127. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  128. ' [ 0 0 1 1 1 1 0 0] [0 0 1 0 1 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 0] SOFTWARE RESET
  129.  
  130. Length = 3
  131.  
  132. Daccommand(1) = &B00101000 ' Command Byte
  133. Daccommand(2) = &B00000000 ' MSB
  134. Daccommand(3) = &B00000000 ' LSB
  135.  
  136. I2csend Dac_addr , Daccommand(1) , Length
  137.  
  138. Locate 1 , 1
  139. Lcd "Reset Dac " ; Err
  140.  
  141. End Sub
  142.  
  143. 'Internal voltage reference on
  144.  
  145. Sub Dac_ref_on()
  146.  
  147. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  148. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  149. ' [ 0 0 1 1 1 1 0 0] [0 0 1 1 1 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 0 1] INTERNAL REFERENCE ON
  150.  
  151. Length = 3
  152.  
  153. Daccommand(1) = &B00111000 ' Command Byte
  154. Daccommand(2) = &B00000000 ' MSB
  155. Daccommand(3) = &B00000001 ' LSB
  156.  
  157. I2csend Dac_addr , Daccommand(1) , Length
  158.  
  159. Locate 1 , 1
  160. Lcd "Dac Ref on " ; Err
  161.  
  162. End Sub
  163.  
  164. 'LDAC register set for asynchronous mode
  165.  
  166. Sub Dac_ldac_async()
  167.  
  168. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  169. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  170. ' [ 0 0 1 1 1 1 0 0] [0 0 1 1 0 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 1 1] INTERNAL REFERENCE ON
  171.  
  172. Length = 3
  173.  
  174. Daccommand(1) = &B00110000 ' Command Byte
  175. Daccommand(2) = &B00000000 ' MSB
  176. Daccommand(3) = &B00000011 ' LSB
  177.  
  178. I2csend Dac_addr , Daccommand(1) , Length
  179.  
  180. Locate 1 , 1
  181. Lcd "Dac Async " ; Err
  182.  
  183. End Sub
  184.  
  185. 'Power up both DAC channels
  186.  
  187. Sub Dac_power_on()
  188.  
  189. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  190. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  191. ' [ 0 0 1 1 1 1 0 0] [0 0 1 0 0 0 0 0] [ 0 0 0 0 0 0 0 0] [ 0 0 0 0 0 0 1 1] POWER UP BOTH DACS
  192.  
  193. Length = 3
  194.  
  195. Daccommand(1) = &B00100000 ' Command Byte
  196. Daccommand(2) = &B00000000 ' MSB
  197. Daccommand(3) = &B00000011 ' LSB
  198.  
  199. I2csend Dac_addr , Daccommand(1) , Length
  200.  
  201. Locate 1 , 1
  202. Lcd "Dac Power " ; Err
  203.  
  204. End Sub
  205.  
  206. 'Set DAC channel A
  207.  
  208. Sub Dac_set_a(value As Word)
  209.  
  210. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  211. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  212. ' [ 0 0 1 1 1 1 0 0] [0 0 0 1 1 0 0 0] [ X X X X X X X X] [X X X X X X X X] SET DAC A
  213.  
  214. Length = 3
  215.  
  216. Dachigh = High(value)
  217. Daclow = Low(value)
  218.  
  219. Daccommand(1) = &B00011000 ' Command Byte
  220. Daccommand(2) = Dachigh ' MSB
  221. Daccommand(3) = Daclow ' LSB
  222.  
  223. I2csend Dac_addr , Daccommand(1) , Length
  224.  
  225. Locate 1 , 1
  226. Lcd "Set Dac A " ; Value ; " " ; Err
  227.  
  228. End Sub
  229.  
  230.  
  231. 'Set DAC channel B
  232.  
  233. Sub Dac_set_b(value As Word)
  234.  
  235.  
  236.  
  237. ' [ Slave Address ] [ Command Data Byte ] [ Most Significant Data Byte ] [ Least Significant Data Byte ]
  238. ' [A7 A6 A5 A4 A3 A2 A1 A0] [R S C2 C1 C0 A2 A1 A0] [D7 D6 D5 D4 D3 D2 D1 D0] [D7 D6 D5 D4 D3 D2 D1 D0]
  239. ' [ 0 0 1 1 1 1 0 0] [0 0 0 1 1 0 0 1] [ X X X X X X X X] [X X X X X X X X] SET DAC B
  240.  
  241. Length = 3
  242.  
  243. Dachigh = High(value)
  244. Daclow = Low(value)
  245.  
  246. Daccommand(1) = &B00011001 ' Command Byte
  247. Daccommand(2) = Dachigh ' MSB
  248. Daccommand(3) = Daclow ' LSB
  249.  
  250. I2csend Dac_addr , Daccommand(1) , Length
  251.  
  252.  
  253. ' Przekształcenie wartości Ib = 0 - 65535 na napięcie wyświetlane na LCD
  254. Napiecie = Ib / 65536
  255. Napiecie = Napiecie * 5
  256.  
  257. '
  258.  
  259. Locate 2 , 1
  260. Voltages = Fusing(napiecie , "&&.&&&")
  261. Lcd "Set Dac B " ; Voltages
  262. End Sub
Do sterowania tym przetwornikiem potrzebujemy kodu 0 - 65536, (co odpowiada napięciu wyjściowemu 0 - 5V)
Czyli do DAC trzeba wysyłać wartość 0 - 65536.
A wartość ustawiona x 4 da nam wartość napięcia wyjściowego i tym samym wartość wyświetloną na LCD.

Przeszukując Twoją stronę Bartku, znalazłem kod do obsługi enkodera, (ten z kondensatorami 22n pomiędzy A i B a GND), który na lcd daje właśnie kod 0 - 65536.
Załadowałem go do mojego procka i działa pięknie, tylko jak zrobić wybór napięcia na wyświetlaczy lcd, np.: 12,445V?

Wiem już, jak przekształcić wartość wyświetlana na wyświetlaczu na kod 0 - 65536, który trzeba wysłać do DAC.
Zmienną Ib = od 0 do 65536 wysyłamy do DAC.
  1. Amp = 2.5 ' wartość napięcia na wyświetlaczu
  2. Ampi = Amp / 5
  3. Ampi = Ampi * 65536
  4. Ib = Ampi


Bo używając samego kodu z enkodera musiałbym przekręcić od 0 do 65536 impulsów żeby dojść od zera do 20V. To bez sensu byłoby i zajęłoby z 10 minut.
Pomyślałem, że możnaby to zrobić w ten sposób, że wybieram switchem enkodera po kolei poszczególne pozycje wartości napięcia, np.: 5,555V, to najpierw ustawiam wartość tysięcznych volta, potem setnych volta, dziesiętne i jedności, po czym kolejne kliknięcie switch enkodera ładuje to napięcie za pomocą kodu 0 -65536 do przetwornika DAC.
Myślę, że to byłoby najlepsze rozwiązanie. Ale nie wiem jak utworzyć taką wartość na lcd, by móc po kolei zmieniać poszczególne wartości 0 - 9.
Awatar użytkownika
niveasoft
Posty: 1216
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przetwornik DAC do zasilacza

Post autor: niveasoft » 06 kwie 2021, 7:11

To jest proste jak świński ogon. Napisałem to zanim wypiłem kubek kawy.
Zwiększaj całą zmienną z blokadą przekroczenia zakresu. Np. If Zmienna > 5000 then Zmienna = 5000.

Kolejne naciśnięcia przycisku zwiększają zmienną Pos która wskazuje na literkę w stringu. Ta wybrana miga. Pomijana jest kropka.
Ta sama zmienna Pos steruje aktualnym mnożnikiem Enkodera.
Testowane w symulatorze.
Teraz trzeba dopisać czasówkę by migało tylko przez jakiś czas po naciśnięciu, ale tu już sobie chyba poradzisz ;)

Może jeszcze trzeba to rozbudować o miganie dwoma cyframi w przypadku > 9V z przodu czyli 10V-20V
  1. $regfile = "m328pdef.dat"
  2. $crystal = 16000000
  3. $hwstack = 128
  4. $swstack = 128
  5. $framesize = 255
  6. $baud = 115200
  7. $sim                                                        'symulator
  8.  
  9. Dim Pos As Byte , Mig As Byte , Mnoznik As Word
  10. Dim Volt_str As String * 10 , Temp_str As String * 10
  11.  
  12. Volt_str = "5.555V"
  13.  
  14. Enc_sw Alias Pinc.5 : Set Portc.5
  15.  
  16. Do
  17.  
  18.   If Enc_sw = 0 Then
  19.    Incr Pos : If Pos > 5 Then Pos = 1
  20.    If Pos = 2 Then Pos = 3                                  'przeskocz kropkę
  21.   End If
  22.  
  23.    If Mig = 0 Then
  24.     Mig = 1
  25.      Temp_str = Volt_str
  26.    Else
  27.     Mig = 0
  28.      Mid(temp_str , Pos) = " "                              'wstaw spację w miejscu pos (migaj)
  29.    End If
  30.  
  31.     Locate 1 , 1 : Lcd Temp_str
  32.  
  33.    Select Case Pos
  34.     Case 1
  35.      Mnoznik = 1000
  36.     Case 3
  37.      Mnoznik = 100
  38.     Case 4
  39.      Mnoznik = 10
  40.     Case 5
  41.      Mnoznik = 1
  42.    End Select
  43.  
  44.   Wait 1
  45.  
  46. Loop
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Re: Przetwornik DAC do zasilacza

Post autor: Michał6201 » 06 kwie 2021, 23:05

Niestety enkoder nie zmienia wartości poszczególnych pozycji.
Jedyne co robi, to zmienia po kolei migające pozycje za pomocą przycisku Enc_sw.

A powinny zmieniać się pozycja jedności od 0 do 20
Natomiast po przecinku pozostałe pozycje od 0 do 9

Nie da się zapisać Incr Temp_str, wywala błąd.
  1. $regfile = "m32def.dat"
  2. $crystal = 11059200
  3.  
  4. ' Konfiguracja LCD 2X16
  5.     Config Lcdpin = Pin , E = PortA.3 , Rs = PortA.2 , Db7 = PortA.7 , Db6 = PortA.6 , Db5 = PortA.5 , Db4 = PortA.4
  6.     Config Lcd = 16x2
  7.     Cursor Off
  8.     Cls
  9.  
  10. Dim Pos As Byte , Mig As Byte , Mnoznik As Word
  11. Dim Volt_str As String * 10
  12. Dim Temp_str As String * 10
  13.  
  14.  
  15. ' config for encoder
  16. Config Portd.2 = Input : Portd.2 = 1 : Encoder_a Alias Pind.2
  17. Config Portd.3 = Input : Portd.3 = 1 : Encoder_b Alias Pind.3        'to też pin INT1
  18. Config PORTD.7 = Input : PORTD.7 = 1 : Enc_sw Alias PIND.7
  19.  
  20. Config Int1 = Rising         'przerwanie  generować będzie rosnące zbocze
  21. Enable Int1 : On Int1 Encoder_isr Nosave
  22.  
  23. Dim Encoder_turn_left As Byte , Encoder_turn_right As Byte
  24. '-------------------------------------------
  25. Dim Zmienna As Word
  26.  
  27. Enable Interrupts
  28.  
  29.         Volt_str = "0.000V"
  30. Do
  31.  
  32.  
  33.   If Enc_sw = 0 Then
  34.    Incr Pos : If Pos > 5 Then Pos = 1
  35.    If Pos = 2 Then Pos = 3                                  'przeskocz kropkę
  36.   End If
  37.  
  38.    If Mig = 0 Then
  39.     Mig = 1
  40.      Temp_str = Volt_str
  41.    Else
  42.     Mig = 0
  43.      Mid(temp_str , Pos) = " "                              'wstaw spację w miejscu pos (migaj)
  44.    End If
  45.  
  46.     Locate 1 , 1 : Lcd Temp_str
  47.  
  48.    Select Case Pos
  49.     Case 1
  50.      Mnoznik = 1000
  51.     Case 3
  52.      Mnoznik = 100
  53.     Case 4
  54.      Mnoznik = 10
  55.     Case 5
  56.      Mnoznik = 1
  57.    End Select
  58.  
  59.   Wait 1
  60.  
  61.  
  62. '##### encoder turns left ######
  63. If 0 < Encoder_turn_left Then
  64. Decr Encoder_turn_left
  65. 'tutaj Twój kod -
  66.  
  67. Decr Temp_str
  68. 'Locate 1 , 10 : Lcd Zmienna1 ; "    "
  69.  
  70. Gifr.intf1 = 1  'dla Mega8, M32 itp
  71. Enable Int1
  72. End If
  73.  
  74. ' #### encoder turns right ######
  75. If 0 < Encoder_turn_right Then
  76. Decr Encoder_turn_right
  77. 'tutaj Twój kod +
  78.  
  79. Incr Temp_str
  80. 'Locate 1 , 10 : Lcd Zmienna1 ; "    "
  81.  
  82. Gifr.intf1 = 1  'dla Mega8, M32 itp
  83. Enable Int1
  84. end if
  85.  
  86.  
  87.  
  88. Loop
  89. End
  90.  
  91. 'tutaj obsługa przerwania zewnetrznego z enkodera
  92. Encoder_isr:
  93.  
  94.   $asm
  95.   PUSH R23
  96.   PUSH R24
  97.   PUSH R26
  98.   PUSH R27
  99.   !in R24, sreg
  100.   PUSH  R24
  101.   $end asm
  102.  
  103.   Disable Int1
  104.  
  105.     If Encoder_a = 1 Then
  106.       Incr Encoder_turn_right
  107.     Else
  108.       Incr Encoder_turn_left
  109.     End If
  110.  
  111.   '          Tuned with NoSave Tool
  112.  
  113.   $asm
  114.   POP  R24
  115.   !out sreg, r24
  116.   POP R27
  117.   POP R26
  118.   POP R24
  119.   POP R23
  120.   $end asm
  121.  
  122. Return
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Re: Przetwornik DAC do zasilacza

Post autor: Michał6201 » 07 kwie 2021, 22:37

Jeszcze dopisałem do każdej pozycji inną zmienną ale to bez sensu działa, bo znikają ustawione wartości i nijak nie da się tego wysłać do DAC.
Bardzo proszę o pomoc, jak to poprawnie napisać.
  1. ' OBSŁUGA ENCODERA
  2.  
  3.  $regfile = "m32def.dat"
  4. $crystal = 11059200
  5.  
  6. ' Konfiguracja LCD 2X16
  7.     Config Lcdpin = Pin , E = PortA.3 , Rs = PortA.2 , Db7 = PortA.7 , Db6 = PortA.6 , Db5 = PortA.5 , Db4 = PortA.4
  8.     Config Lcd = 16x2
  9.     Cursor Off
  10.     Cls
  11.  
  12. Dim Pos As Byte , Mig As Byte , Mnoznik As Word
  13. Dim Volt_str As String * 10
  14. Dim Temp_str As String * 10
  15.  
  16.  
  17.               Dim Temp As Byte
  18. ' config for encoder
  19. Config Portd.2 = Input : Portd.2 = 1 : Encoder_a Alias Pind.2
  20. Config Portd.3 = Input : Portd.3 = 1 : Encoder_b Alias Pind.3        'to też pin INT1
  21. Config PORTD.7 = Input : PORTD.7 = 1 : Enc_sw Alias PIND.7
  22.  
  23. Config Int1 = Rising         'przerwanie  generować będzie rosnące zbocze
  24. Enable Int1 : On Int1 Encoder_isr Nosave
  25.  
  26. Dim Encoder_turn_left As Byte , Encoder_turn_right As Byte
  27. '-------------------------------------------
  28. Dim Zmienna1 As Word
  29. Dim Zmienna2 As Word
  30. Dim Zmienna3 As Word
  31. Dim Zmienna4 As Word
  32.  
  33. Enable Interrupts
  34.        Volt_str = " .   V"
  35. Do
  36.  
  37.  
  38.   If Enc_sw = 0 Then
  39.    Incr Pos : If Pos > 5 Then Pos = 1
  40.    If Pos = 2 Then Pos = 3                                  'przeskocz kropkę
  41.   End If
  42.  
  43.    If Mig = 0 Then
  44.     Mig = 1
  45.      Temp_str = Volt_str
  46.    Else
  47.     Mig = 0
  48.      Mid(Temp_str , Pos) = " "                              'wstaw spację w miejscu pos (migaj)
  49.    End If
  50.  
  51.    Locate 1 , 1 : Lcd Temp_str
  52.  
  53.    Select Case Pos
  54.     Case 1
  55.      Mnoznik = 1000
  56.      Locate 1 , 1 : Lcd Zmienna1 ; "."
  57.     Case 3
  58.      Mnoznik = 100
  59.      Locate 1 , 3 : Lcd Zmienna2
  60.     Case 4
  61.      Mnoznik = 10
  62.      Locate 1 , 4 : Lcd Zmienna3
  63.     Case 5
  64.      Mnoznik = 1
  65.      Locate 1 , 5 : Lcd Zmienna4
  66.    End Select
  67.  
  68. Wait 1
  69.  
  70.  
  71. '##### encoder turns left ######
  72. If 0 < Encoder_turn_left Then
  73. Decr Encoder_turn_left
  74. 'tutaj Twój kod -
  75.  
  76.  
  77. Decr Zmienna1
  78. Decr Zmienna2
  79. Decr Zmienna3
  80. Decr Zmienna4
  81.  
  82.  
  83.  
  84. Gifr.intf1 = 1  'dla Mega8, M32 itp
  85. Enable Int1
  86. End If
  87.  
  88. ' #### encoder turns right ######
  89. If 0 < Encoder_turn_right Then
  90. Decr Encoder_turn_right
  91. 'tutaj Twój kod +
  92.  
  93. Incr Zmienna1
  94. Incr Zmienna2
  95. Incr Zmienna3
  96. Incr Zmienna4
  97.  
  98.  
  99. Gifr.intf1 = 1  'dla Mega8, M32 itp
  100. Enable Int1
  101. end if
  102.  
  103.  
  104.  
  105. Loop
  106. End
  107.  
  108. 'tutaj obsługa przerwania zewnetrznego z enkodera
  109. Encoder_isr:
  110.  
  111.   $asm
  112.   PUSH R23
  113.   PUSH R24
  114.   PUSH R26
  115.   PUSH R27
  116.   !in R24, sreg
  117.   PUSH  R24
  118.   $end asm
  119.  
  120.   Disable Int1
  121.  
  122.     If Encoder_a = 1 Then
  123.       Incr Encoder_turn_right
  124.     Else
  125.       Incr Encoder_turn_left
  126.     End If
  127.  
  128.   '          Tuned with NoSave Tool
  129.  
  130.   $asm
  131.   POP  R24
  132.   !out sreg, r24
  133.   POP R27
  134.   POP R26
  135.   POP R24
  136.   POP R23
  137.   $end asm
  138.  
  139. Return
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Re: Przetwornik DAC do zasilacza

Post autor: Michał6201 » 08 kwie 2021, 1:34

Zrobiłem coś takiego. Niby działa i mogę zmieniać poszczególne cyferki w wartości napięcia na LCD, ale:
- nie miga wybrana pozycja
- czasami zamiast zwiększać wartość o jeden, to zmniejsza, tak jakby się mylił
- przy przejściu do następnej pozycji przenosi wartość cyfry, więc ustawiając części dziesiąte i przechodząc do jedności można przenieść np cyfrę 6 i tym samym nagle dać na wyjściu DAC 6V. To dyskwalifikuje to rozwiązanie w zasilaczu. Tu nie może być błędów tego typu.

A kod wygląda tak:
  1.  
  2.  
  3.  
  4.  
  5. ' OBSŁUGA ENCODERA
  6.  
  7.  $regfile = "m32def.dat"
  8. $crystal = 11059200
  9.  
  10. ' Konfiguracja LCD 2X16
  11.     Config Lcdpin = Pin , E = PortA.3 , Rs = PortA.2 , Db7 = PortA.7 , Db6 = PortA.6 , Db5 = PortA.5 , Db4 = PortA.4
  12.     Config Lcd = 16x2
  13.     Cursor Off
  14.     Cls
  15.  
  16. Dim Pos As Byte , Mig As Byte , Mnoznik As Word
  17. Dim Volt_str As String * 10
  18. Dim Temp_str As String * 10
  19.  
  20.  
  21.               Dim Temp As Byte
  22. ' config for encoder
  23. Config Portd.2 = Input : Portd.2 = 1 : Encoder_a Alias Pind.2
  24. Config Portd.3 = Input : Portd.3 = 1 : Encoder_b Alias Pind.3        'to też pin INT1
  25. Config PORTD.7 = Input : PORTD.7 = 1 : Enc_sw Alias PIND.7
  26.  
  27. Config Int1 = Rising         'przerwanie  generować będzie rosnące zbocze
  28. Enable Int1 : On Int1 Encoder_isr Nosave
  29.  
  30. Dim Encoder_turn_left As Byte , Encoder_turn_right As Byte
  31. '-------------------------------------------
  32. Dim Zmienna1 As Word
  33. Dim Napiecie As Single
  34. Dim Voltages As String * 10
  35.  
  36. Enable Interrupts
  37.       Volt_str = "5.555V"
  38.  
  39. Do
  40.  
  41.  
  42.   If Enc_sw = 0 Then
  43.    Incr Pos : If Pos > 5 Then Pos = 1
  44.    If Pos = 2 Then Pos = 3                                  'przeskocz kropkę
  45.   End If
  46.  
  47.    If Mig = 0 Then
  48.     Mig = 1
  49.      Temp_str = Volt_str
  50.    Else
  51.     Mig = 0
  52.      Mid(Temp_str , Pos) = " "                              'wstaw spację w miejscu pos (migaj)
  53.    End If
  54.    Temp_str = Fusing(Napiecie ,"&&.&&&")
  55.    Locate 1 , 1 : Lcd Temp_str ; "V "
  56.  
  57.    Select Case Pos
  58.     Case 1
  59.      Mnoznik = 1000
  60.     Case 3
  61.      Mnoznik = 100
  62.       Case 4
  63.      Mnoznik = 10
  64.     Case 5
  65.      Mnoznik = 1
  66.  
  67.    End Select
  68.  
  69. Wait 1
  70.  
  71. '##### encoder turns left ######
  72. If 0 < Encoder_turn_left Then
  73. Decr Encoder_turn_left
  74. 'tutaj Twój kod -
  75.  
  76. Decr Zmienna1
  77. Napiecie = Zmienna1 / Mnoznik
  78. If Napiecie < 0 Then Napiecie = 0
  79.  
  80. Gifr.intf1 = 1  'dla Mega8, M32 itp
  81. Enable Int1
  82. End If
  83.  
  84. ' #### encoder turns right ######
  85. If 0 < Encoder_turn_right Then
  86. Decr Encoder_turn_right
  87. 'tutaj Twój kod +
  88.  
  89. Incr Zmienna1
  90. Napiecie = Zmienna1 / Mnoznik
  91. If Napiecie > 20 Then Napiecie = 20
  92.  
  93. Gifr.intf1 = 1  'dla Mega8, M32 itp
  94. Enable Int1
  95. end if
  96.  
  97.  
  98.  
  99. Loop
  100. End
  101.  
  102. 'tutaj obsługa przerwania zewnetrznego z enkodera
  103. Encoder_isr:
  104.  
  105.   $asm
  106.   PUSH R23
  107.   PUSH R24
  108.   PUSH R26
  109.   PUSH R27
  110.   !in R24, sreg
  111.   PUSH  R24
  112.   $end asm
  113.  
  114.   Disable Int1
  115.  
  116.     If Encoder_a = 1 Then
  117.       Incr Encoder_turn_right
  118.     Else
  119.       Incr Encoder_turn_left
  120.     End If
  121.  
  122.   '          Tuned with NoSave Tool
  123.  
  124.   $asm
  125.   POP  R24
  126.   !out sreg, r24
  127.   POP R27
  128.   POP R26
  129.   POP R24
  130.   POP R23
  131.   $end asm
  132.  
  133. Return
  134.  
Czy ktoś z Wam pomoże mi poprawić ten kod, aby nie robił takich błędów?
Awatar użytkownika
niveasoft
Posty: 1216
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przetwornik DAC do zasilacza

Post autor: niveasoft » 09 kwie 2021, 6:36

Moment. Muszę wyjechać około ósmej, ale tu roboty najwięcej jest chyba z połączeniem tego do testu na płytce :D
Awatar użytkownika
niveasoft
Posty: 1216
Rejestracja: 17 sie 2015, 12:13
Kontakt:

Re: Przetwornik DAC do zasilacza

Post autor: niveasoft » 09 kwie 2021, 8:05

Dobra. Tyle zrobiłem w pół godziny. Chyba wszystko działa.
Teraz spadam.
  1. $regfile = "m32def.dat"
  2. $crystal = 11059200
  3. $hwstack = 64
  4. $swstack = 16
  5. $framesize = 64
  6.  
  7. Const Timeout_time = 8                                      'x500ms
  8.  
  9. Config Submode = New
  10.  
  11. ' config LCD 2X16
  12. Config Lcdpin = Pin , Rs = Porta.2 , E = Porta.3 , Db4 = Porta.4 , Db5 = Porta.5 , Db6 = Porta.6 , Db7 = Porta.7
  13. Config Lcd = 16x2
  14. Cursor Off
  15. Cls
  16.  
  17. '-------------------------------------------
  18. ' config for encoder
  19. Config Portd.2 = Input : Portd.2 = 1 : Encoder_a Alias Pind.2
  20. Config Portd.3 = Input : Portd.3 = 1 : Encoder_b Alias Pind.3       'to też pin INT1
  21. Config Portd.7 = Input : Portd.7 = 1 : Enc_sw Alias Pind.7
  22.  
  23. Config Int1 = Rising                                        'przerwanie  generować będzie rosnące zbocze
  24. Enable Int1 : On Int1 Encoder_isr Nosave
  25.  
  26. Dim Encoder_turn_left As Byte , Encoder_turn_right As Byte
  27. '-------------------------------------------
  28. ' config Timer2
  29. Config Timer2 = Timer , Prescale = 1024 , Clear_timer = 1
  30.  Compare2 = 107                                             '10ms @11MHz/1024
  31.  
  32. 'settings
  33. Dim 500ms As Byte , Mig As Byte , Timeout As Byte
  34.  
  35. Dim Napiecie As Single , Napiecie_ee As Eram Single
  36. Dim Pos As Byte , Pos_ee As Eram Byte
  37. Dim Mnoznik As Word
  38. Dim Volt_str As String * 10
  39. Dim Temp_str As String * 10
  40.  
  41.  
  42.  
  43. Enable Interrupts
  44.  
  45.  
  46. Sub Show_voltage
  47.  
  48.  Temp_str = Fusing(napiecie , "#.&&&")
  49.  Volt_str = Format(temp_str , "      ")                     'dwa znaki+kropka+trzy znaki
  50.  
  51.  If Mig = 1 Then
  52.     Select Case Pos
  53.      Case 1
  54.        Mid(volt_str , 1) = "  "                             'wstaw spację w miejscu pos (migaj)
  55.      Case 2
  56.        Mid(volt_str , 4) = " "
  57.      Case 3
  58.        Mid(volt_str , 5) = " "
  59.      Case 4
  60.        Mid(volt_str , 6) = " "
  61.     End Select
  62.  End If
  63.  
  64.  Locate 1 , 1 : Lcd Volt_str
  65.  
  66. End Sub
  67.  
  68. Sub Set_dac
  69.  'przelicz Single Napiecie i wyslij do DAC
  70.  
  71. End Sub
  72.  
  73. ' eeprom reading
  74. '------------------------------
  75. Pos = Pos_ee
  76. If Pos > 4 Then
  77.  Pos = 4 : Pos_ee = Pos
  78.  Napiecie_ee = 0
  79. End If
  80.  Napiecie = Napiecie_ee
  81. '------------------------------
  82.  
  83. Call Show_voltage()
  84.  Call Set_dac()
  85.  
  86. Do
  87.  
  88.    Debounce Enc_sw , 0 , Enc_sw_sub , Sub
  89.  
  90.    '##### encoder turns left ######
  91.    If 0 < Encoder_turn_left Then
  92.       Decr Encoder_turn_left
  93.    'tutaj Twój kod -
  94.  
  95.      If Timeout > 0 Then
  96.       Select Case Pos
  97.        Case 1
  98.         Napiecie = Napiecie - 1.0
  99.        Case 2
  100.         Napiecie = Napiecie - 0.1
  101.        Case 3
  102.         Napiecie = Napiecie - 0.01
  103.        Case 4
  104.         Napiecie = Napiecie - 0.001
  105.       End Select
  106.  
  107.       If Napiecie < 0 Then Napiecie = 0
  108.        Mig = 0 : Call Show_voltage
  109.  
  110.      End If
  111.  
  112.      Timeout = Timeout_time                                 'przedłuzaj/uruchamiaj timeout przy kazdym kliku
  113.       Gifr.intf1 = 1                                        'dla Mega8, M32 itp
  114.       Enable Int1
  115.    End If
  116.  
  117.    ' #### encoder turns right ######
  118.    If 0 < Encoder_turn_right Then
  119.       Decr Encoder_turn_right
  120.    'tutaj Twój kod +
  121.  
  122.      If Timeout > 0 Then
  123.       Select Case Pos
  124.        Case 1
  125.         Napiecie = Napiecie + 1
  126.        Case 2
  127.         Napiecie = Napiecie + 0.1
  128.        Case 3
  129.         Napiecie = Napiecie + 0.01
  130.        Case 4
  131.         Napiecie = Napiecie + 0.001
  132.       End Select
  133.  
  134.       If Napiecie > 20.0 Then Napiecie = 20.0
  135.        Mig = 0 : Call Show_voltage
  136.  
  137.      End If
  138.  
  139.  
  140.      Timeout = Timeout_time                                 'przedłuzaj/uruchamiaj timeout przy kazdym kliku
  141.       Gifr.intf1 = 1                                     'dla Mega8, M32 itp
  142.       Enable Int1
  143.    End If
  144.  
  145.  
  146.    If Tifr.ocf2 = 1 Then                                    '10ms
  147.     Tifr.ocf2 = 1
  148.  
  149.     If 500ms < 49 Then
  150.      Incr 500ms
  151.     Else
  152.      500ms = 0
  153.        If Mig = 0 Then Mig = 1 Else Mig = 0
  154.  
  155.  
  156.  
  157.  
  158.  
  159.        If Timeout > 0 Then
  160.         Decr Timeout
  161.         If Timeout = 0 Then
  162.          'wyślij do DAC
  163.           Mig = 0
  164.  
  165.            Napiecie_ee = Napiecie                           'zapamietaj dopiero po Timeoucie
  166.  
  167.           Call Set_dac
  168.  
  169.         End If
  170.  
  171.  
  172.         Call Show_voltage()
  173.        End If
  174.  
  175.     End If
  176.  
  177.    End If
  178.  
  179. Loop
  180. End
  181.  
  182. Enc_sw_sub:
  183.  
  184.  If Timeout > 0 Then
  185.  
  186.    Incr Pos : If Pos > 4 Then Pos = 1
  187.    Pos_ee = Pos
  188.  
  189.  End If
  190.   Timeout = Timeout_time                                 'przedłuzaj/uruchamiaj timeout przy kazdym kliku
  191.  
  192. Return
  193.  
  194.  
  195. 'tutaj obsługa przerwania zewnetrznego z enkodera
  196. Encoder_isr:
  197.  
  198.    $asm
  199.       PUSH R23
  200.       PUSH R24
  201.       PUSH R26
  202.       PUSH R27
  203.       !in R24, sreg
  204.       PUSH  R24
  205.    $end Asm
  206.  
  207.    Disable Int1
  208.  
  209.    If Encoder_a = 1 Then
  210.       Incr Encoder_turn_right
  211.    Else
  212.       Incr Encoder_turn_left
  213.    End If
  214.  
  215.   '          Tuned with NoSave Tool
  216.  
  217.    $asm
  218.       POP  R24
  219.       !out sreg, r24
  220.       POP R27
  221.       POP R26
  222.       POP R24
  223.       POP R23
  224.    $end Asm
  225.  
  226. Return
Awatar użytkownika
Michał6201
Posty: 127
Rejestracja: 03 paź 2015, 20:07

Re: Przetwornik DAC do zasilacza

Post autor: Michał6201 » 10 kwie 2021, 18:12

Dziękuję Ci bardzo. W życiu bym tego nie ogarnął.

Teraz sobie zrobiłem ten kod na dwa enkodery, Jeden służy do ustawiana napięcia, a drugi do ustawienia ograniczenia prądowego.

Jedn enkoder działa na INT1, a drugi na INT0
ODPOWIEDZ