Hallo Community!
Ich arbeite gerade an einem RS485 Bus. Der Bus besteht aus vier Mega48
und Max485 als Busbaustein. Ein Master und 3 Slaves werden im
half-duplex-mode betrieben. Ich möchte den multi prozessor communication
mode zum Einsatz bringen. So weit so gut.
Der Busaufbau entspricht der beigefügten Grafik. Die Busleitungen
enthalten zwei 120 ohm Terminierungswiderstände sowie an einem Busende
Biaswiderstände mit je 1k. Ich denke dass der Aufbau soweit in Ordnung
ist (momentan am Steckbrett).
Ich hätte mir folgende Übertragung vorgestellt:
Die Uart (Fleury) wird im 9-bit Modus betrieben.
Der Master sendet mit gesetztem Adressbit eine Slaveadresse (zb. 0x44)
und dannach einen Datenstring mit dem jeweiligen Kommando.
Die Slaves haben alle das MPCM-bit gesetzt.
Der Slave mit der richtigen Adresse setzt jetzt sein MPCM-bit zurück und
empfängt die Daten. Das funktionier auch recht gut.
zum Problem:
Auslesen der empfangenen Datenstrings.
Der Master sendet ein Kommando zb. led! (Das Rufzeichen ist das
Stringende).
zusammen mit der Adresse wird jetzt folgendes übertragen Mled! (M = 0x44
Adresse). Ein Slave gibt zur Kontrolle auf ein lcd aus. Bei der ersten
Übertragung wird aber MMled!übertragen (zumindest laut lcd). Die
nächsten paar Male passt es wieder. und dann zb. MMed! oder !led! oder
irgend sowas. Und dann passt es wieder.
Kann mir da jemand auf die Sprünge helfen?
Ich hab echt schon viele Stunden damit verbracht aber ich finde den
Fehler nicht. Ziel ist natürlich dass der richtige String ankommt bzw.
richtig ausgelesen werden kann.
anbei der code:
Master:
1
#ifndef F_CPU
2
#define F_CPU 8000000UL
3
#endif
4
5
6
#include<avr/io.h>
7
#include<avr/interrupt.h>
8
#include<util/delay.h>
9
#include<stdio.h>
10
#include<stdlib.h>
11
#include<string.h>
12
#include"uart.h"
13
14
15
16
intmain(void)
17
{
18
DDRB=(1<<PINB0)|(1<<PINB2);// Set PB0 and PB2 as output
19
PORTB&=~(1<<PINB2);// set PB2 to zero and listen to incoming data - 0 = listen, 1 = send
20
21
DDRD&=~(1<<PIND5)|(1<<PIND6)|(1<<PIND7);// set PD5 PD6 and PD7 as input
22
PORTD=(1<<PIND5)|(1<<PIND6)|(1<<PIND7);// activate pull-up at PD5 PD6 and PD7
23
24
//uart init select baud-rate and cpu-clock
25
uart0_init(UART_BAUD_SELECT(9600,F_CPU));
26
27
_delay_ms(100);
28
sei();
29
30
31
while(1)
32
{
33
34
_delay_ms(1000);
35
UCSR0B|=(1<<TXB80);//set adressbit
36
PORTB|=(1<<PINB2);// set bit to send data
37
38
//send adress
39
RS485_transmit(0x44);
40
_delay_ms(100);
41
42
UCSR0B&=~(1<<TXB80);// set adressbit to zero so data can be transmit
43
44
uart0_puts("led!");
45
_delay_ms(500);
46
PORTB&=~(1<<PINB2);// switch back to zero and listen to incoming data
47
48
}
49
}
Slave:
1
#ifndef F_CPU
2
#define F_CPU 8000000UL
3
#endif
4
5
6
7
#include<avr/io.h>
8
#include<avr/interrupt.h>
9
#include<util/delay.h>
10
#include<stdio.h>
11
#include<stdlib.h>
12
#include<string.h>
13
#include"RS485_Routines.h"
14
#include"lcd-routines.h"
15
16
17
uint8_treceived=0;// to store adress
18
charbuf[];// Buffer for lcd
19
charcomp[]=("Dled!");
20
21
22
voiduart0_gets(char*test)
23
{
24
unsignedintc;
25
26
c=uart_getc();
27
if(!(c&UART_NO_DATA))
28
{
29
*test=c;
30
test++;
31
32
do{
33
c=uart_getc();
34
if(!(c&UART_NO_DATA))
35
{
36
*test=c;
37
test++;
38
}
39
}while(c!='!');
40
41
42
}
43
}
44
45
intmain(void)
46
{
47
DDRB=(1<<PINB0)|(1<<PINB2);// set PINB0 and PINB2 as output
48
PORTB&=~(1<<PINB2);// switch PB2 to zero and listen to incoming data
49
50
lcd_init();
51
lcd_clear();
52
lcd_setcursor(0,1);
53
lcd_string("RS485 Test");
54
55
56
//uart init select baud-rate and cpu-clock
57
uart0_init(UART_BAUD_SELECT(9600,F_CPU));
58
59
UCSR0A|=(1<<MPCM0);
60
_delay_ms(200);
61
sei();
62
63
while(1)
64
{
65
66
67
chartest[8]="";
68
69
70
71
received=UDR0;
72
if(received==0x44){// this is my adress
73
UCSR0A&=~(1<<MPCM0);
74
//blink_led();
75
76
lcd_setcursor(0,2);
77
sprintf(buf,"My adress = 0x%x",received);
78
lcd_string(buf);
79
received=0;
80
81
uart0_gets(test);
82
83
lcd_setcursor(0,4);
84
lcd_string(test);
85
86
if(strcmp(comp,test)==0){
87
blink_led();
88
}
89
90
91
}//if
92
93
}//while
94
95
}//main
Ich bitte euch nochmals um Hilfe, da ich mit meinem Latein am Ende bin
und das noch ziemlich neu für mich ist.
Solltet Ihr noch Info benötigen gebt mir bitte bescheid.
Danke im Voraus!
Grüße
mw73
Ist etwas viel auf's mal.
Mit einem Oszilloskop wuerde man nun einen Pin togglen.
Und nie blockierend implementieren ... du weisst ja nicht mal wo das
Programm am Warten ist.
Und wenn man sich Arbeit sparen will, verwendet man einen zweiten UART
zum Debuggen.
Der einfachere Ansatz, auch wenn er schwieriger erscheint, ist eine
Statusmaschine, und ein, zwei oder mehrere Pins fuer das Oszilloskop.
Und dann programmiert man nicht blockierend.
Blockierend bedeutet, die Rechenzeit wird verballert, da geschieht sonst
nichts. Macht man nicht.
HAllo,
hier mal ein paar Tips.
1. Ich habe mir angewöhnt Übertragungsfehler zu zulassen. Wichtig ist
dabei die Fehlerbehandlung (CRC,ACK,NACK, FrameError....)
2. Das Senden und Empfangen in einer ISR verlegen.
3. Empfänger und Sender sollten die gleiche Sprache sprechen (Protokoll)
z.b. EmpfängerAdr,SenderAdr,LängeDaten,Daten....,CRC.
4. Nach dem Empfangen solltest du das MPCM bit wieder setzen.
ms
Da fehlt jeglicher Test, ob überhaupt ein neuer (gültiger) Wert im UDR
drin ist.
Du liesst da u.U. Zwischenwerte aus, falls die Bits von der Hardware
einzeln gesetzt/gelöscht werden. Was ja nicht komplett unwahrscheinlich
ist, schließlich kommen die einzeln an.
Hallo Zusammen,
zuerst einmal Danke für eure schnellen Antworten!!!
@Zwölf Mal Acht:
Ich bin mir jetzt nicht sicher wie Du das genau meinst mit "blockierend
implementieren" bzw. wie ich das jetzt anders machen könnte. Ich hab
mich auf alle Fälle mit dem Konverter an die RX/TX Leitungen des
angesprochenen Slaves gehängt und mittels Terminal überprüft ob der
String ankommt. Wie gesagt, der String kommt an RX des Slaves an. Am
Terminal steht Mled!
Also der String geht zum Empfänger und zwar richtig geschrieben, egal
wie oft ich ihn sende.
@Sabberlotte:
Danke für den Tipp, werde ich gleich ausprobieren. Meinst Du die 10k
auch an VSS oder nur VCC? und die 120ohm passen aber oder?
@MS:
So weit bin ich eigentlich noch gar nicht, denn so wie es aussieht, wird
ja nicht einmal der einzige String der momentan gesendet wird richtig
übertragen bzw. richtig eingelesen denn wenn ich mich mit dem Konverter
an die RX Leitung des Slaves hänge, steht am Terminal immer der richtige
Text.
Das fehlende MPCM bit werde ich gleich überprüfen ober ich glaube das
habe ich beim kopieren übersehen.
@Jim Meba:
Hier wird die Adresse ausgelesen. Das funktioniert aber einwandfrei im
Gegensatz zum Auslesen des Strings.
Ich habe schon versucht nur in Schleifen alle Slaves über die Adressen
nacheinander anzusprechen. Das funktioniert wirklich gut. Jeder
angesprochene Slave meldet sich per LED.
Ich werde jetzt die Widerstände tauschen und testen, ob ich das MPCM bit
wieder gesetzt habe. Ich melde mich dann wieder.
Ich denke aber, dass das Problem beim Einlesen des Strings besteht. Da
hatten die meisten Leute Probleme mit Fleurys uart (hab ich in den
ganzen alten Postings gelesen).
Grüße
Markus
Hallo Zusammen,
melde mich zurück
@ms:
Nein, ich kann ja damit nur Text vom uC aufs Terminal übertragen.
Also es sieht so aus:
Ich habe die Bias-Widerstände getauscht - von 1k auf 10k
hat aber nichts gebracht oder verändert.
@ms:
Danke für die Aufmerksame Beobachtung mit dem fehlenden setzen des
MPCM-Bits.
Ich hatte es wahrscheinlich durchs viele herumtesten übersehen.
Das ganze hat jetzt folgende Auswirkungen:
in ca. 90% wird jetzt folgender String gesendet: DDled!
Ich verstehe aber nicht warum er D (die Adresse) zweimal im String
stehen hat, sollte ja nur einmal drin stehen??
alle paar mal sendet er dann !led! --> hier wird die Adresse verschluckt
und dafür ein Rufzeichen vor dem eigentlichen String gesetzt.
Hat hier jemand eine Idee?
Grüße
Markus
Markus W. schrieb:> @Sabberlotte:> Danke für den Tipp, werde ich gleich ausprobieren. Meinst Du die 10k> auch an VSS oder nur VCC? und die 120ohm passen aber oder?
10k nur an VCC (Pullup)!
Markus W. schrieb:> Ich habe die Bias-Widerstände getauscht - von 1k auf 10k> hat aber nichts gebracht oder verändert.
VCC > 560 Ohm > A > 120 Ohm > B > 560 Ohm > GND ...
... aber nur an einer Seite / die andere nur 120 Ohm zwischen A und B.
Hallo ms!
wow, danke, voll nett von Dir!!
Ich werden den code gleich am Nachmittag testen und gebe heute abend
bescheid.
Vielen Dank noch mal!
Grüße
Markus
Hallo Markus,
habe ich gerne gemacht da RS485 mein "Steckenpferd" ist.
Der Code ist zum Teil aus einem Produktivsystem.
Es fehlt aber noch eine TimeOut,Prüfsumme und CallBack Funktion.
ms
Hallo ms!
Ich bin noch am testen, hab den code aber leider noch nicht zum laufen
gebracht.
Nach einfügen der stdbool.h konnte ich den code zwar kompilieren, es
läuft allerdings nicht einmal das lcd an.
Die Ausgabe "RS485 test" ist ja die erste Anweisung in de main. Die
sollte doch zumindest kommen?
Ich hab Deinen code noch nicht ganz durchschaut aber so wie ich es
verstanden habe, ist die Fleury uart jetzt nicht mehr erforderlich denn
Baudrate und die Register werden ja jetzt im Hauptprogramm festgelegt.
SIGNAL(SIG_UART_RECV) --> ist das die alte Konvensation für den Aufruf
der ISR ? in der ersten Fleury Uart habe ich diesen Aufruf schon einmal
gelesen. Wurde aber dann geändert in ISR(UART0_RECEIVE_INTERRUPT).
Ich teste weiter und hoffe es zum Laufen zu bekommen.
Grüße
Markus
Danke Sabberlotte für den Tipp mit den Widerständen, hab jetzt die
richtigen eingesetzt - Danke!
Hallo ms!
Nur so eine Idee, würde es Sinn machen, Deine Programmteile in die ISR
der Fleury Lib zu implementieren? Diese hat ja eine eigene ISR welche
ausgelöst wird, wenn ein byte empfangen wurde.
...oder würdest Du mir raten mein Vorhaben auf Deinem Code aufzubauen
und die Lib gar nicht mehr zu verwenden?
Ich bin jetzt etwas verunsichert.
Grüße
Markus
achja, eines noch,
heute morgen hab ich noch an meiner version gearbeitet und sie soweit
lauffähig gebracht, dass der Master immer den selben slave über seine
Adresse anspricht und immer den selben String "led!" sendet. Der String
kommt jetzt auch fehlerfrei an.
hier der code des slaves:
charcomp[]=("led");// testmode: master always sends the same string - ADDRESS(0x44) + String(led!) ! = end of string
31
32
// for debug
33
voidblink_led(void){
34
35
PORTB|=(1<<PINB0);
36
_delay_ms(500);
37
PORTB&=~(1<<PINB0);
38
_delay_ms(500);
39
}
40
41
42
43
// helper function for get string - this is a waiting function
44
uint8_tuart_getc_wait()
45
{
46
unsignedintc;
47
48
do{
49
c=uart0_getc();
50
}while(c==UART_NO_DATA);
51
52
return(uint8_t)c;
53
}
54
55
56
// function to receive a whole string
57
voiduart_gets(char*Buffer,uint8_tMaxLen)
58
{
59
uint8_tNextChar;
60
uint8_tStringLen=0;
61
62
NextChar=uart_getc_wait();
63
64
while(NextChar!='!'&&StringLen<MaxLen-1){
65
*Buffer++=NextChar;
66
StringLen++;
67
NextChar=uart_getc_wait();
68
}
69
70
// put a zero at the end of string
71
*Buffer='\0';
72
}
73
74
75
76
intmain(void)
77
{
78
DDRB=(1<<PINB0)|(1<<PINB2);// set PINB0 and PINB2 as output
79
PORTB&=~(1<<PINB2);// switch PB2 to zero and listen to incoming data
80
81
lcd_init();
82
lcd_clear();
83
lcd_setcursor(0,1);
84
lcd_string("RS485 Test");
85
86
87
//uart init select baud-rate and cpu-clock (fleury uart)
88
uart0_init(UART_BAUD_SELECT(9600,F_CPU));
89
90
UCSR0A|=(1<<MPCM0);// slave: set the MPCM-bit
91
_delay_ms(200);
92
sei();// enable interrupts
93
94
95
96
while(1)
97
{
98
99
100
101
received=UDR0;
102
if(received==0x44){// this is my adress
103
UCSR0A&=~(1<<MPCM0);// now set MPCM zero and receive data
104
//blink_led();
105
106
107
lcd_setcursor(0,2);
108
sprintf(buf,"My adress = 0x%x",received);
109
lcd_string(buf);
110
received=uart0_getc();// empty rxbuffer (address isn't used in data)
111
received=0;
112
113
114
115
c=uart_getc();// receive data
116
uart_gets(Line,sizeof(Line));
117
118
UCSR0A|=(1<<MPCM0);// set MPCM-bit
119
120
121
lcd_setcursor(0,3);
122
lcd_string(Line);
123
124
counter+=1;
125
lcd_setcursor(0,4);
126
lcd_string("cnt:");
127
sprintf(bufc,"%4d",counter);
128
lcd_setcursor(5,4);
129
lcd_string(bufc);
130
131
lcd_setcursor(11,4);
132
lcd_string("err:");
133
sprintf(bufec,"%4d",errcounter);
134
lcd_setcursor(16,4);
135
lcd_string(bufec);
136
137
138
139
if(strcmp(comp,Line)==0){
140
blink_led();
141
lcd_setcursor(0,2);
142
lcd_string(" ");
143
lcd_setcursor(0,3);
144
lcd_string(" ");
145
146
}
147
else{
148
149
errcounter+=1;
150
151
lcd_setcursor(11,4);
152
lcd_string("err:");
153
sprintf(bufec,"%4d",errcounter);
154
lcd_setcursor(16,4);
155
lcd_string(bufec);
156
}
157
158
159
160
}//if
161
162
163
164
165
166
167
}//while
168
169
170
171
172
173
}//main
soweit so gut.
Jetzt kommt das Problem:
wenn jetzt der Master einen anderen Slave mit seiner Adresse anspricht
und andere Daten sendet (zb. "aus!") und danach wieder der andere slave
mit der 0x44er Adresse angesprochen wird, empfängt dieser Daten des
vorher angesprochenen.
Du hast mir ja bereits gesagt, dass MPCM nur mittels ISR funktioniert.
Normalerweise dürfte der 0x44er Slave den String des 0x43er gar nicht
empfangen, da MPCM zu diesem Zeitpunkt gesetzt ist und der Master ja nur
mit gesetztem Adressbit die Adresse sendet.
Grüße
Markus
Hallo Markus,
Markus W. schrieb:> SIGNAL(SIG_UART_RECV) --> ist das die alte Konvensation für den Aufruf
ja (ist schon Jahre her das ich meine Lib geschrieben habe)
Markus W. schrieb:> ...oder würdest Du mir raten mein Vorhaben auf Deinem Code aufzubauen> und die Lib gar nicht mehr zu verwenden?
Die Entscheidung kann ich dir nicht abnehmen.Es kommt darauf an was Du
machen willst.
Markus W. schrieb:> (zb. "aus!")
Noch ein Tip: Versuche keine "Texte" für kommandos zu nehmen das macht
dir später das leben schwer.
ms
Hallo Makus,
Markus W. schrieb:> Normalerweise dürfte der 0x44er Slave den String des 0x43er gar nicht> empfangen
Doch darf er deine Lib verwendet einen RingBuffer.Die Lib ist echt gut
aber du hast da wenig kontrolle.
Dein Master sendet ca. alle 600ms einen Frame.Ist die LCD-Lib so schnell
dass Du das MPC-Bit rechtzeitig setzen kannst bevor das Frame vom
anderen in den Ringbuffer gelangt.
ms
Hallo ms!
Danke für die Antworten.
Ich werde erstmal versuchen Deine Version zum Laufen zu bekommen.
Ich habe mich jetzt etwas damit auseinander gesetzt und ich denke dass
sie wirklich perfekt ist.
Kannst Du mir noch eine Verständnisfrage beantworten, wenn ich Deinen
Code verwende, brauche ich die Fleury Lib nicht mehr oder?.
Grundsätzlich soll dieses Projekt keine große Sache werden. Der Master
soll lediglich zu bestimmten Zeiten Kommandos an die Slaves schicken.
Diese sollen die jeweiligen Kommandos mit der Liste vergleichen und
diese dann ausführen. Dannach eine Rückmeldung an den Master.
Du meintest, ich solle die Texte mit Kommandos austasuchen. Meinst Du
damit zb. Zahlen in einer uint_8t Variable oder in einen String
umwandeln? Wie könnte denn da die Überprüfung aussehen ob die Zahl zu
ende eingelesen wurde?
Kannst Du mir noch kurz erklären, wie ein kompletter Frame aussieht.
Also Ziel soll es sein, alle Informationen in ein Array zu schreiben
(char Test[10]. An Stelle null kommt die Adresse, an Stelle 1, die
Adresse vom Master, an Stelle 3 die Länge der Daten, dann an Stelle 4
das Kommando und zum Schluss die checksumme. Ist das so richtig?
Der Master sendet dann diese Informationen der Reihe nach oder
zb. uart_transmit(0x44) //Zieladresse
uart_transmit(0x01) //Adresse Master
usw.
wäre dass so richtig.
... ich hoffe ich nerve Dich nicht mit meinen Fragen aber ich bin noch
Anfänger. Ich habe zwar versucht mich in die Thematik mit dem RS485
einzulesen aber ich habe sehr wenig Informationen darüber gefunden, wie
man so eine Bus richtig aufbaut.
Danke für Deine Hilfe
Grüße
Markus
Hallo Markus
Markus W. schrieb:> Kannst Du mir noch eine Verständnisfrage beantworten, wenn ich Deinen> Code verwende, brauche ich die Fleury Lib nicht mehr oder?.
nein die brauchst du nicht mehr
Markus W. schrieb:> Du meintest, ich solle die Texte mit Kommandos austasuchen.
ja z.B. LED(_1) AN ist bei mir 0x10 0x01, LED(_1) AUS = 0x11 0x01;
LED(_1) toggel = 0x12 0x01.
aber dazu am Wochenende mehr.
ms
Hallo ms!
Ich hab gestern dran gearbeitet. Der Code "läuft jetzt an".
Die erse Zeile am lcd erscheint.
Allerdings gibt es Probleme beim einlesen der Adresse. Diese wird
scheinbar
nicht erkannt. Ich hab mit der debug led folgendes festgestllt:
in der ISR wird die erste if-Abrage durchlaufen
1
if(NET_UCSRA&((1<<FE0)+(1<<DOR0)))
geht in die nächste if-Abfrage rein
1
if(NET_UCSRB&(1<<RXB80))// OK mit 9. bit
und bleibt schließlich bei der Adressabfrage hängen
1
if(ucRxByte==NET_ADRESS)
Ich hab testweise versucht ucRXByte mit einer uint8_t variable zu
ersetzten
und an dieser Stelle eine lcd-Ausgabe durchgeführt. Es wird jetzt 0x80
ausgegeben???
Ich werde heute weiter testen.
Achja
>für das weiter vorgehen, hast du dich schon mal mit Struct,Zeigern und>Funktionszeigern beschäftigt?
struct hatte ich noch nie benötigt, mit Zeigern habe ich mich etwas
beschäftigt.
Grüße
Markus
Hallo ms!
Danke für den Hinweis!!!
Ich hab es jetzt zum Laufen bekommen.
Du kannst Dir ja gar nicht vorstellen was mir passiert ist,
Ich hatte die define F_CPU die ganze Zeit unterhalb der include
util/delay.h
Als ich testweise die debug-led in der while-schleife blinken lassen hab
bin ich drauf gekommen.
Jetzt funtioniert das Senden und empfangen wie gewollt auch mit mehreren
Teilnehmern.
... Glaubst Du dass Du das Wochenende noch einmal ein paar Minuten Zeit
findest und mir noch etwas die Zusammensetzung eines kompletten Packets
erklären könntest?
Auf alle Fälle vielen vielen Dank für Deine kompetente Hilfe!!!!!!!!!!!
Ich hab durch Deinen Code viel zu diesem Thema dazu gelernt.
Schönen Abend und LG
Markus
Hallo Markus,
hier noch ein Stück code nicht zum Testen sondern zum analysieren.
Daraus ergibt sich schon das komplette Packet.
Sieht schlimm aus ist es aber nicht.
Er vielleicht nicht aber ich wäre da nicht abgeneigt. Lese bisher nur
mit aber ich entwickle auch grad ein Gerät u.a. mit mehrere uCs (geplant
sind bisher Atmega328er) die verschiedene Motoren/Aktuatoren/Sensoren
steuern/auswerten sollen. Als Kommunikation möchte ich gerne einen
RS485-Bus benutzen, bisher dachte ich daran einen MAX485 zu verwenden um
damit den Bus aufzubauen.
ms schrieb:> Noch ein Tip: Versuche keine "Texte" für kommandos zu nehmen das macht> dir später das leben schwer.
Ganz im Gegenteil, Texte kann man sehr einfach vergleichen und debuggen
(sniffen). Außerdem lassen sie sich leicht merken.
Kryptische Binärwerte nimmt man nur dann, wenn es auf maximale Datenrate
ankommt. Und dann muß man sich beim Debuggen immer ne Tabelle daneben
legen, was sie bedeuten. Oder man schreibt ein extra Programm, was sie
wieder in verstehbare Texte umsetzt.
Hallo Peter,
Peter D. schrieb:> wenn es auf maximale Datenrate> ankommt.
Das stimmt nicht ganz es kommt nicht auf die maximal Datenrate an
sonderen das der Prozessor nicht viel zeit zum Parsen verschwenden soll.
Er sollte lieber so viel Zeit für seinen eigentliche Arbeiten verwenden
die er bekommen kann.
Ich sehe die kommunikation nicht als Hauptaufgabe des Prozessors!!!
Peter D. schrieb:> Oder man schreibt ein extra Programm
das gehört nun mal dazu und ist auch nicht schwer.
ms
ms schrieb:> Hallo,>> O.k. können wir machen.> Wird es kommerziell genutzt?>> ms
Nutzung ist für meinen Hobbyraum gedacht. Ich will mir so eine Art CNC
und/oder Laser-Gravierer bauen (um schlicht und ergreifend zu lernen).
Eigentlich könnte also die komplette Steuerung auch ein einziger uC
übernehmen, ich will mir aber auch mal die Kommunikation zwischen uCs
anschaun bzw. damit arbeiten und hab mich hier für RS485 entschieden.
Daher habe ich mir überlegt: Ein uC steuert nur die Motoren an, ein uC
wertet die Positionen aus, ein weiterer kümmert sich um die restlichen
Sensoren (beim Lasergravierer z.B. die Steuerung der Energie des
Lasers). Ein vierter uC soll sich um die Kommunikation mit einem PC
kümmern, sodass das System vom PC aus steuerbar ist. Das Ganze ist noch
in der Entwicklung (auf Papier und in meinem Kopf), nichts in Stein
gemeißelt und der Hintergrund ist einfach nur, dass ich das mal
ausprobieren möchte wobei das Hauptaugenmerk auf dem Bussytem, hier
RS485, liegt, sprich also der Weg ist hier eigentlich das Ziel.
ms schrieb:> Das stimmt nicht ganz es kommt nicht auf die maximal Datenrate an> sonderen das der Prozessor nicht viel zeit zum Parsen verschwenden soll.
Ich nehme hier auch immer Klartext-Kommandos. Binärwerte, so denke ich
mir, waren in der Vergangenheit u.a. auch deswegen benutzt worden, weil
sie Speicherplatz (neben CPU-Load beim Parsen) sparten, oder?
Hallo Köhler
M. K. schrieb:> Ich nehme hier auch immer Klartext-Kommandos. Binärwerte, so denke ich> mir, waren in der Vergangenheit u.a. auch deswegen benutzt worden, weil> sie Speicherplatz (neben CPU-Load beim Parsen) sparten, oder?
könnte auch eine Rolle spielen.
Anderes Beispiel:
Dein uC muss ein Sensorsignal auswerten in der Regel mit y=m*x+b da
kommt
ein float für maximale Genauigkeit raus (geht aber auch mit long).
Jetzt muss du diesen wert übertragen mit 6 Nachkommastellen.
Das sind Vorkomma+6 Byte.
Binär sind es immer 4 Byte.
ms
Hallo ms!
Würdest Du mir auch Deine Hardware Lösung zur verfügung stellen, da die
sicher viel besser ist als meine Standard Lösung. Natürlich auch für
rein private Nutzung.
Ich analysiere gerade Deinen crc-code und melde mich zum Wochenende.
Danke nochmal für den Code.
Danke auch an Peter für Deinen Beitrag.
Schönen Abend und LG
Markus
ms schrieb:> Jetzt muss du diesen wert übertragen mit 6 Nachkommastellen.> Das sind Vorkomma+6 Byte.> Binär sind es immer 4 Byte.
Na na na, Wert und Befehl sind jetzt aber zwei unterschiedliche paar
Schuhe, oder?
Aber du hast recht, das macht schon Sinn einen Float so zu übertragen,
ich übertrage Floats auch oft so ;)
guten morgen M.K.
M. K. schrieb:> Na na na, Wert und Befehl sind jetzt aber zwei unterschiedliche paar> Schuhe, oder?
Da mach ich keinen unterschied. Die art und weise wie man das umsetzt
sollte durchgängig gleich sein (sonst braucht man 2 Tabellen zum
debuggen ;-))
m.s
Das ist sicherlich auch nicht verkehrt es durchgängig gleich zu machen,
es kommt halt drauf an was man machen will. Ich finde halt bei Befehlen
Klartext nicht falsch weil man dann sich die Sache auch in drei Jahren
nochmal anschaun kann und weiß was da passiert ohne einen Blick in eine
Codetabelle werfen zu müssen. ;)
Aber genug davon, meine erste Idee mit dem MAX485 schaut so aus, dass
ich Rx/Tx entsprechend aufgelegt habe und DE bzw. !RE auf einen freien
Portpin. Defaultmäßig werde ich wohl immer nur auf den Bus lauschen es
sei denn der Master sagt, dass ich auch quatschen darf. Im Moment fehlt
mir noch die Idee wie ich es handhaben soll wenn zwei Slaves
gleichzeitig quatschen wollen. Lasse ich den Master regelmäßig fragen ob
jemand was zu sagen hat oder soll ich die Slaves regelmäßig den Master
fragen lassen ob sie ihre Informationen weiter reichen dürfen. Spontan
finde ich die erste Variante schöner aber auch nicht optimal.
Hallo M.K.
Jetzt komms pas auf :-)
Nimm dir das Leben als Beispiel.
In der Schule hat der Lehrer das sagen. Der schüler antwortet nur nach
auforderung und das in einer angemessen zeit ohne um drum herum zu
quatschen.
Das ist die Autoritäre Art.
Es gibt auch Lehrer die eine Art Redenstock haben die die Schüler immer
durchgeben nur der mit dem Stock(Token) darf Reden.
Das ist die Laissez-faire Art.
Je nach System und Anforderung muss man auswählen welche Art sich am
besten eignet
ms
Die Idee mit dem Redestock gefällt mir für meinen Fall am besten jetzt
wenn ich so drüber nachdenke, kann aber sein dass das für mich völliger
Mumpitz ist und ich besser die Reihe durchgehe und immer frage...da muss
ich mich nochmal schlau machen was bei mir schlauer wäre.
Hallo,
Ich habe mal mein Bus-System angehängt.
Der Grundaufbau ist bei Master und Slave immer gleich (OK unnötig aber
kostet ja nicht die Welt).
Der Bus geht über normales Netzwerkkabel oder Patchkabel.
Es gibt ein Y-Verteiler der Verteilt den Bus zum Slave und zum nächten
Y-Verteiler oder End-Slave.
Beim Master ist es möglich den zweiten Abschlußwiderstand zu setzen
(Achtung da verdoppelt sich die Leitungslänge).
Bei einem End-Slave wird halt der R dort gesetzt und beim Master
nicht(Jumper).
Das einfügen eines neuen Slave in das bestehende System ist dadurch kein
Problem (neues Dachfenster).
ms
Hallo Leute,
jetzt nochmal zu meinem Aufbau.
Die Grundschaltung ist nichts neues man könnte sie noch aufblusten mit
Würth und Co. Ist aber aus meiner erfahrung nicht nötig. Genau dieser
Aufbau wurde bei einer Testphase beim DLR in Köln verwendet. Da habe ich
für einen Tag die Langarmzentriefuge gemietet. Ich musste die
Stromaufnahme eines Lüfters bei verschiedene G-Kräfte messen (bis ca
10G). Der Bus wurde über ein (zwei) Koaxkabel zu einem Schleifring in
die Gondel übertragen. Das war nun mal die einzige möglichkeit in die
Gondel zu kommen.
Ich kann euch sagen es gab keine Problem.Ich kann euch nicht sagen wie
lang das Koax war aber ich gehe von ca. 200m aus.
Es ist keinem aufgefallen das der Schirm nicht angeschlossen ist.Muss
natürlich sein.GND->100 Ohm-> Schirm.
ms
Hallo ms!
Danke nochmal für alle Unterlagen bis jetzt. Den Aufbau werde ich mir
später genauer ansehen. Ich versuch erst mal den Packetaufbau und den
crc check auf die Reihe zu bekomen. Ich melde mich zum WE und hoffe dass
ich bis da hin soweit bin.
Sag mal, wie viel kostet die Tagesmiete für die Langarmzentrifuge?
Bin sehr beeindruckt von dem was Du machst.
LG
Markus
Hallo Markus,
Markus W. schrieb:> Sag mal, wie viel kostet die Tagesmiete für die Langarmzentrifuge?
so genau kann ich dir das nicht sagen ist schon echt lange her. Aber die
waren glaub ich froh dass sich das Ding mal wieder dreht. Es war
garnicht mal so teuer 2000-2500,- glaube ich noch zu wissen.
Markus W. schrieb:> crc check auf die Reihe zu bekomen
Da gibt es auch viel zum nachlesen es gibt aber auch verschieden Arten.
Halte Dich nicht zu lange damit auf. Es fehlt ja noch das Senden und die
Kommando Auswertung.
ms
Hallo ms!
Ich hab mich jetzt soweit mit dem Code beschäftigt. Einiges ist soweit
auch klar, vieles jedoch nicht und teilweise fehlen mir noch die
Zusammenhänge.
Darf ich Dir einige konkrete Fragen stellen?
Ich hab mich soweit in die Theorie des crc-checks eingelesen und das
soweit auch verstanden. Allerdings is mir Deine Umsetzung nicht so ganz
klar.
void CalcCRC(unsigned char data)
könntest Du mir die in zwei drei Sätzen erklären (die Bildung vom Flag
und die weiteren zwei if-Abfragen).
Dann zur ISR
... dort wo zb. die Adresse eingelesen wird ist mir soweit klar.
Die Adresse geht einmal in RXAdress.
Dann startet ein neuer Frame.
Es wird die Checksumme berechnet
und in den Header geschrieben --> was wird hier hinein geschrieben?
könntest Du mir auch noch die folgenden if-Anweisungen kurz erklären
(wo der header einmal auf 1,2 oder ungleich 0xff geprüft wird?)
Was ist eigentlich das Info Byte?
Oje, mit dem Body sieht's nicht viel besser aus.
Tut mir leid, aber mit diesen Einträgen in header und body kann ich
nicht viel anfangen.
...oder muss da die Senderoutine schon dementsprechend angepasst sein?
wann wurde überhaupt in den header geschrieben, wenn dieser auf zwei
geprüft wird. Wenn die RxAdresse eingelesen wird, wird ja der header auf
0 gesetzt?
so viele Fragen :-(
Ich hoffe das wird Dir nicht zuviel.
LG
Markus
Hallo Markus,
Markus W. schrieb:> void CalcCRC(unsigned char data)> könntest Du mir die in zwei drei Sätzen erklären (die Bildung vom Flag> und die weiteren zwei if-Abfragen).
Können wir das bis zum schluß aufheben.
https://de.wikipedia.org/wiki/Zyklische_Redundanzpr%C3%BCfungMarkus W. schrieb:> Tut mir leid, aber mit diesen Einträgen in header und body kann ich> nicht viel anfangen.
Du must dir klar machen dass die ISR bei jedem Byte ausgelösst wir.
Zwischen den einzelnen Bytes macht der uC irgend was anderes.
RXHeader und RXBody sind Hilfsvariablen in denen wir die Positionen
speichern.
Am Anfang Senden wir ja die Adresse im 9bit Format das ist der
eindeutige Start von einem Frame (die ISR wird nur bei einem 9Bit Byte
Ausgelöst bei einem 8 bit Byte passiert nichts). Ist das Frame für mich
gedacht schalten wir um in den 8 bit Modus(ab jetzt wird die ISR bei 8
bit ausgelöst). Gleichzeitig werden alle Hilfsvariablen
initalisiert.RXHeader wird um ein erhöht da ich weis das nächste Byte
ist das InfoByte.
1
if(RxHeader==1)// Info BYTE
2
{
3
stRxData.InfoByte=ucRxByte;
4
RxHeader++;// RxHeader um eins erhöhen!!!!!!!!!!!!!!!!
5
CalcCRC(RxByte);
6
return;
7
}
Nachdem das InfoByte empfangen ist wird der RXHeader nochmal um ein
erhöht
da jetzt die SenderAdr kommt.
1
if(RxHeader==2)// Sender ADR
2
{
3
stRxData.TxAddress=ucRxByte;
4
RxHeader++;// RxHeader um eins erhöhen!!!!!!!!!!!!!!!!
5
CalcCRC(ucRxByte);
6
return;
7
}
Jetzt wird RXHeader nochmal erhöht
Beim nächsten Byte werden die zwei ersten IF abfragen mit RXHeader nicht
mehr durchlaufen sondern die nächste.
1
if(RxHeader!=0xFF)// DATA Länge
2
{
3
4
RxHeader=0xFF;// RxHeader auf das Maximum setzen!!!!!!!!
5
stRxData.DataLength=ucRxByte;
6
CalcCRC(ucRxByte);
7
return;
8
}
Hier wird die länge der Nutzdaten übertragen (+ 2Byte CRC16)
Ab jetzt muss ich sorge tragen dass die ganze Header Geschichte nicht
mehr durchlaufen wird also RXHeader = 0xff
RXBody ist 0 beim Start haben wir die Variable so initalisiert.
Da ich weiss dass jetzt die Nutzdaten kommen muss ich die nach der reihe
in meinen Buffer schreiben (stRxData.Data[RxBody] = ucRxByte;)
Aber nur die Nutzdaten die zwei letzten sind CRC16. Um diese raus zu
filtern gibt es das MAKRO INCLUDE_CRC(stRxData.InfoByte) (<-- da war ein
fehler). Das Makro überprüft ob der Sender eine CRC16 mitgeschickt hat
oder nicht. der Sender Signalisiert das mit dem InfoByte sobald da 0x10
drin steht gibt das Makro 2 zurück ansonsten 0.
Ist keine CRC nötig wird eingelsen bis RxBody == stRxData.DataLength
ist.
Danach wir dem MainThread eine Info gegeben dass neue Daten verfügbar
sind DataOK = true (wird aber noch eine CallBack funktion).
Ist eine CRC berechnung nötig werden die zwei letzten Byte eingelesen
und mit der Lokal berechneten CRC (crc16)verglichen. Ist alles OK Signal
an MainThread.
ms
Hallo Markus,
noch was das InfoByte benutze ich um während dem Emfangen entscheidungen
zu treffen um dass sich das Haupprogramm sich nicht kümmern soll.
Z.B. kann der Sender einen einfache Antwort (ACK oder NACK) anforden
oder eine qualifizierte(antwort mit messdaten). Die einfache wird
automatisch an den sender gesendet sobald der Frame kompett eingelesen
ist. Die andere muss das Hauptprogramm zusammenstellen.
Es könnte ja auch mal sein das Infomationen in Fragmente aufgeteilt
werden müssen im InfoByte könnte man die FragmendID mittschicken und dem
Hauptprogramm erst Info geben sobald alle Fragmente empfangen sind.
ms
Hallo ms!
Vielen Dank für Deine ausführlichen Erklärungen.
Das waren jetzt die Zusammenhänge die ich noch benötigt habe.
Ich hab zwar gestern abend den Teil der ISR, wo die Adresse empfangen
wird ins Visual Studio geschrieben und mit printf ausgeben lassen. Dabei
ist mir auch schon aufgefallen, dass der Header auf 1 gesetzt wurde.
Das heißt jetzt, ich kann mein Programm dementsprechend abändern.
Ich muss dazu meine Senderoutine anpassen auf Adresse, Infobyte,
Nutzdaten
Ich werde mich gleich dran machen und melde mich wenn ich soweit bin.
Vielen Danke noch einmal, dass Du mir das so aufbereitest, dass ich für
mich eine einzigartige Chance komplexere Dinge zu lernen.
LG
Markus
Hallo Markus,
Markus W. schrieb:> Das heißt jetzt, ich kann mein Programm dementsprechend abändern.
ja kannst du.
Ich gehe jetzt nachhause leg mich hin und heute mittag werde ich eine
Senderoutine zusammen stellen. Die kannst du in ruhe analysieren und
Ideen daraus entwickeln.
ms
if(RxBody<(stRxData.DataLength-(INCLUDE_CRC(stRxData.InfoByte))))// DATA
231
{
232
233
stRxData.Data[RxBody]=ucRxByte;
234
CalcCRC(ucRxByte);
235
RxBody+=1;
236
if(!INCLUDE_CRC(stRxData.InfoByte)&&
237
(RxBody==stRxData.DataLength))// Keine CRC nötig
238
{
239
NET_UCSRA|=(1<<MPCM0);
240
DataOk=true;
241
}
242
return;
243
}
244
if(RxBody==(stRxData.DataLength-2))// CRC16 High
245
{
246
RxCrc16=ucRxByte<<8;
247
stRxData.Data[RxBody]=ucRxByte;
248
RxBody++;
249
return;
250
}
251
if(RxBody==(stRxData.DataLength-1))// CRC16 Low
252
{
253
254
RxCrc16|=ucRxByte;
255
stRxData.Data[RxBody]=ucRxByte;
256
CalcCRC(0);
257
CalcCRC(0);
258
RxBody=RxHeader=0;
259
if(crc16!=RxCrc16)// fehler CRC
260
{
261
NET_UCSRA|=(1<<MPCM0);
262
return;
263
}
264
else// alles OK
265
{
266
NET_UCSRA|=(1<<MPCM0);
267
DataOk=true;
268
return;
269
}
270
}
271
272
if(RxBody==MAX_DATA_LENGTH)
273
{
274
NET_UCSRA|=(1<<MPCM0);
275
return;
276
}
277
278
}
279
280
281
intmain(void){
282
unsignedcharbuf[20];
283
DDRB=(1<<PINB5)|(1<<PINB2);// set PINB0 and PINB2 as output
284
285
NetInit();
286
_delay_ms(200);
287
sei();
288
289
while(1){
290
291
292
_delay_ms(1000);
293
sprintf(buf,"LED");
294
Net_SendChar(0x44,&buf[0],3);
295
296
297
}// while
298
299
}// main
ab jetzt sollte man den Code in Dateien aufteilen.
Du siehts es ist garnicht so schwer.
Im nächsten Kapitel werden wir uns mit den Kommandos beschäftigen.
ms
Hallo ms!
Danke Dir erneut für den Code.
Ich hatte heute vormittag keine Zeit zum testen, bin aber
jetzt wieder voll dabei und mach mich gleich ans Werk.
Ich melde mich später wie ich zurecht kommme.
LG
Markus
Hallo ms!
ich hab jetzt mal beide Codes am laufen (den Mastercode muss ich noch
genauer studieren)
Da ja das ganze System jetzt anders funktioniert hab ich noch eine
Frage.
Die If-Abfrage nach dem Rufzeichen (Stringende) ist ja jetzt hinfällig.
1
if(ucRxByte!='!')// EndZeichen empfangen
2
{
3
test[ucRxCount]=ucRxByte;
4
ucRxCount++;
5
return;
6
}
Diese hab ich auch in der ISR weg gelassen. Ich lasse mir die Nutzdaten
(im jetztigen Fall LED) auf das Lcd ausgeben. Es kommen aber hinterher
noch zwei Hieroglyphen. Kann es an der fehlenden Null-Terminierung
liegen?
ich lese die Nutzdaten jetzt in der while schleife aus
Hallo Markus,
Markus W. schrieb:> warum hab ich die Hieroglyphen am ende des Strings?
sorry mein fehler habe vor lauter hin und her kopieren immer diese Zeile
mit kopiert
1
if(RxBody==(stRxData.DataLength-2))// CRC16 High
2
{
3
RxCrc16=ucRxByte<<8;
4
// -- > stRxData.Data[RxBody] = ucRxByte;
5
RxBody++;
6
return;
7
}
8
if(RxBody==(stRxData.DataLength-1))// CRC16 Low
9
{
10
11
RxCrc16|=ucRxByte;
12
// --> stRxData.Data[RxBody] = ucRxByte;
ich habe mal meine Datei angehängt schau sie Dir mal an.
Und ja! Sollte jemand mal nachfragen. Über den RS485-BUS mit MPCM Mode
ist es möglich einen Bootloader mit einzubauen das hat den vorteil dass
die anderen Slaves garnicht mitbekommen das ein ander gerade geflasht
wird da der Loader ja nur im 8bit modus läuft. Einziger knackpunkt ist
das umschalten von TXEnable.
ms
Hallo ms!
Danke, jetzt funktioniert es !!
Sag mal, ich bin gerade am durchsehen und vergleichen des Master Codes
mit der Version die Du mir heute geschickt hast.
Da ist mir aufgefallen, und ich hab es auch schon öfters gelesen, dass
die Adresse optional aus dem EEProm gelesen werden kann.
Wie sinnvoll ist das überhaupt die Adresse ins EEProm zu verfrachten?
Du betreibst Deine Controller mit Bootloader? Geht es Dir hierbei
hauptsächlich ums flashen während des Betriebs?
Ich werde jetzt den Master Code besser studieren und etwas Code hin und
her schicken.
LG
Markus
Hallo Markus,
Markus W. schrieb:> Wie sinnvoll ist das überhaupt die Adresse ins EEProm zu verfrachten?
ja oder willst Du für jeden Slave den Compiler neu anschucken.
Ich mach das immer so. Slave flashen. EEProm an stelle x lesen ist das
0xff
ist das ein neuer slave und bekommt die Adresse 0x00. Der Master scan
zyklisch den Bus ab ob ein neuer Slave da ist. Ist einer da kann ich mit
dem kommando SET_NET_ADR ihm eine ADR zuweisen (ins EEProm schreiben).
Markus W. schrieb:> Geht es Dir hierbei> hauptsächlich ums flashen während des Betriebs?
Ja. Stell dir vor deine Teile sind irgend wo in der Welt verteilt. Und
du sollst einen neue Firmware aufspielen. Da ist doch ein Bootloader
doch nicht schlecht. Meist habe ich ein Linux System als Master auf dass
ich von der ferne zugreifen kann. Da muss ich nur das Hex hinüber
schieben und den Bootloader starten.
ms
Hallo ms!
wow, ich bin wirklich sehr beeindruckt!!!!
Du lässt also die Adressen vergeben.
... Wie gesagt als Anfänger hab ich mir über so etwas keine Gedanken
gemacht.
In meinem Mini-System hab ich einen Master und drei Slaves. Da ist die
Vergabe kein Problem.
Aber der Ansatz ist wirklich sehr Interessant.
Vollprofi eben !!!!
LG
Markus
Hallo Markus,
ich empfehle dir für deinen Master eine größere Platform. Für kleinere
Aufgaben ist ein ATmega noch i.O. Ich habe keine Ahnung was du vor hast.
Ich teste gerade eine Himbeere mit Win10 als Master sieht bis jetzt
nicht schlecht aus.
ms
Hallo Markus,
die Lib ist noch nicht Wasserdicht.Die Kommunikation ist im moment nur
einseitig (der Master sendet und der Slave empfängt) es sollte aber sein
dass der Slave den empfang bestätigt. Auch ganz wichtig es muss eine
Timeout funktion oder ähnlich beim Senden eingebaut werden da ich die
Erfahrung gemacht habe dass das TXEnable PIN bei kleinen Atmegas nicht
zuverlässig zurück geshalten wird (deswegen die zwei NOPs).Du kannst dir
ja bis zum WE mal gedanken machen (auch die anderen sind gerne
Eingeladen) wie man sowas mit einbauen kann.
ms
Hiho
Die Adresse würde ich eher in Hardware setzen und über gpio auslesen.
Dann brauchst du gar nichts mehr programmieren und kannst die Teile
einfach aus dem Lager nehmen.
Da musst du aber natürlich die Pins über haben und einen DIP Switch dran
packen.
Grüße
Hallo ms!
Danke für die weiteren Gedankenansätze. Ich hab es ja noch gar nicht
erwähnt, ich möchte mit diesem System einmal meine Rolläden steuern.
Es handelt sich daher um eine geringe Anzahl an controllern. Es soll
einen Master und fünf Slaves geben. Zusätzlich soll das System von einer
einfachen Wetterstation beeinflusst werden (Wind, Lichtstärke, Uhrzeit
usw.).
Ich habe mir auch schon mal Gedanken über den Einsatz eines Rasp
gemacht, bin aber fürs erste froh, wenn das mit den Mega soweit
funktioniert.
Ich möchte mir jetzt wirklich, wie Du es vorgeschlagen hast in den
nächsten Tagen Gedanken über einen erweiterten Kommunikationsablauf,
sowie Timeouts und Codeauslagerung Gedanken machen und Dir diese bis zum
nächsten WE mitteilen.
Vielen Danke für die Unterstützung bis jetzt.
LG
Markus
Hallo Markus,
das ist mal ein gutes Projekt um den Bus zu erreichen. Meine
Technikerarbeit habe ich mit einer Wetterstation gemacht (WXT510
Vaisala) die hängt noch bei mir an der Hütte. Ich glaube daher stammt
auch die crc Routine.
ms
Hallo ms!
Ich hätte eben vor, das Projekt langsam wachsen zu lassen. Zuerst eine
einfache Zeitsteuerung, bei der der Master die Rolläden Öffnungs- und
Schließbefehle zu bestimmten Zeiten gibt. Wenn das soweit läuft, soll
die Wetterstation mit ins Spiel kommen und eben zb. bei starkem Wind die
Rolläden öffnen oder bei dunkelheit unabhängig von der Uhrzeit
schließen.
Auch eine kleine Alarmanlage soll integriert werden (Fensterabsicherung
durch Glasbruchsensor, Reedkontakt und Ultraschallsensor).
Ich hab die Rolläden vor ein paar Monaten bekommen, hab sie
zwischenzeitlich über einen Webserver gesteuert (2560+W5100). Das hat
auch sehr gut funktioniert, war aber nur testweise ein kleines
Spaßprojekt.
LG
Markus
Hallo ms!
ich würde morgen gerne beginnen, den Code in auszulagern. Wie würdest Du
das managen? Machst Du für Master und Slave jeweils eigene Routinen oder
machst Du eine gemeinsame Routine die beide verwenden können. Reicht
eine Datei für alle bis jetzt vorkommenden Routinen zb. RS485.c (und .h)
LG
Markus
Hallo Markus,
ich würde alles was mit der Uart zu tun hat in eine Datei packen
(Driver).
Alles was mit der Aktion zu tun hat in eine eigene (Service).
Tools wie crc usw. in eine eigene.
Master und Slave benutzen den gleichen Code.
ms
Hallo ms!
Ich bin gerade noch mit dem Auslagern beschäftigt. Ist etwas viel für
mich.
Würde es Sinn machen, sämtliche globale Variablen in einen eigenen
Header "Globals.h" auszulagern?
Mit den includes könnte man ja das selbe machen - oder?
Bin da noch ziemlich viel am tüfteln.
Grüße
Markus
Markus W. schrieb:> Würde es Sinn machen, sämtliche globale Variablen in einen eigenen> Header "Globals.h" auszulagern?
Das mache ich in der Tat immer so. Grundgerüst meiner Header-Files:
1
#ifndef globals_h
2
#define globals_h
3
4
//meine variablen
5
6
#endif /* globals_h */
Mit dem #ifndef wird verhindert, dass man den Header mehrfach einbindet
aber ich denke, dass das bekannt ist, oder?
Hallo ms!
so, ich hab jetzt eine lauffähige Version des ausgelagerten Codes.
Könntest Du einmal kurz einen Blick drauf werfen. Ich bin mir bei
einigen Dingen nicht sicher. Speziell bei den Includes. Wie gesagt es
läuft zwar und wurde fehlerfrei compiliert, was aber nicht heisst, dass
es gut ist.
Vielleicht kannst Du kurz drüber schauen. Ich hab da sehr lange
gebraucht dafür, hab aber sowas noch nie vorher gemacht.
LG
Markus
Uh, meinst du jetzt mich oder ms? However, ich werd am WE leider nicht
dazu kommen mir das genau anzuschaun, frühestens nächstes WE komm ich
dazu. Ich zieh nämlich am Montag um. Aber ich werde einen Blick
wagen...oder zwei oder drei ;)
EDIT: Ich habs nur mal kurz überflogen: Die ISR des USART ist für meinen
Geschmack zu lange, die Checks würde ich auslagern in die Mainloop und
in der ISR nur das empfangene Zeichen wegspeichern.
Hallo Markus,
erst einmal respect. Ich habe da noch ein paar Anmerkungen. Ich stehe
nicht auf globale Variablen da besteht die Versuchung diese irgendwo im
Code zu manipulieren. Es ist immer besser die Variable explizit
anzuforden. Gibt es keine möglichkeit diese Variable anzufordern hat das
einen Grund. In C++ ist das einfacher. Auch solltest du genaue
Schnittstellen definieren zwischen den einzelenen Units. So ist es
einfacher z.B. die Unit Service in eine Desktopanwendung oder sogar in
eine Android App zu verwenden ohne diese neu schreiben zu müssen.
ich werde mich heute mal mit deinem Code beschäftigen. Welchen Konverter
hast du? In welcher Sprache programmierst Du in VS C++ oder C#.
ms
Hallo ms!
Danke für die schnelle Antwort!!
Ich beschäftige mich zur Zeit ausschließlich mit Mikrocontrollern und
verwende daher C und Atmel Studio. Wenn ich mehr Erfahrung gesammelt
habe kann ich mich auch einmal in andere Bereiche vorwagen aber momentan
bin ich schon sehr zufrieden, wenn ich meine uC-Projekte einigermaßen
realisieren kann. Könntest Du mich hierbei noch etwas unterstützen, um
wirklich eine RS485 Master-Slave-Kommunikation aufzubauen.
@M.Köhler, Danke auch für Deinen Beitrag und Hilfe!!
LG
Markus
Hallo Markus,
klar helfe ich dir weiter. Da mein Code schon ca.12 Jahre alt ist und
ich mich auch weiter entwickelt habe sehe ich noch einige
Verbesserungen.
Ich habe mal mit der CRC Angefangen. Das Senden geht jetzt so:
CRC=CalcCRCBuffer(&stTxData.RxAddress,stTxData.DataLength+2);// + 2 Byte Header (normal 4 aber da CRC schon +2 ist aber nicht berechnet wird reichen 2 aus)
9
stTxData.Data[stTxData.DataLength-(CRC_HI+1)]=CRC.cCRC16[CRC_HI];// CRC Hi einfügen
10
stTxData.Data[stTxData.DataLength-(CRC_LO+1)]=CRC.cCRC16[CRC_LO];// CRC lo einfügen
11
}
12
NetTxCount=4+stTxData.DataLength;
13
NetTxCount_temp=NetTxCount;
14
NetTxPtr=&stTxData.RxAddress;
15
NetSetTxEnable(true);
16
if(Dev_Config->MasterMode)NET_UCSRB|=(1<<TXB80);// nur beim Master
17
NET_UCSRB|=(1<<UDRIE0);// Tx Empty einschalten
18
19
}
In der Bild Datei sieht man dass die CRC gleich bleibt (CRC1 ist die
alte version CRC2 die neue)
ms
Hallo Markus,
hier nochmal eine erweiterung damit kannst du ganz einfach int,Float
übertragen ohne Bits hin und her zu schieben. Es gibt hier ein Beitrag
bei dem man versucht eine int zu übertragen(bin mal gespannt wie das
ausgeht). Für uns ist das ganz einfach und sogar sicher!!!
Hallo ms!
hat perfekt funktioniert!!
Allerdings hab ich eine Frage.
Du hast Dir wahrscheinlich irgendwo eine Config oder eine Funktion
geschrieben, wo Du festlegst, ob Du den Code für einen Master oder Slave
verwendest.
1
if(Dev_Config->MasterMode)NET_UCSRB|=(1<<TXB80);// nur beim Master
Ich habe das TXB80 jetzt einfach ohne Abfrage für Master gesetzt.
Als nächstes teste ich ob ich den code als Slave verwenden kann. bis
jetzt habe ich ja für den Slave Deinen Code verwendet, den Du ganz zu
Beginn gepostet hast.
In weiterer Folge soll ja der Slave zurück senden können.
Ich mach mich gleich an die Arbeit.
LG
Markus
Hallo Markus,
Master und Slave verwenden zwar den gleichen Code zum senden und
empfangen
aber beide haben unterschiedliche Aufgaben. Deswegen mein hinweis so zu
programmieren dass man ganz einfach gerätespezifische dateien
austauschen kann. Ein Lichttaster hat andere Funktionen wie eine
Rolladensteuerung.
1
typedefstruct{
2
unsignedcharMyAdr;// meine Adr
3
boolMasterMode;// Ich bin Master??
4
unsignedintspeed;// Baud
5
fptrNetTaskfptrCallBackOnOk;// CallBack bei neue Daten
6
}st_Dev_Config;
7
8
/*
9
// Slave Main
10
int main(void) {
11
unsigned char buf[20];
12
DDRB = (1 << PINB5) | (1 << PINB2); // set PINB0 and PINB2 as output
13
DDRC =0xff;
14
st_Dev_Config my_Dev_config;
15
16
my_Dev_config.fptrCallBackOnOk = NetAktion;
17
my_Dev_config.MasterMode = false; // Jetzt bin ich nur ein Slave <-------------------------------------------
18
my_Dev_config.MyAdr = 0x44; // oder aus EEProm auslesen
19
my_Dev_config.speed = 9600;
20
21
NetInit(&my_Dev_config);
22
_delay_ms(200);
23
sei();
24
25
while (1) {
26
27
if(LCD_Update)
28
{
29
//lcd_string(&LCD_buf); // da ich deine LCD Lib nicht habe ist das ausgeklammert.
30
LCD_Update = false;
31
}
32
33
34
35
} // while
36
37
} // main
38
*/
39
// Master Main
40
41
42
43
intmain(void){
44
unsignedcharbuf[20];
45
DDRB=(1<<PINB5)|(1<<PINB2);// set PINB0 and PINB2 as output
46
DDRC=0xff;
47
st_Dev_Configmy_Dev_config;
48
49
my_Dev_config.fptrCallBackOnOk=NetAktion;
50
my_Dev_config.MasterMode=true;// Jetzt bin ich der Master im Bus <--------------------------------------------------
51
my_Dev_config.MyAdr=0x01;// oder aus EEProm auslesen
Hallo ms!
ich hab's bis jetzt noch nicht zum Laufen gebracht.
Wenn ich es heute nicht mehr schaffe, melde ich mich morgen zurück.
Wünsch Dir noch einen schönen Abend.
LG
Markus
Hallo ms!
so, jetzt läuft es wie gewünscht und die Zusammenhänge werden immer
klarer.
Die größten Probleme hatte ich mit der My_Dev_config, da ja teilweise
noch im Code die defines für Baudrate und Adresse vorhanden waren. Auch
in anderen Codeteilen waren Referenzen auf "NET_ADDRESS" usw. vorhanden.
Einige Fragen hätte ich trotzdem noch denn ich musste einiges
auskommentieren um den Code lauffähig zu bekommen.
1
my_Dev_config.fptrCallBackOnOk=NetAktion;//auf NetAktion habe ich keine Referenz
2
3
4
typedefvoid(*fptrNetTask)(st_protokoll_Data*)// --> gehört das überhaupt rein?
5
6
7
8
typedefstruct{
9
unsignedcharMyAdr;// meine Adr
10
boolMasterMode;// Ich bin Master??
11
unsignedintspeed;// Baud
12
//fptrNetTask fptrCallBackOnOk; // CallBack bei neue Daten --> hab ich aus auskommentiert, lief sonst nicht
13
}st_Dev_Config;
Vielleicht könnstest Du Dir das bei Gelegenheit ansehen.
LG
Markus
Hallo ms!
Ich habe jetzt den Code in beiden Varianten (Master & Slave) bis auf die
oben genannten Punkte soweit am Laufen.
Denkst Du wir könnten uns am Wochenende darüber unterhalten?
LG
Markus
Hallo Markus,
Ich habe mal mein Test Projekt hochgeladen. Da habe ich einen Master und
zwei Slaves. Der Slave 0x44 ist ein Taster der 0x45 ist eine Lampe.
Die Funktion: bei einem kurzem Click auf den Taster wird die Lampe(LED)
langsam hoch gedimmt nochmal kuzer Click wird die Lampe langsam runter
gedimmt. Bei long Click geht die Lampe sofort an/aus.
Der Master regelt das ganze.
Es gibt da noch einen schönheitsfehler aber ist bei zwei Slaves nicht so
wichtig.Mein Aufbau ist auch im Anhang.
ms
Hallo Markus,
noch eine Info.Der Slave fragt ständig den Taster ab gibt es eine
Änderung wird der Status zwischen gespeichert bis der Master den Status
abfragt. Danach wird der Status gelöscht. Also Master fragt ab --> Slave
Antwortet braucht aber eine Bestätigung vom Master das er die Daten
bekommen hat --> Master sendet ein ACK --> Status wird gelöscht.Beim
LightService sendet das Slave nur ein ACK beim setzen der LED. Eine
Antwort mit Daten zählt als Positiv ACK für den Master.
Der nächste Schritt ist das einfügen einer TimeOut funktion und der
beschäftigung mit Mutex und Semaphore. Je nach Auslegung sind bei der
kummunikation Prioritäten zu setzen. Bei einem Rauchmelder ist das
erfassen der Umgebungsluft wichtiger wie das abhandeln einer anfrage.
ms
Hallo ms!
Danke für diese Info. ich bin gerade beim Durcharbeiten - absoluter
Proficode!!!
Einiges ist für mich noch sehr verwirrend. Ich muss mich eben
einarbeiten.
Ich werde versuchen das innerhalb der kommenden Woche zu erledigen und
am Wochenende meine Erkenntnisse posten. Ich wäre Dir sehr dankbar, wenn
Du kommendens WE wieder rein schauen könntest.
LG
Markus
Hallo ms!
So, melde mich wieder zurück.
Ich hatte zwar diese Woche nicht so viel Zeit (Stress wegen Studium)
aber es ist für mich absolut interessant Deinen Code zu studieren.
Für mich ist der Code nicht mehr ganz so trivial und es bedarf daher
einiges an Zeit, die Verweise und Funktionen nach zu vollziehen.
Ich hätte da auch eine Frage.
Der Slave (und auch der Master) rufen ja im Modul Scheduler folgende
Funktion auf:
void dispatchTasks(void)
Welche Funktion hat hier das "delay" und welchen Wert bezw. von wo
erhält es seinen Wert?
1
if(!task_list[i].delay&&
2
task_list[i].status==RUNNABLE)
aha jetzt hab ich noch was gefunden
Der Slave übergibt ja die einzelnen Tasks
1
// adds a new task to the task list
2
// scans through the list and
3
// places the new task data where
4
// it finds free space
5
voidaddTask(uint8_tid,task_ttask,
6
uint16_tperiod)
7
{
8
uint8_tidx=0,done=0x00;
9
while(idx<MAX_TASKS)
10
{
11
if(task_list[idx].status==STOPPED)
12
{
13
task_list[idx].id=id;
14
task_list[idx].task=task;
15
task_list[idx].delay=period;
16
task_list[idx].period=period;
17
task_list[idx].status=RUNNABLE;
18
done=0x01;
19
}
20
if(done)break;
21
idx++;
22
}
23
24
}
delay ist der Wert von period
was ist dann period, welche Bedeutung hat es? (in dem Fall wird für
jeden Task 10 übergeben)
Das ist mir noch etwas unklar.
lg
Markus
Hallo Markus,
delay ist die zählvariable periode ist Merkervariable.
Jede ms wird die funktion schedulerMainTask aufgerufen die zählt delay
um 1 nach unten. In dispatchTasks wird nachgeschaut ob delay 0 ist wen
ja wird die funktion Task aufgerufen. Danach wird delay auf den wert von
Periode gesetzt und das Spiel fängt von vorne an. Bei einer ID >= 50
wird nur einmal die Taskfunktion aufgerufen (single shot).
ms
Guten Morgen,
Na Du bist ja ein echter Frühaufsteher!
Danke für die Erklärung, die hat geholfen.
Ich hätte allerdings noch eine Frage.
Der Slave initiert ja seine Tasks.
addTask(1, floorLightTask, 10);
addTask(2,buttonTask,10);
Dann werden die Tasks ja der Liste hinzugefügt und schließlich in
dispatch tasks aufgerufen.
// call the task
(*task_list[i].task)();
Wenn ich jetzt im Modul floorlightservice nachsehe, gibt es da nur eine
Funktion floorlight (ohne Task) aber ich denke, dass das die Funktion
ist, die aufgerufen werden soll.
lg
Markus
Hallo Markus,
floorlightask ist ein "hintergrund Task" aus der floorlight.c. die
regelt das dimmen. Der service wird unten bei jedem durchlauf
aufgerufen.
ms
Hallo ms!
Da hab ich noch was wichtiges gefunden.
Du hast ja folgende typedef enum angelegt:
eine in button.h --> button_state_t;
und eine in floorlight.h --> floorLight_state_t;
Beide beinhalten aber unterschiedliche Aufzählungskonstanten.
Die floorlightservice.c beginnt jetzt mit folgender Deklaration:
1
button_state_tbuttonStateFloorLightService;
Im selben Modul kommt dann folgede Funktion (ich hab nur die ersten zwei
Zeilen eingefügt):
1
voidfloorLight(void)// wird in der while-schleife von main aufgerufen
Müsste das nicht heissen if(buttonStateFloorLightService == B_STATE_OFF)
Also "B_STATE_OFF" nicht "STATE_OFF", da ja in der typdef enum
button_state_t das so festgelegt wurde.
Tut leid, ich bin gerade etwas confused.
lg
Markus
Hallo ms!
meld mich wieder zurück.
Ich hab mir diese Woche den Slave-Code weiter durchgesehen. Ich weis
jetzt soweit bescheid, wie sich die verschiedenen Statuswerte ergeben.
Später hätte ich zum Slave-Code noch ein paar geziehlte Fragen.
...Nein, eigentlich müsste ich Dich gleich fragen.
Du hattest am Anfang geschrieben dass der Ablauf so ist:
Ein Master, ein Slave (Taster 0x44), ein Slave (Lampe 0x45)
Wenn ich jetzt den Code durchspiele hab ich folgendes Problem:
Der Slavecode hat ja die Adresse 0x45, also die Lampe. In der
while-Schleife des Codes wird ja ständig die Funktion floorlight() aus
dem Modul floorlightservice.c aufgerufen.
Diese wiederum ruft gleich in der ersten Zeile folgendes auf:
1
if(buttonStateFloorLightService==B_STATE_OFF)buttonStateFloorLightService=getButtonState();// getButtonState() wird in button.c aufgerufen
Für mich sieht das aus, wie wenn die Funktion getButtonState() (aus dem
Modul Button.c) direkt aufgerufen wird. Da es aber ein anderer Slave
ist, sollte ja die Anfrage über den Bus laufen? - oder sehe ich das
falsch?
Könntest Du mir das kurz erklären?
Ich bin jetzt wieder beim Master Code und überlege mir gerade das
Zusammenspiel zwischen Master und Slave.
Meiner Meinung nach stellt ja (muss ja eigentlich auch so sein) der
Master die erste Anfrage. und zwar:
In der while-schleife des Masters wird über die Funktion Masterservice()
(im Modul Masterservice.c) die Funktion SlaveButtonState() aufgerufen.
Diese sendet eine Anfrage eben über den Buttonstate des Slaves.
Kannst Du mir den Senderahmen dieser Funktion und der Funktion
SlaveSetLight() kurz erklären.
SlaveButtonState()
mit buf legst Du ja ein array für die Nutzdaten fest.
Was bedeuten die Daten in buf[0] (0x02)?
und jetzt der frame:
1
Net_SendChar(device[0].adr,&buf[0],1,CRC_BIT);
also device[0].adr = 0x44 (Slave mit Taster)
&buf[0] sind ja die Daten (bitte noch um Erklärung)
dann kommt 1 (bitte um Erklärung)
und dann CRC_Bit --> sollte das nicht ein Aufruf sein?
Ich hab mir auch die Argumente in der Funktion angesehen.
Der Funktion NetSendChar zufolge sollten ja die Übergabeargumente
folgendes bedeuten:
1, RX Adresse (ist klar)
2, sind wohl die Daten
3, aha, unsigned int len (in der for schleife werden wohl die Nutzdaten
eingelesen bis len oder?)
4, bleibt noch das Info Byte.
Könntest Du mir bitte diese Routinen noch etwas genauer erklären in
Bezug auf die Sendeargumente.
SlaveButtonState
SlaveSetLight --> diese hat andere Argumente
LG
Markus
Hallo Markus,
Markus W. schrieb:> Ein Master, ein Slave (Taster 0x44), ein Slave (Lampe 0x45)
Beide Slave haben die gleiche funktionen. Der Master aber fragt nur beim
0x44 den Taster Status ab und gibt ihn an den 0x45 weiter. FloorLight
und Button haben KEINE Verbindung zueinander!!!
Markus W. schrieb:> also device[0].adr = 0x44 (Slave mit Taster)> &buf[0] sind ja die Daten (bitte noch um Erklärung)> dann kommt 1 (bitte um Erklärung)> und dann CRC_Bit --> sollte das nicht ein Aufruf sein?
&buf[0] ist die Adresse im Speicher vom ersten Byte der Daten.
1 bedeutet 1 Byte von buf soll übertragen werden. 2 sind 2 Byte von buf
usw
CRC_Bit = im Info Byte wird das bit für CRC wird mit übertragen gesetzt.
im Anhang eine Beschreibung (ist auf das was wir jetzt erarbeitet haben
beschränkt).
ms
Hallo ms!
Vielen Dank, jetzt ist mir wieder einiges klarer.
Die Framelist ist sehr hilfreich.
Ich arbeite gerade weiter und da ist mir was aufgefallen.
Könntest Du mal einen Blick auf die Typedef Master_state_t
(Masterservice.h) werfen. Du hast für STATE_GET_SWITCH= 0, vergeben,
sendest aber in der Anfrage (SlaveButtonState) 0x02
Bei SlaveSetLight sendest Du 0x01, das ist laut Typedef 0x02
LG
Markus
Hallo Markus,
Master_State ist die StateMaschine vom Master. Da der MasterService von
Main Zyklisch aufgerufen wird muss der Service wissen welche Aktion er
ausführen muss. Das hat nichts mit der Kommunikation zu den Slaves zu
tun.
Markus W. schrieb:> sendest aber in der Anfrage (SlaveButtonState) 0x02
schau mal in die FloorLightService.h(Slave)
da steht
1
#define SET_LIGHT 0x01
2
#define GET_SWITCH 0x02
Hast Du eine Himbeere oder Odroid oder BB (linux) Oder RPI IOT Win10?
Da ist der Master besser aufgehoben.
ms
Hallo ms!
Also mit Linux hab ich überhaupt keine Erfahrung (leider)
Grundsätzlich hab ich nur etwas C Erfahrung, ein kleinwenig C++
Darum weis ich nicht ob ich das mit dem Rasp auch gebacken bekomme.
Natürlich würde es mich sehr ineressieren.
LG
Markus
Hallo Markus,
das bekommst du schon hin.
Linux: QT Setup ist nichts für schwache nerven. Auch die ganzen
berechtigungen nerven manchmal. Großer vorteil du kannst über
RemoteDesktop die pi vom deinem Rechner in der Aktuellen Sitzung aus
bedienen ohne an der pi eine Tastatur oder Montitor angeschloßen zu
haben.
Win10 IOT: ist echt einfach das Setup in VS. Nur das mit der Thread
programmierung ist gewöhnungsbedürftig. Events habe ich noch nicht ganz
raus.
Ich persönlich verwende RAD Studio da ich viel mit datenbanken zu tun
habe war das die beste wahl. Leider noch keine möglichkeit für Linux
soll sich aber mit Gozilla ändern.
Meine empfehlung: einen alten Rechner mit Linux Lubuntu und QT.
RPI-Image für QT mit QMake stelle ich dir bereit. Aber nur sollte was
unter dem Weihnachsbaum sein!!!
ms
Hallo Markus,
welche Wetterstation willst du verwenden? Welche Rohrmotoren sind
verbaut Somfy, elero, roma, nice, came usw
meine Ausbildung habe ich bei Came genossen.
ms
Hallo ms!
wow, Du hast bei Came gearbeitet. Die machen doch auch Zugangskontrollen
und Sicherheitssysteme oder?
... deshalb bist Du so gut drauf!!!
Also ich habe zu Hause Somfy verbaut. Es sind ganz neue mit
Hinderniserkennung. Der Nachteil für mein Projekt ist allerdings, dass
ich ja keine (zugänglichen) Endschalter habe die mir die Endlage
bestätigen. Ich hätte mir für die Ansteuerung eine Kombination aus Zeit
und Strommessung vorgestellt. Ich hab sie ja wie ich sie bekommen habe
spaßhalber über einen Arduino Webserver gesteuert. Das hat aber ganz gut
funktionert.
Hättest Du da eventuell eine bessere Idee?
Achja zur Wetterstation, die hätte ich auch selber gebaut. Also einen
Controller im Außenbereich mit Dämmerungserkennung, Temperaturmessung,
Windmessung, eine RTC, alles was Interessant wäre um die
Rolladensteuerung zu beeinflussen.
...Wie würdest Du das machen?
Oder Du hast doch weiter oben mal geschrieben eine Station integriert zu
haben. Könntest Du mir das auch empfehlen, oder ist die Eigenbau
Variante ausreichend. Wie gesagt, mir gehts dabei nicht so sehr ums
Wetter sondern nur um Einflüsse die für die Steuerung relevant sind.
Einen alten Rechner mit Linux wäre auch kein Problem. Es müsste also
genau Lubuntu und QT sein.
Ich hab zwischenzeitlich nomal beim Christkind nachgefragt. Ja, die
Chancen stehen gut für einen Pi und ein 5" lcd.
Nur wie gesagt ich bin jetzt noch nicht mit dem Code durch und würde wir
so ungefähr bis Weihnachten zum Ziel setzten, den Code soweit verstanden
zu haben.
Ich mach mich gleich wieder ans Werk
LG
Markus
Hallo Markus,
meine WXT ist zu oversize die werden beim DWD oder sogar bei der NASA
eingesetzt. Ich würde Dir Vorschlagen eine Fertige Lösung zu nehmen ELV
usw.
Aber die sollte min eine RS232 Schnittstelle haben. Meine WXT kann Tag
und Nacht nicht unterscheiden.
Endlagen Erkennung wird nicht einfach aber möglich. Hast du eine
Bedieneinheit von Sonfy verbaut(ich habe jede woche von meinem Kumpel
eine zu rep.)?
ms
Hallo ms!
Danke, dann werde ich mich dementsprechend umsehen.
Eine Bedieneinheit hab ich keine drauf von Somfy. Die wurden einfach
montiert und das Kabel haben sie mir dann durch den Schlauch
reingeschoben.
LG
Markus
Hallo ms!
Ich habe mich gestern noch mit dem Master Code beschäftige. Das ist
soweit auch klar. Ich bin jetzt bei dem Punkt, an dem der Master seine
Anfrage sendet, zB. STATE_GET_SWITCH. An diesem Punkt würde ich wieder
Deine Hilfe benötigen und zwar was den eigentlichen Sendevorgang
betrifft.
Also, diese Daten werden ja in der Funktion SlaveButtonState generiert
und an die Funktion Net_SendChar weiter gegeben, wo sie in die
Strukturvariable stTxData eingelesen werden.
Jetzt wird die Funktion Net_SendFrame aufgerufen und auf das Infobyte
überprüft. Dannach kommt die CRC-Kalkulation.
Dann wird die Variable Net_TxCount mit 4 + der Datenlänge befüllt und
der Inhalt der Variable Net_TxCount_Temp zugewiesen.
Frage: An dieser Stelle enden jetzt alle Funktionsaufrufe. Wenn der
Sendepuffer leer ist, wird ja die ISR aufgerufen. Dort wird unter
anderem ein Zeiger NET_UDR = *NetTxPtr erstellt. Dieser zeigt aber auf
keine Variable
Kannst Du mir diesen Ablauf genauer erklären.
Ich hätte Dich auch noch ersucht, den Vorgang für das Auslesen der Daten
für den Slave noch etwas zu erklären, also wie jetzt die Anfrage zB.
STATE_GET_SWITCH vom Slave verarbeitet wird. Da hab ich noch Probleme
damit.
LG
Markus
Hallo Markus,
Markus W. schrieb:> Zeiger NET_UDR = *NetTxPtr erstellt. Dieser zeigt aber auf> keine Variable
falsch!!!
1
st_protokoll_DatastRxData;
2
st_protokoll_DatastTxData;
3
4
unsignedchar*NetTxPtr;// <--- hier wird der Zeiger erstellt
5
unsignedcharNetTxCount;
6
unsignedcharNetTxCount_temp;
7
net_timeout_tnet_timeout;
hier wird dem Zeiger die Adresse(im Speicher)von dem ersten Element der
struct stTxData zugewiesen das ist .RxAddress
1
NetTxCount=4+stTxData.DataLength;
2
NetTxCount_temp=NetTxCount;
3
NetTxPtr=&stTxData.RxAddress;// Adresse wir zugewiesen
hier wird der Inhalt der Adresse auf die NetTxPtr zeigt in das NET_UDR
geschrieben
1
NET_UDR=*NetTxPtr;
buttonStateFloorLightService ist die Zustandsvariable die nur durch den
Master zurückgesetzt werden kann.
1
caseGET_SWITCH:
2
Net_RunOnAck(clearButtonStateNetFloorLight);// <--- Die funktion wird ausgeführt sobald der Master ein ACK Sendet
3
Net_SendChar(RxFrame->TxAddress,&buttonStateFloorLightService,1,CRC_BIT|NEED_ACK);// NEED_ACK zeigt dem MAster an das er nach erhalt ein ACK senden muss
Halo ms!
Ich hätte da fürs Verständnis noch einmal Deine Hilfe benötigt.
Und zwar ist mir nicht klar, wo genau die zu sendenden Daten in die
USART transferiert werden.
Hier werden ja die Daten in die Struktur eingelesen:
1
voidNet_SendChar(unsignedcharptr_RXAddress,unsignedchar*val,unsignedintlen,unsignedcharinfoByte)// hier werden die Daten in die Strukturvariable eingelesen
2
{
3
intloop;
4
stTxData.RxAddress=ptr_RXAddress;
5
stTxData.TxAddress=Dev_Config->MyAdr;
6
stTxData.InfoByte=infoByte;
7
stTxData.DataLength=len;
8
for(loop=0;loop<len;loop++){
9
stTxData.Data[loop]=*val++;
10
}
11
Net_SendFrame();
12
}
... und jetzt wird Net_SendFrame() aufgerufen:
1
voidNet_SendFrame(void)
2
{
3
uCRC16_tCRC;// uCRC16_t = typdef union aus crc16.h
CRC=CalcCRCBuffer(&stTxData.RxAddress,stTxData.DataLength+2);// + 2 Byte Header (normal 4 aber da CRC schon +2 ist aber nicht berechnet wird reichen 2 aus)
8
stTxData.Data[stTxData.DataLength-(CRC_HI+1)]=CRC.cCRC16[CRC_HI];// CRC Hi einfügen
9
stTxData.Data[stTxData.DataLength-(CRC_LO+1)]=CRC.cCRC16[CRC_LO];// CRC lo einfügen
10
}
11
NetTxCount=4+stTxData.DataLength;// ? destination, info, source, len
12
NetTxCount_temp=NetTxCount;
13
NetTxPtr=&stTxData.RxAddress;// hier wird dem Zeiger die Adresse(im Speicher)von dem ersten Element der struct stTxData zugewiesen das ist .RxAddress
14
NetSetTxEnable(true);
15
/*if(Dev_Config->MasterMode)*/NET_UCSRB|=(1<<TXB80);// nur beim Master
Hallo ms!
Ich glaube ich weis jetzt wie das funktioniert. Ich hoffe ich geb jetzt
keinen Quatsch von mir.
Also, Im Modul Net_sendFrame() wird ja dem Zeiger die Adresse des ersten
Elemnents von stTxData zugewiesen (RxAddress).
1
NetTxPtr=&stTxData.RxAddress;
Dannach wird ja TX empty aktiviert.
Dadurch die ISR(USART_UDRE_vect)
Hier wird (bei gesetztem 9. Bit) die RX Adresse gesendet
1
NET_UDR=*NetTxPtr;
Jetzt kommt meine Vermutung, jetzt werden dem Zeiger die Adressen der
weiteren Elemente der Struktur stTxData übergeben (Eine Adresse ´pro
Durchlauf).
1
NetTxPtr++;
und zwar so lange, bis die Anzahl an zu sendenden Elementen, die über
Net_TxCount festgelegt und bei jedem Durchlauf runtergezählt werden auf
null ist.
1
NetTxCount--;
Könnstest Du mir das bitte bestätigen oder ggf. korrigieren.
Danke und LG
Markus
Hallo ms!
Ich möchte mich an dieser Stelle mal
recht herzlich bei Dir bedanken
und wünsche Dir und Deiner Familie ein recht frohes Weihnachtsfest.
LG
Markus
Hallo ms!
Da es doch schon eine Weile her ist, seit Deinem letzten Posting, wollte
ich mal nachfragen ob Du noch weiter mit mir arbeiten möchtest.
Vielleicht kannst Du Dich kurz diesbezüglich melden.
LG
Markus
Hallo Sabberlotte,
Danke für die Info!
Das aber fast nicht zumutbar denn der Code ist ist sehr umfangreich.
...aber ich werde mir gezielte Fragen überlegen bei denen mir vielleicht
jemand helfen kann.
Danke erstmal ;-)
lg
Markus
Guten Abend Zusammen!
Könnte mir jemand von euch bei einem Problem helfen?
Ich hab meinen RS-485 Bus soweit einmal am laufen (Schaltplan und
Oszi-Bilder im Anhang).
Ich hab den Bus auf einem Steckbrett aufgebaut. Es sind ein Master und
zwei Slaves vorhanden.
Wenn er läuft tut er das ganz gut und ohne Probleme. Jedoch kann es
sein, dass sich nach dem Einschalten nichts tut.
Der Master beginnt die Kommunikation und fragt den ersten Slave zyklisch
ab.
Ich habe bereits sehr viel wegen diverser Probleme gelesen und sämtliche
bias- bzw. Terminierungsvarianten durchprobiert. Es ändert sich nichts.
Wenn der Bus nach dem Einschalten nicht läuft, und man führt beim Master
einen Reset aus, dann wird eine Übertragung durchgeführt. Beim nächsten
Reset wieder eine Übertragung aber immer nur eine einzige.
Wenn ich an irgendeinen Busteilnehmer meinen USB-Konverter am RX-Pin
anstecke, funktioniert der Bus immer nach jedem Einschalten.
Bin momentan etwas ratlos. Vielleicht hat von euch jemand eine Idee.
Aktuelle Widerstandsconfig: 2x 120R Terminierung am Anfang und Ende.
Einmal bias 680R von Leitung A auf VCC und einmal bias 680R von Leitung
B auf VSS. Leitungslänge ca. 6 Meter Cat5. Bustreiber sind Max485, alles
auf dem Steckbrett und mit 5V versorgt über ein Labornetzteil.
Für Ideenansätze wäre ich sehr dankbar.
Grüße
Markus
Markus W. schrieb:> Wenn er läuft tut er das ganz gut und ohne Probleme. Jedoch kann es> sein, dass sich nach dem Einschalten nichts tut.>> Der Master beginnt die Kommunikation und fragt den ersten Slave zyklisch> ab.
Was denn nun ?
Wenn der Master den ersten Slaven zyklisch abfragt, dann tut sich was
auf dem Bus.
Antwortet der Slave nicht oder was ?
Was macht der Master überhaupt ?
Den ersten Slaven zyklisch abfragen oder alle Slaven nacheinander
zyklisch abfragen ?
> Wenn der Bus nach dem Einschalten nicht läuft, und man führt beim Master> einen Reset aus, dann wird eine Übertragung durchgeführt. Beim nächsten> Reset wieder eine Übertragung aber immer nur eine einzige.
Was heisst Übertragung ?
Master sendet und kriegt keine Antwort vom Slaven oder Master sendet
und kriegt Antwort vom ersten Slaven aber es geht danach nicht weiter ?
> Wenn ich an irgendeinen Busteilnehmer meinen USB-Konverter am RX-Pin> anstecke, funktioniert der Bus immer nach jedem Einschalten.
Soll heissen ?
Der Slave ist getrennt oder USB-Konverter parallel am RX-Pin ?
Die anderen Slaven antworten jetzt ohne Probleme ?
Markus W. schrieb:> Das aber fast nicht zumutbar denn der Code ist ist sehr umfangreich.
Der Code ist wahrscheinlich die Ursache aber trotzdem könntest du
etwas präziser sein bei der Fehlerbeschreibung.
Und die ganze Geschichte mit 9-bit ist bei RS485 sowas von unnötig,
weil fehleranfällig...
z.B. sagt ATMEL folgendes:
Ok, ich versuchs besser zu erklären.
Die Kommunkation sieht so aus, der Master fragt den ersten Slave ab, ob
an dessen Taster eine Änderung statt gefunden hat. Der Slave gibt dem
Master den Status des Tasters bekannt. Wurde der Taster am ersten Slave
gedrückt (long oder short-click) dann gibt der Master den Befehl an den
zweiten Slave, die dort angeschlossene led rauf oder runter zu dimmen.
Das funtioniert auch so weit ganz gut. Wenn mit dem Einshalten alles
klappt arbeiten alle Teilnehmer wie gewünscht.
Manchmal aber passiert nach dem Einschalten gar nichts und es gibt keine
Aktivität am Bus. Wenn der Taster an Slave 1 gedrückt wird, sollte ja
die led rauf gedimmt werden. Tut sie dann aber nicht. Wenn man dann beim
Master einen Reset ausführt wird auf einmal die led gedimmt. Jetzt
betätigt man den Taster wieder, und es passiert nichts. Gibt man dem
Master wieder einen Reset, wird die led auf einmal runter gedimmt. Also
jeder einzelne Vorgang geht dann nur noch über einen Reset vom Master.
Jetzt schalte ich den Netzteil ab und dannach wieder ein. Auf einmal
geht wieder alles ganz normal ????
Wenn ich den USB-Konverter an den rx-pin eines Teilnehmers hänge und
schalte dann ein, funktioniert die Kommunikation immer. Der Konverter
wird dabei parallel an einen rx-pin angeschlossen.
Ich bin mir nicht sicher, was die Ursache sein könnte obwohl ich eher
von der Hardware ausgegangen wäre denn mit dem parallel geschalteten
Konverter geht es ja auch immer und sonst eigentlich meistens womit ich
aber nicht sagen möchte das ein Softwarefehler generell ausgeschlossen
werden kann.
Was den 9-bit-Modus betrifft, bin ich leider noch zu unerfahren aber im
Zuge meiner Recherchen bezüglich avr und rs485 hab ich fast
ausschliesslich vom 9-bit-Betrieb gelesen.
Ich hoffe ich habe das Problem etwas besser beschrieben.
Grüße
Markus
Markus W. schrieb:> Aktivität am Bus. Wenn der Taster an Slave 1 gedrückt wird, sollte ja> die led rauf gedimmt werden. Tut sie dann aber nicht. Wenn man dann beim> Master einen Reset ausführt wird auf einmal die led gedimmt. Jetzt> betätigt man den Taster wieder, und es passiert nichts. Gibt man dem> Master wieder einen Reset, wird die led auf einmal runter gedimmt. Also> jeder einzelne Vorgang geht dann nur noch über einen Reset vom Master.
Das könnte bedeuten, dass deine Variablen und Flags nicht auf Null bzw.
bestimmte Werte gesetzt werden, es wird angenommen, dass die Werte
stimmen, bzw. Null sind.
Oder die Slaven warten auf ein zusätzliches Byte.
Oder...
Markus W. schrieb:> Wenn ich den USB-Konverter an den rx-pin eines Teilnehmers hänge und> schalte dann ein, funktioniert die Kommunikation immer. Der Konverter> wird dabei parallel an einen rx-pin angeschlossen.
???
Ein Teilnehmer ist ein Teilnehmer und nicht dein gesammtes Netz.
Rx ist Eingang und noch dazu vom Bus getrennt, so etwas kann nur bei
undefiniertem Pegel passieren. Und undefiniertes Pegel am Rx kann es
nur in 2 Situationen geben:
1) Dein RS-Bus befindet sich in einem undefiniertem Zustand.
2) RE-Pin ist auf High.
Das wiederum sollte nicht passieren wenn beim Rx-Pin (MEGA) Pullup
eingeschaltet ist. USB-Konverter hat wahrscheinlich diesen Pullup
und dadurch wird der Rx-Pin bei MEGA auch auf einen definierten
Zustand gezogen.
Ohne USB-Konverter wird der Slave den RS-Bus wahrscheinlich blockieren.
Aber irgendwie ist das alles unlogisch - wieso geht das dann auf
einmal, was ist mit Slave Nr.2 ?
Ohne LA am Bus und Rx-Pins wird das nur tagelanges rumrätseln geben.
Also ich habe ja bias-Widerstände am Bus und jeder Atmega hat am rx-pin
einen pull-up - hast Du mal einen Blick auf den Schaltplan geworfen, da
ist die aktuelle Beschaltung genau dargestellt.
Variablen und Flags sind ja beim Einschalten immer auf Null, oder nicht
wenn ein Wert zugewiesen wurde, auf jeden Fall immer gleich beim
Einschalten.
Achja und alle RE haben einen pull-down.
Mir fällt ja auch nichts mehr ein hierzu.
Markus W. schrieb:> Variablen und Flags sind ja beim Einschalten immer auf Null, oder nicht
Nein, nur I/O Register haben definierte Werte, alles andere hängt vom
Compiler ab.
> Also ich habe ja bias-Widerstände am Bus und jeder Atmega hat am rx-pin> einen pull-up - hast Du mal einen Blick auf den Schaltplan geworfen, da
Dann würde der USB-Konverter nicht helfen aber der tut es...
so ich hab jetzt noch etwas nachgemessen.
Jedes Mal, wenn am Bus nach dem Einschalten keine Aktivität vorhanden
ist, wird auch vom Master am tx-pin nichts gesendet. Am Master tx ist
high-pegel.
Ich hab jetzt einmal den pull-down Widerstand am RE von 10k auf 47k
erhöht.
Teste weiter
Markus
Markus W. schrieb:> Also ich habe ja bias-Widerstände am Bus
Das sieht in deinen Oszi-Bildern aber ganz anders aus!
Mit Bias-Widerständen dürfte es den "verbotenen" Pegel in NewFile0.bmp
und NewFile1.bmp nicht geben.
Markus W. schrieb:> Ja, aber wie gibts denn das?
Verbotenen Pegel bei korrektem Busabschluss und Biasing gibt es, wenn
zwei oder mehr Teilnehmer gleichzeitig die Treiber auf Senden schalten,
und unterschiedliche Pegel auf den Bus legen.
Ok, also sollte demnach der Fehler in der Software liegen.
Ich hab mittlerweile auch rausgefunden das der Fehler auch mit parallel
geschaltetem USB-Konverter auftritt.
Guten Abend,
@Route66: Ich hab jetzt einmal gemessen ob, wie Du vermutet hast
gleichzeitig auf verschiedenen Stationen gesendet wird. Das kann ich
nicht bestätigen. Bitte Sie Dir die Bilder mal an.
NewFile6 zeigt Master RE/DE und Slave1 RE/DE
NewFile7 zeigt Mster RE/DE und Slave2 RE/DE
NewFile10 zeigt beide Slaves
Grüße
Markus
Hallo Markus,
im Schaltplan sind led2 und c11 und c14 falsch angeschlossen.
Analog bei den Slaves ebenso.
Um das etwas besser nachvollziehen zu können solltest Du mal den
aktuellen! Code vollständig von dem Master und Slaves zeigen. Bild vom
Aufbau auch!
Gruß Sven
Guten Morgen,
zuerst einmal Danke für eure Beiträge!
@Sabberlotte
Werde ich gleich machen. Kannst Du mir noch erklären, wie Du diese Werte
ermittelt hast, da ich ja schon die unterschiedlichsten Vorschläge
bekommen habe.
@Sven
Danke für Deine geneue Beobachtung. Ist mir leider in der Eile passiert.
Ansonsten entspricht der Schaltplan genau dem Aktuellen Aufbau.
Anbei noch der Code, welcher aber sehr umfangreich ist.
Es handelt sich hierbei um den Testcode von ms.
Grüße
Markus
Guten Morgen Markus,
Der Gesamtwiderstand ist: 680+680+60(120/2) = 1420 Ohm
An 5V ergibt das einen Strom von (5/1420) ~ 3,52 mA,
3,52 mA an 60 Ohm ergigt eine Spannung von 211 mV.
Durch Bauteiltoleranzen kann das am MAX485 knapp werden
mit RO=1 (+200mV an A/B).
Markus W. schrieb:> Ah, Danke für die tolle Erklärung!
Die dir bestimmt nicht weiter hilft.
680 Ohm sind fein, lass es ruhig.
Wenn die Buslänge unter 50 Meter ist, brauchst du für das Ganze nicht
einmal die Abschlusswiderstände.
Mahlzeit,
so, ich hab die Widerstände auf 470 ohm getauscht. Wenn der Bus angeht
(also das Einschalten funktioniert) dann sieht man die Änderung auch am
Oszilloskop.
Nur leider war das nicht die Lösung für mein Problem jedoch bin ich über
die Erklärung dankbar.
Ich gehe schon sehr stark von einem Timingproblem aus und werde mal
sehen, was ich da im Code ändern könnte. Vielleicht die delay in der
While-Schleife des Masters erhöhen. Vielleicht sollte ich auch
Baudratenquarze einsetzen. Was denkt ihr darüber.
Grüße
Markus
Hallo Markus,
hast Du mal vor der while Schleife im Master vor sei()
die Wartezeit einfach mal erhöht? 2s oder 5s?
Ist das alles auf dem Steckbrett? Foto?
Ich hatte schon den Fall das die Kontakte nicht immer perfekt waren, da
sucht man sehr lange an einem Grundproblem.
Gruß Sven
Markus W. schrieb:> sehen, was ich da im Code ändern könnte. Vielleicht die delay in der
Vielleicht scheduler + 9-bit rausschmeissen und mit normaler
Statemachine versuchen ?
Warum überhaupt scheduler für einfaches LED an und aus ?
Ein einfaches Rx_ISR in welchem auf SOF und Slave-Adresse geprüft
wird, reicht vollkommen und kann später immer noch erweitert werden.
Und zum Testen lässt man den Master alle 5s abwechselnd stumpf
LED_An und LED_Aus senden, ohne scheduler und 9-bit.
Hallo Zusammen
Danke Sven für Deinen Vorschlag!
Ich habe nach mittag im Mastercode die Wartezeit in der Schleife von 5ms
auf 25ms erhöht und seitdem läuft es.
Weiters muss ich Dir recht geben bezüglich des Steckbrettes. Auch wenn
nicht viel gesteckt ist, ist es jetzt schon voll mit einer Unmenge an
Kabeln.
Danke auch Dir Marc für Deinen Beitrag. Ich hatte zu Beginn einen
stumpfen Code wo der Master alle 3s eine einfache Meldung an den Slave
gesendet hat. Das hat ohne Probleme funktioniert.
Mit dem Scheduler ist das komplizierter geworden. Der Scheduler wird
sich natürlich nicht auf das Schalten einer Led beschränken sondern da
kommen eine Menge Funktionen dazu.
Ich muss noch dazu sagen, dass ich den Code einst weilen nur als Debug
compiliert habe.
Was haltet ihr von der Optimierung mit den Baudraten Quarzen?
Grüße
Markus
Markus W. schrieb:> Was haltet ihr von der Optimierung mit den Baudraten Quarzen?
Ist bei längeren Leitungen und höheren Datenraten unbedingt zu
empfehlen. Ich nutze eigentlich nur noch Baudratenquarze mit 14.7456 MHz
an den Atmegas, früher hatte ich oft 16 MHz Quarze am Start. Die AVRs
sind mir mit 14,7456 MHz aber auch schnell genug und damit sind auch 115
kBd auch auf längeren Strecken kein Problem.
Hallo M. Köhler
Ich hätte die 7,3728 zu Hause. Sollten ja auch gehen oder?
Wenn das mal soweit läuft, hätte ich eine Leitungslänge von ca. 30-40m
und insgesamt 6 Teilnehmern vorgesehen.
Grüße Markus
Ja klar, die gehen auch. Nicht selten nutze ich bei den 14.7456 MHz
Quarzen den Prescaler von 8 (lasse auch die entsprechende Fuse an). Es
geht ja bei dem Spass nur darum, dass man beim UBBR-Value einen glatten
Wert erhält, das geht bei allen ganzzahligen Vielfachen von 0.9216 MHz.
So, jetzt hab ich mal alles als Release kompiliert - wieder die
Einschaltprobleme. Ich versteh das nicht. Wenn es mit dem Einschalten
klappt dann läuft der Bus absolut verlässlich. Aber wie gesagt alle 2-3
Mal Einschalten geht es erst. Dabei hab ich schon großzügige Timings
verabreicht und wenn ich mit dem Oszilloskop schaue (wenn der Bus läuft)
ist kein gleichzeitiges Senden zu sehen. Sehr ernüchternd.
Grüße
Markus
Markus W. schrieb:> Wenn es mit dem Einschalten> klappt dann läuft der Bus absolut verlässlich.
Dann liegt es wahrscheinlich am Einschaltvorgang. Mach dazu am besten
mal ein Flowchart mit Timings und schau dir dabei mal an was passieren
würde, wenn das ein und andere Timing innerhalb seiner Toleranz driftet.
Da könnte es eine blöde Überschneidung geben.
eines find ich allerdings echt merkwürdig. Wenn der Programmer
angeschlossen ist läuft der Bus jedes Mal an. Probleme treten nur auf,
wenn der Programmer nicht an einem Controller hängt.
Da muss doch irgend ein Zusammenhang sein.
Resetbeschaltung: 10k an VCC, 100n gegen Masse.
Ich habe es auch ohne den Kondensator probiert, keine Änderung
Grüße
Markus
Hallo Markus,
zeige doch mal ein Bild von dem Aufbau.
Zum Kondensator: bist Du sicher das das die erwartete Größe ist?
Vielleicht hat er eine viel zu kleine Kapazität.
Der Programmer macht nichts anderes als den Reset auch mit einem Pullup
zu versorgen.
Vielleicht ist auch dein pullup Widerstand defekt ?
Oder Steckbrett Probleme?
Gruß Sven
Hallo Sven,
Wegen der Größe des Kondensators, die sollte soweit passen (hab auch
schon hier im Forum deswegen gelesen).
Ich habe noch Bilder von meinem Aufbau angehängt.
Grüße
Markus
Hallo Markus,
ehrlich gesagt würde ich Dir ganz stark empfehlen jetzt den Schritt zu
gehen und ein paar fertige Boards zu kaufen oder Du entwirfst dein
eigenes. Nach dieser langen Testphase würde ich Dir aber mehr empfehlen
auf fertige Boards mit Rs485 zu setzen. Ja das kostet Geld bietet Dir
aber sofort lauffähige Verbindungen und Erfolgserlebnis.
Was hast Du denn vor wenn es mit den Platinen läuft?
Beispiele:
http://www.chip45.com/products/crumb644-1.1_avr_atmega_modul_board_atmega644p_usb_rs485.php
mit wählbarer Frequenz und Bus direkt drauf.
Es gibt sicher noch weitere Beispiele, war jetzt der erste Treffer.
Gruß Sven
Hallo Sven,
Danke für den Link, ist eine interessante Seite.
Ich weis, das die Beschaltung am Steckbrett sehr ungünstig und
fehleranfällig ist. Da ich eine vollständige Ausrüstung zum Ätzen habe
werde ich mir die Platinen selber entwickeln (oder ggf. auf eine fertige
Lösung zurück greifen). Später möchte ich einmal meine Rolläden damit
steuern.
Eigentlich stehe ich ja noch am Anfang, da das ja nur der Testcode ist.
Ich bin auch immer wieder am Überlegen ob ich den Code verwerfe und was
einfacheres mache, wie es Marc bereits vorgeschlagen hat.
Zur Zeit läuft es aber gar nicht schlecht. Ich habe in der
Initialisierungsphase ein paar kurze delays eingefügt und jetzt
funktioniert das Einschalten jedel Mal. Ich werde mir aber die Zeit
nehmen und ein Flowchart entwickeln.
Eines ist mir jedoch unklar und vielleicht kannst Du oder jemand anders
mir das beantworten. Durch die eingefügten delays in der
Initialisierungsphase hat sich der gesamte Bustransfer verlangsamt (lt.
Oszilloskop).
Klar wäre mir das, wenn ich in der While Schleife delays einfüge aber in
wie fern kann eine verzögerte Initialisierung den Bus beeinflussen?????
Grüße
Markus