Differences

This shows you the differences between two versions of the page.

Link to this comparison view

projekte:clubbus [2016-02-25 03:33]
nd created
projekte:clubbus [2017-01-17 02:01]
Line 1: Line 1:
-====== Clubbus ====== 
  
-<WRAP right> 
- 
-^ Clubbus ​ || 
-^ Kontakt | [[mrq@aachen.ccc.de|mrq]],​ [[spq@aachen.ccc.de|spq]],​ [[pouze@aachen.ccc.de|pouze]],​ [[nd@aachen.ccc.de|nd]] | 
-^ Status | <fc red>​inaktiv</​fc>​ (@DATE@) | 
-^ Interessenten | | 
-^ URL | https://​git.aachen.ccc.de/​~pouze/​klubbus/​ | 
-</​WRAP>​ 
- 
-ENTWURF 
- 
-Zu diesem Dokument: **Norm** steht an den Sachen dran, die für die Implementierung relevant sind. Unter **Info** steht die Begründung für die vorige Norm. 
- 
-==== Protokoll Layer ==== 
-**Header** 
-^Name^Größe in Bytes^Kommentar^ 
-|Preamble|1|immer 0xAA| 
-|Sender|2|little endian uint16_t| 
-|Empfänger|2|little endian uint16_t| 
-|Länge|2|nur des Payloads little endian uint16_t| 
-|CRC|1|das Polynom das AVR in der libc hat...| 
- 
-**Payload** 
-  * keine Garantie von korrekten Daten 
-==== Physical Layer ==== 
-**Norm:** Wir nutzen das Physical Layer des CAN-Bus. **Info:** Das heißt direkt am Bus hängen CAN-Transciever 
- 
-**Norm:** Der Bus ist als Zweidrahtleitung ausgeführt. Die Leitungsimpedanz sollte möglichst nah an 120 Ω sein. Die Leitung ist beidseitig mit 120 Ω abgeschlossen. 
- 
-**Norm:** Leitungsführung:​ Die Leitung wird in Kabeln geführt, die 4 Zweidrahtleitungen enthalten. **Info:** In jedem Kabel gibt es zwei CAN-Leitungen (hin und rück), so dass sich quasi ein Sternförmiger Aufbau ergibt. Das steht schon ziemlich konkret fest und sollte hier nochmal ausführlich normiert und erklärt werden. 
- 
-**Norm:** Anschluss: RJ45 
- 
- 
-==== Bit Layer ==== 
-**Norm:** UART 
-**Info:** UART wird von vielen billigen Microcontrollern nativ unterstützt. Das Protokoll lässt sich einfach mit dem PC debuggen. Es geht sparsam mit der Bandbreite um. 
- 
-==== Medium Access ==== 
-**Norm:** Ohne //bekannte Kollision// darf gesendet werden, wenn die Leitung //frei// ist. 
- 
-**Norm:** Die Leitung ist //frei//, wenn der Empfangstimer abgelaufen ist oder ein korrekt formatiertes Paket vollständig empfangen wurde. 
-**Info:** Der Regelfall ist, dass korrekte Pakete (vollständig) empfangen werden. Dann soll der Nachfolger sofort danach senden können, um den Bus möglichst gut auszulasten. Es kann aber auch sein, dass ein Empfänger verwirrt ist. Dieser Zustand tritt ein, wenn ein Gerät gerade gebootet wurde, oder der Empfang fehlerhaft ist. In dem Fall sorgt der Timer dafür, dass wieder gesendet werden kann, wenn der Bus kurze Zeit unbenutzt ist. Vorher zu senden macht eh keinen Sinn, weil man dann nur in Konkurrenz zu anderen Sendern treten würde. 
- 
-**Info:** Die Zeitdauer des Empfangstimeout wurde noch nicht festgelegt. Wir sind uns aber ziemlich einig, dass es nicht viel länger als ein-zwei Bytes sein sollte. 
- 
- 
-==== Diagramm ==== 
-<​graphviz dot center 1200x0> 
-digraph finite_state_machine { 
- 
-  rankdir="​LR"​ 
-    size="​333"​ 
-    node [shape = circle]; 
- 
-  CHECK_CRC [shape = diamond]; 
-  WAIT_FOR_PREAMBLE [shape = doublecircle];​ 
-  ​ 
-  CHECK_TX_PENDING [shape = diamond]; 
-  CHECK_TX_PENDING -> WAIT_FOR_PREAMBLE [ label = "​no"​ ]; 
-  CHECK_TX_PENDING -> SENDING [ label = "​yes"​ ]; 
- 
-  WAIT_FOR_PREAMBLE -> WAIT_FOR_HEADER_COMPLETE [ label = "rx: preamble"​ ]; 
-  WAIT_FOR_PREAMBLE -> WAIT_FOR_PREAMBLE [ label = "rx: !preamble"​ ]; 
-  WAIT_FOR_PREAMBLE -> WAIT_FOR_PREAMBLE [ label = "rx error" ]; 
-  WAIT_FOR_PREAMBLE -> SENDING [ label = "state set by main" ]; 
-  ​ 
-  WAIT_FOR_PREAMBLE_TIMEOUT -> CHECK_TX_PENDING [ label = "​timeout"​ ]; 
-  WAIT_FOR_PREAMBLE_TIMEOUT -> WAIT_FOR_HEADER_COMPLETE [ label = "rx: preamble"​ ]; 
-  WAIT_FOR_PREAMBLE_TIMEOUT -> WAIT_FOR_PREAMBLE_TIMEOUT [ label = "rx: !preamble"​ ]; 
-  WAIT_FOR_PREAMBLE_TIMEOUT -> WAIT_FOR_PREAMBLE_TIMEOUT [ label = "rx error" ]; 
- 
-  WAIT_FOR_HEADER_COMPLETE -> WAIT_FOR_HEADER_COMPLETE [ label = "rx: !last_header_byte"​ ]; 
-  WAIT_FOR_HEADER_COMPLETE -> WAIT_FOR_PREAMBLE_TIMEOUT [ label = "rx error" ]; 
-  WAIT_FOR_HEADER_COMPLETE -> CHECK_TX_PENDING [ label = "​timeout"​ ]; 
-  WAIT_FOR_HEADER_COMPLETE -> CHECK_CRC [ label = "rx: last_header_byte"​ ]; 
- 
-  CHECK_CRC -> WAIT_FOR_HEADER_COMPLETE [ label = "​wrong_crc && preamble_in_buffer"​ ]; 
-  CHECK_CRC -> CLAIM_BUFFER [ label = "​correct_crc && (header.dest == me) && (sizeof(data_buffer) >= header.size)"​ ]; 
-  CHECK_CRC -> WAIT_FOR_DATA_COMPLETE [ label = "​correct_crc && ((header.dest != me) || (sizeof(data_buffer) < header.size))"​ ]; 
-  CHECK_CRC -> WAIT_FOR_PREAMBLE_TIMEOUT [ label = "​wrong_crc && !preamble_in_buffer"​ ]; 
-  ​ 
-  CLAIM_BUFFER [shape = box]; 
-  CLAIM_BUFFER -> WAIT_FOR_DATA_COMPLETE 
- 
-  HANDLE_DATA [shape = box]; 
-  HANDLE_DATA -> WAIT_FOR_PREAMBLE;​ 
- 
-  WAIT_FOR_DATA_COMPLETE -> WAIT_FOR_PREAMBLE_TIMEOUT [ label = "rx error" ]; 
-  WAIT_FOR_DATA_COMPLETE -> CHECK_TX_PENDING [ label = "​timeout"​ ]; 
-  WAIT_FOR_DATA_COMPLETE -> CHECK_TX_PENDING [ label = "rx: last_data_byte && !buffer_was_claimed"​ ]; 
-  WAIT_FOR_DATA_COMPLETE -> HANDLE_DATA [ label = "rx: last_data_byte && buffer_was_claimed"​ ]; 
-  WAIT_FOR_DATA_COMPLETE -> WAIT_FOR_DATA_COMPLETE [ label = "rx: !last_data_byte"​ ]; 
-  ​ 
-  JAM [shape = box]; 
-  ​ 
-  SENDING -> SENDING [ label = "tx empty" ]; 
-  SENDING -> SENDING [ label = "rx: correct_byte && !last_tx_byte"​ ]; 
-  SENDING -> WAIT_FOR_PREAMBLE [ label = "rx: correct_byte && last_tx_byte"​ ]; 
-  SENDING -> JAM [ label = "rx: wrong byte" ]; 
-  SENDING -> JAM [ label = "rx error" ]; 
-  SENDING -> JAM [ label = "​timeout"​ ]; 
-  ​ 
-  JAM -> POST_JAM_WAIT;​ 
-  ​ 
-  POST_JAM_WAIT -> RANDOM_WAIT [ label = "​timeout"​ ]; 
-  POST_JAM_WAIT -> POST_JAM_WAIT [ label = "​rx"​ ]; 
-  POST_JAM_WAIT -> POST_JAM_WAIT [ label = "rx error" ]; 
-  POST_JAM_WAIT -> POST_JAM_WAIT [ label = "tx empty" ]; 
-  ​ 
-  RANDOM_WAIT -> SENDING [ label = "​timeout && !max_tries"​ ]; 
-  RANDOM_WAIT -> WAIT_FOR_HEADER_COMPLETE [ label = "rx: preamble"​ ]; 
-  RANDOM_WAIT -> RANDOM_WAIT [ label = "rx: !preamble"​ ]; 
-  RANDOM_WAIT -> RANDOM_WAIT [ label = "rx error" ]; 
- 
-} 
-</​graphviz>​ 
-==== Ideen für Nodes ==== 
-   * Thermometer (mehrere -> Heatmap) 
-   * Automatisierung Fenster (Öffnen/​Schließen) 
-   * Automatisierung Heizungsthermostat (Mit elektrischem Thermostatskopf) 
-   * Automatisierung Leinwand Empore 
-   * Auslesen elektrischer Zähler 
-   * Blingblinglichter 
-   * Steuerung HDMI-Matrix 
-   * klingel 
-   * clubstatus button 
-   * licht 
-   * switches ausschalten 
- 
-==== Spannungsversorgung mit Abschlusserkennung ==== 
-Idee: Im alten Entwurf gibt es eine Leitung zur Spannungsversorgung (5V) und eine Pulldown-Leitung,​ um Link zu erkennen. Man kann die aber auch zusammenfassen:​ 
- 
-Auf Versorger-Seite:​ 12V --- R(500kΩ) --- 5V(über Diode) --- Pin\\ 
-Auf Verbraucher-Seite:​ Pin --- Zenerdiode(gegen GND) --- Betriebsspannung 
- 
-Somit kann der Versorger feststellen,​ ob es einen Verbraucher gibt: Wenn die Pin-Spannung 12V ist gibt es keinen Verbraucher,​ ist sie 5V gibt es einen. Die Erkennung kann ziemlich einfach über einen PNP-Transistor mit Emitter=12V realisiert werden. 
- 
-==== Baudrate ==== 
-Würde 500k Baudrate vorschlagen,​​ da das sowohl bei 8 MHz (für RC-Oszilator in tinys) sowie für 20 MHz (für größere AVRs) gut passt. ​ 
- 
-[[http://​wormfood.net/​avrbaudcalc.php?​postbitrate=500000&​clock_speed_table=1&​postclock=8&​u2xmode=1]] 
- 
-==== Remote programming ==== 
-Durch einen akzeptabel hohen timeout bei WAIT_FOR_DATA_COMPLETE könnte ein device, welches dies unterstützt in einen programming mode versetzt werden: 
-  * der programmer versendet ein paket header mit length = 0xffff, dest = <​target>,​ hängt aber nicht unmittelbar alle daten an 
-  * eine magic value (8 byte oder so) sollte dem device zu erkennen geben das das jetzt ein programmer request ist, diese wird unmittelbar angehangen 
-  * der programmer sendet jetzt wiederholt einzelne bytes auf die das device antworten darf, das device darf immer unmittelbar nach einem empfangenen byte vom sender antworten 
-  * hat das device ge'​ack'​t,​ das es im programming mode ist, kann der sender anfangen dem device daten zu schicken 
-  * nähert sich die anzahl ausgetauschter bytes der 0xffff grenze 
-    * informiert der programmer das device darüber 
-    * füllt die vollen 0xffff bytes auf 
-    * versucht möglichst schnell wieder ein 0xffff paket auf dem bus zu "​allokieren"​ 
-    * sendet wieder die magic sequenz am anfang 
-    * das device kann dadurch nach der info, das ein neues paket erwartet wird in eine busy waiting loop gehen, in der es auf die sequenz wartet 
-  * dieses konzept ermöglicht es, eine deutlich primitivere bidirektionale kommunikation auf dem bus zu ermöglichen,​ was gerade für remote programming interessant ist 
Navigation



You are not allowed to add pages