Hallo Forum,
ich möchte Daten in einer Richtung von uC zu uC übertragen und möglichst
nur eine Leitung dafür verwenden. Der empfangende ATTiny hat keinen
Quarz!
Die Leitung sollte ein paar (<10) Meter lang sein können und mehrere
Attinys sollten dran hängen können (Adressierung kriegen wir später ;-).
Was kann man da leicht implementieren (in C)?
Grüße,
Egberto
Hallo,
mehrere 01 am Anfang schicken zum Syncronisieren, dann eine Präambel um
den Anfang zu erkennen, dann die Daten mit Prüfsumme.
Wenn es nicht verloren gehen soll, mehrmals schicken.
Die Kurzzeitstabilität sollte da ausreichen, wenn die Datenpakete nicht
zu groß werden, sonst eben neu syncronisieren.
Sollte eigentlich gehen...
Gruß aus Berlin
Michael
Egberto Gismonti wrote:
> ich möchte Daten in einer Richtung von uC zu uC übertragen und möglichst> nur eine Leitung dafür verwenden. Der empfangende ATTiny hat keinen> Quarz!
Ja, ist kein Problem.
Man kann die Baudrate automatisch ermitteln.
Hier ein Beispiel (Anhang 12. Beitrag):
Beitrag "LCD über nur einen IO-Pin ansteuern"
Peter
Mit einer genugend tiefen Baudrate is das schon moeglich. Denkbar ist
eine positive flanke zu detekieren, und eine Zeit danach (zB 100us)das
Bit zu sampeln.
Du könntest drei verschiedene Zustände auf der Leitung verwenden. Wenn
du dann S0,S1,S2 hast, dann zeigt jeder Zustandswechsel clock an und die
Richtung des Wechsels data.
Also
S1->S0:0 S1->S2:1
S0->S2:0 S0->S1:1
S2->S1:0 S2->S1:1
Jetzt suchst du dir Zustände aus, die du gut implementieren kannst, z.B.
-5V,0V,5V oder 0V,5V,hochohmig
@Peter Danneger
Hallo Peter,
sieht so aus, als wäre es das, was ich brauche (vielen Dank!).
Ich habe noch ein Verständnisproblem: lt deiner Doku setzt man mit 0x13
+ Zahl die Baudrate - ich dachte, das ist autobaud??
Grüße,
Egberto
Luther Blissett wrote:
> Jetzt suchst du dir Zustände aus, die du gut implementieren kannst, z.B.> -5V,0V,5V oder 0V,5V,hochohmig
Und wie soll hochohmig erkannt werden bei? Zumal bei mehreren
Empfängern.
Manchester-Code funktioniert auch über eine Leitung ohne Quarz, da sich
der Empfänger auf die Flanken synchronisieren kann. Die Fenster können
mit einer Toleranz von bis zu 20% sicher ausgewertet werden.
Alexander Schmidt wrote:
> Luther Blissett wrote:>> Jetzt suchst du dir Zustände aus, die du gut implementieren kannst, z.B.>> -5V,0V,5V oder 0V,5V,hochohmig>> Und wie soll hochohmig erkannt werden bei? Zumal bei mehreren> Empfängern.
Ein Spannungsteiler für den ganzen Bus bringt die hochohmige Leitung auf
2.5V könnte ich mir vorstellen. Wenn man es richtig dimensioniert, dann
müssten die slaves eventuell sogar den dritten Zustand detektieren
können indem sie ihre internen pullups aktivieren/deaktivieren.
Hallo,
ich bisher nicht, aber z.B. wohl alle Leute, die einfache Funkmodule
benutzen. Da werden üblicherweise die Daten Manchester-codiert in den
Sender geschoben und aus dem Empfänger wieder rausgeholt...
Man kann durchaus sagen, daß jede Funkstrecke Sender-Empfänger eine
1-Draht Verbindung ist, noch dazu mit dem Nachteil vorkommender
Wackelkontakte ;-)
Gruß aus Berlin
Michael
Das Problem bei 1-Wire ist
1. Auf der Empfängersoftware liegt ein Copyright (oder Patent was auch
immer)
2. sehr "strammes" Timing
Scheint für meinen Zweck ungeeignet.
Grüße,
Egberto
> Das Problem bei 1-Wire ist> 1. Auf der Empfängersoftware liegt ein Copyright (oder Patent
Ist davon auszugehen, dass du deine Schaltung komerziell verwerten
willst?
Falls nein braucht dich das Patent nicht zu kümmern.
Egberto Gismonti wrote:
> Hat denn jemand einen einfachen Codeschnipsel zur unidirektionalen> Übertragung mit Machester-Code (in C)?>> Schon mal vielen Dank
Naja, wenn das Verfahren verstanden hat, sollte es kein Problem sein das
zu kodieren.
Senden - Du schickst einfach (clock xor data) auf den Draht. Damit sich
der Empfänger leichter synchronisieren kann, schickst du am besten am
Anfang einer Nachricht noch eine 0 als startbit vorraus.
void sendbit(bool b) { put(!b); delay(); put(b); delay(); }
Empfänger - Der Empfänger misst einfach die Zeit von Flankenwechsel zu
Flankenwechsel. Da der Sender eine Start-0 mitgeschickt hat, bekommt er
gleich eine ansteigende Flanke der Länge t (die dem delay() entspricht).
Wenn du dir jetzt z.B. das Manchester Code Beispiel auf Wikipedia
anschaust, dann siehst du, daß ein Puls der Länge 2*t nur dann vorkommt,
wenn sich das Datenbit ändert. Ansonsten bekommst du zwei Pulse der
Länge t. Ohne Gewähr hingehackt:
1
// wartet auf die nächste Flanke (egal welcher Richtung)
2
// gibt zurück wie lange das gedauert hat.
3
unsignedwtf();
4
5
// Aufzurufen, wenn das Startbit sichtbar wird, am Eingang liegt 1 an.
6
voidreceive()
7
{
8
boolbit=0;
9
unsignedt=wtf();// länge des 1-er Puls
10
while(1)
11
{
12
unsignedtx=wtf();
13
if(eps(tx,t))
14
{
15
tx=wtf();
16
if(eps(t,tx))
17
{
18
output(bit);
19
t=(t+tx)/2;// der Drift folgen
20
}
21
else
22
error();
23
}
24
elseif(eps(tx,2*t))
25
{
26
bit=!bit;
27
output(bit);
28
t=(2*t+tx)/4;// der Drift folgen
29
}
30
elseerror();
31
}
32
}
eps(x,y) ist Vergleich mit akzeptabler Fehlermarge.
Egberto Gismonti wrote:
> Das Problem bei 1-Wire ist> 2. sehr "strammes" Timing
Das würd ich nicht so sehen: Nach dem kurze Low Impuls sampled der
Empfänger in einem recht breiten Zeitfenster. Laut Datenblatt liegt
dieses Fenster 15-45µs nach dem vom Master erzeugten Impuls. Selbst mit
50% Taktabweichung sollte Onewire also noch funkionieren.
versuchs doch mal damit, wenn 2 Systeme nicht Absolut genau zueinander
sind, is es vl. in einem gewissen Maße Relativ genau.
versuchs mal mit:
1/3 LOW + 2/3 HIGH = 1
2/3 LOW + 1/3 HIGH = 0
also du hast einen zähler und zählst einfach wieviele clock pulse high
sind und wieviele low sind. dann schaust du welche der beiden größer ist
ob hightime oder lowtime. Wenn die Hightime länger war ist eine 1
übertragen worden. und bei Lowtime > Hightime --> 0 Übertragen worden,
also mit zb 15~20 Clock zyklen pro Bit funktioniert das schon wirklich
sehr gut. Meiner ansicht nach der beste weg um Asnychronität
auszugleichen.
lg
Gehtdich Nixanduspammbot wrote:
> also du hast einen zähler und zählst einfach wieviele clock pulse high> sind und wieviele low sind. dann schaust du welche der beiden größer ist> ob hightime oder lowtime. Wenn die Hightime länger war ist eine 1> übertragen worden. und bei Lowtime > Hightime --> 0 Übertragen worden,> also mit zb 15~20 Clock zyklen pro Bit funktioniert das schon wirklich> sehr gut. Meiner ansicht nach der beste weg um Asnychronität> auszugleichen.>> lg
Das ist auch eine schöne Idee. Wenn man unterschiedliche Pegellängen
benutzt, dann kann man auch auf beiden Flanken Daten übertragen. Man
sendet zunächst ein Synchronisationszeichen. Wenn der darauffolgende
Pegel die gleiche Länge t hat, dann wird 0 kodiert. Hat er eine andere
Länge, dann 1. Die andere Länge könnte z.B abwechselnd t*3/2 und t*1/2
sein, so daß die mittlere bitrate erhalten bleibt.
Die Synchonisation-Aktion kann man sich doch sparen, wenn man die Bits
über ein bestimmte Periodenlänge verteilt, und die Information ob 1 oder
0 über die Pulslänge realsiert.
Dann bräuchte man nur die Puls- und die Periodendauer (per ICP) messen
und könnte aus dem Tastgrad den Bitwert feststellen.
So ähnlich arbeiten Modellbaufernsteuerungen ja auch.
Hallo.
Von den ganzen Einleitungsbussen gibts von TI einen, der sich HDQ nennt.
Diesen habe ich mal im wesentlichen kopiert. Der Bus überträgt die Daten
bitseriell, mit einem 10us-Low als "1" und 30us-Low als "0", bei einer
minimalen Zykluslänge von 80us. Für die Rahmensynchronisation wird dem
Ganzen ein 60us-Low vorangestellt, und der Frame mit ACK/NACK bestätigt.
Dazu habe ich einen ext. Interrupt auf fallende Flanke getriggert. Im
Interrupt wird 80us lang ein Schleifenwert erhöht, solange der PIN low
ist. Die Auswertung des Zählerstandes führt zu High/Low/Break.
Gemacht habe ich das, weil es auf die Datenrate nicht ankam. Zudem ist
der Bus unempfindlich gegenüber Glitches, die nach der fallenden Flanke
kommen (war bei mir durch einf. opt. Isolation mit Optokoppler der
Fall).
Der Manchester ist ziemlich aufwendig in Software und braucht ne
Synchronisation (bekanntes 1.Bit).
Wenn man dessen Vorteil der Gleichspannungsfreiheit nicht braucht,
sollte man ihn daher nicht benutzen.
Wennn man keine Lust hat, ne Software-UART mit automatischer
Baudratenerkennung zu verwenden, bietet sich die Impulslängenmodulation
an, z.B.:
4*T = Startbit
2*T = 1-Bit
1*T = 0-Bit
Vorzugsweise wählt man T so, daß ein 8Bit-Timer im Empfänger nach 3*T
überläuft und der Comparator auf 1,5*T vergleicht.
Im Flankeninterrupt setzt man ihn zurück auf 0 und wertet diese beiden
Flags aus.
Peter
chris schrieb:> http://www.roboterclub-freiburg.de/AtmelAVR/Softwa...
Hallo Chris,
in meinem Thread:
Beitrag "Re: mehrere MC seriell über Datenbus verbinden (1Draht)"
hast Du geschrieben, daß Du 360KBit/s erreichst.
Ich habs mir daraufhin mal angesehen.
Also ich komme nur auf 1/(2*18,75µs) = 26,7kBit für 0-Bits bzw. 17,8kBit
für 1-Bits.
Ich verstehe auch nicht, wie sich der Slave auf den Empfang
synchronisieren kann, bzw. überhaupt mitkriegt, daß der Master sendet.
Es kann doch nicht sein, daß der Slave keine Main-Task machen kann,
sondern immer nur auf den Empfang wartet.
Und was passiert, wenn der Master schon ein Bit gesendet hat, ehe der
Slave auf Empfang geht?
Wie erfolgt eine Störerkennung bzw. Resynchronisation?
Die Prämisse bei meinem Code liegt nicht auf Geschwindigkeit.
Sondern der Slave soll nicht bei seiner Task behindert werden und auch
eigene Interrupts ausführen können.
Er macht also seine eigenen Aufgabe völlig unabhängig vom Master.
Und erst, wenn der Master was will, adressiert er den Slave.
Die Kommunikation darf die eigentliche Aufgabe nicht stören oder
verzögern.
Auch muß die Kommunikation nach einer Störung wieder alleine aufsetzen
können.
Peter