Queremos hacer un intérprete de comandos sencillo y así poder cambiar parámetros (como los valores del pid) de forma rápida y ver rápidamente el resultado, sin tener que recompilar y subir el sketch. Tambien lo usaremos en el futuro para lanzar rutinas concretas o pruebas determinadas.
Creamos una función comando_lee_serial
que acumula los caracteres introducidos
por el puerto serie en un pequeño buffer (inicialmente de 16 caracteres,
creemos que será suficiente). Esta función se puede llamar en el bucle de main()
y no es bloqueante, aunque en las pruebas que estamos haciendo actualmente nos
conviente esperar la introdución de comandos hasta que lancemos la orden especial
‘go’
void comando_lee_serial() {
while (Serial.available()) {
caracter = Serial.read();
buffer[buffer_idx] = caracter;
if (caracter == COMANDO_FIN) {
if (buffer_idx > 0) {
buffer[buffer_idx] = 0;
_procesa_buffer();
comando_init();
}
} else {
buffer_idx += (buffer_idx > COMANDO_MAX_TAMANO-1?0:1);
}
}
}
Hemos decidido que los comandos tendrán la forma \<comando\> \<parametro\>
,
separados por un espacio. Para simplificar, sólo permitiremos 0 o 1 parámetro.
El comando especial _go_
simplemente pone una variable a true que se puede consultar en
el bucle principal (por ejemplo, para lanzar una prueba).
comando_prompt();
while (!comando_go()) {
comando_lee_serial();
}
Serial.println("GO!");
No nos complicamos la vida y lo que tenemos es una lista de strcmp
con las instrucciones
que vayamos definiendo.
void _procesa_comando(char *token, char *parametro) {
if (!strcmp(token, "kp")) {
motores_set_kp_lineal(atof(parametro));
Serial.print("kp=");
Serial.println(motores_get_kp_lineal());
} else if (!strcmp(token, "kd")) {
motores_set_kd_lineal(atof(parametro));
Serial.print("kd=");
Serial.println(motores_get_kd_lineal());
}
else if (!strcmp(token, "ki")) {
motores_set_ki_lineal(atof(parametro));
Serial.print("ki=");
Serial.println(motores_get_ki_lineal());
}
}
Todo es muy sencillo y rápido. Como todo lo que estamos haciendo últimamente, al no tener exactamente claras las necesidades, lo programamos en prototype mode y veremos cómo resulta. No hay (ni creemos que habrá) control de errores, eco local, ni nada. Si queremos ver lo que tecleamos, usaremos el modo estándar de las comunicaciones serie y lanzaremos el monitor de esta forma:
pio device monitor --echo