Balanser Li.xxx, Atmega32+MCP3424


Witam.
Na początku oświadczam że nie jestem bystry w Bascom i proszę o wyrozumiałość.
Chodzi mi o to aby pomiary były wyświetlane na wyświetlaczu 4x20 znaków. Cały program opiera się o Atmega32 oraz przetwornik MCP3424 bo takie posiadam, i w takowej konfiguracji wszystko działa elegancko, poza jednym faktem że nie wiem jak rozbudować kod aby wyniki były wyświetlane sekwencyjnie - ch1; B1=4.20V, ch2; B2=4.20V, ch3; B3=4.20V; ch4; B4=4.20V.
Adresy tych kanałów MCP3424 to:
&B&B10011100 - ch1, &B10111100 - ch2, &B11011100 - ch3, &B11111100 - ch4.
Tak miej więcej miałoby wyglądać na lcd.
Dodam że próbowałem z powieleniem obszaru programu Do ..... Loop i taka metoda jest nie za bardzo funkcjonalna.
Zapewne można by użyć instrukcji;

Select Case
lecz nie potrafię tego zrobić.


'$sim
$regfile = "m32def.dat"
$crystal = 16000000
Rem =============================================
 'Ustawienia wyświetlacza LCD 4*20
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 20 * 4
Cls
 Cursor Off
Waitms 500
Locate 1 , 1
Lcd " Monitor i Balancer"
Waitms 200
Locate 2 , 1
Lcd " Li-ion, Li-Fe, Pb."
Waitms 200
Locate 3 , 1
Lcd "Karol Ferenc 2014(c)"
Waitms 200
Locate 4 , 1
Lcd "wersja 2.0 - U.L.A."
Waitms 1000
 Cls
 
 Waitms 100
'Config Portc = Output                                       'wszystkie końcówki jako wyjścia
'       Portc = &B11100000
Config I2cdelay = 20
Config Sda = Portc.1
Config Scl = Portc.0
Config Single = Scientific , Digits = 3
 
'Const Addressw = 210                                        'slave write address  210
'Const Addressr = 211                                        'slave read address   211
Const Addressw = 208                                        'slave write address
Const Addressr = 209                                        'slave read address
Rem **************** Zmienne **************
 
Dim Pomiar1 As Byte
Dim Pomiar2 As Byte
Dim Pomiar3 As Byte
Dim Pomiar4 As Byte
 
Dim Nap1 As Long
Dim Nap2 As Long
Dim Nap3 As Long
Dim V1 As Single
Dim Vref As Single
 
Do
' Gosub B1
' Gosub B2
' Gosub B3
' Gosub B4
 
 V1 = 0
 Vref = 0
 
 I2cinit
 I2cstart
 I2cwbyte Addressw                                          '&HD2 Adrest układu MCP3421 A1T
 'I2cwbyte &B10010000                                       'Adres 12bit
 'I2cwbyte &B10010100                                       'Adres 14bit
 'I2cwbyte &B10011000                                       'Adres 16bit
  I2cwbyte &B10011100                                       'Adres 18bit  3,75 SPS
 I2cstop
 
 I2cstart
 I2cwbyte Addressr                                          '&HD3 Adrest układu MCP3421 A1T
 I2crbyte Pomiar1 , Ack                                     ' górna wartość
 I2crbyte Pomiar2 , Ack                                     ' średnia wartość
 I2crbyte Pomiar3 , Ack                                     ' dolna wartość
 I2crbyte Pomiar4 , Nack                                    ' koniec pomiaru
 I2cstop
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
  Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
 
If Pomiar1 = 255 Then V1 = 0
 Vref = Fusing(v1 , "#.###")
  Locate 1 , 1 : Lcd "B1=" ; V1 ; " "
Waitms 100
'Return
Loop
End

Dlaczego wybór padł na MCP3424 bo sterowanie odbywa się przez I2c i ma przyzwoite parametry.




Portret użytkownika EDC

Odp. Balanser Li.xxx, Atmega32+MCP3424

To chyba nieskomplikowane.. Bartek Ci to pomoże napisać. Rozumiem, że te adresy zmieniać się maja tutaj?

I2cwbyte &B10011100                                       'Adres 18bit  3,75 SPS

-

BARTek
Moja strona

Portret użytkownika Karlos123

Zgadza się. To te miejsce

Zgadza się. To te miejsce

I2cwbyte &B10011100 


Tak sobie siedzę przerabiam ten program, jedno dodaje drugie usuwam i sprawdzam w symulatorze i jak na razie jeszcze nie osiągnąłem rezultatu.Oto fragment przeróbki. Na wyświetlaczu nic niema poza startowym ekranem.
Dim Pomiar1 As Byte
Dim Pomiar2 As Byte
Dim Pomiar3 As Byte
Dim Pomiar4 As Byte
 
Dim Nap1 As Long
Dim Nap2 As Long
Dim Nap3 As Long
Dim V1 As Single
Dim Vref As Single
Dim I As Byte
Dim Chanel As Word
Do
   For I = 1 To 4
     V1 = 0
 Vref = 0
    Select Case I
         Case 1 : Chanel = &B10011100 : Then Gosub B1       'CH0
         Case 2 : Chanel = &B11001100 : Then Gosub B2       'CH1
         Case 3 : Chanel = &B10111100 : Then Gosub B3       'CH2
         Case 4 : Chanel = &B11111100 : Then Gosub B4       'CH3
 
      End Select
 
 
 I2cinit
 I2cstart
 I2cwbyte Addressw                                          '&HD2 Adrest układu MCP3421 A1T
 'I2cwbyte &B10010000                                       'Adres 12bit
 'I2cwbyte &B10010100                                       'Adres 14bit
 'I2cwbyte &B10011000                                       'Adres 16bit
  I2cwbyte Chanel                                           ' &B10011100                              'Adres 18bit  3,75 SPS
 I2cstop
 
 I2cstart
 I2cwbyte Addressr                                          '&HD3
 I2crbyte Pomiar1 , Ack                                     ' górna wartość
 I2crbyte Pomiar2 , Ack                                     ' średnia wartość
 I2crbyte Pomiar3 , Ack                                     ' dolna wartość
 I2crbyte Pomiar4 , Nack                                    ' koniec pomiaru
 I2cstop
 
 
 
Loop
 
B1:
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
   Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
If Pomiar1 = 255 Then V1 = 0
  Home
 Vref = Fusing(v1 , "#.###")
  Locate 1 , 1 : Lcd "B1=" ; V1 ; " "
 Waitms 100
 
 
B2:
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
    Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
If Pomiar1 = 255 Then V1 = 0
  Home
 Vref = Fusing(v1 , "#.###")
  Locate 2 , 1 : Lcd "B2=" ; V1 ; " "
 Waitms 100
 
 
B3:
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
    Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
If Pomiar1 = 255 Then V1 = 0
  Home
 Vref = Fusing(v1 , "#.###")
  Locate 3 , 1 : Lcd "B3=" ; V1 ; " "
 Waitms 100
 
 
B4:
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
     Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
 If Pomiar1 = 255 Then V1 = 0
   Home
 Vref = Fusing(v1 , "#.###")
  Locate 1 , 11 : Lcd "B4=" ; V1 ; " "
 Waitms 100
 Next I
End

Portret użytkownika EDC

Balancer

Prosze. Testnij ;)

'$sim
$regfile = "m32def.dat"
$crystal = 16000000
$hwstack = 128
$swstack = 64
$framesize = 64
Rem =============================================
 'Ustawienia wyświetlacza LCD 4*20
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 20 * 4
Cls
 Cursor Off
Waitms 500
Locate 1 , 1
Lcd " Monitor i Balancer"
Waitms 200
Locate 2 , 1
Lcd " Li-ion, Li-Fe, Pb."
Waitms 200
Locate 3 , 1
Lcd "Karol Ferenc 2014(c)"
Waitms 200
Locate 4 , 1
Lcd "wersja 2.0 - U.L.A."
Waitms 1000
 Cls
 
 Waitms 100
'Config Portc = Output                                       'wszystkie końcówki jako wyjścia
'       Portc = &B11100000
Config I2cdelay = 20
Config Sda = Portc.1
Config Scl = Portc.0
Config Single = Scientific , Digits = 3
 
'Const Addressw = 210                                        'slave write address  210
'Const Addressr = 211                                        'slave read address   211
Const Addressw = 208                                        'slave write address
Const Addressr = 209                                        'slave read address
Rem **************** Zmienne **************
Dim Index As Byte
Dim Linia As Byte
Dim Pozyc As Byte
Dim Batt_nr As String * 3
 
Dim Pomiar1 As Byte
Dim Pomiar2 As Byte
Dim Pomiar3 As Byte
Dim Pomiar4 As Byte
 
Dim Nap1 As Long
Dim Nap2 As Long
Dim Nap3 As Long
Dim V1 As Single
Dim Vref As Single
 
'*** START ***
Do
 
Gosub Read_mpc
 
Waitms 100
 
Loop
End
'*** KONIEC ***
 
 
 
Read_mpc:
Incr Index
  If Index = 5 Then Index = 1
 
 V1 = 0
 Vref = 0
 
 I2cinit
 I2cstart
 I2cwbyte Addressw                                          '&HD2 Adrest układu MCP3421 A1T
 'I2cwbyte &B10010000                                       'Adres 12bit
 'I2cwbyte &B10010100                                       'Adres 14bit
 'I2cwbyte &B10011000                                       'Adres 16bit
     Select Case Index
       Case 1
        I2cwbyte &B10011100                                 'Adres 18bit  3,75 SPS
       Case 2
        I2cwbyte &B10111100                                 'Adres 18bit  3,75 SPS
       Case 3
        I2cwbyte &B11011100                                 'Adres 18bit  3,75 SPS
       Case 4
        I2cwbyte &B11111100                                 'Adres 18bit  3,75 SPS
      End Select
 I2cstop
 
 I2cstart
 I2cwbyte Addressr                                          '&HD3 Adrest układu MCP3421 A1T
 I2crbyte Pomiar1 , Ack                                     ' górna wartość
 I2crbyte Pomiar2 , Ack                                     ' średnia wartość
 I2crbyte Pomiar3 , Ack                                     ' dolna wartość
 I2crbyte Pomiar4 , Nack                                    ' koniec pomiaru
 I2cstop
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
  Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
 
  Select Case Index
   Case 1
    Batt_nr = "B1="
    Linia = 1
    Pozyc = 1
   Case 2
    Batt_nr = "B2="
    Linia = 2
    Pozyc = 1
   Case 3
    Batt_nr = "B3="
    Linia = 3
    Pozyc = 1
   Case 4
    Batt_nr = "B4="
    Linia = 1
    Pozyc = 10
  End Select
 
   If Pomiar1 = 255 Then V1 = 0
 Vref = Fusing(v1 , "#.###")
  Locate Linia , Pozyc : Lcd Batt_nr ; V1 ; " "
 
Return

-

BARTek
Moja strona

Portret użytkownika Karlos123

Teraz to już postęp, wszystko

Teraz to już postęp, wszystko się wyświetla na lcd tylko jak pominę tą linię

 If Pomiar1 = 255 Then V1 = 0
to wyświetlany wynik nie skacze raz max a raz min. A czy można dodać jeszcze jeden układ tak aby po całej sekwencji pierwszego rozpoczął się odczyt z drugiego, ma to na celu iż balanser będzie 6-scio kanałowy, a jeden scalak ma tylko 4 kanały. Adresowanie ustawia się na zworce "A0,A1 piny" i w sofcie.

Portret użytkownika EDC

Odp. Balancer

Wiesz co, jak bym przeczytał notę do tego układu to już cale bym to napisał :P i nic by nie zostało dla Ciebie.
A tak to tylko przeczytalem to co zamieściłes :D Nie wiem o co tam chodzi z brakiem tego odczytu. Ma być robiony co jakiś czas czy jak?
Poniżej kod na dwa układy ;)

$sim
$regfile = "m32def.dat"
$crystal = 16000000
$hwstack = 128
$swstack = 64
$framesize = 64
Rem =============================================
 'Ustawienia wyświetlacza LCD 4*20
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
Config Lcd = 20 * 4
Cls
 Cursor Off
Waitms 500
Locate 1 , 1
Lcd " Monitor i Balancer"
Waitms 200
Locate 2 , 1
Lcd " Li-ion, Li-Fe, Pb."
Waitms 200
Locate 3 , 1
Lcd "Karol Ferenc 2014(c)"
Waitms 200
Locate 4 , 1
Lcd "wersja 2.0 - U.L.A."
Waitms 1000
 Cls
 
 Waitms 100
'Config Portc = Output                                       'wszystkie końcówki jako wyjścia
'       Portc = &B11100000
Config I2cdelay = 20
Config Sda = Portc.1
Config Scl = Portc.0
Config Single = Scientific , Digits = 3
 
Const Addressw2 = 210                                       'slave write address  210
Const Addressr2 = 211                                       'slave read address   211
Const Addressw1 = 208                                       'slave write address
Const Addressr1 = 209                                       'slave read address
Rem **************** Zmienne **************
Dim Index As Byte
Dim Linia As Byte
Dim Pozyc As Byte
Dim Batt_nr As String * 3
 
Dim Adres_wpis As Byte
Dim Adres_odcz As Byte
 
Dim Pomiar1 As Byte
Dim Pomiar2 As Byte
Dim Pomiar3 As Byte
Dim Pomiar4 As Byte
 
Dim Nap1 As Long
Dim Nap2 As Long
Dim Nap3 As Long
Dim V1 As Single
Dim Vref As Single
 
'*** START ***
Do
 
Gosub Read_mpc
 
Waitms 100
 
Loop
End
'*** KONIEC ***
 
 
 
Read_mpc:
Incr Index
  If Index = 7 Then Index = 1
   If Index <= 4 Then Adres_wpis = Addressw1 Else Adres_wpis = Addressw2
   If Index <= 4 Then Adres_odcz = Addressr1 Else Adres_odcz = Addressr2
 
 V1 = 0
 Vref = 0
 
 
 I2cinit
 I2cstart
 I2cwbyte Adres_wpis                                        '&HD2 Adrest układu MCP3421 A1T
 'I2cwbyte &B10010000                                       'Adres 12bit
 'I2cwbyte &B10010100                                       'Adres 14bit
 'I2cwbyte &B10011000                                       'Adres 16bit
     Select Case Index
       Case 1
        I2cwbyte &B10011100                                 'Adres 18bit  3,75 SPS
       Case 2
        I2cwbyte &B10111100                                 'Adres 18bit  3,75 SPS
       Case 3
        I2cwbyte &B11011100                                 'Adres 18bit  3,75 SPS
       Case 4
        I2cwbyte &B11111100                                 'Adres 18bit  3,75 SPS
       Case 5
        I2cwbyte &B10011100                                 'Adres 18bit  3,75 SPS
       Case 6
        I2cwbyte &B10111100                                 'Adres 18bit  3,75 SPS
      End Select
 I2cstop
 
 I2cstart
 I2cwbyte Adres_odcz                                        '&HD3 Adrest układu MCP3421 A1T
 I2crbyte Pomiar1 , Ack                                     ' górna wartość
 I2crbyte Pomiar2 , Ack                                     ' średnia wartość
 I2crbyte Pomiar3 , Ack                                     ' dolna wartość
 I2crbyte Pomiar4 , Nack                                    ' koniec pomiaru
 I2cstop
 
  Nap1 = 65536 * Pomiar1
  Nap2 = 256 * Pomiar2
 
  Vref = Nap1 + Nap2
  Vref = Vref + Pomiar3
 
  Vref = Vref * 2.048
  Vref = Vref * 5
  V1 = Vref / 131071
 
  Select Case Index
   Case 1
    Batt_nr = "B1="
    Linia = 1
    Pozyc = 1
   Case 2
    Batt_nr = "B2="
    Linia = 2
    Pozyc = 1
   Case 3
    Batt_nr = "B3="
    Linia = 3
    Pozyc = 1
   Case 4
    Batt_nr = "B4="
    Linia = 1
    Pozyc = 10
   Case 5
    Batt_nr = "B5="
    Linia = 2
    Pozyc = 10
   Case 6
    Batt_nr = "B6="
    Linia = 3
    Pozyc = 10
  End Select
 
   If Pomiar1 = 255 Then V1 = 0
 Vref = Fusing(v1 , "#.###")
  Locate Linia , Pozyc : Lcd Batt_nr ; V1 ; " "
 
Return

-

BARTek
Moja strona

Portret użytkownika Karlos123

Jestem Ci bardzo wdzięczny za

Jestem Ci bardzo wdzięczny za wszelką okazaną mi pomoc, a co do tego przetwornika MCP3424 to podaję link - http://ww1.microchip.com/downloads/en/DeviceDoc/22088b.pdf
Może ja czegoś po prostu nie zrozumiałem z tych informacji. Jeśli po twojej analizie będzie konieczna zmiana w sofcie to byłbym bardzo wdzięczny.

Portret użytkownika EDC

Odp. Balancer

Nigdy nie używałem zewnętrznego ADC. Tak pobieżnie patrząć to SPS oznacza Samples Per Second - ilośc odczytów na sekundę. Jeśli sam wybierasz SPS 3,7 to nie można chyba odwiedzać ADC częściej niż co 300ms. Jeśli dane nie są gotowe to zwraca bład czy jakoś tak. Nie musisz chyba znać napięcia co 100ms. Spróbuj pozmieniać czasy. Czytanie całości mi się nie uśmiecha ..ale może z ciekawości :)

-

BARTek
Moja strona

Portret użytkownika Karlos123

Balancer

Witaj Bartek, sam program który przerobiłeś jest cacy! Natomiast jeśli chodzi o dziwne liczby na wyświetlaczu np. Vin=0.5V to pokazywał 1307.xxxxx-e takie śmieci lub jak to określiłeś błędem zwrotnym. Jak zmieniłem

 Dim Pomiar1 As Byte
Dim Pomiar2 As Byte
Dim Pomiar3 As Byte
Dim Pomiar4 As Byte
na
Dim Pomiar1 As Word
Dim Pomiar2 As Word
Dim Pomiar3 As Word
Dim Pomiar4 As Word
to te wyniki nabrały porządnego sensu i są prawidłowe. Teraz jak już to wszystko działa to czy można wrzucić na taki zestaw:
Procek atmega128 lub atxmega128a1 , wyświetlacz graficzny 192x64, klawiatura 4x4.? chodzi oto że projekt będzie rozwijany i uniwersalny.
Moje założenie to zasilacz 0-30V , 0-10A, ładowarka, balancer itp.

Portret użytkownika EDC

Odp. Balancer

Wszystko można. Program przepisałem tak że czytanie odbywa się sekwencyjnie po jednym odczycie czyli nie trwa długo. Można bezproblemowo dodać obsługe klawiatury a wyświetlanie przesunąć do osobnego podprogramu.
Nie wiem czy nie będzie Ci przeszkadzać że Xmegi sa 3,3 volt`owe.
Można oczywiście działać na dużym procesorze, ale ja jeszcze nie napisałem programu który byłby większy niż 64KB. Bardziej przydają się dodatkowe piny mikrokontrolera.
Zastanawiałbym się jak bym miał coś kupić, ale jak już coś masz to składaj na tym co masz :D

-

BARTek
Moja strona

Portret użytkownika Karlos123

Balancer

Faktycznie xmegi są zasilana 3.3Vi to jest trochę kłopotliwe, można by stosować translatory napięć, ale za to powiększają się i koszty i PCB itd.
Zastosuje atmega128 bo taki posiadam, a ilość pinów sterujących jest w zupełności wystarczająca nawet z wyświetlaczem graficznym i tą klawiaturą, i pomiarem temp 2xDS18B20. Ciekawi mnie jeszcze jedna sprawa, czy odblokowanie przerwań i timerów nie będzie zakłócało pracy odczytu przetworników bo jak prubuję włączyć np. Enable Interrupts to głupoty chińszczyzna wyświeta się. Posiadam jeszcze przetwornik MCP3208 12bit i MCP3304 13bit, ale ich sterowanie odbywa się w spi no i dla mnie to też czarna magia. Co do tego mcp3208 to program balancera i sam balanser spisuje się lepiej i odczyty są szybsze w porównaniu MCP3424 który próbuję uruchomić. Teraz cały czas testuję w symulatorze w przeróżnych wariantach tego mcp3424.

Portret użytkownika EDC

Odp. Balancer

Quote:
jak próbuję włączyć np. Enable Interrupts to głupoty chińszczyzna wyświeta się

Tak się dzieje bo, pewnie nieświadomie, używasz programowej I2C.
I2C wymyślił i opatentował Philips. Atmel nie mógł go na początku używać więc by móc się komunikować z układami wyposażonymi w te magistrale obsługiwał je programowo. Po pewnym czasie opracowali swoje rozwiązanie i nazwali TWI (Two Wire Interface). Od tej pory sa one wbudowane jako osobny moduł sprzętowy jak Timer, Uart lub SPI. Moduł TWI nie ma problemów z przerwaniami. Działa obok jak piec w kotłowni. Softwarowe/programowe I2C to nic innego jak program który macha pinami i jego działanie można przerwać własnie przerwaniem. Teraz to do czego zmierzam.
Jeśli procesor posiada sprzętowe TWI to należy z niego korzystać. Włącza się je powołując do programu bibliotekę która to obsługuje. Co ciekawe nawet kod programu się zmniejsza ;) Trzeba jednak podłączyć się do pinów oznaczonych w nocie jako SDA i SCL.
To trzeba wpisać gdzieś na początku programu zanim użyjesz I2C
$LIB "I2C_TWI.LBX"

Jeśli tylko masz chęci to za niedługo będziesz wiedział tyle samo albo więcej :)
Warto mieć pod ręką polskiego Helpa (jak nie znajdziesz to daj znać na maila to Ci linknę ;) i skrót do Wiki Bascom w przeglądarce :D http://wiki.mcselec.com/bavr/BASCOM-AVR_Help
Tam można przeczytać o innych bibliotekach do TWI (I2Cv2.lib, I2c.lib)
SPI jest proste. Mniej "typowe" układy można obsłużyć poleceniami Shiftout i Shiftin. Kliknij na opis w wiki ;)

Na końcu przerwania trzeba przemyśleć. Czyli te cykliczne ustawić na największe czasy jakie Ci są potrzebne, albo możesz ustawić. Programowanie to chęci plus umiejętności i pomysłowość w rozwiązywaniu problemów ;)
Niech Ci lutownica dobrze grzeje a procesor słucha hahahahaha :D

-

BARTek
Moja strona