Hoop gegevens filteren uit UART stroom

Ik heb een device dat een stroom gegevens genereert en dat naar een PIC 18F4550 stuurt.

Uit deze gegevens moet ik een aantal keer een stroom gegevens filteren.

Stel je de volgende reeks voor:

&é"'((§§è!"Dier": "Aap"'((§èè§('"Soort": "Harig""'(§è!çà"Voedsel": "Bananen""é(§§èè!"Dier": "Kip" "("'§"'§"Soort": "Raar"(ç§ç!(§è"Voedsel": "Graantjes"ç!è§(')àç!"Dier": "Olifant"'(§è!çà'è!!ygjytg"Soort": "Slurfig"§('è§!è"Voedsel": "Koekjes"'(§è!ç

Hier komt drie keer de reeks "Dier" "Soort" en "Voedsel" in voor.
Wat ik nodig heb is een tactiek om daar reeksen van te maken bijvoorbeeld:

Dier1 = Aap
Dier2 = Kip
Dier3 = Olifant
Soort1= Harig
Soort2 = Raar
Soort3 = Slurfig
Voedsel1 = Bananen
Voedsel2 = Graantjes
Voedsel3 = Koekjes

De reeks van te ontvangen data kan lang zijn (>3000bytes).

Wat is de best mogelijke tactiek?
Bestaan daar goede oplossingen voor?

De gegevens komen met 9600baud binnen dus ik denk dat ik tussen elke ontvangen byte wel even kan checken of het een mogelijke hit is?

Ik zoek dus gewoon een tactiek waarmee ik dat het simpelst kan oplossen.

Arco

Special Member

Het ligt eraan wat voor compiler je gebruikt. Bij Mikrobasic gebruik ik gewoon de StrStr() functie om substring te vinden... (in een buffer van ingekomen data)
Ik gebruik soms ook 2 UARTS om data te filteren en modificeren. (data komt via UART1 binnen en gaat via UART2 weer uit, pic zit dan tussen DTE en DCE)

[Bericht gewijzigd door Arco op zondag 24 juli 2016 00:02:44 (43%)

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Het ligt er ook nogal aan op welk platform je zit. Windows, Linux, MacOS, of moet het een op zich staand iets zijn, dan kun je denken aan Arduino, Raspberry Pi, of een eigen microcontroller bord.

Zo zijn er tientallen manieren van aanpak, waar je nul komma niets over zegt.

Mijn echte naam: Joris | Mijn elektronica website: Fuzzcraft.com

Op 24 juli 2016 00:00:05 schreef Arco:
Het ligt eraan wat voor compiler je gebruikt. Bij Mikrobasic gebruik ik gewoon de StrStr() functie om substring te vinden... (in een buffer van ingekomen data)
Ik gebruik soms ook 2 UARTS om data te filteren en modificeren. (data komt via UART1 binnen en gaat via UART2 weer uit, pic zit dan tussen DTE en DCE)

Ik gebruik (oh, wat zeg ik nu??), Flowcode om dat te programmeren.
Hier zit ook een circular buffer in maar die is te klein om alle data te bevatten.

In die macro "circular buffer" is ook een find string..

Moet mij daar eens in verdiepen

Op 24 juli 2016 00:22:15 schreef Fuzzbass:
Het ligt er ook nogal aan op welk platform je zit. Windows, Linux, MacOS, of moet het een op zich staand iets zijn, dan kun je denken aan Arduino, Raspberry Pi, of een eigen microcontroller bord.

Zo zijn er tientallen manieren van aanpak, waar je nul komma niets over zegt.

Zoals ik zei, een PIC 18F4550.
Dus redelijk basic qua functies..

OK, sorry. Verkeerd begrepen, ik dacht dat je de stream tussen twee punten ergens mee wilde aftappen.

Je werkt dus met die 18F4550.

Als de buffer te klein is, dan moet je verschillende keren de buffer inladen en als de buffer vol is je zoekopdracht doen. Als dat niet snel genoeg gaat, dan gebruik je twee buffers, en verwerk je de ene terwijl de andere volloopt.

[Bericht gewijzigd door Fuzzbass op zondag 24 juli 2016 00:47:22 (47%)

Mijn echte naam: Joris | Mijn elektronica website: Fuzzcraft.com

Je wilt actie ondernemen als er "banaan" of "aap" langskomt?

de standaard truuk is om een statemachine te maken. als je dan "a" ontvangt gaat ie naar de state "a ontvangen", en kan ie nog naar een hoop andere states maar ook naar "nog een a ontvangen". daarna kan door ontvangst van "p" de statemachine "aap" afhandelen of met "r" nog mogelijk doorlopen naar "aardbei".

Er zijn programmas die gegeven zo'n lijst met te herkennen woorden de statemachine voor je schrijven (de sourcecode voor die statemachine!).

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 24 juli 2016 00:46:37 schreef rew:
Je wilt actie ondernemen als er "banaan" of "aap" langskomt?

de standaard truuk is om een statemachine te maken. als je dan "a" ontvangt gaat ie naar de state "a ontvangen", en kan ie nog naar een hoop andere states maar ook naar "nog een a ontvangen". daarna kan door ontvangst van "p" de statemachine "aap" afhandelen of met "r" nog mogelijk doorlopen naar "aardbei".

Er zijn programmas die gegeven zo'n lijst met te herkennen woorden de statemachine voor je schrijven (de sourcecode voor die statemachine!).

Ok, dank u..
Ik was in die richting al bezig.
Soms denk ik dat ik veel te ver zoek, maar schijnbaar moet ik zo basic blijven zoeken..

Omdat ik nooit echt heb leren programmeren denk ik soms dat er standaard oplossingen zijn voor dergelijke problemen. Dan weet ik niet hoe ik dat moet benoemen om het te zoeken.

Bedoel je niet dat je eigenlijk een multidimensionale array wil?

In PHP doe je bijvoorbeeld voor een voorraad en verkoop array van automerken:

code:


$cars = array
  (
  array("Volvo",22,18),
  array("BMW",15,13),
  array("Saab",5,2),
  array("Land Rover",17,15)
  );

In veel andere talen zijn er vergelijkbare manieren. Je kan de array vullen door bijvoorbeeld:

$beesten[$teller]['naam']=$gevonden_naam;
$beesten[$teller]['soort']=$gevonden_soort;
$beesten[$teller]['voer']=$gevonden_voer;

De teller hoog je na elk gevonden dier op. Als je dan wil weten welk beest nummer 9 is dan doen je:

print "Beest nummer 9 is een $beesten[9]['naam'] en die eet $beesten[9]['voer']. en ziet er $beesten[9]['soort'] uit.

Ik zal even de post van K7Jz verduidelijken.
Zoals net gezegd is, is deze oplossing niet echt praktisch:

code:


Dier1 = "Aap"
Dier2 = "Kip"
Dier3 = "Olifant"

Waarom niet?: een variable kun je in de meeste programmeertalen niet dynamisch maken.

Dit soort dingen sla je beter in een array op (of je nu bij 0 of 1 begint maakt voor het voorbeeld even niet uit):

code:


Dier[1] = "Aap"
Dier[2] = "Kip"
Dier[3] = "Olifant"

Hier ontstaat weer een ander probleem: Hoe weet je of je alle keywords hebt? (in dit voorbeeld "Dier" / "Soort" / "Voedsel").
Als je vantevoren exact weet welke keywords je hebt kun je meerdere arrays maken, voor elk keyword een array dat maakt het een stukken simpeler.

Maar stel dat het niet zo is dus je weet niet wat je kunt verwachten? Dan zul je een meerdimensionaal array moeten maken. Bijvoorbeeld:

code:


variable["Dier"][1] = "Aap"
variable["Dier"][2] = "Kip"
..
variable["Voedsel"][2] = "Graantjes"

Dit ziet er dan al netjes overzichtelijk uit.
Afhankelijk van je gebruikte programmeertaal kan deze constuctie simpel te implementeren zijn maar ook heel complex!
(in C heel lastig, perl/python/ruby => makkie)

Een string als index gebruiken (in dit geval "Dier") is in een aantal high level (script) talen erg simpel: Zoiets noemt men een hash table / dictonary etc. De index noemt men dan de "key" en de inhoud de "value".
Ik weet niet of dit in flowcode kan.

Nu even over de string ontleden: Ik jouw voorbeeld zie ik regelmatig dit stuk string langs komen:

code:


.... "key" : "value" ....

Als dat echt consistent en altijd zo is kun je dat relatief makkelijk "parsen" mits de "key" een beperkte lengte heeft.

Je ontvangt alle tekens in een (ring) buffer als je nu een ":" tegenkomt kijk je in de buffer achteruit naar de eerste complete string die tussen de string quotes ("") staat, dat is je key en sla je die tijdelijk op.

Dan ga je verder kijken in de ontvangen buffer tot je weer een nieuwe string hebt gevonden, dus een stuk text tussen "". Dat is nu je value.

Nu heb je nog een andere uitdaging: Je zult per "key" een teller moeten bijhouden waar je mee doornummert. Dit kun je ook in een hash-table opslaan, bijvoorbeeld:

code:


count["Dier"] += 1;

Hierbij dien je rekening te houden dat als je een key tegenkomt die je nog nooit gezien hebt, eerst de hashentry op nul moet zetten.
Dus krijg je zoiets als pseudo code:

code:


if defined count[key] {
    count[key] += 1
} else {
    count[key] = 0
}
index = count[key]
// Opslaan
variable[key][index] = value

In sommige programmeertalen kun je meteen de hash variable incrementen, een "undefined" entry wordt bij een increment als 0 verondersteld.

Ik hoop dat je er iets aan hebt en je me nog kunt volgen, anders leg ik het nog wel verder uit.

1-st law of Henri: De wet van behoud van ellende. 2-nd law of Henri: Ellende komt nooit alleen.

Volgens mij heeft die 18F4550 teweinig ram/eeprom geheugen om al die te herkennen variabelen op te slaan, tenzij je het heel beperkt houdt.

LDmicro user.

Allemaal al bedankt.

Het moet allemaal vrij simpel dus ik dacht dat er echt basic "best practices" voor zouden bestaan.

In de programmeertaal kan niet veel enkel maar de basic bewerkingen qua nummerieke variabelen en string variabelen.

Maar, ik maak vooruitgang, ook al is het een hoop code.

Ik heb voor elke naam voor een veld een unieke code gevonden die die beschrijft (stel je voor in het voorbeeld dat ik gaf rt": is de enige keer dat dit voorkomt en dit geeft mij zeker het begin van de soort.

Ik zoek naar telkens er een r voorbijkomt en dan moet het volgende teken een t zijn, of ik reset de zoektocht.
Als alle tekens van de naam van het veld gepasseerd zijn zoek ik naar de eerste ".
Vanaf dan sla ik alle tekens op in een string variabele. Dit doe ik tot er weer een " voorbij komt, dan is alles van de eerste soort binnen.
Zo doe ik dat voor alle velden en de inputs.

Het lijkt te werken ook al is dit in mijn ogen nogal omslachtig.

Arco

Special Member

Noemt men een string parser; is vrij simpel te implementeren en heel gebruikelijk...

Arco - "Simplicity is a prerequisite for reliability" - hard-, firm-, en software ontwikkeling: www.arcovox.com

Ik ken dat flowcode niet, maar het zou kunnen dat die niet zo handig is met strings en zo.

Zo'n programma als "lex" wat sourcode voor je maakt zal dat wel niet in flowcode kunnen. Zelf maken is tricky.

De bottebijl methode is om de laatste 6 karakters te bewaren, te kijken of "dier:" daarin voorkomt, en dan te zoeken naar de quotejes.

four NANDS do make a NOR . Kijk ook eens in onze shop: http://www.bitwizard.nl/shop/

Op 24 juli 2016 23:58:24 schreef Arco:
Noemt men een string parser; is vrij simpel te implementeren en heel gebruikelijk...

Gevonden op WWW, dank u.
Soms weet ik niet hoe dit te benoemen.

Op 25 juli 2016 07:53:15 schreef rew:
Ik ken dat flowcode niet, maar het zou kunnen dat die niet zo handig is met strings en zo.

Zo'n programma als "lex" wat sourcode voor je maakt zal dat wel niet in flowcode kunnen. Zelf maken is tricky.

De bottebijl methode is om de laatste 6 karakters te bewaren, te kijken of "dier:" daarin voorkomt, en dan te zoeken naar de quotejes.

Mijn botte bijl methode lijkt te werken.

Wat ik nu doe is een interupt aanroepen als er een teken binnenkomt via UART, dan gaan kijken of die één van mijn filterelementen bevat.
Als dat zo is zoek ik of al mijn filterelementen gevonden worden om daarna alles wat tussen aanhalingstekens op te slaan in een string.

Het werkt, het enige obstakel heb ik schijnbaar net de wereld uitgeholpen.

Bedankt allemaal