Closed Ralf9 closed 4 years ago
Mir ist auch aufgefallen, daß am Ende von MS Nachrichten recht oft ein O steht
if (MdebLevel == 1) {
Ich weisst nicht, woher diese Variable kommt, aber
if (FiFo.count())>0 wäre vielleicht die richtige Abfrage?
O am Ende bedeutet lediglich, dass der "message" Puffer voll war und dadurch dann processMessage() aufgerufen wurde.
MdebLevel ist eine EEPROM konfig Variable, damit kann die debug Ausgabe ein/ausgeschaltet werden. Da es mit dem state nicht so funktioniert hatte, verwende ich jetzt eine extra Variable, damit funktioniert es jetzt. Die printMsgSuccess wird nach dem printMsgRaw auf true gesetzt
#define addr_MdebLevel 0xf0
void loop() {
....
musterDec.printMsgSuccess = false;
while (FiFo.count()>0 ) { //Puffer auslesen und an Dekoder uebergeben
aktVal=FiFo.dequeue();
state = musterDec.decode(&aktVal);
if (MdebLevel == 1 && musterDec.printMsgSuccess) {
MSG_PRINT(F("MD="));
MSG_PRINTLN(FiFo.count(), DEC);
musterDec.printMsgSuccess = false;
}
if (state) {
blinkLED=true; //LED blinken, wenn Meldung dekodiert
}
}
}
void initEEPROM(void) {
....
getFunctions(&musterDec.MSenabled,&musterDec.MUenabled,&musterDec.MCenabled);
MdebLevel = EEPROM.read(addr_MdebLevel);
spricht eigentlich was dagegen die FIFO_LENGTH von 50 auf 100 zu erhöhen?
Ich denke bei der Datenkomprimierung macht es Sinn erst mal nur den message Puffer zu komprimieren. Bei 255 Byte passen dann 680 Einträge rein. Da müssten eigentich auch weniger Einträge reichen. Z.B. bei 500 Einträgen werden ca 60 Byte frei.
Ich wollte eigentlich am Wochenende testen wie gut es mit dem 8 MHz pro mini funktioniert. Anstatt dem bestellten pro mini habe ich leider einen 16 MHz pro micro erhalten:-(
Ich teste gerade erst Mal mit 4 Bit pro Wert. Das ergibt ein paar Vorteile... Mit drei Bit, wird einiges schwieriger und recheningensiver.
Ich habe noch ein bisschen mit dem TX Puffer gespielt und ein paar Tests durchgeführt.
Wenn der FiFo 50 Einträge hat, dann ist er im ungünstigsten Fall nach 4,5 Millisekunden übergelaufen.
Am Beispiel Arctech Protokoll sind 12 Millisekunden bei 50 Einträgen.
Realistisch haben wir etwas mehr als die 12 Millisekunden, da ich hier schon den ungünstigsten Fall angenommen habe.
Den Messagepuffer zu vergrößern hilft uns bei dieser Thematik auch nicht weiter. So haben wir nur noch mehr Daten zu übertragen.
Den Fifo können wir durchaus in Maßen vergrößern, das geht allerdings auch mit dem Seriellen TX Puffer
@Ralf9 Ich habe die bitstore Klasse etwas erweitern müssen und dabei festgestellt, dass ein Bug enthalten war. Ich habe es bei Verwendung von 4 Bits pro Wert getestet. Ich mache noch Tests mit 1 und 2 Bit... Bei 3 oder mehr als 4 wird es derzeit nicht funktionieren, da müsste ich mir dann doch noch mehr überlegen.
Ich verfolge erst mal 4 bit/wert weiter und versuche dann erst mal die Ausgabe so zu realisieren, dass die Ausgabe identisch zu Heute ist.
Ja, 4 Bit müsste erstmal reichen. 3 Bit ist wahrscheinlich recht kompliziert und aufwändig.
Vom Prinzip ist das so.
Bei 3 Bit hat man das Problem, dass 2 Bit in der einen variable und das letzte dritte Bit in einer anderen Variable stehen.
Das kann man ausrechnen, macht es aber etwas kompliziert.
Überschaubar ist noch, die Variablen im Puffer nicht 8 Bit sondern 16 Bit groß zu machen. Dann könnte man 5 Werte speichern und das letzte Bit frei lassen.
Ich mache jetzt aber erst mal mit der Variante 4 Bit weiter. Es fehlt "nur" noch die serielle Ausgabe der Daten. Und ein paar Messungen zur Rechenzeit.
Hallo Sidey,
Ich habe mir auch mal mit dem 3,3V 8MHz pro mini einen CC1101 Signalduino zusammen gebaut. Ich habe den Eindruck, daß bei 8 MHz die Signalverarbeitung etwas langsamer ist. Dies macht sich dadurch bemerkbar, daß bei 8 MHz nach der Signalverarbeitung und Ausgabe der Nachricht gegenüber dem nano etwas mehr Daten im FIFO sind. Ich lasse nach dem Ausgeben der Raw Nachricht den FiFo.count ausgeben. Bei 8 MHz sind 50 FIFO Einträge zu wenig. Kannst Du ungefähr abschätzen ob ich bei einem Freeram von ca 730 den FIFO auf ca 80-90 erhöhen kann?
MS;P1=537;P2=-9035;P3=-2101;P4=-4141;D=1213141414131313141313131413131313141313141414141313141413131313141313141413;CP=1;SP=2;R=11;O;
MD=9
MS;P0=-2087;P1=547;P2=-4133;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6;
MD=22
MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6;
MD=36
MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6;
MD=38
MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6;
MD=50
MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6;
MD=50
MU;P0=588;P1=570;P2=-4181;P3=-2102;D=01213131313131313131313121312131313131213121312121212121213131313101310131212131212131313131313131313131213121313131312131213121212121212131313131013101312121312121313131313131313131312131213131313121312131212121212121313131310131013121213121213131313131;CP=1;R=7;O;
MD=22
MS;P0=-2093;P1=575;P2=-4167;P3=-9071;D=1310121210121210101010101010101010121012101010101210121012121212121210101010;CP=1;SP=3;R=4;
MD=4
Ja, kannst Du erhöhen, aber vermutlich bringt es mehr, die serielle Datenrate zu modifizieren.
Grüße Sidey
Ralf9 notifications@github.com schrieb am 11.02.2017:
Hallo Sidey,
Ich habe mir auch mal mit dem 3,3V 8MHz pro mini einen CC1101 Signalduino zusammen gebaut. Ich habe den Eindruck, daß bei 8 MHz die Signalverarbeitung etwas langsamer ist. Dies macht sich dadurch bemerkbar, daß bei 8 MHz nach der Signalverarbeitung und Ausgabe der Nachricht gegenüber dem nano etwas mehr Daten im FIFO sind. Ich lasse nach dem Ausgeben der Raw Nachricht den FiFo.count ausgeben. Bei 8 MHz sind 50 FIFO Einträge zu wenig. Kannst Du ungefähr abschätzen ob ich bei einem Freeram von ca 730 den FIFO auf ca 80-90 erhöhen kann?
MS;P1=537;P2=-9035;P3=-2101;P4=-4141;D=1213141414131313141313131413131313141313141414141313141413131313141313141413;CP=1;SP=2;R=11;O; MD=9 MS;P0=-2087;P1=547;P2=-4133;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6; MD=22 MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6; MD=36 MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6; MD=38 MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6; MD=50 MS;P0=-2087;P1=547;P2=-4418;P3=-9050;D=1310121212101010121010101210101010121010121212121010121210101010121010121210;CP=1;SP=3;R=6; MD=50 MU;P0=588;P1=570;P2=-4181;P3=-2102;D=01213131313131313131313121312131313131213121312121212121213131313101310131212131212131313131313131313131213121313131312131213121212121212131313131013101312121312121313131313131313131312131213131313121312131212121212121313131310131013121213121213131313131;CP=1;R=7;O; MD=22 MS;P0=-2093;P1=575;P2=-4167;P3=-9071;D=1310121210121210101010101010101010121012101010101210121012121212121210101010;CP=1;SP=3;R=4; MD=4
-- Diese Nachricht wurde mit K-@ Mail gesendet.
Hallo Sidey,
ich habe mal versucht für die MS Nachrichten eine Reduzierung einzubauen. # ist das Trennzeichen. z.B. aus "P1=" wird "#1" und aus "CP=" wird "#C" Das Datenbyte hat den folgenden Aufbau "1yyy1xxxx" x=3Bit-Wert1 y=3Bit-Wert2
Ms#11f0#2-f46#3-3cb#4-7a1#D����������������������������������������������������������������#C1#S2#Rfb
Ms#11e7#2-3c2#3-f18#4-79b#54c0#D����������������������������������������������������������������#C1#S3#Rfa
Ms#0-3be#11f2#3-795#4-f50#D����������������������������������������������������������������#C1#S4#Rfa
Ms#1-3f8#21e2#3-f5c#4-78c#D����������������������������������������������������������������#C2#S3#Rfb
if (MredEnabled) {
int patternIdx;
preamble.concat("Ms"); // Message Index
for (uint8_t idx = 0; idx < patternLen; idx++)
{
if (pattern[idx] == 0 || histo[idx] == 0) continue;
preamble.concat('#'); preamble.concat(idx);
patternIdx = pattern[idx];
if (patternIdx < 0) {
preamble.concat("-");
patternIdx = -patternIdx;
}
preamble.concat(String(patternIdx, HEX)); // Patternidx=Value
}
preamble.concat("#D");
postamble.concat("#C");
postamble.concat(String(clock, HEX));
postamble.concat("#S");
postamble.concat(String(sync, HEX));
postamble.concat("#R");
postamble.concat(String(rssiValue, HEX));
if (m_overflow) {
postamble.concat("#O");
}
}
else {
und hier werden zum test alle 64 möglichen Datenwerte ausgegeben
int8_t SignalDetectorClass::printMsgRaw(...
...
byte x;
byte y;
byte n;
for (x=0; x<8; x++) {
for (y=0; y<8; y++) {
n = x << 4;
n = n + y;
n = n | B10001000;
Serial.write(n);
}
}
Ich weiss noch nicht, wie uns das jetzt weiterhilft. Ich bin doch dabei die Daten mit der Klasse Bitstore zu speichern.
Dadurch wird die seriell ausgegebene raw-Nachricht mehr als halbiert
Der Teil im Abschnitt D wird ja schon durch die Bitstore Klasse halbiert...
Beim restlichen Teil der Nachricht können auch noch einige Bytes gespart werden. Wenn man beim seriellen Ausgeben die 2 x 4Bit auf 2 x 3Bit reduziert, dann können die Daten keine ASCII Zeichen kleiner 136 (B10001000) enthalten sein und die Rückwandlung wird dadurch recht einfach
Die Ausgabe sieht dann so aus: MSG_PRINT(message[m_start] | B10001000);
Wenn auf bitstore umgestellt ist, dann können wir die Bits ja komplett seriell ausgeben. Die einzelnen Werte brauchen wir dann ja nicht mehr anfassen.
Mit der Methode getByte() kommt das dann komplett. Das Verändern der Daten könnten wir sparen oder?
Also gut,
Ich habe mir den Code jetzt noch mal näher angesehen und deine Beschreibung gelesen. Hätte ich wohl besser gleich machen sollen... ;)
Du hast den Nachrichtentyp auf Ms geändert. Soll mit dem kleinen s die komprimierte Nachricht signalisiert werden?
Die P=xyz hast Du auf Hex Schreibweise geändert.
Ich denke, das können wir noch weiter optimieren. Wir wissen, dass wir Zahlen von -32001 bis +32001 darstellen wollen. Dafür brauchen wir 16 Bit inkl. Vorzeichen.
Das können wir mit Serial.write(lowByte(pattermIdx)); Serial.write(highbyte(pattermIdx)); übertragen.
Im Abschnitt D# hast Du jeweils das 8 und 4 Bit auf 1 gesetzt. Das soll dazu dienen, dass es keine lesbaren ASCII Zeichen gibt oder? Ich glaube ich habe alle Kombinationen Mal durchprobieren und erst mal kein Problem gesehen. Vielleicht ist das nicht so schlecht. Irgendwie müsste ja auch noch signalisiert werden, ob in einem Byte eine oder zwei Werte stehen. Das könnte man eventuell mit diesem Bit signalisieren.
Die Strings preamble und postamble möchte ich übrigens ausbauen und direkt seriell ausgeben. In einem lokalen branch habe ich das ganze auch schon umgesetzt.
Aktuell schlagen noch zwei unit Tests fehl. Da bin ich aber noch nicht sicher, ob das ein Fehler vom Test oder von den Libs ist.
Soll ich den branch mal hochladen?
Ich denke, das können wir noch weiter optimieren.
Wir wissen, dass wir Zahlen von -32001 bis +32001 darstellen wollen.
Dafür brauchen wir 16 Bit inkl. Vorzeichen.
Damit dürfte die Reoptimierung in der 00_SIGNALduino.pm recht aufwendig werden. Ich habe an eine Reoptimierung im Prinzip wie folgt gedacht:
if ($rmsg=~ s/^\002(M(s|u);.*;)\003/$1/) {
@msg_parts = split(";",$rmsg);
foreach my $msgPart (@msg_parts) {
....
damit dies so funktioniert, dürfen in der reduzierten raw Nachricht in den Abschnitten P und D die folgenden Zeichen nicht enthalten sein:
<\002><"M">
<";"><\003>
"\n"
"\r"
";"
Wenn bei den bytes der Patternwerte das 8te Bit 1 ist, dann müsste es passen. Aus z.B. Pi = bin16Bit (vfedcba98 76543210) wird dann 10v70iii 16543210 1fedcba98 v ist das Vorzeichen.
Du hast recht im Abschnitt D müsste es auch passen, wenn das 8te Bit 0 ist. Da die low- und high Nibble nur 0-7 enthalten, dürften die obrigen Zeichen nicht enthalten sein. z.B. \003 kann zwar enthalten sein, ";" \003 kann aber nicht enthalten sein.
Ja, mit Ms und Mu wird die reduzierte Nachricht signalsiert
Der aktuelle Stand ist hier: dev-r33_messagecompression
Folgendes wird nur am Anfang einer Zeile gesucht. Wenn es in der Nachricht vorkommt, dann ist es kein Problem:
<\002><"M">
Den Endemarker, könnte man mit einem $ auch auf das Zeilenende ausrichten:
\003
@Ralf9
Ich habs nun soweit umgestellt, dass zumindest das Testprogramm läuft: f713424f55327954c0842bdacf2598861bc75335
Die message Variable ist somit kein Array mehr, sondern ein Objekt. Auf die Inhalte kann man wie bei einem array zugreifen, verändern kann man die Werte so aber nicht.
Ich habe dann auch noch ein paar Testfälle für die Verarbeitungsdauer erstellt: RFD-FHEM/signalDecoderTest
calcHisto() dauert immerhin gute 2 Millisekunden bei 254 Einträgen im Puffer.
Ein komplettes Verarbeiten eines Puffers dauert fast 25 Millisekunden (inkl. serielle Ausgabe)
Edit: Ich habe die Dauer für die calcHisto Funktion drastisch reduzieren können.
Hallo Sidey, das hört sich gut an. Die Routinen für die Reduzierung der MS raw Nachrichten habe ich mittlerweile auch fertig. Mit einer kleinen Anpassung müsste es auch für die MU raw Nachrichten funktionieren. Dies hat den kleinen Nachteil, daß die raw Nachrichten nun im seriellen Monitor nicht mehr lesbar sind.
Ms;���;���;���;���;D;C1;S2;RF5;
Ms;���;��;�ă;�ď;���;�ȁ;D$#!#!!#!#!##!####!#!#!#!!!!!!##!g!###!;C2;S4;RFB;
Hier ist der Ausgabeteil für die MS raw Nachricht. Die Rückwandungsroutine für die 00_SIGNALduino.pm werde ich noch commiten
int patternInt;
uint8_t patternLow;
uint8_t patternIdx;
MSG_PRINT(MSG_START); MSG_PRINT("Ms"); MSG_PRINT(SERIAL_DELIMITER);
for (uint8_t idx = 0; idx < patternLen; idx++)
{
if (pattern[idx] == 0 || histo[idx] == 0) continue;
patternIdx = idx;
patternInt = pattern[idx];
if (patternInt < 0) {
patternIdx = idx | B10100000; // Bit5 = 1 (Vorzeichen negativ)
patternInt = -patternInt;
}
else {
patternIdx = idx | B10000000; // Bit5 = 0 (Vorzeichen positiv)
}
patternLow = lowByte(patternInt);
if (bitRead(patternLow,7) == 0) {
bitSet(patternLow,7);
}
else {
bitSet(patternIdx, 4); // wenn bei patternLow Bit7 gesetzt ist, dann bei patternIdx Bit4 = 1
}
Serial.write(patternIdx);
Serial.write(patternLow);
Serial.write(highByte(patternInt) | B10000000);
MSG_PRINT(SERIAL_DELIMITER);
}
uint8_t n;
n = mend - mstart -1; // Zeichenanzahl im messagepuffer
if (n % 2 == 0) {
MSG_PRINT("D"); // Zeichenanzahl gerade
}
else {
MSG_PRINT("d"); // Zeichenanzahl ungerade
}
for (uint8_t i = mstart; i <= mend; i=i+2)
{
n = message[i] << 4;
n += message[i+1];
Serial.write(n);
}
MSG_PRINT(SERIAL_DELIMITER);
MSG_PRINT("C"); MSG_PRINT(clock, HEX); MSG_PRINT(SERIAL_DELIMITER);
MSG_PRINT("S"); MSG_PRINT(sync, HEX); MSG_PRINT(SERIAL_DELIMITER);
MSG_PRINT("R"); MSG_PRINT(rssiValue, HEX); MSG_PRINT(SERIAL_DELIMITER);
if (m_overflow) {
MSG_PRINT("O"); MSG_PRINT(SERIAL_DELIMITER);
}
MSG_PRINT(MSG_END);
MSG_PRINT("\n");
Irgendwo ist im branch messageCompression ein bug.. mir hat es gerade das fhem log zugefahren mit:
sduino/msg READ: 20290 Wo 20290 ausgegeben wird, habe ich noch nicht herausgefunden.
Bezüglich der Lesbarkeit, könnte man einen seriellen Treiber schreiben, der das löst. Ob sich der Aufwand lohnt bezweifle ich aber etwas. Einfacher wäre es vielleicht ein kleines serielles Programm zu erstellen, das die Rückwandlung vornimmt.
Ich habe die Rückwandungsroutine für die 00_SIGNALduino.pm commited. Sie ist doch etwas aufwändiger geworden als ich ursprünglich dachte. Ich wollte sie recht universell halten, damit sie auch damit zurechtkommt falls an die raw Nachricht debug Infos angehängt werden. Es könnte z.B. mit T20; die Verarbeitungsdauer in hex ms angehängt werden.
Ich denke der Aufwand für eine serielle Rückwandlungsroutine lohnt sich nicht. Wenn der signalduino per lan oder wlan angebunden ist, dann werden die raw Nachrichten im telnet Fenster angeschaut.
Da macht es mehr Sinn die Reduzierung abschaltbar zu machen. Wer sich dann die raw Nachrichten im seriellen Monitor anschauen will, kann die Reduzierung kurz abschalten. Z.B CDR zum abschalten und CER zum Einschalten der Reduzierung. Ein get config ergibt dann "MS=1;MU=1;MC=1;Mred=1"
Wir können es ja so machen, dass die Ausgabe erst mal unkomprimiert ist und sich das SIGNALduino Modul die Ausgabe dann auf die komprimierte Form umstellt.
Bei der Baudrate habe ich auch überlegt, ob das Modul nicht einfach die Baudrate ändern könnte.
Ja, das ist eine gute Idee. Wir können dafür einen neuen Befehl XR einführen. Ist wie XE, zusätzlich wird dann noch die Reduzierung aktiviert. In der sub SIGNALduino_CheckCmdResp könnte dazu z.B. folgendes eingebaut werden
if ($ver =~ m/^V 3\.3\.1[a-zA-Z]/) { # Nachrichten reduzierung wird nur unterstuetzt wenn hinter der Version ein Buchstabe steht
SIGNALduino_SimpleWrite($hash, "XR"); # enable receiver and enable raw message compress
} else {
SIGNALduino_SimpleWrite($hash, "XE"); # enable receiver
}
Im code ist ein bug.
Der Arduino schmiert ab. Im Unittest taucht der Fehler nicht auf.
Leider habe ich den Fehler noch nicht gefunden. Am generellen Ablauf haben wir ja nichts geändert. Der Fehler müsste danach in der Verwendung des message Objektes liegen, was ich aber recht gut durchgetestet habe.
Interessant finde ich noch, dass der Fehler erst nach ein paar Minuten auftaucht. Das deutet darauf hin, dass es eher ein Problem mit der Speicher Nutzung ist.
Kannst Du mal Deinen aktuellen Code nach dev-r33_messagecompression commiten?
@Ralf9
ich habs noch mal aktualisiert... waren noch zwei Fehler die ich gefunden habe.
ist dies Dein aktueller Code? https://github.com/RFD-FHEM/SIGNALDuino/blob/dev-r33_messagecompression/src/_micro-api/libraries/signalDecoder/src/signalDecoder.cpp
Mir ist nicht klar wie es damit funktionieren soll.
inline void SignalDetectorClass::addData(const uint8_t value)
{
message += value;
//message.addValue(value);
messageLen++;
}
if (message[i] == pattern_pos) //
muß dies nicht so heissen?
if (message.getValue(idx) == pattern_pos)
genauso hier:
if (message[i] == idx2)
und hier. Wenn in der message[i]) 2 mal 4 Bit gespeichert sind, passt es so nicht:
for (uint8_t i = mstart; i <= mend; ++i)
{
MSG_PRINT(message[i]);
}
Die klasse Bitstore ist mit zwei Operatoren ausgestattet. Message ist ein Objekt der Klasse Bitstore und kein "array"
[] ist quasi identisch zu getValue(index) und += ist identisch zu addvalue(value)
Ich habe die Vermutung, der crash passiert nur, wenn der MC Decoder aktiv ist.
Grüße Sidey
Folgendes habe ich im Seriellen Monitor jetzt mal gehabt:
MC;LL=0;LH=-1056;SL=1799;SH=904;D=55555555332AAD5552CCD2CAB2B4B2AAAAB4CACB4AB2AAD4CAB2;C=487;L=207;R=13; MU;P1=904;P2=-3076;P3=-1056;P4=-565;P8=8481;P10=8197;P12=31744;P16=13;P17=12800;P19=-11239;P20=-19206;P21=-2943;P22=-25349;P23=-11263;P25=-19453;P26=-30467;P27=-9215;P28=-27397;P30=31995;P31=-5117;P32=19539;D=20300021000011002000102324300023243220232430004124161141000611412430002324300021303000232430002324300041243000433010004330100043243601232416114124300023241611412430002130300041243000433010002324300023243000232430002130300041241611412430002130360123241;CP=0;R=13; 20290 20290
Also völliger Murks ab Beginn der MU Nachricht
Die klasse Bitstore ist mit zwei Operatoren ausgestattet. Message ist ein Objekt der Klasse Bitstore und kein "array"
[] ist quasi identisch zu getValue(index) und += ist identisch zu addvalue(value)
Ich finde dies macht es nur unnötig kompliziert und erzeugt neue Fehlerquellen. Dadurch ist der Code auch schwerer zu verstehen. Ich denke um dies zu verstehen braucht man recht gute programmier Kenntnisse und muss sich recht tief hineindenken. Meine programmier Kenntnisse reichen nicht aus um dies komplett zu verstehen. Ich kann es nur ungefähr erahnen wie es funktioniert.
Das mit den Operatoren ist doch genau so wie beim String Objekt.
Zumindest habe ich die Ausgabe von 20290 ausfindig gemacht:
if (bytecount >= buffsize) Serial.println('OOB');
mit
Serial.println("OOB");
Kommt dann die richtige Ausgabe. Beachtlich ist, dass es oft zu einem oob event kommt,
Ich glaube ich habe einen Fehler ausfindig gemacht. Der musste eignentlich im aktuellen Code auch enthalten sein.
Aus dem einfachen Mustererkenner ist doch ein etwas schwer zu verfolgender Code geworden. Die Zustandsvariablen sollten das Auslösen von Aktionen vereinfachen. Das hat mich gestern doch einige Stunden gekostet herauszufinden, in welchem Abschnitt das Problem auftaucht.
Identifiziert habe ich zwei Stellen an denen buffermove aufgerufen wird. Wird buffermove mit dem Parameter 0 oder 255 aufgerufen, dann passiert nichts.
Der Erste Aufruf wurde auch schon in der Vergangenheit abgefangen. Die 255 (liegt außerhalb vom Message Buffer) habe ich jetzt erst abgefangen. Das führt zu einer Endlosschleife. Früher wurde wohl einfach ein byte einer anderen Variable verschoben (nicht gut).
Zumindest habe ich festgestellt, dass die Variable mend den Wert 255 einnehmen kann. Wenn mend 255 ist, dann müsste messsageLen auchn255 betragen. Das wird im buffermove abgefangen und wir drehen uns im Kreis.
Nach den bezreffenden Aufrufen von buffermove wird ungeachtet des Ausgangs m_truncated auf true gesetzt, was am Ende von process message wiederum dazu führt, dass kein reset aufgerufen ist.
Zusammengefasst:
Lösungswege: Wir könnten an etlichen Stellen auf messagelen >= maxMsgLen prüfen und dann gewisse Aktionen auslösen.
Alternativ konnten wir auch noch b_overflow auswerten.
Es besteht auch die Möglichkeit die Variable messagelen durch die valuelen aus der Klasse Bitstore zu ersetzen. (Sollte auf jeden Fall mal gemacht werden)
Die eigentliche Quelle des Peoblemes liegt aber meiner Meinung nach im setzten der Variable m_truncated obwohl kein Puffer verschoben wurde. Vielleicht sollten wir m_truncated in buffermove setzen, wenn etwas verschoben wurde oder messagelen immer auf 0 setzen, wenn nicht geschoben werden konnte.
Evtl können wir auch auf das buffermove verzichten, wenn wir die messagebuffer Größe auf 508 erhöhen. Die größte mir bekannte raw Nachricht ist ein Oregon v2 Sensor mit 104 Bit, dieser müsste eigentlich noch in den messagebuffer reinpassen. Ist Dir noch eine größere raw Nachricht bekannt?
Naja, 104 bit können 208 Pulse oder auch mehr sein.
Beim Oregon v3 werden bei manchen Sensoren zwei Nachrichten hintereinander übertragen. Ob dann eine Nachricht komplett in den Puffer passt weiss ich nicht. Zumindest müsste es halt sichergestellt werden.
Dann hat man noch das Problem, dass eventuell noch weiter Signaldaten im Puffer sind. Die kann man nur erhalten, wenn man den Puffer nicht komplett leert.
Das Erhöhen des Puffers halte ich nicht unbedingt für die richtige Variante. Es löst das Problem ja nicht, es vermeidet es unter Umständen nur. Anstelle vom move könnte man den Puffer auch ein Zeiger auf Start verpassen und es eher wie einen ring buffer betreiben.
Ich habe gestern nur noch ein bisschen gesucht.
Das Problem mit m_truncated und dem vollen Puffer scheint ein Folgefehler zu sein.
Irgendwann läuft valcount und messagelen auseinander. Das dann movebuffer nicht mehr klappt ist verständlich. Ich muss doch noch etwas weiter suchen, um den Initialen Fehler zu finden. Immerhin habe ich festgestellt, dass ich den Fehler schnell reproduziert bekomme, wenn ich auf einer Fernbedienung mal 2 Sekunden gedrückt halte.
Hast Du schon mal getestet ob der Fehler auch im dev-r33_cc1101 aufritt? Dieser Fehler hätte doch eigentlich schon auffallen müssen, oder tritt der Fehler nur auf, wenn die empfangene Nachricht größer als der messagebuffer ist?
Ich habe es nicht getestet, aber ich bin recht sicher, dass der Fehler schon lange auftritt.
Man könnte mal prüfen, ob messagelen auf 255 geht. Davon gehe ich aus.
Der Fehler wird jetzt erst transparent, da die bitstore Klassen prüft, ob außerhalb ihres Speicherbereiches gearbeitet werden soll.
Die messagelen Variable hat halt in “falsche“ Speicherbereiche geschrieben und dann nach einem Überlauf wieder bei 0 begonnen.
In der dev-r33_cc1101 passt auch einiges nicht. Ich habe eine debugausgabe eingebaut. Mit der messageLen passt was nicht.
MS;P0=370;P1=-1084;P2=1120;P3=-395;P4=-11254;D=04012301010101010101010101010101010101012301230101;CP=0;SP=4;R=77;
mstart 26 mend 75 messageLen 177
MS;P2=-1113;P3=1106;P4=-416;P5=342;P6=-11307;D=56523452525252525252525252525252525252523452345252;CP=5;SP=6;R=74;O;
mstart 49 mend 98 messageLen 254
MS;P0=-413;P1=338;P2=-1112;P3=1106;P4=-11272;D=14123012121212121212121212121212121212123012301212;CP=1;SP=4;R=75;
mstart 45 mend 94 messageLen 196
MS;P0=-11295;P1=346;P2=-1113;P3=1104;P4=-420;D=10123412121212121212121212121212121212123412341234;CP=1;SP=0;R=72;O;
mstart 49 mend 98 messageLen 254
MS;P0=-404;P1=355;P2=-1092;P3=1127;P4=-11264;D=14123012121212121212121212121212121212123012301230;CP=1;SP=4;R=75;
mstart 45 mend 94 messageLen 146
MS;P1=-3924;P2=481;P3=-980;P4=-1955;D=21232423242423242324232324232323232423242324242323242424242323242423242323;CP=2;SP=1;R=249;
mstart 74 mend 147 messageLen 160
Was Passt da nicht? mend ist immer kleiner als messageLen... und mstart ist kleiner als mend.. Sieht für mich gut aus.
mstart 49 mend 98 messageLen 254
ist das ok, daß das message Ende bei 98 ist, die messageLen aber 254 ist?
Ja, ich würde sagen das ist in Ordnung. Das besagt nur, dass an Position 49 und 99 die Sync Sequenz gefunden wurde. Der Puffer müsste dann ab von 1bis98 gelöscht werden. Die Werte ab 99 rutschen dann an Position 0.
Ich habe in der cc1101 Version
if (start > messageLen - 1 || start == 0) { DBG_PRINT(__FUNCTION__); DBG_PRINT(" start oor "); DBG_PRINT(start);
eingefügt.
Die Funktion bufferMove liefert dann ab und an Folgende Meldung: bufferMove start oor 132
Kann dann zwischen 99 und 254 eine weitere Nachricht im message buffer sein?
Ist es ok, daß am Ende von jedem processMessage() Aufruf ein message buffer reset durchgeführt wird?
if (!m_truncated)
{
reset();
}
zwischen 99 und 254 sind bestimmt noch Wiederholungen.
der Reset ist okay an der Stelle, solange m_truncated nicht aufgerufen wurde. m_truncated sollte immer dann gesetzt sein, wenn im Puffer platz gemacht wurde
Es gibt demnach Temperatursensoren, bei denen es zwischen den Wiederholungen keine Pause gibt.
if (!valid)
{
// Try output
m_overflow = (messageLen == maxMsgSize) ? true : false;
processMessage();
}
Momentan wird hier bei jedem nicht validen empfangenen Puls ein Reset durchgeführt, auch wenn die minMessageLen noch nicht erreicht wurde. Und bei jedem reset wird der komplette message buffer gelöscht. Ist dies notwendig, wenn es keine MC Nachricht ist?
Wenn die messageLen noch kleiner als minMessageLen ist, ist es eigentlich unnötig bei jedem nicht validen pulse den kompletten reset durchzuführen. Es wird jedes mal der komplette message buffer gelöscht, auch wenn z.B. nur 5 Einträge drin sind. Es müsste auch ein vereinfachter reset reichen:
if (!valid) {
if (mcDetected == true || messageLen >= minMessageLen) {
// Try output
m_overflow = (messageLen == maxMsgSize) ? true : false;
processMessage();
} else {
// vereinfachter reset
message.reset(messageLen); // message buffer nur bis messageLen löschen
messageLen = 0;
patternLen = 0;
pattern_pos = 0;
for (uint8_t i = 0; i<maxNumPattern; ++i)
histo[i] = pattern[i] = 0;
tol = 150;
}
inline void SignalDetectorClass::addData(const uint8_t value)
{
if (message.addValue(value))
{
messageLen++;
}
}
Ein message buffer überlauf dürfte hier eigentlich nie vorkommen. Dies bedeutet ja, daß pulse verloren gehen. Bei einem vollen message buffer müsste doch vor dem addData ein buffermove oder message reset erfolgen.
ich habe versucht nach jeder gesendeten Raw Nachricht den freien FIFO zu senden, aber irgendwas passt nicht. Es funktioniert nicht so wie ich gedacht habe. Der freie FIFO wird nicht nach jeder Raw Nachricht gesendet. Mache ich da einen Denkfehler?