Forum: Mikrocontroller und Digitale Elektronik Integer -> Char -> USART -> Char -> Integer (Übertragungsprotokoll)


von ATMega16_Einsteiger (Gast)


Lesenswert?

Guten Tag,

ich möchte Messwerte (Integer) vom PC an der uC über USB (FT232 im 
Einsatz) senden. Zur Zeit benutze ich den USART. Ich zerlege auf dem PC 
mein Integer in die unterschiedlichen Ziffern und sende im festen 
Datenformat:

z.B. Integer 123 -> Char  "0" "1" "2" "3"

Auf dem uC interpretiere ich die "Zahl" als:

atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123

Nun kann ich sie weiterverarbeiten. Ziemlich umständlich. Hat wer einen 
einfachen Alternativansatz ?Setze es in C auf dem ATMega16 um.

Vielen Dank

von Peter II (Gast)


Lesenswert?

du kannst es dcoh einfach binär senden.

Integer 123 wird dann als "0x00 0x7b" also 2 zeichen gesendet. Du musst 
nur ein Protokoll definieren damit du den anfang und das ende der zahlen 
erkennst.

von Jobst M. (jobstens-de)


Lesenswert?

Ich finde Klartext prima. Lässt sich auch einfach debuggen. Ich verstehe 
auch gerade nicht, welches Problem Du beseitigen möchtest.


Gruß

Jobst

von W.S. (Gast)


Lesenswert?

Peter II schrieb:
> du kannst es dcoh einfach binär senden.

Jaja. Das ist die einfachste und zugleich dümmste Methode, denn sie 
enthält keinerlei Mittel, um die zwei beteiligten Rechner zu 
synchronisieren. Stell dir vor, jemand will Zahlen >255 senden. Was 
dann? Hoffen, daß nie was dazwischenkommt? Nee, irgendeine Art Protokoll 
ist schon nötig.

Aber was soll das?
"atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123"

Ich verstehe nicht den tieferen Sinn dieses langen Schriebses. 
Wahrscheinlich würde ich das sinngemäß etwa so machen und die Zahlen 
mit nem Komma voneinander separieren:

var
  L : longint;
  C : Char;

L:= 0; C:= #0;
repeat
  if CharAvailable(MyComport)
  then begin
         C:= GetTheChar(MyComport);
         if C in ['0'..'9'] then L:= L*10+(C-'0');
until (C=',') or (MyState=HaveNoLustMehr);

DoSomething(L);
GoToBed;
end.

W.S.

von Peter II (Gast)


Lesenswert?

W.S. schrieb:
>> du kannst es dcoh einfach binär senden.
> Jaja. Das ist die einfachste und zugleich dümmste Methode, denn sie
> enthält keinerlei Mittel, um die zwei beteiligten Rechner zu
> synchronisieren.

klar doch - aus dem Grund verwendet PPP oder Ehternet auch Klartext.

Text ist das dümmste was man machen kann, dann dann muss man auf beiden 
seiten wandeln denn für ein computer ist das so nicht verständlich. 
Warum sollen sich 2 Computer in der Sprache der Menschen unterhalten?

von Ingo (Gast)


Lesenswert?

Du kannst es auch per Hand umrechnen indem du von der Zahl eine 59 glaub 
ich abziehst, müsst mal gucken welchen hex Wert eine 0 hat. Da sparste 
dir zumindest das atoi.


Ingo

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

ATMega16_Einsteiger schrieb:
> z.B. Integer 123 -> Char  "0" "1" "2" "3"
>
> Auf dem uC interpretiere ich die "Zahl" als:
>
> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123

Und warum bastelst Du nicht aus den vier Zeichen einen String, den Du 
dann atoi vorwirfst?

atoi("0123") = 123 ...

von Rolf M. (rmagnus)


Lesenswert?

ATMega16_Einsteiger schrieb:
> Auf dem uC interpretiere ich die "Zahl" als:
>
> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123
>
> Nun kann ich sie weiterverarbeiten. Ziemlich umständlich.

Du kannst auch einfach atoi("0123") machen, dann kannst du dir das 
Zusammenbasteln von Hand sparen.

von Dauergast (Gast)


Lesenswert?

Peter II schrieb:
> klar doch - aus dem Grund verwendet PPP oder Ehternet auch Klartext.

Die meisten Protokolle verwenden in der Tat Klartext.

Peter II schrieb:
> Text ist das dümmste was man machen kann, dann dann muss man auf beiden
> seiten wandeln denn für ein computer ist das so nicht verständlich.

ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu 
übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob 
ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als 
binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt 
werden.

> Warum sollen sich 2 Computer in der Sprache der Menschen unterhalten?

Man kann natürlich auch ASN.1 nehmen. In den meisten Fällen ist das aber 
schlicht Overkill.

von Peter II (Gast)


Lesenswert?

Dauergast schrieb:
> Die meisten Protokolle verwenden in der Tat Klartext.

nur keine bei denen aus auf geschwindigkeit und effizienz ankommt.

Auch würde ich mich mit "meisten" sehr zurück halten, ich kenn kaum 
Protokolle außerhalb von http (inc. mail) wo etwas im klartext gemacht 
wird. ( PPP, XMODEM, ETHERNET, IP, TCP, X25, ISDN, TDS (sql-server) usw. 
)

> ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu
> übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob
> ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als
> binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt
> werden.

warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen) 
lösung sinnvoll sein?

Weil ebend der computer nicht weiss was für daten kommen definiert man 
ja ein Protokoll in diesem ist festgelgt welche Daten wie übertragen 
werden.

> Man kann natürlich auch ASN.1 nehmen. In den meisten Fällen ist das aber
> schlicht Overkill.
ASN.1 ist wirklich etwas übertrieben, ich würde es aber einem XML parser 
vorziehen wenn es schnell und resourcen schonden werden soll.

von Dauergast (Gast)


Lesenswert?

Peter II schrieb:
> warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen)
> lösung sinnvoll sein?

Wesentlich ineffizienter ist es nur, wenn Du auf beiden Seiten zufällig 
dieselbe Wortbreite, Endianität und dasselbe Alignment hast. Aber das 
ist eher selten, und noch seltener für die Zukunft vorhersehbar.

von Peter II (Gast)


Lesenswert?

Dauergast schrieb:
> Wesentlich ineffizienter ist es nur, wenn Du auf beiden Seiten zufällig
> dieselbe Wortbreite, Endianität und dasselbe Alignment hast. Aber das
> ist eher selten, und noch seltener für die Zukunft vorhersehbar.

gut dann ist es nur noch 5mal so effizent und nicht mehr 10mal effizent.

von DirkB (Gast)


Lesenswert?

ATMega16_Einsteiger schrieb:
> z.B. Integer 123 -> Char  "0" "1" "2" "3"
>
> Auf dem uC interpretiere ich die "Zahl" als:
>
> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123

"1" ist ein String. Das Zeichen wäre '1'.
Eine String ist ein Nullterminiertes char-Array.
atoi erwartet als Argument ein Nullterminiertes char-Array und kein 
einzelnes Teichen. Das klappt also nicht so, wie du es probierst.

Ansonsten kannst du von den empfangenen Zeichen einfach '0' abziehen.
1
char text[] = "0123";
2
zahl = atoi(text);
3
//oder
4
zahl = (text[0] -'0') * 1000 + (text[1] -'0') * 100 + (text[2] -'0') * 10 +(text[3] -'0');
5
//oder
6
for(i=0, zahl=0;text[i];i++)
7
  zahl = zahl * 10 + (text[i] -'0');
Wobei die letzten beiden keine Rücksicht auf Buchstaben oder 
Sonderzeichen nehmen :-(

von Rolf M. (rmagnus)


Lesenswert?

Peter II schrieb:
> Dauergast schrieb:
>> Die meisten Protokolle verwenden in der Tat Klartext.
>
> nur keine bei denen aus auf geschwindigkeit und effizienz ankommt.

Auf Applikationsebene sind im Internet so gut wie alle gängigen 
Standard-Protokolle textbasiert. Manche neueren Protokolle wie Jabber 
benutzen sogar XML.

>> ASCII-Text ist in der Tat eine der schlausten Arten, Daten zu
>> übertragen, oft sogar zu speichern. "Der" Computer "weiß" keineswegs, ob
>> ihm Zahlen in 8/16/32/... Bit Breite, mit oder ohne Vorzeichen, als
>> binäre Ganzzahl oder als Fließkomma, in Little oder Big Endian vorgelegt
>> werden.
>
> warum sollte eine ineffizienzte (mehr Platz und mehr CPU-Resourcen)
> lösung sinnvoll sein?

Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel 
einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es 
sinnvoller, diese Vorteile zu nutzen.

von nickname (Gast)


Lesenswert?

Uc: Sprintf(string,"%d",Zahl);  send-uart-s(string);
Pc: get_String(String); atoi(String);
Is zwar Ucseitig nicht Ressourcensparend aba am einfachsten!
Bessere Variante wäre mit Bitshift den integer in 2 chars umwandeln und 
pcseitg wieder zusammensetzen : char = integer <<8; usw.. ( pseudocode-> 
siehe tutorial Bitoperationen)

von Peter II (Gast)


Lesenswert?

Rolf Magnus schrieb:
> Auf Applikationsebene sind im Internet so gut wie alle gängigen
> Standard-Protokolle textbasiert. Manche neueren Protokolle wie Jabber
> benutzen sogar XML.

richtig aber hier geht es um ein übertragungsrpotokoll auf der Seriellen 
Leitung und übertragungsprotkolle sind auf den unteren schichten sind 
meist keine Text Protokolle.

> Uc: Sprintf(string,"%d",Zahl);  send-uart-s(string);
> Pc: get_String(String); atoi(String);
schon die verwendung von Sprintf macht es noch schlimmer, es gibt auch 
itoa!

Hast du mal auf einen µC die anzahl der Take für diese beiden zeilen dir 
angeschaut? Wir reden hier mindestens vom ein paar 100.

uint16_t zahl;

uc: send( Zahl, sizeof(Zahl) );
pc: Read( Zahl, sizeof(Zahl) );


bei bedarf kann man noch ein LittleEdian/Bigendian swap einbauen.

> Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel
> einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es
> sinnvoller, diese Vorteile zu nutzen.
ist schon erstaunlich das das ganze Wissen um die Verarbeitung von 
Binären daten in den letzen Jahren verloren gegangen ist. Vor 10Jahren 
hatte die Programmieren damit keine Probleme. Aber heute muss ja alles 
auf XML gemacht werden, sonst wüssten die CPUs gar nicht mehr was sie 
machen sollen.

von Anja (Gast)


Lesenswert?

Peter II schrieb:
> ist schon erstaunlich das das ganze Wissen um die Verarbeitung von
> Binären daten in den letzen Jahren verloren gegangen ist.

Da gab es auch noch Methoden wie z.B. das "sixeln" um unabhängig von 
7,e,1 oder 8,n,1 auf der seriellen übertragen zu können.

Gruß Anja

von Rolf M. (rmagnus)


Lesenswert?

Peter II schrieb:
> richtig aber hier geht es um ein übertragungsrpotokoll auf der Seriellen
> Leitung und übertragungsprotkolle sind auf den unteren schichten sind
> meist keine Text Protokolle.

Auf RS232 hat man meistens keine unteren Schichten. Wozu auch?

>> Uc: Sprintf(string,"%d",Zahl);  send-uart-s(string);
>> Pc: get_String(String); atoi(String);
> schon die verwendung von Sprintf macht es noch schlimmer, es gibt auch
> itoa!

Was macht es schlimmer? Es braucht natürlich mehr Ressourcen, aber wenn 
man die zur Verfügung hat, wird dadurch gar nichts schlimmer. Wie es 
immer so schön heißt: Man bekommt von Atmel kein Geld für nicht 
benutzten Speicher zurück. Und mit sprintf hab ich den Vorteil, daß ich 
auch gleich eine komplette Zeile auf einmal erzeugen kann, statt die aus 
lauter Einzelwerten mühevoll zusammenzubasteln.
Wenn die Ressourcen nicht verfügbar sind, braucht man natürlich eine 
andere Lösung. Aber programmiertechnisch ist sprintf die einfachste 
Möglichkeit.

> Hast du mal auf einen µC die anzahl der Take für diese beiden zeilen dir
> angeschaut? Wir reden hier mindestens vom ein paar 100.

Und? Unmittelbar danach werden wahrscheinlich Tausende von Taktzyklen in 
einer Schleife verbraten, die nix andres tut, als darauf zu warten, daß 
der nächste Programmzyklus losgeht.

> uint16_t zahl;
>
> uc: send( Zahl, sizeof(Zahl) );
> pc: Read( Zahl, sizeof(Zahl) );
>
>
> bei bedarf kann man noch ein LittleEdian/Bigendian swap einbauen.

Um sowas braucht man sich bei Text nicht kümmern. Auch nicht um ein 
Protokoll, das es schafft, nach Unterbrechungen wieder den Anfang des 
nächsten Datenpakets zu finden. Das ergibt sich bei zeilenweiser 
Textübertragung quasi von selbst.

>> Es ist programmiertechnisch die einfachste. Außerdem läßt es sich viel
>> einfacher debuggen. Wenn der Overhead nicht besonders stört, ist es
>> sinnvoller, diese Vorteile zu nutzen.
> ist schon erstaunlich das das ganze Wissen um die Verarbeitung von
> Binären daten in den letzen Jahren verloren gegangen ist. Vor 10Jahren
> hatte die Programmieren damit keine Probleme.

Ich schrieb nicht, daß es ein Problem ist, sondern nur, daß es 
umständlicher ist.

> Aber heute muss ja alles auf XML gemacht werden, sonst wüssten die CPUs
> gar nicht mehr was sie machen sollen.

XML finde ich dann auch etwas übertrieben. Wenn man sich Sachen wie 
xmlrpc anschaut, hat man das Gefühl, daß es die Erfinder darauf angelegt 
haben, den Overhead so groß wie nur irgend möglich zu machen.

von Einsteiger_ATMega16 (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

Danke für die Antworten. Habe mein Programm angehängt. Ich übergebe vom 
PC aus:


0100001234 => Pin 0 Status 1 (High) Verzögerung 1234 us etc.

Also:
01000012341100001234210000123431000012344100001234

für einen Vorgang. (Ich habe am Controller 5 Kanäle nach Außen geführt.

Mein Problem:
Die Pins werden richtig geschaltet. Die Verzögerung in us stimmt nicht 
(mit Oszilloskop überprüft). Trage ich in die Delayfunktion einen festen 
Wert selber ein ..also nicht über die Variable Time[n], dann stimmen die 
Zeiten.

Hat wer Anregungen wo ich mit der Fehlersuche beginnen kann. Ich suche 
schon etwas länger. Habe mir alles Ausgeben lassen, die Zeichen werden 
scheinbar richtig übertragen.

Danke

von Marcus P. (marc2100)


Lesenswert?

Hi,
ich habe es zwar noch nicht selbst versucht, aber laut dem 
AVR-GCC-Tutorial
kann man dort keine Variablen einsetzen.

von Karl H. (kbuchegg)


Lesenswert?

ATMega16_Einsteiger schrieb:

> z.B. Integer 123 -> Char  "0" "1" "2" "3"
>
> Auf dem uC interpretiere ich die "Zahl" als:
>
> atoi(0)* 1000 + atoi(1) * 100 + atoi(2) * 10 + 1* atoi(3) = 123
>
> Nun kann ich sie weiterverarbeiten. Ziemlich umständlich. Hat wer einen
> einfachen Alternativansatz ?Setze es in C auf dem ATMega16 um.


Marcus hat ja schon darauf hingewiesen, dass du bei _delay_us keine 
Variable verwenden kannst.
Das heißt: Du kannst schon. Nur stimmen die Zeiten nicht.

Zu deiner ursprünglichen Frage.

Wenn du das hier
1
      ....
2
      for (j = k;j<k+8;j++)
3
      {
4
        Time[j] = usart_receive_char();
5
      };
6
      ....
7
8
      weiterer Code mit vielen Hilfsvariablen und einer
9
      Wahnsinnsmultiplikation, die letzten Endes dafür sorgt, dass
10
      in Time_us_ die richtige Zahl entsteht.

so schreibst
1
      ....
2
      Time_us_[i] = 0;
3
4
      for (j = 0; j < 8; j++)     // das k braucht kein Mensch da drinnen
5
      {
6
        Time_us_[i] = 10 * Time_us_[i] + usart_receive_char() - '0';
7
      }
8
      ....

hast du an dieser Stelle bereits alles beisammen:
Die Umrechnung von Zeichen in einen echten Integer (das was bei dir die 
Funktion char_to_int gemacht hat) UND die Aufsummierung zur 
vollständigen Zahl (das was deine Multiplikationen mit den 
Hilfsvariablen gemacht haben).

OK, nicht ganz. Deine Hilfsfunktion char_to_int hat noch Fehlerprüfung 
gemacht. So gesehen wäre der 100% Ersatz
1
int char_to_int( char c )
2
{
3
  if( c >= '0' && c <= '9' )
4
    return c - '0';
5
6
  return 0;
7
}
8
...
9
...
10
11
      Time_us_[i] = 0;
12
13
      for (j = 0; j < 8; j++)     // das k braucht kein Mensch da drinnen
14
      {
15
        Time_us_[i] = 10 * Time_us_[i] +  char_to_int( usart_receive_char() );
16
      }
17
      ....

von Rolf M. (rmagnus)


Lesenswert?

Einsteiger_ATMega16 schrieb:
> Mein Problem:
> Die Pins werden richtig geschaltet. Die Verzögerung in us stimmt nicht
> (mit Oszilloskop überprüft). Trage ich in die Delayfunktion einen festen
> Wert selber ein ..also nicht über die Variable Time[n], dann stimmen die
> Zeiten.

Du hast also weder die Doku der avr-libc, noch die Warnung des Compilers 
gelesen. Solltest du mal tun.

von Einsteiger_ATMega16 (Gast)


Lesenswert?

Ich habe keine Warnung erhalten. Die avr-libc habe ich echt nicht 
gelesen. Jedenfalls bin ich bei der Delay Funktion nicht drüber 
gestolpert. Sorry.

Ich habe die Funktion:

void pause(int zeit)
{
 int i;
 for (i = 0;i<zeit;i++)
  { _delay_us(1);}
};

nun genommen, bekomme aber immernoch falsche Zeiten. Hat wer eine Idee?

Danke

von Karl H. (kbuchegg)


Lesenswert?

Einsteiger_ATMega16 schrieb:

> Ich habe die Funktion:
>
> void pause(int zeit)
> {
>  int i;
>  for (i = 0;i<zeit;i++)
>   { _delay_us(1);}
> };
>
> nun genommen, bekomme aber immernoch falsche Zeiten. Hat wer eine Idee?

jetzt läufst du in ein anderes Problem rein.

In einem Programm ist es ja nicht so, dass nur ein _delay_us Zeit 
verbraucht, sondern auch der Rest des Programmes. Solange die _delay_us 
Zeiten groß gegenüber dem Rest sind, spielt das keine allzugroße Rolle.

Hier aber landest du mit 1us schon in Zeitbereichen, in denen die 
komplette Schleifensteuerung zeitlich gesehen in einer ähnlichen 
Größenordnung liegt, bzw. je nach Taktfrequenz sogar darüber.

d.h dein _delay_us(1) verbraucht schon 1 µs. Aber die for-Schleife 
drumherum verbraucht nochmal oder gar noch mehr Zeit als diese 1us.

Und deshalb stimmen dann die Zeiten nicht.


Ist wie beim Fliegen. Der Flug München-Berlin dauert 50 Minuten. Kann 
man deswegen sagen, du kannst in 50 Minuten in Berlin sein? Nein, kann 
man nicht. Denn du musst erst mal zu Flughafen fahren, musst dort eine 
gewisse Zeit vorher dort sein. Musst das Checkin-Procedere über dich 
ergehen lassen, etc. etc. Summa summarum brauchst du daher für einen 50 
Minuten Flug reale 4 Stunden.


Vielliecht verstehst du jetzt schön langsam, warum hier bei Wartezeiten 
ala _delay_ms bzw _delay_us alle die Hände über dem Kopf 
zusammenschlagen. Wenn die Zeiten exakt sein sollen, bzw. länger sein 
sollen, ist das alles nicht zu gebrauchen. _delay_xx sieht zwar auf den 
ersten Blick super einfach aus, ist es aber nicht. Wenn die tatsächliche 
Wartezeit auch etwas länger sein darf UND vor allen Dingen, wenn es 
nicht zu lange ist (Millisekunden Bereich), kann man es benutzen. Aber 
für alles andere ist das nicht brauchbar. Da führt kein Weg an der 
Benutzung eines Timers vorbei.

von W.S. (Gast)


Lesenswert?

Peter der Großartige schrieb:
> Text ist das dümmste was man machen kann, dann dann muss man auf beiden
> seiten wandeln

Du schriebest Unsinn. Versuch doch bitte mal, zuerst zu denken und dann 
zu schreiben.


Und unser Einsteiger_ATMega16 schrieb:
> Ich übergebe vom PC aus:
>
> 0100001234 => Pin 0 Status 1 (High) Verzögerung 1234 us etc.
>
> Also:
> 01000012341100001234210000123431000012344100001234
>
> für einen Vorgang.

Oh du Einsteiger, mach es lieber anders. Das was du da gepostet hast, 
ist schlecht, weil es einfach extrem unflexibel ist. Du bist auf der 
"Denkschiene" der festen Blöcke, wo alle Positionen festgelegt und starr 
sind und alle Kommandos nicht atomar, sondern zusammengesetzt sind. 
Jaja, man kann zwar so leben, aber besser ist es, nur atomare Kommandos 
zu benutzen. Das sind welche, die nur 1 Information transportieren.

Ich geb dir mal ein Beispiel. Nehmen wir an, du brauchst im Moment 3 
verschiedene Kommandos:
- Pin High setzen
- Pin Low setzen
- Verzögerungszeit vereinbaren
Dann wäre es ne günstige Sache, zuerst nen numerischen Wert (also ne 
Zahl) zu schicken und dann das atomare Kommando, also eines, das 
wirklich nur 1 Sache bewerkstelligt.
Beispiel:
(V setzt die Verzögerungszeit, L setzt auf Low, H setzt auf High)
1234V1H2H34H99V4L
Bedeutung:
1234V  setzt die Verzögerungszeit auf 1234 us
1H     setzt Pin 1 auf High
2H     setzt Pin 2 auf High
34H    setzt Pin 34 auf High
99V    setzt die Verzögerungszeit auf 99 us
4L     setzt Pin 4 auf Low

Auf diese Weise kannst du formatfrei ohne führende Nullen senden, mit 
jedem Buchstaben synchronisiert sich der Kommandostrom selbst und du 
kannst jederzeit noch andere Kommandos erfinden, ohne daß es die bereits 
bestehenden Kommandos stört.

Mit deinem o.g. Block
01000012341100001234210000123431000012344100001234
bist du längst nicht so flexibel.

W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:

> Auf diese Weise kannst du formatfrei ohne führende Nullen senden, mit
> jedem Buchstaben synchronisiert sich der Kommandostrom selbst und du
> kannst jederzeit noch andere Kommandos erfinden, ohne daß es die bereits
> bestehenden Kommandos stört.

Und ... auch nicht ganz unwichtig:
Du brauchst nur das Senden, was sich auch tatsächlich verändert.

Womit dann auch dem 'Nicht Text' Argument mehr oder weniger der Boden 
unter den Füssen weggezogen wird.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.