40 Spannungen einlesen und an AtMega8 übertragen

Gast #1898578
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
Gast #1898590
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
Gast #1898642
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
Gast #1898680
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
Gast #1898684
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.
Gast #1898688
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.
Gast #1898703
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
Gast #1898746
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.
Gast #1898799
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
Gast #1899429
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.
#1899498
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
Gast #1899545
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.
Gast #1899561
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
Gast #1899574
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?
Gast #1899652
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
Gast #1899690
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.
Gast #1899776
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
Gast #1899816
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.
Gast #1899823
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?
#1900142
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
Gast #1900264
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.
Gast #1900439
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
#1900455
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
Gast #1900468
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 ?
Persönliche Seite #1900548
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.
#1900578
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
Gast #1900790
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.
Gast #1901163
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.
Gast #1901679
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 ?
Persönliche Seite #1903628
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 ;-)
#1903682
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
Angehängte Dateien:
Gast #1904219
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?
#1904454
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
Gast #1904662
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
Gast #1904687
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.
#1904729
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
#1904909
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?
Gast #1904958
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 ?
Gast #1905065
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.
Gast #1906600
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.
#1909198
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
Gast #1910387
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.
Gast #1910395
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 ?
Gast #1924817
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.
Gast #1926165
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
#1926265
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
Gast #1926291
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
#1926312
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
Gast #1926354
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.
#1926552
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
Gast #1927117
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
}
Gast #1938678
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
#1941233
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
Angehängte Dateien:
Gast #1943531
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
Angehängte Dateien:
Gast #1943709
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?
Gast #1943765
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
Gast #1943773
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
#1943822
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
#1943830
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
#1943844
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
Gast #1943879
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?
Gast #1943892
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
#1944115
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
Gast #1944200
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 
?
Gast #1944266
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
Angehängte Dateien:
#1945891
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
#1945903
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
#1950009
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
#1950288
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
#1951049
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
#1954282
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
#1954285
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
#1954292
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
#1954294
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
Angehängte Dateien:
#1958661
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
#1961537
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
Angehängte Dateien:
#1962223
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
#1962301
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
#1962665
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
Angehängte Dateien:
#1962741
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
#1964010
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
#1967681
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 ?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren