Hallo,
ich sitze gerade an einem Projekt und steht vor dem Problem meine
Konfiguration zu verwalten.
Bei dem Projekt handelt es sich um eine programmierbare Relaiskarte für
meine Wohnzimmerwand.
Ich möchte mich hier ansich nicht über die Relaiskarte unterhalten
sondern nur über die Software.
Es sind derzeit 8 Ausgänge die über eine Fernbedienung angesteuert
werden. Hier sollen die Tasten aber programmiert werden ähnlich der
Harmony von Logitech.
So kann ich also definieren wenn ich die Taste 1(DVD schauen) drücke das
dann die ersten 3 Ausgänge geschaltet werden.
TV -> AN
AV -> AN
DVD -> AN
Der Rest der Ports soll entweder abgeschaltet oder unberücksichtigt
bleiben.
Die Schaltung steht soweit, empfangen der IR-Signale und die UART
(Senden/Empfangen) ebenfalls.
Das System wird am Computer angeschlossen. Nun kann ich eine neue Taste
definieren. Drücke ich diese wird sie auf dem PC empfangen in Form von:
1
R:<Protokoll>:<Adresse>:<Command>;
Die Taste bekommt einen Namen geben wie oben geschrieben "DVD schauen"
Dieser Name steht derzeit nur innerhalb der Konfiguration zur Verfügung.
Später evtl. auch auf einem Display.
Jetzt kann ich noch definieren welchen Zustand die 8 Ausgänge einnehmen
sollten:
1
0=OFF/1=ON/-=unberücksichtigt
Die Taste ist jetzt in der Konfigurationssoftware definiert und soll auf
den Controller übertragen werden. Derzeit übertrage ich sie so:
Die Zeilen haben immer eine Feste Länge.
Bis hier funktioniert es auch schon. Nun soll natürlich die
Konfiguration auch irgendwie im Controller abgelegt werden. da würde
sich ja nun der EEPROM anbieten. Aufgebaut ist es mit einem Mega8 also
stehen mir 512Byte zur Verfügung. Eine Tastenzeile hat 40 Zeichen
512/40=12 Somit könnte ich 12 Tasten speichern. Das ist mir eigentlich
schon viel zu wenig. Denn Jeden Ausgang einzeln würde ja bedeuten das
ich schon 8 von 12 belegt hätte und somit nur noch 4 für Kombinationen
zur Verfügung hätte.
1. Die Frage ist erst einmal nach einer Möglichkeit genug Informationen
speichern zu können. Ich könnte zwar die ":" weg lassen, da ich eine
feste Länge habe aber das bringt mich ja auch nicht wirklich viel
weiter.
Wäre es sinnvoll einen kleinen EEPROM anzusteuern mit mehr Speicher oder
lieber eine Kleine SD-Karte? Eventuell ein ganz anderer Ansatz?
Dazu kommt das die Datenspeicherung natürlich kosten technisch nicht den
Rest des Projektes übertreffen soll. Schaltung liegt derzeit bei rund 4€
ohne Relais.
2. So lange bin ich noch nicht bei den Mikrocontrollern, habe also noch
ein wenig nachzuholen gerade in der Sprache C. Bin im Bereich
Pascal/Delphi eher tätig.
Es wäre dann noch zu klären wie man es am ehesten umsetzt die Daten zur
Laufzeit zu lesen. Ansatz aus meiner Erfahrung: Ich habe eine definierte
Länge somit müsste ich den "Speicher" nach der Zeichenkette
"<Protokoll>:<Adresse>:<Command>" durchsuchen und wenn diese passt die
Zeile laden und die Ports setzen. Diese stehen ja auch immer an einer
bestimmten Stelle vom Offset entfernt. Ich könnte es natürlich auch
alles direkt im Programm definieren aber da geht mir echt die
Flexibilität flöten die ich gerne hätte.
Mal eine Andere Konfiguration schnell ändern, die Fernbedienung
austauschen, andere Tasten nutzen, es kommt ein Gerät hinzu, ein Gerät
wird entfernt. Klar kommt das meiste eher selten vor aber es kann ja
schon einmal vorkommen. Auch wenn für so etwas fürs Wohnzimmer mit 8
Ports schon eine Menge ist, wäre es ja auch nicht auszuschließen das
ganze über Schieberegister zu erweitern. Kleine Gimmicks mit
irgendwelchen Lampen fürs Ambiente z.B. Oder ganz banal eine
Urlaubssteuerung. Ich kenne heute noch Leute die irgendwelche
Gerätschaften per Zeitsteuerung Schalten um den Schein zu erwecken als
wären sie noch da…
Natürlich muss ich auch zugeben das ich mich eventuell ein wenig damit
übernehme aber da muss ich nun durch :) Hoffe hier auch tatkräftige
Unterstützung und Nachsicht wenn ich etwas nicht gleich kapiere oder es
durch Delphi oder aber auch den PC anders gewohnt bin es umzusetzen.
Das Auslesen der gesamten Konfiguration wollte sich in einem Block
setzen:
1
PC->µC: READ_CONF;
2
µC->PC: BEGIN_CONF;
3
C:DVD Schauen:02:1234:0001:11100-00;
4
C:TV :02:1234:0002:10000-00;
5
C:AV :02:1234:0003:01000-00;
6
C:Konsole :02:1234:0002:00100-00;
7
END_CONF;
Es soll zudem noch ein wenig Speicher über bleiben um eventuell später
eine Uhr mit einzubauen, Sleep Timer, Display und nen WakeUp also
Zeitgesteuert Ports schalten und USB…
Das ist aber nicht primär. Ggf. kommt dann noch ein größerer Controller
ran. Erst sollte aber das Minimum funktionieren.
Kann mir jemand helfen hier eine akzeptable Lösung zu finden und hat
evtl. auch noch etwas Nachsicht mit meinen C-Kenntnissen?
Gruß
Daniel
> Wäre es sinnvoll einen kleinen EEPROM anzusteuern mit mehr Speicher> oder lieber eine Kleine SD-Karte? Eventuell ein ganz anderer Ansatz?
Vielleicht hab ich das ja auch missverstanden. Aber du musst ja nicht
deine Konfiguration im Klartext, so wie du sie vom PC bekommst
speichern. Weder im EEPROM noch im Arbeitsspeicher, mit der der Mega
dann im Endeffekt die Tasten auswertet.
Du hast 8 Ausgänge. Da bieten sich schon mal die 8 Bits eines Bytes als
'Speicher' für jeweils einen Relais-Zustand an.
Genauso wie das hier
Bis auf den Namen, reicht es doch, wenn der Mega aus der
Tasteninformation eine Zahl von 0 bis n macht, mit dieser Zahl dann in
ein Array geht und sich aus dem Array 2 Bytes rausholt, in denen
bitmässig codiert ist, welches Relais zu setzen bzw. rückzusetzen sind
und dann genau diese Ausgänge schaltet.
So ganz klar ist mir nicht, was da jetzt das Problem ist. Aber mir
scheint du speicherst dir viel zu viele nutzlose Information auf dem
Mega in Klartext-Form.
Guten morgen,
naja bei den Ausgängen habe ich ja 3 Zustände OFF/ON/Status beibehalten.
Beispiel: Ich möchte DVD schauen und drücke die Taste 1. Ich habe vorher
aber das Licht angeschaltet welches auf Port 5 und 6 liegt. Diese darf
ich also nicht berühren. Wenn das Licht an ist, soll es an bleiben und
wenn es ausgeschaltet ist dann soll es auch ausgeschaltet bleiben.
Ich glaube es ist ein Verständnisproblem.
Wenn ich die IR Daten im original Speicher werden 5 Bytes genutzt
anstatt 10 aber selbst das bringt mich ja auch nicht so weit das ich n
Möglichkeiten speichern kann.
Zudem wollte ich nicht den ganzen kram hin und her Konvertieren. Mag
sein das ich da vielleicht noch defiziete habe weil ich mich um so etwas
nie kümmern musste.
Daniel schrieb:> Guten morgen,>> naja bei den Ausgängen habe ich ja 3 Zustände OFF/ON/Status beibehalten.
Deswegen ja auch 2 Bytes.
ON_Byte: In dem Byte besagt ein 1 Bit, dass das zugehörige Relais auf
ein zu schalten ist.
OFF_Byte: Im diesem Byte besagt ein 1 Bit, dass das zugehörige Relais
auf aus zu schalten ist.
Ein 0 Bit in beiden Bytes besagt: lass dieses Relais in Ruhe.
Wenn du die 8 Relais an einem Port beisammen hast, dann geht das
schalten aller 8 Relais in einem Aufwasch dann ganz einfach
1
Relaisport=(Relaisport|ON_Byte)&(~OFF_Byte);
fertig. Alle 8 Relais werden laut Vorgabe im ON_Byte bzw. OFF_Byte
geschaltet.
Ist im ON_Byte ein 1 Bit wird der AUsgang auf 1 geschaltet. Ist im
OFF_Byte ein 1 Bit, wird das Relais ausgeschaltet. Ist in beiden ein 0
Bit dann verändert dieser eine Ausgang seinen Zustand nicht.
Wie du das ganze über die UART überträgst, ist damit ja nicht gesagt.
Lass ruhig die Textübertragung. Dagagen hab ich sicher nichts
einzuwenden. Aber speichern musst du das ganze nicht als Text, wenn du
mit 2 Bytes dieselbe Information genausogut speichern kannst. Dann muss
eben der Empfangscode, der das ganze dann im EEPOM speichert den Text
auswerten und die beiden Bytes zurechtbasteln.
Darum gehts mir. Ich hatte in deinem Eröffnungsposting den Eindruck,
dass dir dieser letzte Punkt nicht so recht klar ist.
> Zudem wollte ich nicht den ganzen kram hin und her Konvertieren
Ähm. Du musst diesen Text aber so und so irgendwann mal auswerten. Ob du
den Text jetzt beim Drücken einer Taste auseinanderklamüserst um zu
sehen, welches Relais wie zu schalten ist, oder ob du den prinzipiell
identischen Code nach dem Erhalt des Konfigurationstextes über die UART
laufen lässt und das Ergebnis davon in einer Form abspeicherst, so dass
sie
a) weniger Platz braucht
b) beim Tastendruck dann trivial auszuwerten ist
ist doch gehupft wie gesprungen. Den Text analysieren bleibt dir so und
so nicht erspart. Der einzige Unterschied besteht darin, wann genau
diese Analyse stattfindet: Nachdem der Konfigurationsstring übertragen
wurde ODER nachdem ein Tastendruck festgestellt wurde.
Und seien wir uns mal ehrlich. So kompliziert ist die Analyse eines
Strings "11100-00" dann auch wieder nicht
Fertig. Das schreibt sich schneller als es sich textuell erklärt.
Für die Speicherung der Information zu einer Taste noch ein schönes
struct gebaut
1
#define MAX_KEY_NAME_LEN 20
2
3
structkeyInfo_
4
{
5
charname[MAX_KEY_NAME_LEN];
6
uint8_tkeyCode;
7
uint8_tinfoOn;
8
uint8_tinfoOff;
9
};
daraus dann ein Array für alle Tasten, ein entsprechender Code, der aus
den Informationen von der Fernsteuerung einen Tastencode errechnet und
die ganze Sache ist soweit abgesteckt, dass man es erfolgversprechend
zum laufen kriegt.
pro Taste 23 Byte, macht bei 512 Byte 22 Tasten. Wenn das zu wenig ist,
dann bleibt nur noch die Namenslänge abzuspecken. Kommt man anstelle von
19 Zeichen auch mit 9 Zeichen für den Namen aus, dann sind es schon 39
Tasten, die ins 512-Byte EEPROM passen. Und das ist dann ja doch schon
eine Menge Holz auf einer Fernbedienung. Wenn man es ein wenig geschickt
anstellt, kann man den keyCode auch noch einsparen, indem man direkt aus
den Informationen, die man von der Fernbedienung kriegt, einen
Arrayindex errechnet, und wir sind bei 42 Tasten maximal.
Jetzt hat es in meinem Hirn scheinbar auch klick gemacht.
Wenn ich das Obige Beispiel aufgreife, nur zum Verständnis:
11100-00 würde ON_Byte = E0 und OFF_Byte = 1B werden, so ist das doch
gemeint oder?
Das würde bedeuten ich hätte pro Datensatz 6Byte gespart. Wenn ich nun
vom IRMP das Protokoll(1Byte), Adresse(2Byte) und Command(2Byte) nutze
habe ich wirklich einiges gespart. Also 7Byte für IR+Ports und dann ein
paar für den Namen.
Wenn ich für den Namen dann 17 Zeichen lasse komme ich auf 21
Datensätze.
Sind schon einmal 9 mehr aber irgendwie noch zu wenig. Wenn ich die 8
Ports einzeln schalte bleiben noch 13. Eine Taste für Alles aus, bin ich
bei 12.
Mein Kopf sagt mir das sollte bei weitem ausreichen. Mein Herz möchte
gerne mehr, gerade wenn für Erweiterungen noch Platz sein soll, z.B.
weitere 8 Ports für ein Licht Spiel... Ist aber denke ich erst einmal
Nebensache.
Ich brauche also nun eine Funktion die mit aus den 8 Zeichen jeweils das
On und das OFF-Byte erzeugt. Zudem eine weitere Funktion die Zeichen in
uint8_t und uint16_t wandelt. Natürlich noch eine die mir einen
Substring aus dem String herausholt.
Ich merke schon die Defizite wenn man es nur gewohnt ist auf einem PC zu
programmieren. Das fällt einem wesentlich leichter, zumal C nicht gerade
zu meinem Sprachgebrauch gehört. Hätte damals was anständiges lernen
sollen ;)
Korrigiert mich wenn ich hier falsch denke, ist alles Neuland für mich.
Bleibt noch die Frage wie ich das am besten im EEPROM suche.
Eine Taste wird gedrückt. Es wird mit das Protokoll, Adresse und Command
übergeben.
Protokoll ist 02; Adresse BF40; Command 0002.
Nun gehe ich an die erste Adresse + 17Bytes im EEPROM und prüfe die
ersten 5Bytes. Passen diese lese ich die nachfolgenden 2Bytes aus zum
setzen der Ports. Sollte das nicht passen gehe ich weitere 24Bytes
weiter und Prüfe wieder 5Bytes bis ich etwas passendes gefunden habe
oder ins leere laufe.
Ich habe gelesen das der Zugriff auf den EEPROM relativ langsam ist und
eine Suche innerhalb auch nicht gerade das beste sein soll. Ist das
überhaupt dann performant so vorzugehen?
Mein erstes Projekt war ein Belichtungstimer. der ist dagegen ja echt
ein Kinderspiel...
Da war ich wohl zu langsam und es beantwortet sich schon etwas.
Das mit dem KeyCode der Fernbedienung ist mir allerdings noch nicht so
ganz klar. Ich nutze das IRMP. Protokoll könnte ich wohl raus lassen.
Bisher haben alle meine Fernbedienungen das NEC Protokoll aber auf die
Adresse würde ich schon gerne mit achten. Ich habe jetzt die Länge siehe
oben vom Namen etwas kürzer aber dafür Protokoll, Adresse und Command
mit drin.
Daniel schrieb:> Jetzt hat es in meinem Hirn scheinbar auch klick gemacht.>> Wenn ich das Obige Beispiel aufgreife, nur zum Verständnis:> 11100-00 würde ON_Byte = E0 und OFF_Byte = 1B werden, so ist das doch> gemeint oder?
Mal sehen. In 11100-00 ist codiert
On 11100000
Off 00011011
Also: 0xE0 bzw. 1B. Jep. Stimmt.
> Das würde bedeuten ich hätte pro Datensatz 6Byte gespart. Wenn ich nun> vom IRMP das Protokoll(1Byte),
Brauchst du das wirklich?
Wenn die Fernsteuerung erst mal steht, ändert sich diese Information ja
nicht.
Eine Fernsteuerung sendet immer mit einem Protokoll. Und zwar immer mit
derselben.
Eine Phillips Fernsteuerung benutz ein anderes Protokoll als eine von
Samsung. Und die wieder ein anderes Protokoll als eine Fernsteuerung von
NEC. Aber derselbe Klotz, den du in der Hand hältst benutzt immer das
gleiche Protokoll.
> Adresse(2Byte) und Command(2Byte) nutze
Ach da würde ich mir mal ansehen, in welchem Zahlenbereich sich da die
Werte bei deiner konkreten Fernbedienung bewegen. Da geht sicher was. 2
Byte pro Teilbereich sind viel Holz. Adresse ist normalerweise das
'Gerät'. Hast du wirklich 65535 unterschiedliche Geräte? Oder sind es
konzeptionell dann doch eher maximal 4 (also 2 Bit anstelle von 2 Byte).
Hast du wirklich 65536 unterschiedliche Kommandos oder bewegt sich diese
Zahl dann doch eher im Zahlenraum 0 bis 127? Oder gar 0 bis 63, was
vorteilhaft wäre, dann das wären dann nur 6 Bit. Zusammen mit den 2 BIt
von der Geräteadresse macht das wieder 8 Bit und das wäre dann perfekt
um in einem einzelnen uint8_t zusammengefasst zu werden. Konzeptionell
maximal 4 Geräte mit jeweils 64 unterschiedlichen Kommandos - das sollte
auch den verwöhntesten Ansprüchen der nächsten Jahre mehr als genügen.
Zur Not muss man eben die einzelnen Bits eindeutig machen. Das kann man
aber erst sagen, wenn man sich mal angesehen hat, was deine
Fernbedienung eigentlich wirklich konkret liefert, wenn man eine Taste
(jede Taste) mal drückt und sich ansieht, was da daher kommt.
> Mein Kopf sagt mir das sollte bei weitem ausreichen. Mein Herz möchte> gerne mehr, gerade wenn für Erweiterungen noch Platz sein soll, z.B.> weitere 8 Ports für ein Licht Spiel... Ist aber denke ich erst einmal> Nebensache.
Es gibt ja immer noch Tastenkombinationen.
Denk an die alten Taschenrechner. Da gibt es eben eine Taste, die in die
zweite Bedieneben schaltet. Aus der Tastenfunktion x^2 wird so mal ganz
schnell sqrt(x). Und aus sin(x) wird dann sin-1(x), aus exp(x) wird ein
ln(x), einfach indem man vorher die Taste INV drückt (oder wie auch
immer die auf deinem Taschenrechner heißt). Spricht ja nichts dagegen,
dass du eine Taste 'Lichtprogramm' hast, die du drückst, dann noch eine
Zahlentaste 0 bis 9 hinterher und du hast aus 10 Lichtprogrammen eines
ausgewählt, obwohl die Tasten 0 bis 9 eigentlich eine ganz andere
Bedeutung haben (zb Einzelrelaisansteuerung)
Du denkst mir da zu eindimensional. Sieh dich in deiner Umgebung um. Man
kann viel lernen, indem man beobachtet, wie andere Dinge machen. Und
plötzlich geht einem dann oft sogar ein Licht auf, WARUM die das genau
so gemacht haben.
> Nun gehe ich an die erste Adresse + 17Bytes im EEPROM> und prüfe die ersten 5Bytes. Passen diese lese ich die> nachfolgenden 2Bytes aus zum setzen der Ports. Sollte das> nicht passen gehe ich weitere 24Bytes weiter und Prüfe wieder> 5Bytes bis ich etwas passendes gefunden habe oder ins leere laufe.
Machs doch nicht so komplizert.
Was interessieren dich da Bytezahlen?
Wenn ein Benutzer eine Taste drückt, reicht es, wenn die Schaltung ein
paar Hunderstel Sekunden später reagiert. Du hast alle Zeit der Welt.
Für einen Menschen ist das immer noch praktisch 'sofort'.
> Bleibt noch die Frage wie ich das am besten im EEPROM suche
Indem du dir einen Datensatz nach dem anderen ins SRAM holst (daher auch
der struct) und dann vergleichst
1
uint8_tkeyInfoSizeEEMEM=0;
2
structkeyInfo_eemem_KeyDesc[22]EEMEM;
3
4
5
uint8_tnrKeysInEEPROM;// wieviele sind befüllt? (Wird bei Programmstart aus dem EEPROM geholt)
Karl Heinz Buchegger schrieb:> Du denkst mir da zu eindimensional. Sieh dich in deiner Umgebung um. Man> kann viel lernen, indem man beobachtet, wie andere Dinge machen. Und> plötzlich geht einem dann oft sogar ein Licht auf, WARUM die das genau> so gemacht haben.
Das stimmt leider...
Zum Speichern der IR-Daten. Natürlich habe ich nicht so viele Commandos
und auch nicht so viele Geräte. Ich habe aber daheim eine RGB LED Kette.
Diese reagiert z.B. auf die Fernbedienung von sich selbst, auf die
meines Verstärkers und die meines Receivers. Sie wird also sicher nur
das Commando auswerten. Ich müsste also nun im Source Protokoll und
Gerät festlegen. Oder aber auch im EEPROM damit ich mal die
Fernbedienung tauschen kann. Das ist mir wichtig. Es werden hier 2
Schaltungen gebaut. Eine für einen Kollegen und eine für mich. Ich würde
him nun ungerne vorschreiben was er für eine Fernbedienung zu nutzen
hat.
Dann wäre ich dafür damit ich da relativ flexibel bin diese Daten im
EEPROM ebenfalls abzulegen. Einmal das Protokoll und das Gerät. Diese
aber eben separat und nicht mit im Struct der IR-Codes. Damit habe ich
da zumindest die Freiheit auch mal die Fernbedienung zu ändern.
Bin gerade auf der Arbeit und kann natürlich nicht nachsehen was diese
Fernbedienung so alles aufgibt. es ist von meinem TV, die ich derzeit
angeschlossen habe. Da soll natürlich mal eine eigene hin.
Der Ansatz mit der Doppelbelegung ist nicht schlecht aber dann muss ich
natürlich hier am Source so abändern dass dann neben Den Ports auch eine
Art Shift Funktion zur Verfügung steht. Die Fernbedienung die ich nutzen
möchte später hat ca. 40 Tasten und ist von meinem alten AMP. Da brauch
man nicht unbedingt eine Shift Funktion. Tasten wären zu genüge
vorhanden.
Wäre allerdings noch das Auslesen auf dem EEPROM.
> Ich habe gelesen das der Zugriff auf den EEPROM relativ langsam ist
Langsam ist relativ.
Für einen µC ist es langsam. Für einen Menschen ist es immer noch
schnell.
Denn aus Sicht eines µC sind wir
schnarch-langsame-super-zeitlupen-Säcke.
Und wenn es dann tatsächlich zu langsam ist, dann gibt es auch dann noch
Mittel und Wege :-)
Zb mit einem Index im Speicher. zb. durch aufsteigendes Sortieren und
binäre Suche. Zb durch Hashing. zb durch ....
Aber erst mal: implementier es so, dass es leicht zu lesen und zu
verstehen ist. Und DANN siehst du dir an, ob es zu langsam im Gebrauch
ist. Optimier nicht, solange nicht feststeht, dass du überhaupt
optimieren musst. Erst mal ist es viel wichtiger ein korrektes Programm
zu haben. Ein korrektes Programm welches zu langsam ist, ist immer noch
nützlich. Ein schnelles Programm, welches nicht korrekt funktioniert ist
hingegen zu gar nichts zu gebrauchen.
Du bist ja verdammt schnell, da komm ich mit den Fragestellungen ja gar
nicht mehr nach und meist sind die dann schon beantwortet. :)
Die Hilfe ist mal echt klasse auch wenn ich mir dabei gerade sehr klein
vorkomme.
Kann den Feierabend ja schon nicht mehr abwarten. :)
Werde das bis zum Feierabend auf mich wirken lassen und dann versuch ich
es so umzusetzen.
Ich bedanke mich schon einmal vorab für die große Hilfe die du geleistet
hast und auch die Geduld.
Klasse Forum :)
Hab mir mal schnell in C das ganze kopiert und getestet.
In der Convert Funktion ist ein kleiner Fehler drin. Nachdem die 8 Ports
gelesen sind wird erneut eine Bit Verschiebung gemacht wodurch das erste
Bit weg fällt.
Ist mit C darum kein uint8_t
Wo ich aber nun hänge ist es die Zeichenkette zu zerlegen. Ich tue mich
verdammt schwer damit :(
Jetzt hat es geklappt nachdem ich die Terminierung weg gelassen habe am
Anfang. Ich dachte ich könnte die Zeichenkette auf "" setzen
1
voidReadName(constchar*str,char*strname)
2
{
3
inti;
4
//strname[0] = '\0';
5
6
for(i=2;i<21;i++)
7
{
8
strname[i-2]=str[i];
9
}
10
strname[i-2]='\0';
11
}
Eine SubStr Funktion gibts ja so nicht. Ich müsste mir eine bauen. Bevor
ich mich aber an so etwas setze, auch wenn sicher nur eine kleinigkeit
ist, gehts auch schöner?
Jetzt kommt der Punkt an dem ich das Struct füllen muss... Graus...
Daniel schrieb:> Hab mir mal schnell in C das ganze kopiert und getestet.> In der Convert Funktion ist ein kleiner Fehler drin. Nachdem die 8 Ports> gelesen sind wird erneut eine Bit Verschiebung gemacht wodurch das erste> Bit weg fällt.
Schreib es dem Umstand zu, dass ich direkt hier drinnen 'programmiere'
:-)
Aber wenn schon, dann bitte so.
Daniel schrieb:> Eine SubStr Funktion gibts ja so nicht.
Na ja. Kann man schon machen.
Aber typischerweise 'zerlegt' man einen String nicht dadurch, dass man
Teilstrings durch die Gegend kopiert, sondern indem man sich Pointer
mitten in den String hinein merkt. Bei dir geht das sogar ganz
wunderbar, weil dein Original da diese ':' als Trenner hat, die man
durch \0 ersetzen kann und dann entsprechende Teilstrings hat.
Und das beste am ganzen :-) : genau da schlägt dann die Stunde von
strtok()
Daniel schrieb:> Tut mir leid, ich bin immer ein Sonderfall ;)> Habs aber begriffen.>> War der Befehl nun ein Wink mit dem Zaunpfahl? :)
Der Zaunpfahl-Balken ist eigentlich:
Du solltest in Betracht ziehen erst mal ordentlich C zu lernen, ehe du
dich an reale Projekte wagst. Das hat doch keinen Sinn, wenn du von den
Möglichkeiten deiner Programmiersprache gerade mal 10% beherrscht.
:-)
Aber natürlich hab ich den Zaunpfahl auch ausgearbeitet :-)
Brauch halt auch ein wenig Zeit dafür.
> Aber typischerweise 'zerlegt' man einen String nicht dadurch, dass> man Teilstrings durch die Gegend kopiert, sondern indem man sich> Pointer mitten in den String hinein merkt. Bei dir geht das sogar> ganz wunderbar, weil dein Original da diese ':' als Trenner hat,> die man durch \0 ersetzen kann und dann entsprechende Teilstrings> hat.> Und das beste am ganzen :-) : genau da schlägt dann die Stunde> von strtok()
(ohne Fehlerbehandlung)
(wobei die 0 in der Zeichnung als die C-String Nullterminierung \0 zu
lesen ist)
jeder Pointer zeigt auf den Beginn eines 0-terminierten Strings.
Nichts wird stringmässig umkopiert. Lediglich ein paar ':' sind gegen
'\0' ausgetauscht worden (und natürlich auch der ; zum Schluss, was in
der Zeichnung nicht sichtbar ist).
Alles perfekt um die Funktion
1
ConvertToOnOffByte(Bits,&On,&Off);
damit aufrufen zu können, bzw. den Namen in eine STruktur kopieren zu
können
Verdammt so schnell kann ich mir die Funktion ja schon fast nicht mehr
selber anschauen.
Wollte aber sagen, mein Beispiel funktioniert auch, auch wenn es nicht
so spektakulär ist.
1
charMyData[35]="C:Name der Taste 1:0001:11100-00;";
2
char*pch;
3
pch=strtok(MyData,":");
4
while(pch!=NULL)
5
{
6
printf("%s\n",pch);
7
pch=strtok(NULL,":");
8
}
Verdammt so schnell kann ich mir die Funktion ja schon fast nicht mehr
selber anschauen.
Wollte aber sagen, mein Beispiel funktioniert auch, auch wenn es nicht
so spektakulär ist
> Ist mit C darum kein uint8_t
Doch!
Du willst da einen uint8_t haben!
Brauchst doch nur stdint.h inkludieren und du hast diese Datentypen.
Und wenn nicht (weil dein Compiler zu alt ist), dann machst du dir eben
welche
Dann will ich mal ein wenig meines Fortschritts zeigen.
Hab es mit dem EEPROM noch nicht drin, musste mich erst einmal richtig
in den Source denken.
Die Zeile die ich mittels UART zum setzen der Konfiguration übergebe
habe ich so angepasst das diese ins struct gesetzt wird und dann die
Ports setzt. Das klappt auch wunderbar.
Hier wird das Struct, Protokoll und Adresse zugewiesen
Damit habe ich das Stuct, Protokoll und die Adresse.
Das setzen der Ausgänge funktioniert ebenfalls wenn ich die Line ändere.
Muss jetzt noch an dem Übertragungsprotokoll arbeiten um die ersten drei
Bytes zu setzen im EEPROM für Protokoll und Gerät und dann das Auslesen
und Speichern der Daten. Ein weiteres Byte für die Anzahl der
Datensätze.
Ich danke dir für die Hilfe, bin Stolz das es mit deiner Hilfe bis hier
hin so gut klappt. Ist spät und ich muss so langsam ins Bett, leider...
Ja mit C habe ich echt meine Probleme. Vieles von der Stringverarbeitung
übernimmt die Pascal IDE bereits für mich. Wenn man allerdings sucht
aber nicht die passenden Suchwörter findet läuft man leider leicht ins
leere. Als nächstes steht ein vernünftiges C Buch auf meiner Liste.
Freue mich allerdings das mir dennoch so gut geholfen wird.
Die Pointer Variablen könnte man allesamt wegoptimieren, wenn man auf
Fehlerbehandlung verzichtet, was bei einem maschinell erzeugtem String
durchaus drinnen ist.
wie ist Line definiert?
Ich hoffe mal für dich als
1
charLine[47];
und nicht als Array der Länge 46 oder kleiner. Denn sonst greift deine
Sicherheitsabfrage ins Leere um hier
1
Line[StringLen]='\0';
schlimmeres zu verhindern.
Solche magischen Zahlen mitten im Code sind schlecht. Entweder man macht
sich ein entsprechendes #define mit einer konstanten Zahl dafür, oder
man arbeitet gleich mit sizeof. Dann sucht sich der Compiler selbst die
Größe des Arrays raus.
Guten morgen,
Warum müssen es 47 sein? Ich dachte die Terminierung ist nur ein
Zeichen. 45 Zeichen + '\0' sollten dann doch 46 sein?
1
Line[StringLen]='\0';
Hier ist StringLen = 46.
Mit der Konstanten geb ich dir allerdings recht. Bisher ist das eben
alles noch ein Versuchs Source. Wie gesagt ist eigentlich erst mein
zweites Projekt abgesehen von LEDs blinken zu lassen und auf Tasten zu
reagieren sowie ein paar Timer.
Als ich das Projekt angefangen habe, hatte ich die Ausmaße noch nicht im
Kopf. Jetzt wird mir schon klar das es etwas umfangreicher ist. Anfangs
sollten auch keine Keys über die Software programmiert werden.
Mir scheint mit dem EEPROM stehe ich echt auf Kriegsfuß...
Ich darf mir sicher gleich wieder etwas anhören aber da muss ich dann
wohl durch...
Warum erwartet eeprom_write_byte als Adresse ein uint8_t aber
eeprom_write_word ein uint16_t?
Block nen Void....
Ich kann ein Byte, Word und Stuct speichern/lesen aber schlau werde ich
da nicht wirklich draus.
Bitte nicht auf das strcmp achten, das ist nur zum testen. In meinem C
Programm habe ich das schon abgeändert. Dort hole ich mir den ersten
Teilstring mit Hilfe vom Index des ':' und kopiere dann mit strncpy den
Bereich heraus, damit ich nicht einen falschen Befehl interpretiere.
Im Programm soll es ja bisher so aussehen an der ersten Adresse steht
das genutzte Protokoll gefolgt vom Gerät, danach folgt nrKeysInEEPROM.
Damit sollten die ersten 5 Bytes beschrieben sein. Ab da also Adresse 4
folgen dann die Tasten.
Die Adresse wäre dann doch eemem_KeyDesc[i] + mein Offset.
1
structkeyInfo_eemem_KeyDesc[22]EEMEM;
Die Zeile verstehe ich so das insgesamt 22 Adressen existieren die einen
Abstand in der Größe des Structs haben.
Gibt es die Möglichkeit so etwas zu testen direkt in C bzw. ohne den
EEPROM des Controllers zu belasten?
Hallo,
bin leider gestern nicht zum Programmieren gekommen aber es steht ja nun
das Wochenende an, dann gehts weiter.
Habe mir allerdings überlegt das es unsinnig ist den Tasten Namen zu
geben. Selbst wenn ich irgendwann mal ein Display anschließen sollte
sehe ich das von der Couch aus eh nicht. Ich gebe also den Ports Namen.
Diese können dann auch kleiner ausfallen, da ja ein gerät dich eine
recht kurze Bezeichnung hat.
1 Byte Protokoll
2 Byte Gerät
40-80 Byte pro Port
1 Byte geschriebene Datensätze
Das macht dann 43-83 Byte und habe dann 429 - 469 Byte frei für die
Konfigurationsdaten.
Ein Datensatz besteht dann nur noch aus 4Byte(2 Byte Adresse und 2 Byte
für On/Off Byte). Damit habe ich dann nun doch eine verdammt große Menge
die ich abspeichern könnte.
Da hätte ich auch eher drauf können kommen...
Guten Abend,
mittlerweile funktioniert schon ein wenig mehr.
Lesen / schreiben des IR-Systems
Lesen / schreiben der Portnamen inkl. Prüfung ob sie geschrieben sind
Lesen / schreiben Anzahl der Datensätze
Auslesen aller Portnamen in einem durchlauf
die Struct wurde um ein Byte vergrößert für zusätzliche Informationen
Nun sitze ich gerade daran die Konfiguration in den EEPROM zu
übertragen.
Auf Windows Seite existiert bisher ein recht einfaches Programm um die
Informationen lesen und schreiben zu können.
Hier mal die Prozedur zum auslesen der Portnamen:
Guten morgen,
Gestern liefen die ersten Tests mit dem SOurce auf dem Controller bis
zum setzen der Ports. Da wurde ich dann auf dem "Es funktioniert" Effekt
raus gerissen da sich irgend etwas aufgehangen hat am Controller.
Das ist meine Main.
Zuerst werden die Ports 2-7 für 1.5 Sekunden auf On gesetzt und dann
deaktiviert(ist noch auf dem Anfang). Dann wird die UART inizialisiert.
Danach das IRMP initialisiert, Die Callback LED und die Routine gesetzt.
Init_IR(); liest aus dem EEPROM das Protokoll und die Geräteadresse der
Fernbedienung. WorkOnCommand(); fragt die UART Schnittstelle ab.
Soweit klappt es auch. Ich kann die Keys in den EEPROM schreiben und
auch wieder auslesen. Drücke ich nun eine Taste auf der Fernbedienung
die nicht gespeichert ist meldet er auch 'Key not found'.
Drücke ich die Taste 'Power' die gespeichert ist mit '--000000' meldet
er auch 'Set Ports done'.
Drücke ich die Taste '1' mit '--000001' so wird der letzte Port gesetzt.
Wird nun die Taste 'Power' gedrückt geht der Port auch wieder aus.
Drücke ich die Taste 'OK' mit '--110011' so gehen auch die
entsprechenden Ports an und meldet auch hier wieder 'Set Ports done'.
Nun fangen die Probleme an. Es werden keine Tasten mehr erkannt.
UART funktioniert noch, ich kann die Konfiguration abrufen und auch
setzen. die callback für die IR Aktivität verrichtet auch noch ihren
Dienst. Sie blinkt wenn ich die Fernbedienung betätige. Es wird aber
eben kein IR Signal mehr ausgegeben. IRMP ist unverändert es ist nur das
NEC Protokoll aktiv.
Ich muss dazu sagen das es sich hier um den PORT C handelt und da
natürlich auch UART genutzt wird. Darum sind hier die ersten beiden Bits
immer mit '-' gesetzt. Da er allerdings meldet 'Set Ports done' sollte
dort ja nicht das Problem liegen. Die Main läuft ja ebenfalls noch,
sonst würde UART ja nicht mehr funktionieren.
Wo könnte hier noch das Problem liegen?
Gruß Daniel
Daniel S. schrieb:> Drücke ist Key1 so werden die Ports gesetzt. Drücke ich Key3 werden alle> abgeschaltet. Drücke ich Key2 so werden auch diese gesetzt. Drücke ich> wieder Key3 so werden sie auch wieder abgeschaltet. Drücke ich> allerdings Key1, Key2, Key3 dann wird Key1 und Key2 ausgeführt. danach> ist Ende...
"Ist Ende" heißt, dass irmp_get_data() niemals mehr TRUE zurückliefert?
Zeigt die Callback-LED weiterhin was an?
1
>voidWriteMyPorts(uint8_tinfoOn,uint8_tinfoOff)
2
>{
3
>uint8_ti,a=7;
4
>
5
>for(i=0;i<8;i++)
6
>{
7
>if((infoOn&(1<<i))&&!(infoOff&(1<<i)))
8
>{
9
>OUT_PORT|=(1<<a);
10
>}
11
>elseif(!(infoOn&(1<<i))&&(infoOff&(1<<i)))
12
>{
13
>OUT_PORT&=~(1<<a);
14
>}
15
>else
16
>{
17
>
18
>}
19
>a--;
20
>}
21
>}
Ein Tipp: Für einen AVR ist das Schieben von Bits über eine variable
Anzahl ein Riesenaufwand. Aus den Befehlen 1<<i bzw. 1<<a wird richtig
viel Maschinencode. Besser ist es hier, eine Maske durchzuschieben -
immer um den konstanten Wert 1. Schau Dir oben mal an, wie das Karl
Heinz es macht, z.B. in ConvertToOnOffByte().
NumDS würde ich von 0 bis < CurrNumDS laufen lassen, dann sparst Du den
Abzug von 1 zwei Zeilen tiefer. Überhaupt solltest Du mehr von 0 und
nicht von 1 an "denken" beim Programmieren ;-)
Wie ist eigentlich CONF_DATASETS_START_ADDR definiert? Eventuell muss da
bei der Berechnung von Addr die C-Pointerarithmetik beachtet werden.
Einen Fehler kann ich direkt nicht sehen, aber ich vermute, dass Du
entweder in einer Endlosschleife landest oder Dir irgendwas im RAM durch
einen Programmierfehler kaputtschießt. Ich sehe nur nicht auf Anhieb,
wo.
Aber Moment, was sehe ich denn da:
> if (Mode == NO_KEY)> {> if (irmp_get_data(&irmp_data))
Kann es sein, dass Du vergisst, Mode wieder zurückzusetzen auf NO_KEY,
wenn Du mal einen Frame mit gesetztem IRMP_FLAG_REPETITION Bit
empfängst?
Wenn Mode auf KEY_RECEIVED bleibt, wird niemals mehr ein IR-Telegramm
empfangen!
Statt
1
>if(irmp_data.flags&IRMP_FLAG_REPETITION)
2
>{
3
>// Benutzer hält die Taste länger runter entweder:
4
>// ich ignoriere die (Wiederholungs-)Taste oder:
5
>// ich benutze diese Info, um einen Repeat-Effekt zu nutzen
6
>}
solltest Du schreiben:
1
if(irmp_data.flags&IRMP_FLAG_REPETITION)
2
{
3
Mode=NO_KEY;uart_puts("Repetition: SET MODE = NO_KEY\r\n");
Hallo und danke für die Antwort.
Die callback zeigt mir weiterhin an wenn ein IR Signal anliegt.
Die Prozedur WritePorts habe ich mir nur mal eben "schnell" sofern man
das bei mir schnell nennen kann geschrieben um festzustellen ob es mit
dem
{c]OUT_PORT = ( OUT_PORT | nextInfo.infoOn ) & ( ~ nextInfo.infoOff
);[/c] ein Problem gibt. Zudem werden mir hier die Ports vertauscht. Hat
ein wenig gebraucht bis mir das aufgefallen ist.
Wenn ich diese eben direkt über die UART setze gibt es weder mit
WritePorts noch mit dem obigen Befehl Probleme.
Das mit dem von 0 anfangen werde ich beherzigen und nachher mal umsetzen
wenn ich daheim bin.
Das hier ist die Definition:
1
#define CONF_PROTOCOL_ADDR 0 // Adresse im EEPROM um das Protokoll abzulegen (1Byte)
2
#define CONF_ADDRESS_ADDR 1 // Adresse im EEPROM um die Adresse abzulegen (2Byte)
3
#define CONF_PORTNAMES_START_ADDR 3 // Start Adresse für die Port Namen (8x10Byte)
4
#define CONF_NUM_DATASETS 84 // Adresse im EEPROM; Anzahl der Geschriebenen Datensätze
5
#define CONF_DATASETS_START_ADDR 85 // Startadresse der Tastendatensätze
6
#define MAX_DATASETS 40 // Anzahl der Datensätze die möglich sind
7
#define MAX_COMMAND_LEN 47 // Maximale Länge des zu empfangen Befehls über RS232
8
#define MAX_PORTNAME_LEN 12 // Länge des Portnamen
9
#define MAX_CMD_TOKEN_LEN 20 // Größe des Befehlstoken
10
#define MAX_KEY_NAME_LEN 20 // Länge des Namens innerhalb eines IR Datensatzes
11
12
structkeyInfo_// IR Datensatz
13
{
14
//char name[MAX_KEY_NAME_LEN]; // Name der Taste
15
uint16_tkeyCode;// Taste auf der Fernbedienung
16
uint8_tOptions;// 1Byte für zusätzliche Informationen
17
uint8_tinfoOn;// On Byte: Hier stehen die On Bits des Ports drin
18
uint8_tinfoOff;// Off Byte: Hier stehen die Off Bits des Ports drin
19
};
20
21
uint8_tStringLen=0;// Anzahl empfangener Zeichen
22
charLine[MAX_COMMAND_LEN];// die Befehlszeile
23
uint8_tIR_Protocol=0xFF;// Das verwendete Protokoll;
24
uint16_tIR_Address=0xFFFF;// Das verwendete Gerät;
Frank M. schrieb:> Aber Moment, was sehe ich denn da:>>> if (Mode == NO_KEY)>> {>> if (irmp_get_data(&irmp_data))>> Kann es sein, dass Du vergisst, Mode wieder zurückzusetzen auf NO_KEY,> wenn Du mal einen Frame mit gesetztem IRMP_FLAG_REPETITION Bit> empfängst?>> Wenn Mode auf KEY_RECEIVED bleibt, wird niemals mehr ein IR-Telegramm> empfangen!
Hier muss ich zugeben das dies erst seit gestern Abend existiert. Ich
wollte einmal sehen ob die Zeit hier nicht passt vom Ablauf her und die
Prozedur eben nicht mehr aufgerufen wird solange die Ports nicht gesetzt
sind. Also Zeittechnisch etwas nicht passt.
Hier hast aber recht, gab grad eine mit dem Brett vor den Kopf. Klar
wenn IRMP_REPETITION_FLAG gesrtzt ist wird der Mode nicht zurück
gesetzt. Kann ich aber mittels UART zurück setzen. :) Dies existierte
vorher nicht und dennoch hing es sich weg. Ich habe die Routine
1
(irmp_get_data(&irmp_data))
nicht weiter intern verfolgt. Das könnte ich noch prüfen.
Wie gesagt es hängt sich nur weg wenn ich die Ports setze, egal ob mit
Write Ports oder direkt.
Daniel schrieb:> Hier hast aber recht, gab grad eine mit dem Brett vor den Kopf. Klar> wenn IRMP_REPETITION_FLAG gesrtzt ist wird der Mode nicht zurück> gesetzt. Kann ich aber mittels UART zurück setzen. :) Dies existierte> vorher nicht und dennoch hing es sich weg. Ich habe die Routine> (irmp_get_data(&irmp_data))nicht weiter intern verfolgt. Das> könnte ich noch prüfen.
Brauchst Du nicht, ich kenne den IRMP-Source zufällig in- und auswendig
:-)
Bitte korrigiere den Fehler, teste bitte, ob Du das Fehlverhalten 1:1
mehrfach hintereinander reproduzieren kannst und dann hänge bitte den
Source als Anhang an, insbesondere:
main.c (oder wie immer das Modul heisst)
irmpconfig.h
Eventuell noch weitere Header-Files, z.B. das, wo
CONF_DATASETS_START_ADDR definiert ist.
Eine Ausgabe auf dem UART, ob irmp_get_data() überhaupt noch aufgerufen
wird und was dessen Return-Code ist, wäre auch noch hilfreich.
Ich verstehe auch den Sinn der globalen(?) Variablen Mode nicht. Wo
brauchst Du die noch außerhalb von Handle_IR_Code()? Wenn nirgendwo,
kann die komplett weg und der Aufruf von irmp_get_data() kann unbedingt
erfolgen.
Gruß,
Frank
Wie gesagt ich hab dies gestern einfach mal eingebaut um zu prüfen was
sich wie verhällt. diesen Source habe ich auch hier gesetzt. Vorher
fehlte der Mode. In der Final soll er natürlich nicht mehr vorhanden
sein.
Werde nachher den Source komplett anhängen. Das Mode nehme ich natürlich
auch wieder raus.
µC ist ein ATMega8 mit 16Mhz. Board ist das Pollin Eval Board. Keine
Ahnung ob es wichtig sein könnte aber ich erwähne es mal.
Habe Mode und DMode nun wieder vollständig entfernt. Bei den meisten
Routinen habe ich nun auch 0 bis < als gesetzt. Bei den anderen muss ich
erst mein Windows Source ändern und werde dann auch die Port Nummern mit
0 beginnen. Musste natürlich bei der Ausgabe über UART wieder +1 nehmen
sonst mag mein Windows Programm das nicht mehr.
WriteToPorts ist nun auch wieder draußen. Diese war nur zum testen
aktiv.
Aktuelle Konfiguration
1
[2013-08-21 20:26:49]-> GET_CONFIG;
2
[2013-08-21 20:26:49]<- READ: GET_CONFIG
3
[2013-08-21 20:26:49]<- GET_CONFIG:BEGIN;
4
[2013-08-21 20:26:49]<- COUNT:3;
5
[2013-08-21 20:26:49]<- L:1:1:10101010:--110-11;
6
[2013-08-21 20:26:49]<- L:2:2:10101010:--1-0000;
7
[2013-08-21 20:26:49]<- L:3:3:10101010:--000000;
8
[2013-08-21 20:26:49]<- GET_CONFIG:END;
L:<DatensatzNr>:<IR-Taste>:<Options>:<Port>;
Die Definition des gesetzten Bit bedeutet '-' = alter Zustand bleibt,
'0' = off und '1' = on.
Solange ich die Ports nicht setze läuft es alles reibungslos. Bei der
gesetzten Konfiguration laufen Taste 2 und 3 ohne Probleme. Drücke ich
aber die Taste 1 dann wird der Port noch gesetzt. Die UART meldet Ports
sind gesetzt und von da an wird immer FALSE gemeldet.
1
irmp_get_data()
wird weiterhin aufgerufen liefert aber ein FALSE zurück.
Das Fehlverhalten ist reproduzierbar. Ich versuche es ja schon einige
male.
Im Anhang alle Dateien des Projekts. Derzeit ist alles in der IR-Demo.c
enthalten. Das war ursprünglich mal die IR Demo vom IRMP. Bin noch in
der Lernphase, ist mein zweites Projekt.
Ich muß mich korrigieren habe eben bemerkt das ich die ganze Zeit von
PortD als Ausgang gesprochen habe, dabei war es PortC. Habe das Programm
nun auf PortD mal umgestellt aber leider hier auch keine Verbesserung.
Daniel S. schrieb:> µC ist ein ATMega8 mit 16Mhz. Board ist das Pollin Eval Board.
Sind da irgendwelche Jumper gesetzt, d.h. bestimmte Pins vom ATmega mit
irgendwelchen Komponenten auf dem Board verbunden?
> Im Anhang alle Dateien des Projekts. Derzeit ist alles in der IR-Demo.c> enthalten. Das war ursprünglich mal die IR Demo vom IRMP. Bin noch in> der Lernphase, ist mein zweites Projekt.
Ich kann auf Anhieb keinen Fehler erkennen. Das schließt aber nicht aus,
dass da einer oder mehrere Fehler sind :-)
Folgende Sachen sind mir aufgefallen:
1. Du hast lange if-Ketten, die sich ungünstig auf die
Bearbeitungs-Geschwindigkeit auswirken:
1
if(strcmp(Command,"SET_IR_SYSTEM")==0)// Setzen des IR-Systems in den EEPROM
2
{
3
CMD_Set_IR_System(Line);
4
}
5
6
if(strcmp(Command,"GET_IR_SYSTEM")==0)// Liest das IR-System fom EEPROM
7
{
8
CMD_Get_IR_System();
9
}
10
11
if(strcmp(Command,"SET_NUM_DS")==0)
12
....
Hier wäre es sinnvoll, ab dem 2. if ein else davorzusetzen, also:
1
if(strcmp(Command,"SET_IR_SYSTEM")==0)// Setzen des IR-Systems in den EEPROM
2
{
3
CMD_Set_IR_System(Line);
4
}
5
6
elseif(strcmp(Command,"GET_IR_SYSTEM")==0)// Liest das IR-System fom EEPROM
7
{
8
CMD_Get_IR_System();
9
}
10
11
elseif(strcmp(Command,"SET_NUM_DS")==0)
12
....
Grund: Der Prozessor kann mit dem Vergleichen aufhören, sobald eine
Bedingung zutrifft, da die Bedingungen sich ausschließen.
Dann ist mir das noch aufgefallen:
1
if(strcmp(Line,"SYS_SYNC")==0)// Synchronisieren des Datenstroms
2
{
3
}
Abgesehen davon, dass diese Zeilen null Effekt haben, muss da nicht auch
Command statt Line stehen?
Was mir noch auffällt: Du hast sehr viele Stringkonstanten im Source,
z.B. bei den obigen if-Statements. Diese werden beim Start des
Prozessors alle ins RAM kopiert. Davon hast Du aber sehr sehr wenig! Was
sagt denn das AVR-Studio zur Data-Größe am Ende des Compiliervorgangs?
Ich vermute, dass durch diese viele Stringkonstanten Dein Stack sehr
knapp bemessen ist, dann irgendwann überläuft und das Programm fortan
nicht mehr korrekt arbeiten kann.
Abhilfe ist sehr einfach:
Ersetze alle Vorkommnisse von
strcmp (Variable, "abcdefgh")
durch
strcmp_P (Variable, PSTR("abcdefgh"))
Dann bleiben die Stringkonstanten im Flash. Das Makro PSTR liefert eine
Adresse aus dem Flash und nicht aus dem RAM zurück, strcmp_P() ist die
äquivalente Form von strcmp, liest aber dann aus dem Flash.
Du musst dann noch am Anfang ein
#include <avr/pgmspace.h>
einfügen.
Das sollte viele Bytes im RAM einsparen, die Dir wahrscheinlich zur
Laufzeit fehlen.
Gruß,
Frank
Guten morgen,
Frank M. schrieb:> Sind da irgendwelche Jumper gesetzt, d.h. bestimmte Pins vom ATmega mit> irgendwelchen Komponenten auf dem Board verbunden?
Auf dem Eval Board sind keine Jumper gesetzt außer für UART, der Rest
ist nicht weiter verbunden. Reset geht direkt auf den ISP und mit Taster
gegen Masse. Auf dem Addon-Board ebenfalls nichts weiter angeschlossen.
Frank M. schrieb:> Ich vermute, dass durch diese viele Stringkonstanten Dein Stack sehr> knapp bemessen ist, dann irgendwann überläuft und das Programm fortan> nicht mehr korrekt arbeiten kann.
Darüber habe ich mir ehrlich gesagt bisher keine Gedanken gemacht. Werde
dies nachher mal umsetzen. So umzudenken vom PC auf µC fällt mir nicht
einfach. Auf dem PC kann man schon mal verschwenderischer mit Ressourcen
umgehen, hat man ja mehr von.
Auf dem PC hätte ich vermutlich auch If - Else genommen. Warum ich das
hier nicht gemacht habe kann ich gerade nicht erklären. Werde das
natürlich auch abändern.
1
if(strcmp(Line,"SYS_SYNC")==0)
Hier ist es egal an wo in dem String der Sub-String steht, es soll auf
jeden Fall dieser Bereich ausgeführt werden.
Frank M. schrieb:> Davon hast Du aber sehr sehr wenig! Was> sagt denn das AVR-Studio zur Data-Größe am Ende des Compiliervorgangs?
Meinst du das hier?:
Task "RunOutputFileVerifyTask"
Program Memory Usage : 6244 bytes 76,2 % Full
Data Memory Usage : 757 bytes 73,9 % Full
Done executing task "RunOutputFileVerifyTask".
Hallo,
Habe entsprechende Anpassungen gemacht aber sehr viel hat es nicht
gebracht.
Task "RunOutputFileVerifyTask"
Program Memory Usage : 6622 bytes 80,8 % Full
Data Memory Usage : 675 bytes 65,9 % Full
Done executing task "RunOutputFileVerifyTask".
Dafür habe ich aber gerade festgestellt das er irgendwann wieder ein
Signal durlässt. Gerade mehrfach getestet. Ich setze --100001 und direkt
danach --000000 läuft ohne Probleme. Hier kann ich auch unbegrenzt hin
und her schalten. Setze ich aber nun auf --111111 dann ist erst einmal
Ende. Nach knapp über einer Minute reagiert er dann wieder mit einem
IR-Signal.
Ich habe nun sehr viele Befehle auskommentiert die ich zum testen so
nicht benötige. Nach dem Kompilieren hat sich der Wert für Data Memory
Usage aber leider nicht geändert. Er steht immer noch auf 675Byte trotz
7 entfernter Befehle. Leider ändert sich hier auch nichts an der
Verarbeitung. Diesmal hat es fast 2 Minuten gedauert bis der nächste
Datensatz angenommen wurde.
Es ist im übrigen egal ob ich den IR-Code auswerte oder direkt den Port
Togle also sobald ein IR Signal ankommt und egal welches es ist ich
togle alle 6 Bits. Selbst dann hängt er für eine Weile. Ob das bei der
Fehlersche hilft weiß ich leider nicht.
Selbiges Problem irmp_get_data liefert FALSE. Die Callback wird aber
noch aufgerufen, die LED reagiert bei eingehendem Signal.
Also bin ich noch einen Schritt weiter gegangen und habe die UART Lib
von P.F. auch komplett entfernt. Hier ebenfalls ein Hänger.
an den Ports selbst kann es ja nicht liegen die setze ich ja für 1.5
Sekunden beim Start.
Selbst dieses funktioniert nicht. Da muß doch echt irgendwo der Wurm
drin sein.
Auf dem Addon Board ist ein TSOP1136 verbaut selbst den habe ich nun
extern wie im Artikel beschrieben angeschlossen. Ergebnis: keine
Änderung. Nun habe ich ihn auf 8Mhz gesetzt aber selbst das bringt keine
Änderung.
Jetzt bin ich ratlos.
Ich habe das Programm nun mal auf einem Mega16 aufgespielt einmal mit
8Mhz und einmal mit 16Mhz und hier läuft das Programm ohne Probleme.
Hier hat sich auch nicht viel geändert:
Task "RunOutputFileVerifyTask"
Program Memory Usage : 5564 bytes 34,0 % Full
Data Memory Usage : 675 bytes 65,9 % Full
Done executing task "RunOutputFileVerifyTask".
Ich frage mich nur warum es nicht auf dem Mega8 laufen will. Abgesehen
davon das ich hier alle Pins des PortC nutzen kann und beim Mega8 hier
noch UART drauf liegt hat sich nichts geändert.
Habe jediglich das Target geändert und die beidem Pins des PortC dazu
genommen.
Hat hier jemand eventuell einen Ansatz warum dieses Problem auftritt
oder sogar schon einmal ein gleiches Problem?
Was ich allerdings noch nicht versucht habe ist einfach mal einen
frischen Mega8 zu nehmen. Habe gerade keinen hier liegen. :(
Würde schon gerne wissen warum der Mega8 diese Probleme macht.
Options = 0x01 bedeutet toggle. Gerade wenn eine Einzeltaste
programmiert ist dann soll natürlich auch nur der Ausgang gesetzt bzw.
zurück gesetzt werden. Bsp: Taste1 = TV - dementsprechend TV an oder aus
wenn ich erneut die Taste betätige.
Es wird geprüft ob die aktuelle Maske der neuen entspricht, falls ja
dann invertieren.
Ist dieses Konstrukt soweit ok?