Beste allemaal,
Het is weer eens raak, ik heb een wazig probleem met een PIC en ik ben intussen echt door mijn ideeën heen.
Ik ben bezig met een Battery Management System. Ja ze zijn ook kant en klaar te krijgen maar die doen niet precies wat ik wil, daarbij vind ik zelf maken leuker .
Het probleem: Ik heb het onboard eeprom in PIC's al in meerdere projecten zonder veel uitdaging gebruikt. Je geeft het adres en je leest of schrijft dat adres. Niet veel bijzonders... Nu ben ik bezig om tijdens het gebruik van de accu de capaciteit te bepalen, dwz: de actuele state of charge wordt berekend op basis van de beste gegevens die op dat moment aanwezig zijn. Het is infeite een zelf lerend systeem dat gaandeweg de capaciteit meet en telkens bij stelt als deze veranderd is of voor bijvoorbeeld zelfontlading compenseert. Om deze gegevens niet kwijt te raken zodra de accu (tijdelijk) helemaal uitgeschakeld wordt schrijf ik de belangrijkste gegevens naar EEPROM en lees deze weer terug tijdens het opstarten van de PIC. De hele code is vrij veel dus heb ik het hieronder samen gevat tot de interessante stukken.
Het vreemde is nu dat als ik de EREAD in de initialisatie boven de CLEAR zet, de berekening werkt zoals bedoeld, behalve dat (natuurlijk) het terug lezen van de gevens niet werkt. Deze worden tenslotte vrijwel direct daarna weer uit het RAM gewist door de clear.
Zet ik de EREAD net onder de clear werkt de berekening niet meer en blijven de waardes constant op 0 staan. Mijn vermoeden is dat dat de waarde is die vanuit het eeprom gelezen wordt en telkens overschreven wordt door die 0. Maak ik van die regels even een comment dan werkt de berekening gewoon weer.
Het lijkt dus haast alsof de PIC elke keer de hele software doorloopt IPV alleen het stuk tussen "hoofdlus" en "goto hoofdlus" met de bijbehorende subroutines. Terwijl de "INITIALISATIE START" niet telkens opnieuw voorbij komt op de seriele poort.Ik kan alleen niet ontdekken wat er dan voor zorgt dat de pic weer helemaal bovenaan begint.
De twee tellers in de interrupt dienen alleen maar om bepaalde berekeningen niet al te vaak te doen omdat ik hier veel met floats reken en dat relatief veel tijd kost. En om het aantal writes naar het EEPROM een beetje te beperken. Het EEPROM zal op z'n hoogst elke 5 min geschreven worden, als de waarde in EEPROM en RAM gelijk is wordt het niet geschreven.
Alle hulp of zelfs maar een zetje in de goede richting wordt zeer op prijs gesteld!!!
Alvast bedankt.
Vriendelijke groet,
Daan Steeman
pic basic code:
Device = 16F1938
Config1 FOSC_HS, WDTE_OFF, PWRTE_OFF, MCLRE_OFF, CP_OFF, CPD_OFF, BOREN_OFF, CLKOUTEN_OFF, IESO_OFF, FCMEN_OFF
Config2 WRT_OFF, VCAPEN_OFF, PLLEN_OFF, STVREN_OFF, BORV_19, LVP_OFF
All_Digital false ;Alle ingangen digitaal
Xtal = 20
Declare Hserial_Baud = 38400 ; Set baud rate to 38400
Declare Hserial_RCSTA = %10010000 ; Enable serial port and continuous receive
Declare Hserial_TXSTA = %00100000 ; Enable transmit and asynchronous mode
Declare Hserial_Clear = On ; Optionally clear the buffer before receiving
Declare Adin_Res 10 ; an/dig converter resolutie van 10 bits
Declare Adin_Stime 500 ; sampletime van 1000us
OPTION_REG.7 = 0
;76543210
ADCON1 = %10000000
ANSELA = %00001111 ; van A0, A1, A2 ANologe ingang maken
ANSELB = %00100000 ; Poortb uitgangen digitale uitgangen maken
INTCON =%01100010
T1CON = %00110101
PIE1 = %00000001
T1GCON =%00000000
T2CON.2 = 1
APFCON = %01000000 ; CCP3 op pin b.5 zetten
CCPTMRS0 = %00000000 ; timer 2 word gebruikt voor alle ccpmodules
CCPTMRS1 = %00000000 ; timer 2 word gebruikt voor alle ccpmodules
PR2 = %11111011 ; timer2 instellen op ongeveer 2000Hz
CCP1CON = %00001100 ;alleen PxA word gemoduleerd. de overige worden als portpins geset
CCP2CON = %00001100 ;alleen PxA word gemoduleerd. de overige worden als portpins geset
CCP5CON = %00001100 ;alleen PxA word gemoduleerd. de overige worden als portpins geset
On_Hardware_Interrupt GoTo Interrupthandler
Symbol EElaagstesom = 0;1,2,3
Symbol EEhoogstesom = 4;5,6,7
Symbol EEsom = 8;9,10,11
Symbol EESOC = 12;13,14,15
Dim Som As Float ; elke seconde word hierbij de capaciteit in Wh bij opgeteld/afgetrokken om het netto van in en uitgaande stroom te krijgen
Dim Hoogstesom As Float ; de hoogste waarde die "SOM" ooit gehad heeft
Dim Laagstesom As Float ; de laagste waarde die "SOM" ooit gehad heeft
Dim SOC As Float ; actuele state of charge in procenten
Clear
HSerOut ["INITIALISATIE start", $0D]
Som = ERead EEsom
Hoogstesom = ERead EEhoogstesom
Laagstesom = ERead EElaagstesom
SOC = ERead EESOC
; Overige initialisatie van overige componenten en berekeningen
INTCON.7 = 1 ;alle intterupts inschakelen
Hoofdprogramma:
;een hele berg aan berekeningen voor dingen als cellen balancen, actuele stroom en spanningen bepalen
SerIn BUSRX, 84, 1000, Timeout1, [Wait("SIG"),Str RXbuffer];wachten op de vraag van de master voor gegevens
Verder:
Select RXbuffer[0]
Case 1
Output BUSTX
SerOut BUSTX, I9600, ["SIG",Dec3 Vcell1, ",", Dec3 Vcell2, ",", Dec3 Vcell3, ",", Dec3 ActueleStroom, $0D, "xxxxxxxxx"] ; die gegevens terug sturen
Input BUSTX
EndSelect
GoTo Hoofdprogramma
End
Timeout1:
GoTo Hoofdprogramma
Interrupthandler:
Context Save
INC Secondeteller
INTCON.7 = 0
;metingen verrichten
;bepalen (zonder al te veel berekeningen) of alle waardes (voornamelijk de celvoltages) binnen de veilige marges liggen
If Secondeteller > 10 Then
; actuele State Of Charge berekenen
Som = Som + (ActueleStroom * Vtot/3600)
If Som > Hoogstesom Then Hoogstesom = Som
If Som < Laagstesom Then Laagstesom = Som
SOC = ((Som - Laagstesom) / (Hoogstesom - Laagstesom))*100
If Vtot > 12.3 And ActueleStroom < 0.5 Then Hoogstesom = Som
If Vtot < 9 Then Laagstesom = Som
HSerOut [Dec5 Som, $09, Dec5 Laagstesom, $09, Dec5 Hoogstesom, $09, Dec5 SOC, $0D]
Secondeteller = 0
Inc Vijfminteller
EndIf
If Vijfminteller > 300 Then
If Hoogstesom != ERead EEhoogstesom Then EWrite EEhoogstesom, [Hoogstesom]
If Laagstesom != ERead EElaagstesom Then EWrite EElaagstesom, [Laagstesom]
If Som != ERead EEsom Then EWrite EEsom, [Som]
If SOC != ERead EESOC Then EWrite EESOC, [SOC]
Vijfminteller = 0
EndIf
INTCON.7 = 1
Context Restore
End