Schönen Feiertag allen ;-) ich hab mir soeben für meinen Code einige Sachen Überlegt. Ich möchte auf "Anfrage" von meinem PC via Bluetooth von meiner Schaltung ein Großes Datenpaket empfangen. Ich möchte ganz genau 15 Spannungen á 10 Bit senden. Das heißt ich habe ein Datenpaket von 150 Bit. Das Bluetooth Modul ist im prinzip eine serielle Verbinung, nach dem sie eingerichtet wurde, also das Modul sendet alles transparent und Kabellos durch. Also wie wenn ich ein Kabel verwenden würde. Jetzt stellt sich mir die Frage, wie realisiere ich dieses rießen Datanpaket. Habt ihr eine Ahnung bzw mir eine Hilfestellung? Hoff Ihr könnt mir helfen, Grüße Pt100
Hi >Jetzt stellt sich mir die Frage, wie realisiere ich dieses rießen >Datanpaket. Das sind im Minimalfall 30 Byte. Was ist daran riesig? MfG Spess
Naja klar aber ich habe ja Funktionen zum senden eines STRINGS. Jetzt frag ich mich, wie ich die Daten in einen String rein bekomm. Ich hab ja verschiedene 10 Bit Varaiblen in Integer drin, so kommen die von meiner Funktion des AD-Wandlers. Also wie "schieb" ich jetzt die Daten da rein? Hoffe auf Hilfe Grüße
okay, danke schonmal. Ich hab mir jetzt das mal durch den Kopf gehen lassen. Da ich die Daten auf dem PC nacher auch Seriell erhalte, muss ich diese dort auch wieder auslesen. Wenn ich jetzt AD-Werte habe und diese per UART ausgebe, dann habe ich im Zweifelsfall verschieden lange Zahlen. Ich brauch dann voranstehende NULLEN. Mit welcher Funktion kann ich diese dann einfügen, bzw muss ich die Zahl in einen String schreiben und Nullen voransetzen? Danach kann ich dann einfach alle Strings nacheinander per UART ausgeben. Die gesamten Daten teil ich mir dann auf dem PC auf. Die Frage stellt sich jetzt nur um die Nullen. Grüße Pt100
Wär echt super, wenn noch jemand eine Idee für die voranstehenden Nullen hat. Nacher soll das ein Strin sein so in der Art: 10230025035610000999.... Also JEWEILS IMMER vier Stellen für eine Spannung, damit ich nacher den String im PC auslesen kann und nach allen vier Stellen diesen wieder in einen Integer umwandle, damit ich mir die Spannungen ausrechnen kann. Gute Nacht
Printf kann Zahlen mit Festlänge und auch mit vorangestellten Nullen ausgeben. http://www.nongnu.org/avr-libc/user-manual/group__avr__stdio.html#gaa3b98c0d17b35642c0f3e4649092b9f1 Z.B. unsigned int a=5,b=10,c=115; char string[13]; sprintf(string, "%04d%04d%04d", a, b, c); Der Output in string sollte so aussehen: 000500100115 Alternativ könnte man die Zahlen auch mit Leerzeichen trennen. Das Rücklesen am PC funktioniert über scanf mit der gleichen Formatanweisung wie das Senden. char string[13]; unsigned int a,b,c; Angenommen, die empfangenen Daten stehen in string sscanf(string, "%04d%04d%04d", &a, &b, &c); Dann stehen jetzt die Zahlen wieder in a, b und c. Grüße, Peter
Pt100 schrieb: > Wär echt super, wenn noch jemand eine Idee für die voranstehenden Nullen > hat. Nacher soll das ein Strin sein so in der Art: > > 10230025035610000999.... Diese Idee ist zwar naheliegend aber nicht so gut Wenn dein PC das erste Zeichen verpasst (weil er zb nach deiner Schaltung gebootet wurde), dann empfängt er 0230025035610000999.... und das sind dann ganz andere Zahlen, obwohl der Sender immer noch dasselbe meinte. Denk mal darüber nach, welchen Vorteil wohl 1023;25;356;1000;999;.... in dieser Hinsicht hat. Mit ein bischen Flexibilität im Datenformat und definierten Fixpunkten an denen sich der Empfänger orientieren kann, kann man viele Probleme von vorne herein ausschliessen ohne dass das gleich in eine programmtechnische Schlammschlacht ausartet.
Guten Morgen, erstml besten DANKE an das was Ihr in den zwei Posts alles geschrieben habt! Hat mir auf jeden Fall weitergeholfen. Also ich werde das jetzt auch so machen! Dann kann ich auf dem PC immer bis zum Semikolon trennen. Das das dann auch Vorteile hat war mir noch nicht so klar, aber wie Ihr das geschrieben habt ist jetzt logisch. Muss ich sonst noch auf was achten? Auf jeden Fall verwende ich jetzt sprintf für die Nullen und trenne danach mit den Sonderzeichen! Besten Dank
Pt100 schrieb: > Guten Morgen, > > erstml besten DANKE an das was Ihr in den zwei Posts alles geschrieben > habt! > Hat mir auf jeden Fall weitergeholfen. > Also ich werde das jetzt auch so machen! Dann kann ich auf dem PC immer > bis zum Semikolon trennen. Das das dann auch Vorteile hat war mir noch > nicht so klar, aber wie Ihr das geschrieben habt ist jetzt logisch. > > Muss ich sonst noch auf was achten? > Auf jeden Fall verwende ich jetzt sprintf für die Nullen und trenne > danach mit den Sonderzeichen! Ähm: Du kannst alles in einem einzigen sprintf machen! Und die führenden 0-en brauchst du gar nicht mehr
1 | for( i = 0; i < 15; ++i ) { |
2 | |
3 | wert = getADCValue( i ); |
4 | |
5 | sprintf( Buffer, "%d;", wert ); |
6 | send_String( Buffer ); |
7 | }
|
8 | SendString( "\n" ); // hinten nach noch einen Zeilenvorschub |
9 | // dann hat es der Empfänger leichter, weil
|
10 | // für ihn die 15 Werte erst mal einfach nur
|
11 | // eine Eingabezeile darstellen
|
>Denk mal darüber nach, welchen Vorteil wohl > 1023;25;356;1000;999;.... >in dieser Hinsicht hat. Noch besser wäre wohl: a1023b25c356 usw. Sonst weiß man ja auch nicht, wann welche Zahl gemeint ist. Grüße, Peter
Peter Diener schrieb: >>Denk mal darüber nach, welchen Vorteil wohl > >> 1023;25;356;1000;999;.... > >>in dieser Hinsicht hat. > > Noch besser wäre wohl: > a1023b25c356 usw. > > Sonst weiß man ja auch nicht, wann welche Zahl gemeint ist. Hatte ich zuerst auch gedacht. Aber im Eröffnungsposting steht, dass der PC die Daten explizit anfordert. Ich würde diese Unterscheidung, so wie du das vorschlägst, trotzdem reinmachen. Einfach deswegen, weil es mir ein Greul ist, wenn der Empfänger Annahmen treffen muss. Im Idealfall (IMHO) 'treibt' der Sender den Empfänger mittels der Datenübertragung so, dass es zu keinen Missverständnissen kommen kann und der Empfänger nur sehr wenig annehmen muss. Erweiterbarer für die Zukunft ist es ausserdem und zudem würde sich das Tor öffnen, dass der Empfänger nur geänderte Werte übertragen muss. Aber das muss der TO entscheiden.
Also die Daten werden vom PC angefortert. Das heißt ich schicke vie Bluetooth den Code für das aktuelle Datenpaket. Danach schickt die Platine mir auf den PC einen String welcher jetzt dann so aussieht: a1023b25c356 Aber ich würde das jetzt alles in eine Zeile knallen. Also erst nach dem letzten Wert den Zeilenvorschub senden. Das sind dann alle 15 Werte, also MAXIMAL 75 Zeichen, also 600 Byte. Mit dem Bluetooth kann ich maximal 115 kBaud. Auf dem PC hab ich mir ein Programm geschrieben mittels MFC in C++. Ich denke die dortigen Funktionen find ich dann schon, damit ich immer direkt das was zwischen den Buchstaben steht ermittle. Viele Grüße
Pt100 schrieb: > Platine mir auf den PC einen String welcher jetzt dann so aussieht: > a1023b25c356 wenn du dir auf dem PC das Leben leichter machen willst, dann machst du zusätzlich noch ein Trennzeichen rein, so dass du beim Auseinanderpfriemeln des Strings auf dem PC einen Fixpunkt hast: nämlich das Trennzeichen. A1023; Jeder Wert wird also in einem Paket übertragen, welches besteht aus * einem Buchstaben, der eine Aussage darüber erlaubt welcher Wert das überhaupt ist, wo er herstammt * Dem Zahlenwert selber * Einer Terminierung (hier IMMER ;) die aussagt wo die Zahl aufhört Von diesen 'Wertpaketen' können (bei dir jetzt) maximal 15 in einer Zeile kommen. Ein komplettes Datenpaket ist also im Grunde einfach nur eine Textzeile (hört mit einem \n auf), in der mehrere Wertpakete enthalten sind. > Aber ich würde das jetzt alles in eine Zeile knallen. Also erst nach dem > letzten Wert den Zeilenvorschub senden. Das sind dann alle 15 Werte, > also MAXIMAL 75 Zeichen, also 600 Byte. Nö. 75 Zeichen sind 75 Byte. Wobei dich das auf einem PC eher weniger interessiert. Der Empfangsbuffer wird mit 512 Bytes Größe festgelegt und wenn dann anstelle der 75 Bytes in 2 Jahren mal 90 daherkommen (weil noch 5 weitere ADC Quellen dazugekommen sind), dann juckt dich das herzlich wenig. > Mit dem Bluetooth kann ich > maximal 115 kBaud. Und? Welche Zeitbeschränkungen hast du am PC? Wie schnell müssen die Werte reinkommen?
Naja auf dem PC hab ich mir das jetzt einfach so gedacht, dass ich eine Sekunde Timeout hab, also sende ich das Flag für die Anforderung und dann springt mein uC in den Interrupt wo er sich ein Arbeitsflag setzt, welches im Hauptprogramm dann die ADC-Wandlungen durführt und die daten so raushaut.
Pt100 schrieb: > Naja auf dem PC hab ich mir das jetzt einfach so gedacht, dass ich eine > Sekunde Timeout hab, also sende ich das Flag für die Anforderung und > dann springt mein uC in den Interrupt wo er sich ein Arbeitsflag setzt, > welches im Hauptprogramm dann die ADC-Wandlungen durführt und die daten > so raushaut. Ja, ist ok. 1 Sekunde ist viel Zeit. Da hast du jede Menge Zeit dir die Daten senderseitig so aufzubereiten, dass der Empfänger sie möglichst einfach auseinanderpfriemeln kann und dabei auch noch Fehlererkennung betreiben kann. Auf dem PC schreibt man sich dann noch eine Funktion, die einen beliebigen String anhand von fixen Trennzeichen in einzelne Strings aufteilt und schon hast du deine Wertpakete wieder. Im Wertpaket sagt dir der erste Buchstabe um welchen Wert es sich handelt und der Rest von diesem Teilstring kann dann zb in atoi reingestopft werden um wieder eine Zahl zu erhalten. Anhand des Kennbuchstabens dann noch die Zahl richtig verteilt (zb in ein Array) und fertig. Senderseitig ist das alles sowieso kein Problem. Wobei sich noch die Frage erhebt, was der µC sonst noch so alles machen soll. Wenn der sonst nichts zu tun hat, schadet es auch nicht, wenn der einfach ständig reihum alle ADC abfrägt und sich die gemessenen Werte zwischenspeichert. Auf Anfrage vom PC werden dann einfach die jeweils letzten Messwerte rausgesendet.
1 | ....
|
2 | |
3 | while( 1 ) { |
4 | |
5 | Value[nextADC] = readADC( nextADC ); |
6 | nextADC++; |
7 | if( nextADC == 15 ) |
8 | nextADC = 0; |
9 | |
10 | if( transmitRequested ) { |
11 | transmitRequested = FALSE; |
12 | for( i = 0; i < 15; ++i ) { |
13 | sprintf( buffer, "%c%d;", i + 'A', Value[nextADC]; |
14 | sendString( buffer ); |
15 | }
|
16 | sendString( "\r\n" ); |
17 | }
|
18 | |
19 | }
|
20 | |
21 | ....
|
22 | |
23 | |
24 | ISR( .... ) |
25 | {
|
26 | char c = UDR; |
27 | |
28 | if( c == 'V' ) // V wie 'Values' ... Werte übertragen |
29 | transmitRequested = TRUE; |
30 | }
|
das kann man dann wunderbar zb mit Hyperterminal oder einem anderen Terminalprogramm testen und so sicherstellen, dass senderseitig erst mal alles klappt ehe man dann anfängt auf dem PC ein Programm zu schreiben.
Hallo, jop, ich hab die Funktionen für die Main-Loop schon geschrieben, der uC hat da dann die Variablen, in denen er den letzten Messwert ablegt. Wenn der Interrupt das Flag setzt, das heißt, wenn der PC Daten anfordert, dann springt er uC nicht wie gewohnt in die ADC-Funktionen sonder überprüft vor der Loop das Flag, falls das gesetzt ist geht ja alles ziemlich schnell, er stellt den String zusammen und schickt den raus. Danach setzt er das Flag zurück und es kann weiter gehn. Wenn ich den String zusammenstelle reicht es im Prinzip eine sprintf Funktion oder? Ich kann ja hier beliebig viele Werte eingeben oder? Und die Sonderzeichen lassen sich ja auch so einfügen. Grüße
Pt100 schrieb: > Wenn ich den String zusammenstelle reicht es im Prinzip eine sprintf > Funktion oder? Kannst du natürlich auch machen. Nur brauchst du dann mehr Speicher für den zwischendurch entstehenden String und abhängig von deiner UART-Funktionalität brauchst du unter Umständen ein bischen mehr Zeit (wird sich aber nicht um viel reißen).
Karl heinz Buchegger schrieb: > Nur brauchst du dann mehr Speicher für den zwischendurch entstehenden > String und abhängig von deiner UART-Funktionalität brauchst du unter > Umständen ein bischen mehr Zeit (wird sich aber nicht um viel reißen). Wie meinst du brauch ich "mehr" Speicher für den String? Ich habe doch in einer Variable den Speicher für den String schon reserviert. Spielt das dann eine Rolle oder kann ich es dann auch besser lösen?
Pt100 schrieb: > Karl heinz Buchegger schrieb: >> Nur brauchst du dann mehr Speicher für den zwischendurch entstehenden >> String und abhängig von deiner UART-Funktionalität brauchst du unter >> Umständen ein bischen mehr Zeit (wird sich aber nicht um viel reißen). > > Wie meinst du brauch ich "mehr" Speicher für den String? Nun ja. Auf einem µC bist du meistens nicht so mit freiem Speicher gesegnet wie auf einem PC. In
1 | for( i = 0; i < 15; ++i ) { |
2 | |
3 | wert = getADCValue( i ); |
4 | |
5 | sprintf( Buffer, "%d;", wert ); |
6 | send_String( Buffer ); |
7 | }
|
8 | SendString( "\n" ); |
muss Buffer, das char Array welches den String aufnimmt, minimal 7 Zeichen gross sein. 4 für die Zahl ( 0 bis 1024), 1 für den Buchstaben, 1 für den Terminator und 1 für das abschliessende \0 das jeder String hat. Ist der Teilstring für einen Wert fertig, wird er sofort an die UART übergeben und übertragen und damit steht dann dasselbe 7-Character Array für den nächsten Wert zur Verwendung zur Verfügung. In
1 | sprintf( Buffer, "A%d;B%d;C%d;E%d;\n" wert[0], wert[1], wert[2], wert[3] ); |
muss Buffer aber schon 26 Zeichen gross sein (und da hab ich nur 4 Werte angenommen), denn so lang kann der komplette String maximal werden.
Okay also dann mach ich den Buffer genau sieben Zeichen lang und schick das alles sofort raus. Die Einzelnen AD-Werte liegen ja immer in einer Variable vor, sodass es egal ist wie weil ich mit dem durchwandeln bin, er nimmt einfach den zuletzt vorliegenden Wert. Dann kann ich die Variable nehmen und in den String schreiben, das braucht dann auch fast keine Zeit oder? Bis jetzt habt Ihr mir echt geholfen großes Lob und danke dafür!
Pt100 schrieb: > Dann kann ich die Variable nehmen und in den String schreiben, das > braucht dann auch fast keine Zeit oder? Im Vergleich zur reinen Übertragungszeit auf der UART ist das dazwischen (fast) alles pipifax. Die Durchlaufzeit wird im wesentlichen davon bestimmt, wie lange die physikalische Übertragung dauert und nicht davon, welche Klimmzüge du machen musst um zum String zu gelangen. Mit einer vernünftigen UART-Lib (zb der vom Peter Fleury), die das Versenden ebenfalls mittels Interrupts macht, kannst du zwischen dem Senden von 2 Zeichen einen guten Teil deiner restlichen Arbeit (wie zb Aufbereitung durch sprintf) erledigen lassen, so dass das dann überhaupt nicht mehr ins Gewicht fällt.
Okay, also Peter Fleury ist vollständig in das Programm integriert, das war schon von anfang an so geplant ;) Hab das jetzt ebenfalls auf vier Schnittstellen umgesetzt. Derzeit hab ich die Varaiblen für die ganzen Spannungen Global angelegt, damit ich diese dann immer in der Loop aktualisiere. Sobald das Flag da ist also im Interrupt gesetzt wurde reagiere ich in meiner Mainloop mit einer Funktion.
Habe gerade überlegt, wenn ich für einen AD-Wert (10 Bit) einen Integer nehm gehn mir ja sechs Bits dirrekt verloren oder? Also bei 15 ADC´s macht das dann etwas über 11 Byte "Müll" Kann ich das irgendwie umgehen?
Ich hab mich mal belesen, wenn ich einen Struct einfüge und dann die Bits seperat zuweiße. Würde ich mir dann den Platz im Prozesor sparen? Ich denke es wird nacher evtl. knapp und dann wäre es super Grüße
Pt100 schrieb: > Habe gerade überlegt, wenn ich für einen AD-Wert (10 Bit) einen Integer > nehm gehn mir ja sechs Bits dirrekt verloren oder? verloren? du meinst deine Variable hat 6Bit die nicht genutzt werden > Ich hab mich mal belesen, wenn ich einen Struct einfüge und dann die > Bits seperat zuweiße. Würde ich mir dann den Platz im Prozesor sparen? mit sowas kannst du sinnvoll sicher keinen Platz sparen. Im SRAM evl. schon aber im Programm (FLASH) würde ein aufteilen der Bits vom AD-Wandler in die Bytes im SRAM einen riesigen Aufwand darstellen. PS: schau dir erst mal deine sonsigen Variablendefinitionen an ob die nicht größer als notwendig deklariert sind. Sascha
Pt100 schrieb: > Ich hab mich mal belesen, wenn ich einen Struct einfüge und dann die > Bits seperat zuweiße. Würde ich mir dann den Platz im Prozesor sparen? Das lohnt nur dann, wenn du die paar Bytes so dringend brauchst, wie ein Verdurstender einen Schluck Wasser
Also dann doch lieber schon 16 Bit Integer nehmen, auch wenn meine 15 AD-Eingänge jeweils nur 10 Bit abliefern? Naja dann mach ich das mal so und wenn es dann doch knapp wird meld ich mich ;-) Besten Dank schonmal!
Hast du dir mal ausgerechnet, was 10 bit Auflösung überhaupt bedeutet? Meinst du nicht, dass andere Komponenten wesentlich weniger Genaugikeit zulassen? Reichen dir nicht vielleicht einfach 8 bit völlig ? Auflösung und Genauigkeit
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.