Combineert 2 State Machines?

Ik wil voordeel halen uit recent advies van dit forum door mijn project opnieuw te doen met behulp van de 'state machine'-logica, in een poging om verspilling van processortijd en het gebruik van variabelen te verminderen.

Ik start met de state-machine van Nick Gammons om de invoer van de seriële poort te verwerken 'voorbeeld http://www.gammon.com.au/statemachine , die alle verschillende mogelijke combinaties voor alle speciale besturingstekens 'gebeurtenissen' tegen alle mogelijke machinetoestanden toont - in wezen een tweedimensionaal raster.

Ik heb mijn doel verfijnd met het verwerken van seriële invoer in een indeling van " opdracht [parameters] [opties] ", vergelijkbaar met een DOS-opdrachtregelindeling, bijvoorbeeld: DIR "c : \ programmabestanden "/ w/s . Dit zou me bevrijden van het nodig hebben van een grote buffer [] en kop [] string, en vermijdt elke paring,

Daarom zijn mijn besturingselementen voor gebeurtenissen: spatie, komma, enkel aanhalingsteken, dubbele aanhalingstekens, forward-slash, Carraige Return en mijn 'statussen' zijn NULL, COMMAND, PARAMETER, OPTIONS

De status OPTIONS voegt tekens toe aan een tijdelijke tekenreeks [] totdat een komma of spatie-scheidingsteken of Carraige Return ervoor zorgt dat die optie naar behoren wordt verwerkt, waardoor de waarde mogelijk wordt opgeslagen in een herkende variabele.

De COMMAND- en PARAMETER 'toestanden' voegen tekens toe aan hun corresponderende commando [] en parameters [] strings, inclusief de speciale controle karakters als ze zijn opgenomen in enkele of dubbele aanhalingstekens (waardoor citaten deel uitmaken van een string indien gebruikt binnen een paar van het andere type).

Er lijkt dus een tweede toestandsmachine nodig te zijn voor NoQuotes, SingleQuotes en DoubleQuotes om de werking van de COMMAND-, PARAMETER- en OPTIONS-staten te wijzigen.

Hier heb ik geen neuronen meer, want het enige dat ik zie is een onmogelijk complex 2-machine-toestand driedimensionaal raster met te veel mogelijke permutaties.

Maar ik vermoed dat er een zeer praktische manier moet zijn om dit te implementeren, omdat het de kern vormt van bijna alle commandoregelhulpmiddelen die dateren uit een tijd dat processorkracht en geheugenbeschikbaarheid zeldzamer waren dan die van kippen, en die oude DOS-opdracht lijnhulpprogramma's moesten zo klein mogelijk zijn als mogelijk was, inclusief het parseren van de opdrachtregel.

Dus kan iemand een haalbaar model (machine-staat of anderszins) voorstellen voor het verkrijgen van het commandoregel-type-formaat uit de invoer?

BIJWERKEN

Oh lieverd ... ik heb zojuist een andere complicatie gezien die ik nog niet eerder had gezien, namelijk dat '/' opties niet altijd aan het einde zijn, wat betekent dat behalve als de opties staat verandert door carraige-return, optietoestand verandering door scheidingsteken moet terugkeren naar de staat voorafgaand aan de wijziging van de optiestatus (pfff, ik hoop dat dat enigszins logisch is). Hoe dan ook, ik denk dat het terug aan de tekentafel is, omdat deze benadering waarschijnlijk te gecompliceerd lijkt, zoals de 2 antwoorden al suggereren.

1
De vraag is heel erg Arduino omdat ik de inkomende serie wil lezen en deze wil 'sorteren' in de opdracht plus optionele parameter plus optionele besturingsopties, daarom gaf de vermelding van de DOS-opdrachtregel slechts een syntaxisvoorbeeld van het vereiste seriële formaat.
toegevoegd de auteur R.M., de bron
Het is voor wat voor lokale 'commando's' en 'parameters de arduino ook geprogrammeerd is om in inkomende series te worden ontvangen, bijv .:' LED1 AAN ', of' IRSEND 'NEC 0xFFEE9123 32 ". De opties zijn voor optionele arduino-naar-Arduino verzenden van besturingsinformatie, zoals/c (hecksum) = nnn,/l (ength) = nnn,/s (ource) = nnn etc. Het idee is om inkomende serie a te lezen byte tegelijkertijd verzenden en naar commando of params of opties sturen, in plaats van een extra grote bufferreeks achteraf te moeten parsen.
toegevoegd de auteur R.M., de bron
De gebruikelijke manier om interacterende staten over te dragen is om de interacties uit te breiden naar hun eigen staat. d.w.z. PARAMETER versus SingleQuotes_PARAMETER DoubleQuotes_PARAMETER, waar hun verwerking vrijwel dezelfde code zou kunnen delen. Zie github.com/Traumflug/Teacup_Firmware/blob/master/gcode_parse‌ .c voor een groot voorbeeld. Dit is ook te breed (je hebt geen syntaxis om te gebruiken) en het staat echt niet ter discussie voor een Arduino-gericht forum.
toegevoegd de auteur Dave X, de bron
Een andere manier om het als een staatsmachine te beschouwen is dat uw toestandsruimte een veeldimensionale vector van toestandsvariabelen is, met een {COMMAND, PARAMETER [], OPTIONS [], enz ...)
toegevoegd de auteur Dave X, de bron
Een soort algemene DOS-syntaxis of de veel gelimiteerde syntaxis voor een bepaald commando? Met een bepaalde opdracht zijn er slechts een beperkt aantal parameters en opties en kan uw/parser/state-machine ze in hun/proces-/toestandvariabelen ordenen, een beetje zoals Teacup dat doet.
toegevoegd de auteur Dave X, de bron
Ik zou denken dat je de opdracht niet kunt verzenden totdat het laatste teken van de laatste optie is geparseerd, dus de COMMAND, PARAMETERS en OPTIONS moeten allemaal slechts een vector zijn van parameters voor de volgende verwerkingsfase. Je moet ze allemaal verzamelen voordat je verder gaat. Is de 'LED1' in 'LED1 AAN' een opdracht? /// Voor uw bijgewerkte Q verandert de '\ n' de status van het systeem van het parseren van bytes naar het opschonen van de parameterstatus en het uitvoeren van een commandostatus/oneshot, bijvoorbeeld github.com/Traumflug/Teacup_Firmware/blob/master/… tot # 390.
toegevoegd de auteur Dave X, de bron

2 antwoord

Suggestie: - probeer niet om de state-machine-hiërarchie in een grote, platte state-machine te "moosh" (dat is een technische term!). Op die manier ligt gekte. Houd bijvoorbeeld de toestandsmachine NULL, COMMAND, PARAMETER, OPTIONS} en, waar u in een van die staten iets anders nodig hebt dan het eenvoudig verzamelen van reeksen, een parser SM die geschikt is voor de soort (n) invoer die u verwacht bij dat punt - een nummer, een aanhalingsteken, een specificatie voor een optie, enz.

3
toegevoegd
U kunt ook overwegen als een middelpunt, een universele parser die verschillende invoertypen aankan, maar losstaat van de hoofd-SM. Je weet het het beste, als je snel een aantal SM-hiërarchieën hebt opgeschaald (dat is 'schets' zoals in 'cirkels en pijlen', niet zoals in 'codering').
toegevoegd de auteur caryden, de bron
Ik denk dat ik het begrijp (waarschijnlijk te laat om gekte te voorkomen, alhoewel ik denk dat de staatsmachine misschien al mijn hoofd heeft 'gemoord'). Gebruik zoals u zegt NULL, COMMAND, PARAMETER als de statussen om doorheen te veranderen. En hoewel NoQuotes, SingleQuotes, Double Quotes en mogelijk Opties zelf een staatsmachine zouden kunnen rechtvaardigen, het best gewoon om ze te behandelen als afzonderlijke processen binnen de hoofdtoestandsmachine.
toegevoegd de auteur R.M., de bron

Persoonlijk denk ik niet dat Nick heeft geadviseerd om het parseren van opdrachtregelpatronen met een toestandsmachine uit te voeren. Zijn voorbeeld gaat over het veranderen van een toestandsmachine op basis van de invoer van de opdrachtregel.
Ik heb een aantal commandoregel-parsers geschreven en ik heb nooit een staatsmachine gebruikt om dit te doen. Ik zou niet adviseren om een ​​staatsmachine te gebruiken om dit te doen.
Eenvoudig parseren van tekenreeksen is veel eenvoudiger.

Edit To answer the remark below:
I would not advice to go byte by byte. I'd advice to go the line by line way. I have written a library to do read line by line and an article on how that one works. http://blog.baeyens.it/#post16
Here a link to the lib https://github.com/jantje/libraries/tree/master/SerialCommunicator.
Here is a parcing code example. It is not so interesting for you as I have it done in a stage by stage way in a very high level way of coding. https://github.com/jantje/libraries/blob/master/SerialBridgeCommunicator/SerialBridgeCommunicator.cpp#L21

Basically the algorithm is=
1 Take the first word;
2 identify the word.
3 If the command is complete ->do it
else Send the rest of the string to a specialized piece of code. (which has the same algorithm)

3
toegevoegd
Ik dacht dat mijn behoeften hetzelfde waren als het voorbeeld van Nicks - om inkomende series een byte tegelijk te lezen en naar commando of params of opties te sturen tijdens de vlucht en actie te ondernemen zoals aangewezen na het lezen van een carraige-return, in plaats van dat je dan een analyse moet uitvoeren extra grote bufferstring na. Maar het maakt niet uit dat ik op de maan schiet - je zei eerder dat je eerder een commandoregel-parser had gedaan ... zou je toevallig een geschikt stroomschema of algoritme hebben?
toegevoegd de auteur R.M., de bron
Ik zou niet adviseren byte byte te gaan. Ik zou adviseren om de regel voor regel te volgen.
toegevoegd de auteur jantje, de bron