Eventuell kann jemand hier etwas damit anfangen: Die aufgabenstellung ist: Es müßen 2 - 20 accus überwacht werden, bzw, ihr lade/entladeverhalten. Die daten sollen per serieller schnittstelle übertragen werden und zwar im klartext. Da an den accus hohe spannungen auftreten können, dürfen max 2 accus an einem kontroller hängen und jede schaltung muß von der anderen , galvanisch, getrennt werden. Als zielplatform wurde ein Tiny85 gewählt ( overkill !! ). Die auswahl auf dem prozessor ist gefallen, weil (mind) zwei ADC vorhanden sind und der pinchange-INT vorhanden ist. Da die anzahl der überwachten teile nie gleich ist, wurde dieDaisy Chain gewählt. Und die daten werden auf einen Open-Collector-Ausgang gegeben. Um das zu bewerkstelligen und auch die eindeutige identifikation des jeweiligen messeinganges zu gewährleisten, muß es also einen master geben und slaves. Der master ist , per definition die nummer 1 und 2. Ist er mit der messung und übertragung seiner daten fertig, gibt er einen Übertragungsimpuls aus. Dieser impuls wird auf einen Interrupteingang des folgenden prozessors gegeben. Sobald dieser ausgelöst wird, misst auch er seine daten und sendet sie. So geht es dann bis zum letzen weiter. Da ich aber den Quelltext nicht für master und slave aufspalten wollte und die schaltung auch universell sein soll, fragt der prozessor , beim start, ob der strobeeingang kurzgeschlossen ist, wenn er es ist, dann wird aus ihm ein master. Der vorteil dieses vorgehens ist, die daten kommen in geordneter reihenfolge af dem bus ..... var i:word; begin DDRB:=0; portb.0:=1; // strobe in pullup DDRB.1:=1; portb.1:=1; // strobe out if pinb.0 = 0 then // testen ist pin 0 gegen masse gezogen ? delay_ms(200);// länger warten, als der strobe dauert slave:=pinb.0; // wert zuweisen 1 = slave , 0 = master err:=Soft_UART_Init(PORTB,3,4,9600,1); // Initialize Soft UART at 9600 bps invertierte logic !! adc_set; temp:=0; GIMSK:= 1 shl PCIE; // turns on pin change interrupts PCMSK:= 1 shr pcint0; // turn on interrupts on pin PB0 SREG_I_bit := 1; // Interrupt enablefür slavebetrieb //slave:=0; while TRUE do // Endless loop begin if slave = 0 then begin Soft_UART_Write(#13); Soft_UART_Write(#10); send_data; end else begin MCUCR.5:=1; MCUCR.1:=1; asm sleep; end; end; end; { Main program } end.
Das datenprotokoll ist #13(return) #10 (newline) DATENSTRING und als abschluß ';' Wenn der prozessor als master läuft sendet er die startsequenz Soft_UART_Write(#13); Soft_UART_Write(#10); send_data; Ist er ein slave , dan sendet die routine nur die daten mit einem ';' als seperator. procedure PCint0_Interrupt(); org IVT_ADDR_PCINT0; begin MCUCR.5:=0; SREG_I_bit:= 0; delay_ms(1); if pinb.0 = 0 then send_data; SREG_I_bit:= 1; end; Die daten werden aufbereitet und per Euklidischen Algorithmus in einem string umgewandelt und per serieller schnittstelle ausgegeben. procedure eukl(ein:word); var e,r,eing:word; c,val:byte; begin eing:=ein; e:=100; for c:=1 to 3 do begin r:=(eing div e); val:='0'+r; // spart 2 Byte Soft_UART_Write(val); eing:=eing - r*e; e:=e div 10; end; Soft_UART_Write(';'); end; als anhang der quellcode
Zur harware: Es werden 1 Tiny benötigt 2 x 9,8k widerstand , 3 x 82k widerstände ( diese können angepasst werden ) 2 x 330 ohm für die optokoppler. 2 x optokoppler ( 4 Pin ) 1 x Spannungsregler 78L05 ( oder eben ein 3,3V modell ), bei bedarf. Wenn die batterie unter 5 Volt nennspannung liegt, kann der regler fallengelassen werden. 1x Elektrolytcondensator 5V 45yF 2x 100nF Kondensator Das platinenlayout liegt als Target3001 vor Leider komme ich mit dem schaltplaneditor nie so zurecht, so daß ich die platine immer von hand zeichen und dann die beschriftung lösche ( der aufdruck ist eh zu eng ). In dem stromlaufplan ist der pin0 ohne anschluss, dieser geht dann an den optokoppler des vorhergehenden prozessors. Wenn er kein vorgänger hat, dann wird er gegen masse gelegt und der prozessor geht davonn aus, daß er zum master wird. Natürlich kann man damit auch andere messwerte aufnehmen und dann auswerten, es muß dann nur eine andere aufbereitung der ADC daten erfolgen. Es hat sich herausgestellt, daß die , interne, referenz sehr streut. Wenn das stört, muß man das konzept auf einen kanal abändern und eine externe referenz anschließen. Im aktuellen falle versorgt die zu messende batterie die schaltung. Zum brennen des Flashes : 8MHZ int Osz , brownout auf 2,7V stellen Für fragen und anregungen binn ich immer zu haben .... Gruß Michael
:
Bearbeitet durch User
UART (egal, ob HW oder SW) und interner Oszillator ist eine wackelige Angelegenheit. Funktioniert nur zuverlässig, mit konstanter Betriebsspannung, Temperatur und Oszillator-Kalibrierung. Würde, wenn wie hier, die Beinchen nicht reichen, auf einen TinyX4er mit externem Quarz ausweichen. mfG
Danke für die antwort .. ja das ist richtig, ich habe das arme ding auf -30 grad gekühlt und auf 90 grad aufgeheizt .. der datenstrom ist nie abgerissen und die messwerte haben um ca 3 -5% gewackelt. Der Fehler, der enststeht, ist hier durch einen rechenterm so angepasst, daß der kritische bereich ( hinreichend ) genau ist In der schaltung ist es nun wahrlich kein präzisionsgerät :-) ABer hier ging es darum, es darf nix kosten und es geht eher um das dynamische verhalten der batterie. Und die schaltung mußte klein und trotzdem mit dem vorschlaghammer aufzubauen sein. Aber das mit x4 ist schon eine schöne sache ... http://fabacademy.org/archives/2013/students/anderson.douglas/week%208%20-%20embedded%20programming.html Das wäre etwas für messwertaufnehmer, die höhere präzision haben sollten und wo die spannung am eingang nicht so dramatisch ist ... Aber du hast mich noch auf die idee gebracht, den internen temperatursensor zu verwursten, wenn die genauigkeit erhöht werden muß.
Michael F. schrieb: > Als zielplatform wurde ein Tiny85 gewählt ( overkill !! ). > Die auswahl auf dem prozessor ist gefallen, weil (mind) zwei ADC > vorhanden sind und der pinchange-INT vorhanden ist. Ich weiß, ich bin da jetzt etwas kleinlich, aber nur zur Klarheit: Es ist nur ein ADC, nicht zwei. Du hast im Attiny85 nur mehrere ADC-Kanäle, d.h. du kannst (und musst) den Eingang des ADCs auf einen anderen Pin umschalten. Schaltpläne immer leserlich gestalten, Bauteilwerte sollten z.B. nicht in Bauteilen drin stehen. Dein Plan könnte hier noch etwas Feinschliff vertragen. Michael F. schrieb: > Zum brennen des Flashes : 8MHZ int Osz , brownout auf 2,7V stellen Hier am besten die Fuses angeben, dann ists eindeutiger ;) Dann noch eine Bitte: Es gibt Code-Tags, die werden einem beim Erstellen von einem Post auch immer angezeigt (oberhalb des Usernamens). Bitte diese auch benutzen, das vereinfacht doch das Lesen von Code ungemein. Bei dir wäre wohl [ code ]Code[ /code ] (ohne die Leerzeichen) angebracht gewesen da es kein C-Code ist, für C-Code gibts [ c ]C-Code[ /c ]. Ansonsten aber: Tolles Projekt, danke für die Veröffentlichung.
Danke für die Info : Also es läuft, wie gedacht, nur .... und danke an den ULRICH und sein SerialComInstruments zur visualisierung. Wenn ich zwei eingänge benutze, zeigt ein eigang ein offset von 0,2V an , der fehler bleibt auch wenn ich beide eingänge gegen masse schalte. Da das systematisch ist, kann ja einfach den wert abziehen, aber seltsam ist es schon ... hier die leseroutine :
1 | function adc_r(ch:byte):word; |
2 | var r:word; |
3 | begin |
4 | ADMUX:=(ADMUX and not(0x1F)) or (ch and 0x1F); // and 0x1F wird eigentlich nicht gebraucht |
5 | ADCSRA:=ADCSRA or (1 shl ADSC); // Starte umwandlung |
6 | |
7 | while ((ADCSRA and (1 shl ADSC)) =(1 shl ADSC)) // warte bis fertig |
8 | do; |
9 | |
10 | r:=ADCl; |
11 | r:=r or ADCh shl 8; |
12 | result:=r shr 6; |
13 | end; |
14 | |
15 | function read_med(ch:byte):word; // wird noch gegen einen rollenden mittelwert ersetzt, der aber leider etwas mehr platz benötigt |
16 | var r:integer; |
17 | i:byte; |
18 | |
19 | begin |
20 | r:=0; |
21 | for i:=0 to 7 |
22 | do |
23 | r:=r+adc_r(ch); |
24 | |
25 | result:=r shr 4; |
26 | end; |
Zusätzlich scheint der wandler auch einen fehler zu produziern, sobald ich zwei spannungen über 0 Volt habe Was ich noch einfügen möchte , ist eine fehlertabelle, da der wandler in dem betriebszustand nicht linear arbeitet. Zur zeit binn ich am überlegen, eine kalibrierungswert an den ADC zu legen ( da die batterie nie unter 3V gehen darf und wird. Überlege folgendes ( dazu wird der Prozessor extern versorgt ). Beim start muß die bedingung sein: Strobe auf masse und an den ADC(MUX) eingang muß eine spannung unter 2V anliegen ( es soll eine 1,024V referenz genommen werden ). Findet er das vor, soll der zuerst der gemessene wert mit der referenz verglichen werden und dann ein korrekturwert ermittelt werden und in das EEprom gespeichert werden. Anderseits kann ich die werte auch einlesen und am PC ermitteln und sie dann in das EEProm schreiben.
:
Bearbeitet durch User
Guten Morgen, wie nieder ohming sind deine Messstellen ? was schon mal helfen könnte ist ein 10nF -100nF Pufferkondensator am ADC Eingang und eine Wartezeit von 1µs nach umstellen des ADC-Eingangs (MUX), bevor die ADC-Wandlung gestartet wird. Dann siehst Du sehr schnell, ob deine Spannungsquellen zu hochohmig sind.
Beitrag #4967630 wurde von einem Moderator gelöscht.
Bitte den admin, den alten beitrag löschen ... Ja das dürfte das problem sein, daß sie sehr hochohmig sind ( 10K ), ich hatte es auch schon in manchen foren ( auch hier gelesen ). Besser wäre tasächlich ein OPV und den eingang dann mit ca 1K zu belasten. Der 100nF zur beruhigung ist auch vorhanden. das problem konnte gelöst werden, indem ich auf ISR umgestiegen binn , jetzt ist auch der offset eindeutig.
1 | //-------------- Also zuallererst die variablen erstellen ---------------- |
2 | const Vref = (1 shl REFS1); |
3 | |
4 | ADSR_int = (1 shl ADPS1) or (1 shl ADPS1) or (1 shl ADPS0) or // Frequenzvorteiler |
5 | (1 shl ADEN) or (1 shl ADIE); // ADC aktivieren interrupt aktivieren |
6 | |
7 | ADSR_en = (1 shl ADPS1) or (1 shl ADPS1) or (1 shl ADPS0) or // Frequenzvorteiler |
8 | (1 shl ADEN); // ADC aktivieren interrupt aktivieren |
9 | |
10 | ADSR_off = (1 shl ADPS1) or (1 shl ADPS1) or (1 shl ADPS0); // Frequenzvorteiler |
11 | |
12 | //------------------ Wird benötigt, auch wenn nichts gemacht wird ----------- |
13 | procedure ADC_Interrupt(); org IVT_ADDR_ADC; |
14 | begin |
15 | end; |
16 | |
17 | // ----------------------Das Prinzig würde auch ohne interrupt laufen, so ist der wer aber sauberer ------ |
18 | function adc_r(ch:byte):word; |
19 | var r,t, |
20 | MC_temp:word; |
21 | begin |
22 | SREG_I_bit:= 1; // interrupt muß an sein |
23 | MC_temp:=MCUCR or (1 shl SE) or ( 1 shl SM0); // das startet die AD-Wandlung |
24 | ADCSRA:=ADSR_int; // vorteiler setzen und adc aktivieren |
25 | |
26 | ADMUX:=Vref or %1101; // dummyread gegen ground |
27 | MCUCR := MC_temp; // der erste wert geht meist daneben, also verwerfen |
28 | asm sleep; end; |
29 | |
30 | MCUCR := MC_temp; |
31 | asm sleep; end; |
32 | t:=ADCl; |
33 | t:=((t or ADCh shl 8)) and %1111111111; // offset gegen null ermitteln |
34 | |
35 | ADMUX:=Vref or ch; // hier erst den echten wert messen |
36 | |
37 | MCUCR :=MC_temp; // das startet die AD-Wandlung |
38 | asm sleep; end; |
39 | |
40 | r:=ADCl; |
41 | result:=((r or ADCh shl 8) - t) and %1111111111; // wert minus offset |
42 | |
43 | ADCSRA:=ADSR_off; |
44 | end; |
:
Bearbeitet durch User
Hallo Hab so ein Batteriemesssystem vor Jahren in der Firma gebaut. Kann bis zu 188 Batterien und von 1.2V bis 12V Batterien. Hab das damals auch mit tiny 45 aufgebaut. Kann somit alle 100ms eine abfrage machen.
alle 100ms ? Aber dann nicht alle hintereinander ? Oder hast du einen quarz genommen und dann mit 118K-baud übertragen ? Gruß Michael
hier noch der datenvisualisierer für das teil. Beitrag "Einfacher Datenvisualisierer für Windows über die serielle schnittstelle". Das schöne ist, wennman nur einen messwert auswerten will, kann man die schaltung billig in ein stromversorgungs/ladegerät einbauen, um das Zeit/spannungsverhalten zu ermitteln. Wenn man nur einen prozessor verwenden will, kann die slavegeschichte raus und es kann wohl auch noch ein Tiny25 verwendet werden. Ob der nur soviel günstiger ist, wage ich zu bezweifeln. Das ganze auf lochraster sollte so in etwa 2 - 3 euro kosten. Handelt es sich um ein Lipolader für eine zelle, kann der kontroller direkt an die batterieklemme geschaltet werden.
:
Bearbeitet durch User
Hallo, da ich gesehen habe, das der schaltplan mist ist und ich auch die frage bekommen habe, wie man die zsammenschaltet, habe ich ihn noch einmal neu gezeichnet und hoffe, daß er nun verständlicher ist ... Nur der 78L05 ist nicht mehr aktuell, sondern wurde gegen ein LDO ersetzt. Bei Lipos würde der regler ganz entfallen. Beim ersten sieht man, daß der übertrag gegen masse gelegt wurde, das bedeutet, er ist der master und stößt alle anderen an. Desweiteren wurde hier unterstellt, daß die batterien alle hintereinander liegen, andernfalls darf der VCC BAT nie an den folgen GND angeschlossen werden !!!! EINE BITTE: kann jemand mal auf den plan sehen und schauen, ob es so logisch ist ?
:
Bearbeitet durch User
Warum hältst du dich nicht an die Forumsregeln?
1 | Wichtige Regeln - erst lesen, dann posten! |
2 | |
3 | Groß- und Kleinschreibung verwenden |
Michael F. schrieb: > EINE BITTE: kann jemand mal auf den plan sehen und schauen, ob es so > logisch ist ? Ja danke, ist nun viel besser und passt grundsätzlich schon. Aber wie erwähnt: Wenn der 78L05 nicht mehr drin ist, sollte auch die Bezeichnung der Realität angepasst werden. Zudem macht der 78L05 ja 5 Volt, was nicht ganz logisch ist. Besser wäre ein 3,3Volt Regler, denn ein SAFT 6V Block geht schon mal unter 5 Volt bei Belastung. Mit einem 5V Regler würde das nicht funktionieren. Und außerdem nimmt bei 3,3 Volt die Schaltung weniger Strom auf. Und Kollege Bernd schrieb mir sowieso, dass die Schaltung mit 3,3 Volt läuft. Man könnte die Versorgungsspannung auch von der Gesamtspannung der zwei Akkublöcke abnehmen, also Nennspannung 12 Volt (9 bis 18V). Vorteil: gleichmäßige Belastung aller Akkus. Da der Strom gering ist, sind die Wäreme-Verluste im Regler durch den höheren Spannungsabfall auch vernachlässigbar. Beispiel: 9 Volt Spannungsabfall am Regler mal 2 mA macht rund 18 mW Verluste. Geht schon. Oder nimmt so eine Platine mehr als 2 mA auf? Und noch etwas: Der untere Teil ist ja der Master für Batterien 1 und 2. Die Anschlüsse sind so beschriftet. Im oberen Block würde ich dann die Anschlüsse mit 2 und 4 bezeichnen. So wird es ganz klar, dass die Akkus alle in Reihe verschaltet sind. Und danke, dass Du Dir die Mühe gemacht hast, es neu zu zeichnen. So wird es klarer auch hinsichtlich der Verschaltung untereinander und mit der Datenleitung zum Rechner. Gruss, Roland
:
Bearbeitet durch User
Sorry : Ja er ist inzwischen durch ein 3,3V Type ersetzt worden. Das Teil wurde mit dem Target3001 gezeichnet. Nur leider komme ich mit der Editierfunktion nicht so zurecht. Deshalb habe ich den 78L08 stehen lassen. Ich unterstelle hier einmal, daß die Schaltung auch für andere Bedürfnisse angepasst werden kann. Also der Master nimmt etwa 7mA (Durchnitt ) auf, ich will ihn aber noch mit einem Wachhund ausrüsten und diesen als timer mißbrauchen, dann sollte es weniger werden. Die Slaves unter 5mA ( Durschnitt ). In Beidem Fällen springt die Spitzenaufnahme auf ca 10 - 15mA, wenn die Optos arbeiten. Aber wie gesagt, es verbietet dir keiner die Aufgaben, der Eingänge so zu Vertauschen, daß VCC Über 2 Batterien geht. Nur dann bitte auf die Spannungsfestigkeit des Reglers achten. Also wenn du möchtest, gebe ich dir die Targetdatei und du darfst sie dann so ändern, wie du sie brauchst, unter der bedingung, daß du sie dann hier postest.
Hallo Michael, gute Idee. Mittlerweile habe mir Target3001 bereits aus dem Netz gesaugt und installiert. Mal sehen, ob ich damit zurechtkomme. Daher jedenfalls bin ich sehr an Deiner Target-Datei interessiert. Ich habe keine Probleme damit, die Ergebnisse dann hier wieder zu veröffentlichen. Ich würde mir am liebsten eine Platine für die Überwachung von 6 Eingängen machen. Einfach deshalb, weil in meinen Fahrzeugen das am praktischsten wäre. Es gibt Akkukästen mit 4 Akkus, mit 6 Akkus und einem mit 11 Akkuks. Zwischen den Akkukästen sind Steckverbinder, Kabel und Stecksicherungen. Diese haben u.U. Übergangswiderstände und damit kleine Spannungsabfälle. Damit kann man mit unseren Messplatinen wahrscheinlich die Grenzen der Akkukästen nicht überspringen. Also wäre eine Sechser-Aufteilung am gescheitesten: Zwei Sechserplatinen für die 2 Sechser-Kästen, eine Platine für den 4-er Kasten und 2 Platinen für den 11-er Kasten. Die kleinen Spannungsabfälle an den Verbindern, also zwischen den Batteriekästen, werde ich mit anderen Mitteln messen. Schaun wir mal, entweder mit Trennverstärkern oder mit U-F Wandlern und über Optokoppler. Trennverstärker habe ich (noch) nicht, U-F Wandler mit Optokopplern schon. Es geht um 5 Messwerte, plus einem Messwert für den Gesamtbatteriestrom über den Spannungsabfall an einem 1 Milliohm Shunt. Ach so: schicke die Datei an rr@solarmobil.net Gruss, Roland
Es exitiert eine Lösung :-) Die schaltung ist so geartet, daß sie gekachelt werden kann. DSie widerstände sehen etwas gequetscht aus, aber in wirklichkeit passt es genau. Gruß Michael
:
Bearbeitet durch User
So hier die target datei .... Also den 78L05 gegen ein 3,3V LDO orsetzen und er Elko wird dann gegen einem von 1µF ersetzt. Der Regler ist der :LP2950ACZ 3,3V Wiso UF wandler ??? Die schaltung ist für jeweils ZWEI ausgelegt und du brauchst nur den letzten Datenausgang und Strobe auf die neue Platine Legen. ( Zur Zeit beherbergt jede Platine 4 Schaltungen , wobei es dir frei steht, nicht alle zu besetzten. ). Ich hab das Dessign extra so ausgelegt, daß du es auch auseinanderklappen könntest und einen langen Streifen erzeugen ) Und der Spannungsabfall an den Verbindern ist unterhalb der Meßfehlergrenze. Es gelte also Platine[1 mit master ] >>>> Platine[2 nur slaves] >>> Planine[3 nur slaves ] .... usw.. Die Länge der Kette wird nur von der Widerholdauer des Masters begrenzt. Je schneller die Abfolge, destso geringer die Zellenzahl. Bei 300ms sollten es etwa 30 Zellen sein. Brauchst du mehr, dann eben, die Abfolge heruntersetzen. Bei der Strommessung, mußt du dann eben einen mit Verstärker ausrüsten und könntest ihn ganz nach hinten, oder ganz vorne anordnen.
:
Bearbeitet durch User
habe auch mal im Jahre 2013 eine Batterieüberwachung gemacht. Hatte damals auch zuerst die Idee für jede Zelle einen Atmel Mikrocontroller zu verwenden und die Datenkommunikation über Optokoppler zu gestalten. War dann aber doch sehr aufwendig weil bis zu 100 Zellen und mehr überwacht werden sollten. Hatte dann aber die Idee mit einer Matrix-Schaltung realisiert mit CD4067. Damit war es dann möglich über die Matrixschaltung jeweils eine Zelle von 10 Stück mit normaler 1,2 Volt Spannung an einen I2C AD Wandler Eingang anzuschalten. Die Ansteuerung der CD4067 habe ich dann über Optokoppler und den I2C Bus über ADUM1251 entkoppelt. Da dann das ganze über einen PCF8574 mit I2C angesteuert wurde, war es möglich verschiedene I2C Adressen für jeweils eine Platine für 10 Zellen auszuwählen. Somit war es möglich mit einem Mikrocontroller bis zu 70 Zellen zu überwachen. Alle Zellen waren natürlich in Reihe geschaltet. Eine Platine für 10 Zellen konnte Spannungen bis zu 20 Volt vertragen (erhöhte Landespannungen usw.) und wenn mehr als 10 Zellen vorhanden waren, dann wurde einfach eine weitere Platine für 10 Zellen in "Reihe" abgehangen. Der Mikrocontroller war ein ATmega8 der über ein Wiznet Ethernet Modul als Server funktioniert hatte und die Daten der Zellen über Netzwerk übertragen konnte. Hatte damals knapp 3 Monate an der Entwicklung der Hardware und Software gesessen! Im Anhang ist noch ein Bild des Prototypen. Natürlich können auch größere Batterien als die AAA Zellen überwacht werden! Die freien Anschlüsse sind Schaltausgänge die ebenfalls pro Batteriezelle eine Funktion haben können.
Hier noch ein Bild vom kompletten Batterieüberwachungssystem inklusive dem ATmega8 und WIZNET Modul. Hier ist das Endprodukt für 40 Zellen wie es z.B. bei Photovoltaik vorkommt gezeigt.
Vielen dank für die vorstellung, daß muß auch eine gute fleißarbeit gewesen sein .. Gruß Michael
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.