Forum: Mikrocontroller und Digitale Elektronik 40 Spannungen einlesen und an AtMega8 übertragen


von Manuel (Gast)


Lesenswert?

Hallo!

Ich habe bereits im Internet und auch hier im Forum gesucht aber nichts 
wirklich passendes gefunden.

Undzwar habe ich 40 in Serie geschaltete LiFePo4 Akkus, bei denen ich 
gerne die Spannung messen möchte und an einen AtMega8 übermitteln will, 
der mir das ganze auf einem Display ausgibt, soweit so gut.

Nun wie messe ich am besten die Spannungen, das Problem ist ja, wenn ich 
mit einem anderen AtMega8 die Spannung direkt messe und alle 6 ADC 
Kanäle ausnutze habe ich in etwa die Spannungen 3.5-7-10.5-14-17.5-20 
das müsste ich alles messen, also Spg. Teiler oder sonstiges davor 
schalten oder? Oder hat jemand eine bessere Idee? Eventuell einen 
eigenen ADC der per SPI verbunden wird ( natürlich über einen 
Optokoppler da ich ja wenn dann mehrere ADC bräuchte um 40 Kanäle zu 
messen )

Besten dank im vorraus!

MfG
Manuel

von STK500-Besitzer (Gast)


Lesenswert?

40*ca. 3,3V sind bei mir >120 V. Das wird schwierig...

von Manuel (Gast)


Lesenswert?

Hallo!

Ja ist klar, deshalb hab ich ja auch geschrieben ich werde mit 
sicherheit mehr als nur einen µC oder ADC brauchen.

Eventuell 5 Attinys oder so die mit jeweils 8 Spannungen messen, wäre ja 
auch ok, und die kommunizieren bzw. senden einfach an einen Haupt µC ( 
AtMega oder was größeres ) der mir das ganze dann am Display anzeigt

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

Mach einen Ausflug zu den üblichen Halbleiterherstellern und suche nach 
Batterieüberwachungs-ICs.

von STK500-Besitzer (Gast)


Lesenswert?

Da wird man wohl ein Spannungsteilergrab bauen müssen.

von Manuel (Gast)


Lesenswert?

Hallo!

Naja die Batterieüberwachungssysteme können mir die Spannungen ja nicht 
per digitalen Datenbus übertragen, sondern steuern doch nur selbst wenn 
zuviel Spannung oder zu wenig Spannung ist, das sie geladen, entladen 
etc. werden.
Mir gehts ja nur um die Spannungsmessung und um die Anzeige auf einem 
Bildschirm.

Wenn ich Spannungsteiler mach, hab ich hohe Ungenauigkeiten, so wie ich 
das sehe, und auf 5-10mV genau hätte ich das schon gerne

mfG
Manuel

von ingo (Gast)


Lesenswert?

In diesem System:
http://www.generex.de/d/products/additional/bacs/bacs_deu.html
hängt über jedem Akku ein µC-Modul, mit dem Zentralteil kommunizieren 
sie über Optokoppler auf einem seriellen Bus (werden vom Master 
gepollt).
Gut durchdacht, muss sowas auch nicht teuer sein.
mfG ingo

von Manuel (Gast)


Lesenswert?

Ok da hast du recht, du meinst also zb. an jede Zelle einen Attiny25 
hängen der hat einen 10-Bit ADC und den per Seriellen Bus mit einem 
Zentralen µC verbinden, richtig ?

von ingo (Gast)


Lesenswert?

Das wäre die aufwändigste, aber auch beste Lösung. Die µC's können ja 
von den Akkus versorgt werden. In dem zitierten System weden die Akkus 
damit auch ausbalanciert (die mit der höchsten Spannung definiert 
entladen), was bei 6- oder 12V Blöcken aber nicht so perfekt 
funktioniert wie bei Einzelzellen. Als Kompromiss wäre vielleicht auch 
möglich, ein µC für n (4?) Akkus und die wieder mit Spannungsteilern 
(nur für die Spannungsmessung).
mfG Ingo

von Manuel (Gast)


Lesenswert?

Hallo, ja stimmt das wäre am vertretbarsten, zumal schon ein tiny13 4 
10-Bit ADCs für kleines Geld integriert hat.

problem ist nur der 10-bit ADC löst auf 1024 auf, bei angenommen max. 4V 
pro Zelle macht das 4mV bei der ersten Zelle, möchte ich aber jetzt 4 in 
Serie geschaltete messen, macht das hier schon 16mV aus. Und gerade bei 
Lithium Akkus sollte man schon etwas genauer messen.

Einen ATtiny oder ähnliches mit nem 12-Bit ADC wirds ja kaum geben, oder 
sonst eine Möglichkeit das besser hinzubekommen.
Subtrahierverstärker oder dergleichen möchte ich eher nicht einsetzen.

von bingo (Gast)


Lesenswert?

Das müsste sogar mit einem ATTiny5 gehen, der aus der betreffenden Zelle 
betrieben wird. Passt die Spannung, meldet er diese nebst einer 
Zellenkennung an die Zentrale, passt die Spannung nicht, meldet er 
entweder die falsche Spannung oder er ist "tot", beides kann die 
Zentrale ja leicht erkennen.

von Manuel (Gast)


Lesenswert?

Ja, müsste auch mit diesem gehen, allerdings hat der laut DBL nur einen 
8-Bit ADC und das macht bei einer Zelle schon nurmehr 16mV Genauigkeit!

von bingo (Gast)


Lesenswert?

> nur einen 8-bit ADC ... 16mV Genaugkeit

Das sind 0,4% und reicht doch locker zur Beurteilung, ob die Zelle ok 
ist ...

von Manuel (Gast)


Lesenswert?

Nein, du verstehst das falsch, ich möchte nicht beurteilen ob die 
Zellenspannung zw. 2.4-3.5V liegt oder so, sondern ich möchte die exakte 
zellespannung messen!

von bingo (Gast)


Lesenswert?

uupps, ich lese gerade, dass Vref beim ATTiny5 Vcc ist. Wenn Du das Teil 
aus der Zelle betreiben willst, musst Du also noch eine 
Referenz-Spannung zur Verfügung stellen. Da gibt es sicher was passendes 
von maxim-ic.com

von Manuel (Gast)


Lesenswert?

Ja ref. Quelle zur not TL431 oder so, aber wie gesagt 8Bit ist zu wenig.

Kennt irgendwer das Celllog hier: 
https://hobbyking.com/hobbycity/store/uh_viewItem.asp?idProduct=9282
http://static.rcgroups.com/forums/attachments/2/7/9/8/6/0/a2838295-137-celllog8.jpg?d=1256529458
Das ist auch mit einem AtMega8 gemacht und angeblich 5mV genau.

von usuru (Gast)


Lesenswert?

also doch ATTiny25, der hat eine interne Referenz und einen 10-Bit ADC

von Frank K. (fchk)


Lesenswert?

Für dieses Problem gibts dem Linear Technologies LTC6802-1.

http://www.linear.com/pc/productDetail.jsp?navId=H0,C1,C1003,C1037,C1786,P86662

fchk

von Manuel (Gast)


Lesenswert?

Ja den hab ich mir auch schon angeschaut, allerdings verstehe ich nicht 
so ganz wie ich die Daten zum AtMega bekomm, zumal es ja mehrere 
Datenleitungen sind die ich da pro LTC6802 verbinden müsste wenn ich das 
richtig verstehe

von usuru (Gast)


Lesenswert?

> Für dieses Problem gibts dem Linear Technologies LTC6802-1.

aber nicht ganz billig, davon bräuchte Manuel 3 Stück ...

von Manuel (Gast)


Lesenswert?

... die wiederum für 3 stk. 100€ insg. kosten

von bingo (Gast)


Lesenswert?

> davon bräuchte Manuel 3 Stück ...

Pardon, ich komme auf 4 (bei 40 Zellen)

von Peter D. (peda)


Lesenswert?

Ich würde das mit 40 Stück ATtiny25 machen.
Der ATtiny kann dann sogar die Temperatur mit messen (direkt auf die 
Zelle draufgepappt).

Die Daten können dann z.B. mit billigen Optokopplern gesendet werden.


Peter

von avion23 (Gast)


Lesenswert?

Ich würde es genau so wie Peter machen:
Vref ist Vcc, gemessen wird die interne Bandgabreferenz. Daraus kann man 
die Zellenspannung ohne Spannungsteiler o.ä. errechnen.

Die Genauigkeit kann fast beliebig erhöht werden durch oversampling. 
14Bit sind damit kein Problem da man ja nicht alle 10ms einen neuen Wert 
braucht.

Der attiny25 verbraucht im power down modus ~5µA und kann per i2c wieder 
aufgeweckt werden.

von bingo (Gast)


Lesenswert?

> Der ATtiny kann dann sogar die Temperatur mit messen (direkt auf die
> Zelle draufgepappt).

Das ist ein nicht zu unterschätzender zusätzlicher Vorteil.

von Franke M. (appletree)


Lesenswert?

Helft mir mal. Wie kann man nur mit dem ATtiny die Temperatur messen???
O_o

von Floh (Gast)


Lesenswert?

Franke Michael schrieb:
> Helft mir mal. Wie kann man nur mit dem ATtiny die Temperatur messen???

Teilweise haben die schon einen Temperatursensor eingebaut, nicht 
übermäßig genau, aber eine fackelnde Zelle kann man damit locker 
erkennen :-)

von Axel R. (Gast)


Lesenswert?

Darf ich mal gaanz vorsichtig fragen, was ihr da empfiehlt?

Was kostet eine Zelle, was kostet die Last (sicher ein Motor?) bzw. das 
was um den Motor verbaut ist und was kostet es, das ganze von der Straße 
zu kratzen, wenn etwas passiert?

Die Multicell Stack Monitore von LT sind die einzige Alternative.

Man muss ab einem bestimmten Punkt einfach aufhören zu basteln und sich 
professionell verhalten. Wenn man keine 100 Euro für drei Schaltkreise 
(mehr) übrig hat, nun... muss man evtl. vier Wochen warten, bis es 
wieder Geld gibt ;)

Aber gut - geht mich ja nichts an.
vielleicht ists ja auch ein Moidellschiffchen odersowas, da ists dann 
egal.

Viele Grüße
Axel

von Manuel (Gast)


Lesenswert?

Ja ich werd es jetzt vermutlich mit einem Attiny13 pro Zelle machen.

Müsste ich doch einfach per USART verbinden können, nur die Frage wie 
ich 40 Eingänge an einen haupt µC schicke

von huehnerfutter (Gast)


Lesenswert?

Über 40 Optokoppler mit open collector, alles an einen pin mit einem 
pullup.

Dann per Software collision dectect.

von MaWin (Gast)


Lesenswert?

> habe ich 40 in Serie geschaltete LiFePo4

Dein Problem sind die 150 Volt.

Du willst vermutlich auf besser als 0.1V,
nämlich 0.01V genau messen, macht 14 bit Messauflösung,
vielleicht bist du auch mit 0.025V zufrieden, wären 13 bit.

Der A/D-Wandler ist nicht das Problem,
aber die Widerstände eines Spannungsteilers müssten auf
0.01% übereinstimmen, und das ist TEUER, richtig teuer.

Deshalb ein anderer Vorschlag:

Du bauste deine Messchaltung für 1 Zelle, von 0 bis nicht
mal 5V. Du schaltest Masse an den Minuspol der Zelle die
du messen willst. Viel Strom muss ja nicht fliessen, ist ja eine 
Spannungsmessung.
Und dann schaltest du den Messeingang an den Pluspol der Zelle.
So sieht deine Schaltung nie mehr als die Spannung einer Zelle.

Sie ist halt nur nicht mit dem Minuspol der Gesamtakkus verbunden.

Bleibt die Frage, womit umschaltest. Mit Bauteilen, die 200V
trennen können. Die müssen nicht mal besonders gut sein, nicht
mal besonders niederohmig, nur sollte der aus-Widerstand schon
1 Mio mal höher sein als der an-Widerstand. Es muss kein Reedrelais
sein.

Das könnte je ein MOSFET machen, aber besser ein IC:
HV219, HV20220 von Supertex oder ähnliche Analogschalter die diese
150V abkönnen.

Die Pegelandlung der Ansteuerung des Multiplexers und der A/D-Wandlung 
beschränkt suich auf wenige leitungen und könnte per Optokoppler 
erfolgen.

Andere Möglichkeit wären LTC6802 oder ATA6870 in Kaskadierung wie laut 
Datenblatt beschrieben.

von Juergen G. (jup)


Lesenswert?

Ich wuerde das Spannung messen 4 ATTiny26 machen lassen.
Der ATTiny26 hat 11 10-bit ADC's + die Pins fuer die Uebertragung.

Ju

von Peter D. (peda)


Lesenswert?

huehnerfutter schrieb:
> Über 40 Optokoppler mit open collector, alles an einen pin mit einem
> pullup.
>
> Dann per Software collision dectect.

Warum so kompliziert?

Der Master schickt ein Startbit an den ersten und der erwacht. Der 
schickt dann seine Daten an den nächsten. Der reicht die Daten durch und 
hängt dann seine Daten an usw.
Der letzte schickt dann die 40 Telegramme an den Master und alle gehen 
schlafen.

Gesendet wird wie bei nem IR-Code: kurzer Puls = 0-Bit, langer Puls = 
1-Bit.
Dann braucht man auch keinen Quarz für jeden ATtiny.


Peter

von Sven (Gast)


Lesenswert?

Was soll der Geiz: 40 ATtiny25 kosten nicht die Welt. Jeder misst eine 
Zelle, wird auch aus dieser versorgt und macht über eine PWM mit NMos 
mit Lastwiderstand das Balancing der Zelle.

Kommunikation wie von Peter beschrieben von Tiny zu Tiny, Pegelanhebung 
mit Transistor und Widerstand, der letzte gibt die Daten über einen 
Optokoppler zurück.

Die ADC-Auflösung kann man mit künstlichem Rauschen erhöhen, gibts ne AN 
von Atmel dazu.

von Anja (Gast)


Lesenswert?

Mhm,

mal überlegen:

wenn normale Controller billiger wären und den technischen Specs genügen 
würden:
Warum werden hierfür spezielle kaskadierte (mit SPI Level-Shifter) 
Controller mit mindestens 14 Bit ADC-Auflösung 3mV Genauigkeit!!! und 
minimalem Stromverbrauch sowie zusätzlicher (Schutz-)Funktionen 
entwickelt die sich einfach über SPI an den Hauptprozessor des BMS 
anschließen lassen?
z.B. hier:

http://focus.ti.com/lit/ds/symlink/bq76pl536.pdf


Gruß Anja

von Manuel (Gast)


Lesenswert?

danke!
Ich hab mich jetzt schon ziemlich fix entschieden, dass ich Attiny13 
oder Attiny25 oder dergleichen nehme und jeden einzeln die Spanung 
messen lasse, das schaut mir am sinnvollsten aus, und Balancing würde 
ich mit denen auch gerne machen, ist ja kein Ding ne PWM an nen LL FET 
und nen Hochleistungswiderstand  je nach Spannung. Ihr würdet also das 
ganze nicht per UART weiterschicken  sondern einfach  mit, langer Puls 
kurzer Puls?
Eine weitere Möglichkeit wäre ja noch per UART jeden Rx der Attiny mit 
dem Tx des Hauptprozessors zu verbinden und der schickt zu allerarst mal 
zb. 30 damit weiss der Attiny der Zelle 30 dass er jetzt seine Daten 
senden muss, allle Tx der Attinys geht in ein Or und an den ausgang 
dessen kommt der Rx des Hauptprozessors
was meint ihr dazu? was Einfachheit, Schnelligkeit etc. betrifft?

von Sven (Gast)


Lesenswert?

Die RC-5 oder ähnlichen Codes sind timingtolerant, bei Uart brauchst Du 
eigentlich einen Quarz.

von gisela (Gast)


Lesenswert?

Für das Pipelining von einem ATTiny zum anderen braucht man aber immer 2 
Optokoppler je µC, für "rein" und "raus". Optokoppler bekommt man oft 
mit Open Collector, sodass ein Pseudobus möglich ist.

Zacwire wäre auch noch ein gutes Protokoll: das Startbit hat einen 
Duty-Cycle von 50%, die Datenbites entweder 25% (=0) oder 75% (=1). Auf 
diese Weise kann der Empfänger anhand der Länge des Startbits das Timing 
für die Datenbits machen. Dann braucht man keinen Quarz und 
temperaturbedingte Schwankungen können auch leicht ausgeglichen werden.

http://www.ist-ag.ch/eh/ist-ag/resource.nsf/imgref/Download_TSic_Zacwire_EN.pdf/$FILE/TSic_Zacwire_EN.pdf

von Simon K. (simon) Benutzerseite


Lesenswert?

Was spricht denn gegen I2C? Ist natürlich schwieriger zu trennen, aber 
das lässt sich leichter ansprechen.

von Sven (Gast)


Lesenswert?

Für die Übertragung brauchst Du pro Stufe einen Transi und 3 
Widerstände.

AVR Ausgang => 33k => Basis, Emitter auf GND, Kollektor => 10k gegen 
+Vcc der nächsten Stufe + 100k an nächsten AVR Eingang

Der nächste AVR sieht bei Low am vorherigen Ausgang seine eigene Vcc, 
bei High das GND des vorherigen AVR, also um die -4V. Durch die internen 
Dioden und den 100k wird das auf sein eigenes GND begrenzt.

Bei geringer erforderlicher Geschwindigkeit kann man die Rs so groß wie 
möglich machen.

Schutz gegen Zellenausfall, Unterbrechung usw. muss man für die gesamte 
Schaltung auslegen.

von Manuel (Gast)


Lesenswert?

Danke Sven das hört sich doch gut an
hierbei sollte ich dannn RC5 oder ähnliches verwendenn richtig? wie 
siehts da mit der Geschwindigkeit aus, wenn ich bei meinem 
Hauptprozessor zb. sag ich  möchte  Zb. Zelle 10 lesen, muss ich ja alle 
40 Zellen durchlaufen um dann die Informationen an den Hauptprozessor 
weiterzugeben, und da es pro Zelle 10 Bit sind, machts bei 40 Zellen 
schon 400 Bit

von Sven (Gast)


Lesenswert?

Ja und, wenn Du das mit 1200 Baud laufen lässt, bekommst Du 3 Messungen 
pro Sek. Ich würd aber noch Bits für Adresse, Zustands-Flags (Fehler) 
und 12 Datenbits vorsehen.

von Sven (Gast)


Lesenswert?

Mach die Schaltung so modular, dass Du die beliebig kaskadieren kannst, 
dann kannst Du mit 3-4 Stück erstmal an billigen Akkus probieren.

Ein extra Modul (ohne AVR) nimmt das Signal der letzten Stelle und setzt 
das über Optokoppler getrennt wieder runter auf den Atmega.

von Manuel (Gast)


Lesenswert?

Das ich das Modular aufbaue hab ich mir auch schon überlegt, das Problem 
mit der Geschwindigkeit ist aber das zb. der erste auf den zweiten min. 
10 Bit sendet der nächste dann 20 usw. also kommt man mit 1200 Baud ws. 
auf 5 sek. pro kompletter Messung oder hab ich da gerade einen 
Denkfehler?

von Peter D. (peda)


Lesenswert?

gisela schrieb:
> Für das Pipelining von einem ATTiny zum anderen braucht man aber immer 2
> Optokoppler je µC, für "rein" und "raus".

Hä?
Was soll das bringen, 2 Optokoppler in Reihe?


Peter

von Frank K. (fchk)


Lesenswert?

Gegen das "Daisy-Chaining" der Kommunikation von einem Attiny zum 
nächsten spricht, dass das ganze nicht mehr funktioniert, wenn eine 
Akkuzelle platt ist und der zugehörige Attiny nicht mehr anläuft und 
damit die Kommunikation unterbricht.

von Peter D. (peda)


Lesenswert?

Frank K. schrieb:
> Gegen das "Daisy-Chaining" der Kommunikation von einem Attiny zum
> nächsten spricht, dass das ganze nicht mehr funktioniert, wenn eine
> Akkuzelle platt ist und der zugehörige Attiny nicht mehr anläuft und
> damit die Kommunikation unterbricht.

Warum?

Der Master kriegt dann ja keine 40 Datenpakete mehr und macht ne 
Hauptabschaltung.
Bzw. schaltet garnicht erst an, bevor sich nicht alle 40 ATtiny gemeldet 
haben.

Oder willst Du etwa die defekte Zelle von den anderen 39 negativ laden 
lassen, bis sie explodiert?
Du magst wohl ein schönes Lithium-Feuerchen.


Peter

von Manuel (Gast)


Lesenswert?

Also ich bin da ganz Peters Meinung, wenn ich die Daten ned bekomm, 
gibts ne Abschaltung logischerweise.

Wobei es doch wirklich so ist bei minimal 10 Bit pro Stufe, und ner 1200 
Baud muss ich ca. 7 Sekunden auf eine Messung warten, das ist nicht 
gerade das was ich mir unter super vorstelle.

von Peter D. (peda)


Lesenswert?

Wie kommst Du auf 7s?

1,2kBit  10 Bit  40 = 0,4s

Und niemand sagt, daß Du mit 1,2kBit senden mußt. Du kannst z.B. 50kBit 
nehmen.


Peter

von Manuel (Gast)


Lesenswert?

Naja die 7 Sekunden kommen ganz einfach daher:
10 bit sendet der Erste an den Zweiten dauert x sekunden
20 der 2. an 3. dauert .. sekunden

der 40 an den Haupt braucht 0.4 sekunden, aber alles davor summiert sich 
ja leider auf

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> der 40 an den Haupt braucht 0.4 sekunden, aber alles davor summiert sich
> ja leider auf

Sagt wer?

Die Bits vom Vorgänger werden einfach nur durchgereicht (externer 
Interrupt setzt den Ausgangspin).
Ist dann Pause, sendet man selber.

Oder man nimmt einen Bit-Puffer, damit sich der Jitter nicht addiert, 
dann hat man eine Bitzeit Verzögerung pro ATtiny.


Peter

von Manuel (Gast)


Lesenswert?

Das heißt sobald am 40. Attiny das erste Startbit vom 39. Attiny kommt 
setzt er Eingang = Ausgang und wartet bis das letzte Stopbit gesendet 
wurde und schickt dann seinen Teil hinten dran oder wie ?

von Peter D. (peda)


Lesenswert?

Ja.

Sehe grade, das mit der Pause funktioniert nicht.
Der vorherige AVR muß ein Endekennzeichen senden und das darf der 
folgende nicht mehr durchreichen, sondern sendet dann selber.
Daher braucht man doch einen Bit-Puffer und hat eine Bitzeit 
Verzögerung.


Peter

von Manuel (Gast)


Lesenswert?

Ja ist wahr, das würde aber nur bedeuten 1-Bit verzögerung pro Attiny 
richtig? was ja kaum was ausmacht, 40-Bit verzögerung bei 1.2kbit/s ist 
ja kaum merkbar

von Simon K. (simon) Benutzerseite


Lesenswert?

Ich finde die Methode etwas "russisch". Wenn das Signal über 40 AVR 
Interrupts gelaufen ist, und dadurch 40 mal den Wechsel 
Hardware->Software->Hardware macht, garantiert dir doch hinten keiner 
mehr die richtige Bitlänge für jedes RS232 Bit. Je nach dem, welche 
anderen Interrupts noch laufen kriegste da doch den übelsten Jitter 
rein.

von Christian H. (netzwanze) Benutzerseite


Lesenswert?

Ich würde das ganze ja einfach als I2C auslegen.

Master sendet reihum die Adressen der Überwachungsbausteine und wartet 
danach kurz auf Antwort. Kommt nichts, stimmt etwas nicht.

Das kann man auch über RS232 machen. Die Überwachungsprozessoren kann 
man direkt parallem schalten. Nur müssen die nicht aktiven µP den 
Datenausgang hochohmig schalten. Erst wenn sie gefragt werden, dürfen 
sie "kurz" senden und dann wieder die Klappe halten.

Damit gibt es kein Problem bezüglich falscher Zeiten oder einer 
unterbrochenen Kette. Auch können den einzelnen µP zusätzliche Befehle 
erteilt werden (Zelle abklemmen/überbrücken; entladen; selbstzerstörung; 
...).

Natürlich die µP durch Optokoppler galvanisch vom Bus trennen.

von Peter D. (peda)


Lesenswert?

Simon K. schrieb:
> garantiert dir doch hinten keiner
> mehr die richtige Bitlänge für jedes RS232 Bit.

Deswegen sagte ich ja schon oben, daß RS232 ausfällt.

Man nimmt nen einfachen Pulslängencode, d.h. die Sychronisation erfolgt 
pro Bit und damit sind selbst Taktfehler von 20% korrigierbar.
Und jeder AVR frischt das Bit vom vorherigen ja wieder auf.


Peter

von Sven (Gast)


Lesenswert?

Die Methode ist so russisch wie ein Schieberegister...

Der Witz, weswegen I2C direkt ausfällt, ist die Pegelanhebung von Zelle 
zu Zelle.

Und eine tote Zelle kann man trotzdem abfragen, indem man den AVRs 
ZDioden verpasst mit Vz > Vakku, die Spannung der AVRs aus den Zellen 
über Dioden entkoppelt, und die Module über Widerstände kaskadiert. 
Liefert eine Zelle eine zu geringe oder keine Spannung, wird der AVR 
über die darüberliegende Zelle mitversorgt und kann die tote Zelle 
melden.

Das mit den ZDioden würd ich sowieso machen, gehört zur 
Schutzbeschaltung für die AVRs. Ist eine Zelle unterbrochen, liegt sonst 
die gesamte Ladespannung über diesem AVR an. Zumindest kurzzeitig.

von manateemoo (Gast)


Angehängte Dateien:

Lesenswert?

Anstelle von 40 uC könnte man 40 Diff-Verstärker aufbauen und mit einem 
uC Auswerten. (10x 4-Fach Opamps, 5x 4051, 2x 4-Fach Opamp (5 
gebraucht),
5x AD Wandler im uC)

von Manuel (Gast)


Lesenswert?

Das ist  teurer, ungenauer und allgemein schlechter würd ich sagen, 
deshalb hab ich mich ja schon entschieden pro Zelle einen Attiny

von MaWin (Gast)


Lesenswert?

> könnte man 40 Diff-Verstärker aufbauen

Mach mal.
Du weisst, welche Widerstandspräzision notwendig ist und was die kosten 
?
Offenbar nicht.

Ein Spannungsspiegel erfordert zwar auch einen OpAmp pro Zelle, stellt 
aber wenigstens nicht so hohe Anforderungen an die Widerstände. Leider 
muß bei denen der Multiplexer die 150V aushalten.

von Manuel (Gast)


Lesenswert?

naja ich würde sagen es ist die einfach wirtschaftliche, sinnvolle und 
beste Lösung pro Zelle einen Attiny zu verbauen!

Svens Ansatz verstehe ich leider nicht ganz, wie ich die Attiny 
Spannungsmäßig entkoppeln sollte ?

von Manuel (Gast)


Lesenswert?

Kann mir das eventuell jemand genauer erklären?
Wäre super

von Kim S. (Gast)


Lesenswert?

http://forum.mysnip.de/read.php?567,288449,289854#msg-289854
Hatte damals Mega88 verwendet, weil gerade welche da waren. Ansonsten 
nimmst du attiny 25 oder 45 etc und zur übertragung optokoppler.
so sieht das bei meinem "Auto aus"

von Manuel M. (manuel21)


Lesenswert?

Was mir außerdem noch aufgefallen ist, jemand meinte mal, ich soll als 
Referenzspannung AVCC nehmen und die interne Ref. Diode messen, das geht 
doch nicht, wie soll ich diese denn an einen ADC Eingang bringen oder so 
messen?

von Simon K. (simon) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Simon K. schrieb:
>> garantiert dir doch hinten keiner
>> mehr die richtige Bitlänge für jedes RS232 Bit.
>
> Deswegen sagte ich ja schon oben, daß RS232 ausfällt.
>
> Man nimmt nen einfachen Pulslängencode...

Ach so, dann habe ich dich missverstanden, entschuldige :-D.

Sven schrieb:
> Die Methode ist so russisch wie ein Schieberegister...

Nicht, wenn man das Prinzip auf UART anwenden möchte. Dann ist das 
höchst-russisch ;-)

von Kim S. (Gast)


Lesenswert?

Du nimmst die interne Ref von 1,1V

von Kim S. (Gast)


Lesenswert?

ach ja, und als Manchester anstelle von UART

von Manuel M. (manuel21)


Lesenswert?

Ja brauch ich also dann noch einen Spannungsteiler davor richig?

Was heißt als Manchester anstelle von UART?

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Anbei mal ein Schaltungsvorschlag mit 4 Zellen.

Welche Geschwindigkeit zuverlässig übertragen wird, kann man ja 
ausprobieren, eventuell die Widerstände kleiner wählen.
1200Bit/s sollte man aber weit überschreiten können.
Ne 8Bit-CRC würde ich noch ranhängen.
Bei stark abweichenden Werten wird der Master eh gleich nochmal 
abfragen.


Wenn die ATtinys per Watchdoginterrupt nach einer bestimmten Zeit 
alleine senden, kriegt man raus, welches die oberste tote Zelle ist.
Ist dann quasi ne Information an den Service.
Funktional ist das aber nicht nötig. Dem Master reicht es zu wissen, daß 
eine Zelle (ATtiny) tot ist.


Peter

von Peter D. (peda)


Lesenswert?

Kim Schmidt schrieb:
> ach ja, und als Manchester anstelle von UART

Wozu brauchst Du denn Gleichspannungsfreiheit?
Man muß es ja nicht unnötig kompliziert machen.

Peter

von Manuel (Gast)


Lesenswert?

Hallo Peter, die Schaltung sieht sehr gut aus, allerdings weiss ich noch 
nivcht wie ich den Eingang einfach auf den Ausgang  durchreichen kann 
sodass keine riesengroße verzögerung durch die Reihenschaltung entsteht?

von Peter D. (peda)


Lesenswert?

Also, der AVR empfängt ein Bit, z.B.:
0-Bit: 100µs Puls + 100µs Pause
1-Bit: 200µs Puls + 100µs Pause

Er entscheidet dann bei 150µs ob es ein 0- oder 1-Bit ist und beginnt es 
weiter zu senden.
Falls die Frequenzen der AVRs etwas abweichen, wird dadurch die Pause 
kürzer oder länger, aber die ist egal.
Daß ein AVR fertig ist, kann z.B. durch einen 400µs-Puls gekennzeichnet 
werden, der wird nicht weitergesendet sondern dann die eigenen Daten 
angehängt.


Peter

von Manuel (Gast)


Lesenswert?

Gut also nicht per UART sondern normal?
zb. Interrupt und der startet nen Timer, nach 150 mikrosekunden weiss 
ich dann ob es 1 oder 0 ist richtig? Nur wie genau ich das weitersenden 
bewerkstelligen kann ist mir noch nicht so klar

von avion23 (Gast)


Lesenswert?

Manuel M. schrieb:
> Was mir außerdem noch aufgefallen ist, jemand meinte mal, ich soll als
> Referenzspannung AVCC nehmen und die interne Ref. Diode messen, das geht
> doch nicht, wie soll ich diese denn an einen ADC Eingang bringen oder so
> messen?
1
 * - Messung der internen Spannung durch die Bandgapreferenz
2
 * V_BG = 1.1V
3
 * U = ?
4
 *  U = V_ref * ADC /1024
5
 *   und weil wir V_ref wollen
6
 *  V_ref = U * 1024 / ADC
7
uint16_t voltage =  (uint32_t)1100 * (uint32_t)1024 /  (uint32_t) readADC();
Steht bei mir so in einem Projekt. ADMUX einstellen, so dass Ref = Avcc.


Warum i2c mit zwei Oktokopplern nicht funktionieren soll verstehe ich 
nicht.

von Peter D. (peda)


Lesenswert?

avion23 schrieb:
> Warum i2c mit zwei Oktokopplern nicht funktionieren soll verstehe ich
> nicht.

Dann hast Du Dir I2C noch nie angeschaut.

I2C ist bidirektional, d.h. Du brauchst 4 Optokoppler und nen Splitter 
(P82B96).
Das Thema war hier aber nicht die Aufwandsmaximierung.

Auch brauchen billige Optokoppler viel Strom und die Zelle soll ja nicht 
allein durch die Kommunikation leergesaugt werden.


Peter

von Manuel M. (manuel21)


Lesenswert?

avion23 schrieb:
> Manuel M. schrieb:
>> Was mir außerdem noch aufgefallen ist, jemand meinte mal, ich soll als
>> Referenzspannung AVCC nehmen und die interne Ref. Diode messen, das geht
>> doch nicht, wie soll ich diese denn an einen ADC Eingang bringen oder so
>> messen?
>
1
>  * - Messung der internen Spannung durch die Bandgapreferenz
2
>  * V_BG = 1.1V
3
>  * U = ?
4
>  *  U = V_ref * ADC /1024
5
>  *   und weil wir V_ref wollen
6
>  *  V_ref = U * 1024 / ADC
7
> uint16_t voltage =  (uint32_t)1100 * (uint32_t)1024 /  (uint32_t)
8
> readADC();
9
>
> Steht bei mir so in einem Projekt. ADMUX einstellen, so dass Ref = Avcc.
>
>
> Warum i2c mit zwei Oktokopplern nicht funktionieren soll verstehe ich
> nicht.


Hallo!

Das ergibt doch keinen Sinn?
Was soll ich dann an den ADC Eigang legen?
Wenn die Refernz jetzt AVCC ist, brauch ich doch irgendwo noch meine 
Bandgapreferenz, aber zu der komm ich ja jetzt nichtmehr?

von Manuel M. (manuel21)


Lesenswert?

Ok ich habs soeben begriffen, kann den AIN0 verwenden um darauf die 
interne Bandgap zu haben und die dann messen ist klar!

Danke!

von Manuel (Gast)


Lesenswert?

Ok anscheinend hab ichs doch noch ned gerafft, wenn ich für den Analog 
Comparator die Bandgap als Refernz aktivier, liegt die doch auch nicht 
an dem externen PIN an, also wie sollte ich da jetzt die Bandgap messen 
können wenn der MUXER auf AVCC steht ?

von Manuel M. (manuel21)


Lesenswert?

Ok hab jetzt nochmal im Internet gesucht und gefunden wies geht, einfach 
den Kanal bei der Messung auf 14 stellen dann kommt die Interne 1.3V 
Bandgapreferenz, jetzt ist es klar.

von avion23 (Gast)


Lesenswert?

Danke Peter,
hast Recht. 4 Optokoppler kosten wirklich Platz und Strom.

Hi Manuel,
genau so geht's. Das mit dem Kanal hätte ich noch schreiben sollen.

Wenn du eine höhere Auflösung (!= Genauigkeit) haben möchtest kannst du 
oversampling verwenden, z.B.
1
voltage += -(voltage >> 8) + readADC();
Das ist ein billiger Tiefpass, der auch die Auflösung erhöht. Von den 8 
zusätzlichen Bits kannst du natürlich nicht viele verwenden. Rest siehe 
app-note von atmel.

von Manuel (Gast)


Lesenswert?

Aber wenn zb. in Voltage 1023  stehen habe, und dannach wieder 1023 
kommt, zieht er 3 ab und es kommt 2043 raus oder? das ist  doch falsch?

von avion23 (Gast)


Lesenswert?

Wenn du mehr Bits haben möchtest, brauchst du natürlich auch einen 
größeren Wertebereich. Anders gesagt: Mit [0, 1023] kannst du nur 10Bit 
darstellen. Für z.B. 12Bit bräuchtest du dann [0, 4095] als 
Wertebereich.
Um auf z.B. 12Bit zu kommen musst du die Zahl anschließend um 6 nach 
rechts shiften. Und natürlich wie gesagt die appnote lesen.

von Manuel M. (manuel21)


Lesenswert?

Hallo!

Soweit ich das verstanden habe, geht es darum, dem Messwert ein 
künstliches rauschen aufzulegen, danach zb. 32 Messwerte zu machen, 
diese zu addieren und danach um 3 nach rechts shiften um 12 Bit zu 
erzeugen, ist richtig so oder ?

Nur wir kann man das künstliche Rauschen auf der internen Bandgap 
Referenz erzeugen, bzw. ist es da schon nicht wesentlich ungenauer, 
aufgrunddessen, dass die Bandgapreferenz sowieso nicht exakt bekannt ist 
?

MfG
Manuel

von avion23 (Gast)


Lesenswert?

Das Rauschen muss nicht künstlich sein, nur vorhanden.

Das Ergebnis wird nicht genauer, man erhöht nur die Auflösung. Aber auch 
das ist schon toll. Messen bedeutet vergleichen. Wenn man z.B. wissen 
möchte, ob der Messwert leicht größer ist als der vorherige, kann man 
das so machen.

von Manuel (Gast)


Lesenswert?

Hallo!

ja hab mich mittlerweile schon eingelesen, klar das es nicht genauer 
werden kann.

Nur denke ich wird mein Eingangssignal zu stabil sein also keinerlei 
1-2LSB Sprünge bei der Messung hervorrufen, sodass ich oversampling 
nicht wirklich anwenden kann um damit eine höhere Auflösung zu erzeugen 
bekommen, deshalb das künstliche rauschen.

Oder meinst du das es auch ohne geht ?

von Peter D. (peda)


Lesenswert?

Wie kommst Du überhaupt darauf, daß 10 Bit nicht reichen?
Hast Du es nachgerechnet, dann zeige mal die Rechnung.

Wie genau mußt Du denn die Zellenspannung messen und in welchem Bereich?


Peter

von Manuel M. (manuel21)


Lesenswert?

Ich habe nie behauptet das 10 Bit nicht reichen, es wurde mir hier nur 
vorgeschlagen trotzdem oversampling zu machen.

5mV genau muss ich messen. Wobei ich da jeden Attiny abgleichen muss mit 
der Bandgap Referenz denke ich mal.

von avion23 (Gast)


Lesenswert?

Hallo Manuel,
ich wollte dir nur eine billige Möglichkeit zum Tiefpassen & Auflösung 
erhöhen geben. Wahrscheinlich möchtest du eh >= 2 bytes übertragen, dann 
kannst du die >= 6bits auch nutzen.

von Manuel (Gast)


Lesenswert?

Stimmt ja!

Danke, werde mich nochmal damit beschäftigen, denn so ganz klar ist mir 
die Sache noch nicht.

Ich habe gelesen, dass ich die Interne bandgap wohl min. 8 mal lesen 
muss, bevor ein richtiger Wert zustande kommt, da diese sehr hochohmig 
ist und von anderen Eingängen oder so beeinflusst werden kann, und das 
erst nach 6 maligem messen nahezu weg ist.

Ist das richtig so?

Eine Frage hätt ich noch zur Datenübertragung, ich verstehe noch nicht 
so ganz wie ich die von einem Attiny zum anderen am besten übertrage. 
Soll da jeweils auch ein Interrupt ausgeführt werden sobald er vom 
anderen Attiny was bekommt oder wie soll ich mir das vorstellen?

Danke

MfG
Manuel

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Soll da jeweils auch ein Interrupt ausgeführt werden sobald er vom
> anderen Attiny was bekommt oder wie soll ich mir das vorstellen?

Ja, Du kriegst an jeder Flanke einen Interrupt.

Z.B. Du Setzt ein Compareregister auf 1,5 Bitzeiten. Bei der Low-Flanke 
setzt Du den Timer zurück und bei der High-Flanke guckst Du nach, ob das 
Comparebit gesetzt ist und schiebst es in das Datenbyte rein (<1,5T = 
0-Bit, >1,5T = 1-Bit).


Peter

von Manuel (Gast)


Lesenswert?

Hallo Peter

Also ganz verstehe ich das nicht, ich mach einen externen Interrupt ist 
klar.

Ich verwende einen Timer, angenommen 1 Bit ist 1ms lang, stell ich 1.5ms 
am Timer ein.

Jede Flanke am Eigang geht es in einen Interrupt, dort wird überprüft ob 
die Flanke nach low geht oder nach high. Was mach ich nun damit? Da 
Blick ich nicht ganz durch

MfG
Manuel

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Ich verwende einen Timer, angenommen 1 Bit ist 1ms lang, stell ich 1.5ms
> am Timer ein.

Ich bezog mich auf meinen obigen Vorschlag:
0-Bit: 1ms Puls
1-Bit: 2ms Puls

Vergiß das mit der Baudrate, das gilt nur für ne UART. Ne UART benötigt 
aber ne zu hohe Genauigkeit des CPU-Taktes.
Daher besser (und einfacher) Pulsweite = Bitinformation.
Eben wie (fast) jede IR-Fernbedienung es macht.


Peter

von Manuel (Gast)


Lesenswert?

Hallo!

Ja die Funktion ist mir klar.

Es geht um die ausführbarkeit.

Zuerst kann ich doch nur entweder auf eine postive oder negative Flanke 
einen Interrupt setzen, laut Tutorial zumindest.

Und ich versteh auch nicht wie ich einen Timer so konfigurieren kann das 
er bei einem vergleichszahlenwert nur ein bit seines Registers auf 1 
setzt zb. CTC macht ja einen ganzen Interrupt, was ich ja nicht haben 
möchte.

von Peter D. (peda)


Lesenswert?

Naja, ins Datenblatt mußt Du schon mal schauen:

Manuel schrieb:
> Zuerst kann ich doch nur entweder auf eine postive oder negative Flanke
> einen Interrupt setzen, laut Tutorial zumindest.

Datenblatt S.51:
"Pin change interrupts PCI
will trigger if any enabled PCINT5..0 pin toggles."


> Und ich versteh auch nicht wie ich einen Timer so konfigurieren kann das
> er bei einem vergleichszahlenwert nur ein bit seines Registers auf 1
> setzt zb. CTC macht ja einen ganzen Interrupt, was ich ja nicht haben
> möchte.

Datenblatt S.84:
"• Bit 4– OCF0A: Output Compare Flag 0 A
The OCF0A bit is set when a Compare Match occurs between the 
Timer/Counter0 and the data
in OCR0A – Output Compare Register0."


Peter

von Manuel (Gast)


Lesenswert?

Hallo!

Ja sorry Peter.

kannst du mal schauen ob das so past?

Danke
1
#include <stdint.h>
2
#include <avr/io.h>
3
#include <avr/interrupt.h>
4
5
ISR(PCINT0_vect)
6
{
7
    if( (PORTB & 1) == 0 ) 
8
  {  TCNT0=0;
9
     TIFR0 |= (1 << OCF0A); //Comparebit löschen
10
  }
11
12
  else
13
  {  
14
  
15
     if(TIFR0 & (1<<OCF0A))
16
     {  //Bit ist 1
17
        TIFR0 |= (1 << OCF0A); //Comparebit löschen
18
     }
19
20
     else
21
     {  //Bit ist 0
22
     }
23
24
  }
25
}
26
27
int main(void)
28
{
29
30
GIMSK = (1<<PCIE);    //Pin-Change-Interupt
31
PCMSK = (1<<PCINT0);  //an PB0
32
33
sei();
34
35
TCCR0B = (1<<CS01);   //8-Bit Vorteiler
36
37
38
OCR0A = 124; //bei 1.5ms
39
40
41
42
while(1);
43
}

von Manuel (Gast)


Lesenswert?

Hallo!

Wie kann ich denn nun am besten das Senden realisieren.

Ich hätte daran gedacht einen Interrupt alle 1ms zu machen, aber das hat 
nicht viel Sinn denke ich.

Der µC sollte nicht ganze Zeit aufgehalten werden mit dem Senden, also 
wärs schon schön wenns mit Interrupt geschieht.

angenommen ich möchte 16Bit senden.
1
void send(char *s)
2
{  for(int i=0;i<16;i++)
3
   {  if(s[i])
4
      {  PORTB &= ~(1<<PB0);
5
         _delay_ms(2);
6
         PORTB |= (1<<PB0);
7
      }
8
      
9
      else
10
      {  PORTB &= ~(1<<PB0);
11
         _delay_ms(1);
12
         PORTB |= (1<<PB0);
13
      }
14
   }
15
}

Ich denke so müsste das ganze funktionieren, aber so wartet der µC ganze 
Zeit und das ist etwas was ich eigentlich vermeiden wollte. Kann mir 
jemand sagen wie ich das ganze besser lösen könnte?

Danke
Lg Manuel

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Ich hab mir mal was überlegt und meinen Vorschlag etwas modifiziert.
Wenn man die Pin-Toggle Funktion zum Senden und den Pin-Change-Interrupt 
zum Empfang nimmt, kann man ja ganz einfach auf jeder Flanke ein Bit 
übertragen.

Anbei ein Beispiel, das ich auf dem STK500 getestet hab. Die beiden 
Datenpins muß man mit einem Jumper überbrücken. Ich hate grad nur nen 
ATmega644 da und habe nur die beiden 8Bit-Timer benutzt.
An den ATtiny25 hätte ich nicht so viele Tasten und LEDs anklemmen 
können.
Die Anpassungen sollten aber leicht sein.

Ich hoffe mal, der Code ist nicht zu kompliziert. Übertragen werden 
4Byte-Pakete.


Peter

von Manuel (Gast)


Angehängte Dateien:

Lesenswert?

Besten Danke Peter!

Ich habe versucht, das ganze mit einem Attiny13 ans laufen zu bekommen, 
erstmal nur das senden, seh ich eh am Oszilloskop ob es past, im Anhang 
ist die Datei.

Der Compiler meldet folgenden Fehler:

../send.c:46: warning: 'TIM0_COMPA' appears to be a misspelled signal 
handler
../send.c:46: warning: 'TIM0_COMPA' appears to be a misspelled interrupt 
handler

Im Datenblatt steht dies allerdings drin, dass dies der passende 
Interrupt handler ist.

Momentan ist am Ausgang des OC0A ein 50/50 Rechteck mit gut 36kHz. Daten 
werden nicht gesendet.

Weißt du was es damit auf sich hat ?

Danke
Lg
Manuel

von Manuel (Gast)


Lesenswert?

Mann bin ich dämlich, es sollte natürlich TIM0_COMPA_vect heißen.

Es funktioniert zwar das senden noch immer nicht aber mal schauen was 
ich noch falsch hab

von Manuel (Gast)


Lesenswert?

Also, er geht jetzt in die IRQ hinein, allerdings kommt er nie in diese 
Abfrage hinein, weshalb nur Nullen rauskommen

if( *dp & 0x80 )

Wenn ich das richtig beurteile, setzt zu den Pointer auf den Anfang des 
Feldes ( beim ersten Durchlauf auf tx_data[0] ) zeigt also auf das LSB
Hab ich nun in der main stehen, tx_data[132] sollte er wenn er *dp 
aufruft doch dieses hier sehen: 10000100 dieses verundet er nun mit 
100000000 das kann doch niemals wahr sein oder ? denn in der *dp steht 
ne 8 Bit variable drin und verundet wird es mit einer 9 Bit wo nur das 
MSB 1 ist.

Hab ich da irgendwo einen Denkfehler?

von Manuel (Gast)


Lesenswert?

Natürlich blödsinn, 0x80 ist eh 1000 0000 sorry

Ich hab den Fehler erkannt, ich hab die Optimierung des Compilers jetzt 
auf O0 gestellt und jetzt funktionierts, sonst nichts verändert nur von 
Os auf O0, war das bei dir auch so, oder kannst du mir sagen wieso das 
so ist ??

Danke

von Manuel (Gast)


Lesenswert?

Nur das "ISR_NOBLOCK" muss ich aus irgendeinen Grund weggeben, sonst 
funktionierts nicht.

Was mir auch aufgefallen ist, mit deiner programmierung erreichst du ja, 
dass er 4T - 4T schickt oder ? also wenn ich das einfach immer senden 
lass, kommt 4T Stop darauf 4T Start darauf 4T Stop darauf 4T Start und 
ab da läuft dann erst die 32 bit Datenabfolge. Dies erreichst du ja 
durch diese Zeile:
1
if( tx_idx > DATA_SIZE * 8 + 1              // after stop bit sent
2
        && PINB & 1<<PB0 )                      // and after output = high
da du hier ja noch +1 schreibst. Ist das gewollt ? bringt das Vorteile?

Danke
Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Ich hab den Fehler erkannt, ich hab die Optimierung des Compilers jetzt
> auf O0 gestellt und jetzt funktionierts,

Ja, der GCC schießt beim Optimieren gerne mal über das Ziel hinaus.
Da Dein Main sehr kurz ist, lädt er die Variablen nur einmal vor der 
Schleife.
Das kann man so verhindern:
1
int main( void )
2
{
3
  DDRB |= 1<<PB0;                       // tx output on
4
  
5
  sei();
6
  for(;;)
7
  {
8
9
    __asm__ volatile ("" ::: "memory");  // das hier einfügen !!!
10
11
    if( tx_busy() == 0 )
12
  {               // if previous transmit done
13
      tx_data[0] = 134;
14
      tx_start();
15
    }
16
  }
17
}

Diese Zeile sagt ihm, daß alle globalen Variablen verändert wurden und 
somit neu geladen werden müssen.


Peter

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Nur das "ISR_NOBLOCK" muss ich aus irgendeinen Grund weggeben, sonst
> funktionierts nicht.

Ohne Optimierung bläht sich der Code extem auf und dann unterbricht der 
Interrupt wohl sich selbst.

Nur 200 Zyklen Bitzeit sind ja auch recht sportlich. Geh mal besser mit 
der F_CPU rauf oder mit dem Bittakt (5kHz) runter.


Das "ISR_NOBLOCK" ist sinnvoll, damit bei gleichzeitigem Empfang der 
Empfang nicht gestört wird.
Das Senden ist ja durch das Toggle on Compare automatisch Jitterfrei.


Peter

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> da du hier ja noch +1 schreibst. Ist das gewollt ?

Ja, das ist notwendig.
Du bereitest ja im Interrupt nur vor, wann die nächste Flanke kommt, 
also das Bit zuende ist.
Ohne das +1 würde der Timer sofort gestoppt und es fehlt das letzte 
Datenbit.

Daß noch ein 2. Stopbit folgt, habe ich im Hinblick auf Stromsparen 
gemacht, d.h. damit der Pin in den Sendepausen wieder high ist, muß die 
Anzahl der Flanken gerade sein.


Peter

von Manuel (Gast)


Lesenswert?

Hallo!

Habs gerade getestet, funktioniert einwandfrei.

Vielen vielen dank schonmal!

Eine Frage hätt ich noch undzwar, wenn ich jetzt pro µC 16-Bit sende, 
wie kann ich es am einfachsten machen, dass der µC empfängt und das was 
er empfängt sofort weitersendet, und nur seine 16-Bit anhängt?

4 Byte immer empfangen und wieder als 4 Byte senden, ist wohl nicht das 
wahre oder doch?

von Manuel (Gast)


Lesenswert?

Wenn tx_idx 32 ist, setzt du ja den Timer sodass es 4T Zeit gibt. Wieso 
kannst du dann nicht bei tx_idx 33 bereits den Timer abschalten, dann 
hättest du die 4T Stopbit doch schon gehabt.

Was ich nicht ganz verstehe ist, wie du das Startbit machst.
Müsste nicht bei tx_start der Wert für 4T im OCR0A hineingeschrieben 
werden?

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Müsste nicht bei tx_start der Wert für 4T im OCR0A hineingeschrieben
> werden?

Ja, sonst ist das erste Paket ungültig.

Ich hab zu Hause kein Speicheroszi, hab also nur mit den Tasten und LEDs 
auf dem STK500 debuggt. Daher ist mir das nicht aufgefallen.


Peter

von Peter D. (peda)


Lesenswert?

Manuel schrieb:
> Eine Frage hätt ich noch undzwar, wenn ich jetzt pro µC 16-Bit sende,
> wie kann ich es am einfachsten machen, dass der µC empfängt und das was
> er empfängt sofort weitersendet, und nur seine 16-Bit anhängt?

Kann man machen, dann muß der letzte aber 80 Bytes senden.
Und Puffern muß man einige Bytes, damit beim Senden keine Pause 
entsteht.
Es kann ja sein, daß der vorherige nen Tick langsamer sendet.
Und es ist kein Senden vom Master zu einem Slave möglich.


Eine andere Möglichkeit:
Der Master sendet 3 Byte, das erste ist die Adresse. Jeder sendet diese 
weiter und zählt die Adresse runter. Ist sie 0, dann ist er adressiert 
und liest die 2 Datenbytes vom Master ein und sendet an deren Stelle 
seine 2 Datenbytes weiter.
Der Master muß also 40 Pakete a 3 Byte senden/empfangen.
Er muß aber nicht auf den Empfang warten, eine Pause von einem Byte 
zwischen den Paketen sollte reichen.
Durch das Runterzählen der Adresse weiß der Master auch, von welchem 
Slave das empfangene Paket ist.


Peter

von Manuel (Gast)


Lesenswert?

Sehr interessante Möglichkeit.

Das ganze würde also so ablaufen:

Master sendet 29 - 0 - 1  ( also 30. Zelle und 0 - 1 heißt sende deine 
Spannung )

der erste bekommts, speicherts ab, macht
if(rx_data[0])
{ rx_data[0]--;
  // muss hier jetzt entweder die ganzen rx_data[0] in tx_data[0] 
machen, oder verwendet rx_data gleich zum senden.
  tx_start;
}
else
{ .... } // Spannung weitersenden

meinst du das so?

Geht aber wesentlich langsamer wenn ich alle 40 Zellen haben möchte oder 
?

von Manuel (Gast)


Angehängte Dateien:

Lesenswert?

So ich hab hier mal nen Screenshot vom Oszilloskop gemacht

Hier sieht man, dass er 3 Stopbits sendet. Mit der Modifikation, im 
tx_start 4T für OCR0A einzutragen, sendet er jetzt auch 4 T Startbit.

Die Frage ist, du meintest du hättest gerne, dass er während der Pausen 
High ist. Nachdem er das erste Stopbit gesendet hat, wäre er beim 
nächsten mal doch auch schon High, und könnte den Timer abdrehen oder 
nicht ?

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Hast recht, der tx_idx Vergleich kann raus:
1
/****************************** Transmission ****************************/
2
3
uint8_t tx_data[DATA_SIZE];
4
uint8_t tx_idx;
5
6
7
ISR( TIMER0_COMPA_vect, ISR_NOBLOCK )           // Transmit interrupt
8
{
9
  uint8_t *dp;          // locals for faster access
10
11
  if( tx_idx < DATA_SIZE * 8 ){
12
    OCR0A = (int16_t)(F_CPU / BIT_CLK / PRESCALER * 1 - 0.5);   // 0-bit: 1T
13
    dp = &tx_data[tx_idx / 8];                  // get byte address
14
    if( *dp & 0x80 )                            // msb first
15
      OCR0A = (int16_t)(F_CPU / BIT_CLK / PRESCALER * 2 - 0.5); // 1-bit: 2T
16
    *dp <<= 1;                                  // shift bits
17
  }else{
18
    OCR0A = (int16_t)(F_CPU / BIT_CLK / PRESCALER * 4 - 0.5);   // stop:  4T
19
    if( PINB & 1<<PB3 )                         // after output = high
20
      TCCR0B = 0;                               // then stop T0
21
  }
22
  tx_idx++;                                     // point to next bit
23
}
24
25
26
uint8_t tx_busy( void )
27
{
28
  return TCCR0B;                                // 0 = tx done
29
}
30
31
32
void tx_start( void )
33
{
34
  tx_idx = 0;                                   // point to first bit
35
  OCR0A = (int16_t)(F_CPU / BIT_CLK / PRESCALER * 4 - 0.5);   // start: 4T
36
  TCCR0A = 1<<COM0A0                            // toggle pin on compare
37
         | 1<<WGM01;                            // Mode 2: CTC
38
  TCCR0B = 1<<CS01;                             // F_CPU / 8;
39
  TIMSK0 = 1<<OCIE0A;  
40
}


Peter

von Manuel M. (manuel21)


Lesenswert?

Danke!

Aber müsste nicht das Startbit beim senden auch anders ausschautn, und 
die Startbit erkennen beim Empfangen?

Denn wie man am Oszilloskop sieht, gibt es keine wirklichen 4T start, wo 
er zuerst mal ne Flanke hat, 4T Zeit und danach ne weitere Flanke.

und der Empfänger ist ja auch sofort auf empfangen, nachdem er das 
Stopbit des vorherigen bekommen hat, so wie ich das gesehen hab.

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel M. schrieb:
> Denn wie man am Oszilloskop sieht, gibt es keine wirklichen 4T start, wo
> er zuerst mal ne Flanke hat, 4T Zeit und danach ne weitere Flanke.

Eine extra Flanke ist unnötig.
Die Zeit seit der letzten Flanke muß nur >3T sein, eine obere Grenze 
gibt es nicht.


Peter

von Manuel M. (manuel21)


Lesenswert?

Stimmt, das heißt es ist gewollt, das du gleich 3T nach der letzten 
Flanke des Stoppbits automatisch das Empfangen aktiviert wird?

Lg

von Manuel M. (manuel21)


Lesenswert?

Hallo!

Also ich hab mir grad mal nen Umsetzer mit nem Attiny2313 gemacht, der 
mir die Daten an RS232 weiterschickt, damit ich mir nachher den 
Datenverkehr zwischen den Attinys besser anschauen kann. Funktioniert 
einwandfrei!

Die Frage ob es Absicht ist, dass direkt nach dem Stopbit der Empfang 
automatisch aktiviert ohne dass das Startbit wirksam ist, bleibt offen?

Eine weitere Frage hätt ich auch noch undzwar, wollte ich eigentlich 
einen Attiny13 verwenden, der hat allerdings nur einen Timer, und 
zusätzlich bräuchte ich noch einen PWM Ausgang, also schon 3 Timer, wenn 
ich alles per Hardware Timer mache. Gibts ne Möglichkeit auch mit einem 
Timer insgesamt auszukommen?

Danke

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Das Start/Stopbit ist beides zusammen. Es reicht eins aus, können aber 
beliebig viele sein.

Wenn der Master nach dem Senden ne Pause macht, kann der Slave den Timer 
zum Senden umschalten, dann reicht ein Timer.
Man kann den Timer auch durchlaufen lassen und dann die Comparewerte zum 
Timer addieren.
Man kann auch statt dem Comparepin nen anderen nehmen und dann im 
Interrupthandler togglen.


Peter

von Manuel M. (manuel21)


Lesenswert?

Hallo!

Das heißt, eigentlich würde es ohne Stopbit genausogehen, richtig?

Also, es ist klar, dass ich den Timer dann umschalten könnte, was mir 
allerdings nicht klar ist, was du allerdings mit Comparewerte zum Timer 
addieren meinst, und was mir das bringt, ist mir noch nicht ganz klar.

Und was bringt es, wenn ich statt dem Comparepin nen anderen nehme und 
das im Interrupt toggle? Bringt, mir doch keine Vorteile, dass ich nen 
Timer spar oder so?

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

Ich meinte natürlich ob ich das Startbit eigentlich garnicht brauche.

Kann ich die 3 Timer auf 1 reduzieren? wohl eher nicht oder? bei der PWM 
Frequenz bin ich relativ wunschfrei, irgendwas zw. 200Hz und 10kHz, 
total egal.

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel M. schrieb:
> allerdings nicht klar ist, was du allerdings mit Comparewerte zum Timer
> addieren meinst, und was mir das bringt, ist mir noch nicht ganz klar.

Dann kann der Timer durchlaufen, z.B. für eine PWM.
Statt:
1
  // CTC Mode:
2
  OCR0A = x; // nächster Interrupt nach x Counts
dann:
1
  // Normal Mode:
2
  OCR0A += x; // nächster Interrupt nach x Counts

Manuel M. schrieb:
> Kann ich die 3 Timer auf 1 reduzieren?

Sollte gehen. Ich würde trotzdem nen ATtiny25 nehmen.


Peter

von Manuel M. (manuel21)


Lesenswert?

Ahja !

Ok alles klar, nur wieso würdest du trotzdem den Attiny25 verwenden, die 
interne BGD ist zu ungenau, ich hab einen hier, der von 5V bis 3V bei 
gleicher Temperatur insgesamt um 100mV schwankt. Ich müsste also sowieso 
ne externe Spannungsreferenz verwenden denk ich mal.
aber wieso würdest du zu dem Attiny25 tendieren ?

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel M. schrieb:
> Ahja !
>
> Ok alles klar, nur wieso würdest du trotzdem den Attiny25 verwenden, die
> interne BGD ist zu ungenau, ich hab einen hier, der von 5V bis 3V bei
> gleicher Temperatur insgesamt um 100mV schwankt.

Glaub ich Dir nicht.
Wie hast Du das gemessen?

> aber wieso würdest du zu dem Attiny25 tendieren ?

Gleiches Gehäuse, kaum teurer als der ATtiny13.
Wenn Du bei der Entwicklung merkst, daß es in einen ATtiny13 paßt, 
kannst Du den ja immer noch nehmen.

Ich würde eh nicht gleich 40 Schaltungen aufbauen, sondern erstmal 2 - 
4.


Peter

von Manuel M. (manuel21)


Angehängte Dateien:

Lesenswert?

Ja ne ich würd eh auch nicht gleich 40 bauen sondern nur mal ein Paar, 
deshalb hab ich ja Attiny25 und Attiny13 hier zum testen.

Ich hab das folgendermaßen gemacht, die Eigenspannungsmessung ganz 
normal, das sende ich raus und der Attiny2313 übersetzt es auf RS232 
sodass ichs am PC anschauen kann.

Ich hab exakte 5.00V angelegt, kalibriert ( Wert für die BGD im EEPROM 
gespeichert ) danach die Spannung bis auf 2.9V hinuntergeregelt und alle 
paar hunder mV den tatsächlichen Wert mit dem angezeigten am PC 
verglichen, im Anhang ist die .xls dazu.

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

Ok anscheinend, hab ich einen kleinen Fehler gehabt, es ist um ca. 
+-15mV falsch über den Gesamten Spannungsbereich.

Aber ich würde trotzdem gerne probieren, dass mit einem Attiny13 zu 
machen, kannst du mir sagen, wie ich am einfachsten/besten es schaffe 
nur einen Timer zu verwenden?

Danke
Lg
Manuel

von Peter D. (peda)


Lesenswert?

Manuel M. schrieb:
> Aber ich würde trotzdem gerne probieren, dass mit einem Attiny13 zu
> machen

Beitrag "mehrere MC seriell über Datenbus verbinden (1Draht)"

Slave1a.c
Warscheinlich heißen einge Register und Bits anders.


Peter

von Manuel M. (manuel21)


Angehängte Dateien:

Lesenswert?

Hallo Peter !

Danke, also auf dem Attiny13 funktioniert es schonmal, nun wollte ich 
das ganze auf einem Attiny2313 machen, der nur empfängt, hier erstmal 
nur, sobald er 2 Bytes empfangen hat, soll er die PORTD auf high 
schalten.
Tut er aber nicht, in den PCINT ISR geht er, allerdings wird rx_idx 
anscheinend nie 255, hast du eine Idee was da schief läuft?

Danke!

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

Ich weiß nun wo der Fehler liegt, weiß aber nicht wie ich ihn beheben 
kann.

Undzwar ist es völlig egal was in OCR0A und OCR0B steht, alle 250µs 
macht er einen Comparematch.

Ich hab mir die Register nochmals angeschaut, mit dem Datenblatt 
verglichen, das sollte eigentlich passen. Hat jemand trotzdem eine Idee 
was da nicht passt?

Danke
Lg
Manuel

von Peter D. (peda)


Lesenswert?

1
  clock_prescale_set( clock_div_1 );

Dann mußt Du auch schreiben:
1
#define F_CPU 8e6


Peter

von Manuel M. (manuel21)


Lesenswert?

Hallo!

Das hast du doch auch geschrieben obwohl du 64 als Prescaler hattest?

Außerdem ändert das nichts daran, dass ich in OCR0A und OCR0B schreiben 
kann was ich will, es wird immer nach 250µs ausgelöst.

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

1
  TCCR0B = (1<<CS01);
2
  OCR0B = 10;
3
  TIMSK = (1<<OCIE0B);

Das müsste doch funktionieren, dass ein TIMER0_COMPB_vect Interrupt 
ausgeführt wird oder?
Also ausgeführt wird er schon, allerdings ist es egal welcher Wert in 
OCR0B steht.
Es ist immer die selbe Zeit bis er in den Interrupt kommt.

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

Hallo!

Ok schonklar, es kann sich ja auch nicht ändern, wenn ich im Interrupt 
dann nicht TCNT0 auf 0 setze !

Problem ist aber trotzdem, der Empfang funktioniert nicht, da alle 250µs 
der Interrupt auslöst, keine Ahnung wie ich das ändern kann ?

Lg
Manuel

von Peter D. (peda)


Lesenswert?

1
8MHz / 5kHz / 8 * 4 = 800
800 paßt nicht in einen 8-Bit Timer, der Compiler sollte ne Warnung 
ausgeben.
Warnungen muß man lesen!


Peter

von Manuel M. (manuel21)


Lesenswert?

Naja, nachdem hier F_CPU 1e6 steht, und ich in den Fuses 1MHz 
eingestellt habe, sinds 100 als ergebnis, und das passt sehrwohl rein!

Lg
manuel

von Peter D. (peda)


Lesenswert?


von Manuel M. (manuel21)


Lesenswert?

Ja ich habs gelesen, verstehe aber nicht was es damit auf sich hat, wenn 
ich Fragen darf, was hat es denn damit auf sich?

Lg

von Peter D. (peda)


Lesenswert?

Damit wird der CPU-Teiler von 8 auf 1 gesetzt.
D.h. die CKDIV8-Fuse ist egal, er läuft immer mit 8MHz.


Peter

von Manuel M. (manuel21)


Lesenswert?

Ahja, ok alles klar, ich schaus mir nochmal an.
Danke

Lg

von Manuel M. (manuel21)


Lesenswert?

Hallo!

ok nun funktioniert es, komischerweise, obwohl ich das selbe vorher 
schonmal versucht habe, in dem ich das clock_prescale_set einfach mal 
mit "//" ausgeklammert habe.

Danke!

Lg
Manuel

von Manuel M. (manuel21)


Angehängte Dateien:

Lesenswert?

Momentan ist das ganze ja so ausgelegt, dass ein Anschluss für Senden 
und Empfangen da ist. Das kann ich so nicht verwenden, da ich ja 
unterschiedliche Massen habe oder ?

Wie im Anhang wirds wohl auch nicht gehen, wenn +5V anliegt ist alles 
klar, da sperren alle Transistoren, aber wenn Masse anliegt, leiten 
alle, und zieht den Strom über den untersten Transistor oder?

Lg
Manuel

von Peter D. (peda)


Lesenswert?

Und wo ist das Problem, nimmst halt nen anderen Pin zum Empfang.

Pin-Change-Interrupt kann doch jeder Pin sein.


Peter

von Manuel M. (manuel21)


Lesenswert?

Ja schonklar, allerdings sind dann nichtmehr alle Parallel geschaltet, 
sondern mehr oder weniger in Reihe. Ich könnte ja wohl auch im Pin 
Change Interrupt den Ausgangspin toggeln, dann würde ich den Ausgang 
gleich haben wie den Eingang, und das könnte an den nächsten weitergehen 
undso weiter. Aber die Vorteile von der Parallelschaltung, dass ich den 
Ausfall einzelner Attinys kontrollieren kann und schnellere Abarbeitung 
hab ich dann nicht.

Müsste es nicht Schaltungstechnisch irgendwie trotzdem funktionieren, 
das ganze muss ja nur in eine Richtung funktionieren, denn wenn der 39te 
Attiny was wegschickt, brauchts der 20te Attiny eh nicht wissen, etc. 
Aber mit der Schaltung wie im vorigen Post ziehts enorm viel Strom wenn 
alle Transistoren durchgeschaltet sind, denk ich mal.

Was meinst du, wies am besten geht ?

Lg

von Manuel M. (manuel21)


Lesenswert?

Du meinst also, Eingang auf einen PIN, Ausgang auf einen anderen PIN.

Abfrage, ob Adressbit gleich der Adresse des µCs entspricht, wenn nicht, 
tx_data mit den eben empfangenen Daten, richtig ?

Wärs da eventuell sogar nicht besser, direkt im PCINT0 Interrupt den 
Transmit PIN zu toggeln, sodass am RX und am TX das gleiche anliegt ( 
kurz Zeitversetzt weil er ja in den Interrupt rein muss, und toggeln 
muss )

Danke!

Lg
Manuel

von Manuel M. (manuel21)


Angehängte Dateien:

Lesenswert?

Hallo!

Was hältst du davon ?

Das einzige Problem ist, dass der Master gleich nachdem er auf empfang 
geschalten hat, einen Pin Change Interrupt bekommt, da die Transistoren, 
ja ne kleine propagation delay haben. Was sagst ansonsten dazu?

Lg
Manuel

von Manuel M. (manuel21)


Lesenswert?

Vermutlich wäre es wirklich einfacher, Tx und Rx zu trennen oder ?

Aber wie wärs da besser, jedem µC die kompletten Bytes empfangen zu 
lassen, danach nachzuschauen obs für ihn bestimmt ist, und dann wenn 
nicht, das selbe wieder raussenden, ansonsten seine Informationen als 
Daten schicken und so kommts dann auch wieder zum Master ?

So könnte der Master eigentlich ständig ( mit 2 Byte Abstand denk ich 
mal ? ) senden, und braucht nicht aufs empfangen warten, weil von wems 
kommt erkennt er an der Adresse.

Wie siehst du das ?

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
Noch kein Account? Hier anmelden.