www.mikrocontroller.net

Forum: Projekte & Code 1-Drahtbidirektionalbus über große Distanz mit AVR


Autor: Clemens Helfmeier (sum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo AVRler,

ich habe gerade ein Projekt, bei dem bidirektional Daten über eine 
größere Distanz übertragen werden müssen. Leider steht dafür lediglich 
eine einzige Ader zur Verfügung, so dass Kreativität gefragt war.

Zum Glück konnte ich das Problem inzwischen lösen. Im Anhang befindet 
sich das Ergebnis:

Eine leicht portierbare Software in C, die den differentiellen 
Manchestercode implementiert. Dieser ist dadurch gekennzeichnet, dass er 
den Takt mitüberträgt. So wird eine binäre Null durch zwei Flanken, eine 
binäre Eins aber nur durch eine Taktflanke gekennzeichnet.
Damit der Empfänger die Taktrate des Senders ermitteln kann, wird vor 
jedem Datum ein Startbit als 0 gesendet, so dass dabei zwei Flanken 
entstehen, an denen die Bitrate des Senders im Empfänger gemessen werden 
kann. Anschließend können zwischen 1 und 16 Bit Daten übertragen werden.

Der Code beinhaltet Sender und Empfänger in einem (schließlich ist es ja 
bidirektional). Gesendet wird einfach durch Aufruf der Routine 
suart_putc, empfangene Daten werden der Anwendung durch eine 
Callbackfunktion übergeben.

Vor dem Verwenden unbedingt die Datei "suart_hw.h" anpassen (ausführlich 
Erklärt). In einer Zielanwendung könnte das Programm dann z.B. so 
aussehen:

suart_hw.h: --Auschnitt--
#define SUART_INPUT_HANDLER(x)      suart_rx_handler(x)
void suart_rx_handler( uint16_t x );

main.c:
#include "suart.h"
#include <stdint.h>
#include <avr/delay.h>

void main( void ) {
    DDRB = 0xFF;           // Ausgabe der empfangenen Daten hier
    suart_init();

    while(1) {
       suart_putc( 0x12 );
       _delay_ms( 20 );
    }
}

void suart_rx_handler( uint16_t x ) {
    PORTB = (x & 0xFF);    // AUsgabe der Daten an PORTB
}


Zum einfachen Demonstrieren bräuchte man zwei Controller, die man 
einfach verbindet und die unterschiedliche Werte senden. Dann erscheint 
an beiden Controllern immer der Wert an PORTB de zuletzt empfangen 
wurde. Da beide Controller unterschiedliche Werte senden (z.B. 0x12 und 
0x34), wird sich der PORTB also ändern.

Das Modul unterstüzt ein lokales Echo. Dies kann z.B. dazu dienen, die 
gesendeten Daten zu überprüfen und notfalls nochmal zu senden (bei 
Kollisionen). Das zurückgegebene Datum wurde vom Bus eingelesen und 
enthält unter Umständen auch Fehler, wenn die Leitung bswp. 
zwischendurch Kurzgeschlossen wird.

Kollisionen treten äußerst selten auf, da die kritische Zeit sehr kurz 
ist. Werden viele Knoten angeschlossen, ist es u.U. Ratsam, einen 
Zufallsanteil in die Wartedauer nach dem Freiwerden des Busses 
einzubauen.

Der Code unterstüzt auch das Senden von Paketen. Dies wird erreicht, 
indem ein nicht sendender Knoten einen sendenen Knoten erst nach einer 
Totzeit auf dem Bus unterbrechen darf. Während dieser Totzeit hat der 
sendene Knoten Zeit, sein Paket (welches dann aus mehreren 
suart_putc()-Aufrufen besteht) fortzusetzten.

Konstruktive Kritik und Kommentare erwünscht!

Clemens

Autor: Elektrikser (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>Im Anhang befindet sich das Ergebnis:

Dürfte ich bitte den Anhang sehen?

Gruß Elektrikser

Autor: Marius S. (lupin) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was bringt dir in deinem Fall die Manchestercodierung? LIN ist zB auch 
ein Eindrahtbus bei dem sich der Slave über das Bitmuster 0x55 
synchronisiert. Bei Manchester hast du das Problem der halben 
Baudrate... was bei langen Strecken wohl nicht so schlimm ist.

Autor: Clemens Helfmeier (sum)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hmm, da scheint was verloren gegangen zu sein. Hoffentlich klappt's 
jetzt ;-)

Marius: Die Manchesterkodierung hat sich erst "entwickelt": Ursprünglich 
sollte es ein reiner UART (RS232) werden, der über das Protokoll und 
etwas sonstigen Code bidirektional wird. Allerdings musste ich am Anfang 
auf jeden Fall eine Synchronisierung vornehmen. Über einen Code (0x55 
z.B.) wäre dies möglich, nur ist es dann nötig, dass immer ganze Pakete 
geschickt werden. Dies in den UART Code mit einzuflechten kam mir nicht 
in den Sinn. Stattdessen dachte ich über ein bestimmtes "Startbit" nach, 
das eben genau zwei Flanken hat und damit die Bitrateninformation 
überträgt. Nunja, und dann wollte ich was tun, "was man kennt". Keine 
Ahnung, warum es dann Manchester geworden ist, aber nahe lag es allemal.

Clemens

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Clemens Helfmeier (sum)

>ich habe gerade ein Projekt, bei dem bidirektional Daten über eine
>größere Distanz übertragen werden müssen. Leider steht dafür lediglich
>eine einzige Ader zur Verfügung, so dass Kreativität gefragt war.

>Eine leicht portierbare Software in C, die den differentiellen
>Manchestercode implementiert. Dieser ist dadurch gekennzeichnet, dass er

Schön und gut. Aber das ist bestenfalls die halbe Miete. Wie sieht es 
denn mit der elektrischen Seite aus? Mit 3.3V CMOS Pegeln sollte man 
nicht über längere Kabel gehen. Wenn sich da die Masse verschiebt, was 
bei langen, eher dünnen Kabeln mit moderaten Strömen schnell mal 
passiert, ist es Essig mit Datenaustausch. Da sollten es besser 
RS232-Pegel sein, dort ist wesentlich mehr Luft für Masseverschiebungen. 
Allerdings braucht man da einen halbduplex/tristate fähigen Tranceiver. 
Gibt es sowas? MAXIM hat da sicher was, oder?

MFG
Falk

Autor: Clemens Helfmeier (sum)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Falk,

wahrscheinlich hast Du Recht. Bei großen Distanzen wird sich die Masse 
verschieben. Der entwickelte Code ist allerdings nur für eine 
Steuereinheit, bei der ich auf geringen Stromverbrauch (<<100mA) setzte. 
Dort wird sich die Masse hoffentlich nicht so weit verschieben. 
Weiterhin habe ich meine AVRs an 5V laufen, so dass auch noch mit 0.5V 
Masseverschiebung eine große Funktionssicherheit gegeben ist (0.5V und 
100mA sind auch immerhin schon 5 Ohm in der Masseleitung. Dann sollte 
man sich über die Verkabelung (10m) Gedanken machen. In meinem 
speziellen Fall habe ich 3x0.75mm² zu liegen, zweimal Versorgung einmal 
Daten.

Was die Sache mit dem Tranceiver angeht: Ja, ist wahrscheinlich eine 
Verbesserung, kostet aber auch einen extra Baustein. Dies wollte ich 
nach Möglichkeit vermeiden.

Grüße,
Clemens

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.