Sfondo
Sto scrivendo firmware C ++ con freertos su penplottingrobot. È un XYplotter di sblocco e il firmware si sta collegando al software mDraw per le istruzioni di comando tramite i driver USB. Il programma MDraw invia comandi Gcode. Se devi sapere, c'è una matita controllata da un servo di modulazione di larghezza d'onda e il plotter viene azionato con motori passo-passo a due assi.
Ai nostri intenti e quegli input mDraw sono ottenuti come std::string
s e inviati a Gcodeparser::parseCommand(std::string)
.
Problema
Esiste una soluzione più elegante di quanto segue ???
// quindi il codice funziona sin d'ora, ma non ha una buona interfaccia o usabilità
Sto utilizzando un parser_task
, con un oggetto Gcodeparser
per analizzare quei Gcodecommands
. .ParseCommand()
memberfunction richiede std::string
come parametro e restituisce un CommandStruct
in base al valore. CommandStruct
contiene solo tipi di dati semplici-vecchi come int
, enum
e bool
. Dopo che un comando legale è stato analizzato, viene quindi inviato a una coda freeRTOS per valore ( CommandStruct
viene inviato alla coda). La coda è necessaria per comunicare con l'altra attività, chiamata execute_commands_task
, che ovviamente sta leggendo questa coda.
Ho diverse possibilità di legale Gcode
s, ma condividono solo due datamembers in comune: enum {M4, G1, G28 ... }baseType
e bool isLegalCommand
.
Altrimenti tutti quei "diversi tipi di basi" Gcode
s possono avere una quantità differente di datamembers, di tipi diversi (in genere bool
o int
datamembers, ma ci sono coordinatevalue
s, pencilservo
valori, clockwisemotordirectionvalue
s ecc ...).
Quindi, la mia soluzione corrente che era stupida (ma funziona), era quella di mettere tutti i datamembers disponibili in quel CommandStruct
. In questo modo puoi utilizzare quella struttura per passare qualsiasi tipo di comando Gcode
nella coda freeRTOS e ottenere comunque dati validi.
Il codice è fastidiosamente brutto perché ci sono datamembers non utilizzati per ogni comando Gcode
...
Ma devo ancora essere in grado di passare qualcosa nella coda freeRTOS che è in grado di trasmettere tutti i dati richiesti.
#pragma once
struct CommandStruct {
enum {
M1,
M4,
M10,
G1,
G28,
M5,
M11,
M28,
M2,
uninitialized
} commandWord; //any Gcode command has commandWord (essentially a basetype)
int commandNumber; //pencilServoParameter, or laserParameter [0,255]
int penUp; //parameter for M2 command
int penDown; //parameter for M2 command
int height; //parameter for M5 command
int width; //parameter for M5 command
int speed; //parameter for M5 command
bool xMotorClockwise; //parameter for M5 command
bool yMotorClockwise; //parameter for M5 command
bool isLegal; //any Gcode command has legality
int xCoord; //coords for G1command HUNDREDTHS of mm
int yCoord; //coords for G1command HUNDREDTHS of mm
CommandStruct() {
commandWord = uninitialized;
commandNumber = -1;
penUp = -1;
penDown = -1;
height = -1;
width = -1;
speed = -1;
xMotorClockwise = true;
yMotorClockwise = true;
isLegal = false;
xCoord = -1;
yCoord = -1;
}
};