Excelentes preguntas...
ea7ln:
Hay algo que me ha llamado la atención, y es que no he tenido que declarar la variable (horizontal) ni (vertical). Tiene algo que ver que le precede en el código "unsigned"?
Imposible referenciar una variable que nunca ha sido declarada, e imposible declararla más de una vez (cuando los nombres coinciden).
La palabra reservada "unsigned" es solo para darle una característica extra un tipo de dato de número entero: no molestarse con lidiar con el signo (sin negativos). Para efectos del programa hubiera sido igual con o sin esta palabra; sin embargo se usa para evitar el sobrecargo de cuidarse con el signo donde por contexto no se necesitan representar valores negativos. ¿Cierto o no que cuidar los signos es un dolor de cabeza al resolver ecuaciones en clase de matemáticas?
ea7ln:
Por otro lado y sin ánimo de abusar, solo intento ir aprendiendo poco a poco, ¿podrías explicarme esta parte del código?
(' ', n, sizeof(n) - 1)] = 0
En tu comentario indicas que es para leer la primera cifrar, ¿pero a que corresponde cada carácter?
Genial que lo preguntes, porque algunos se quedan con la mediocre idea de "si funciona, ¿por qué debo molestare en entenderlo?". En detalle sería así:
n[Serial.readBytesUntil(' ', n, sizeof(n) - 1)] = 0; // Leo la primera cifra
Debido a que los caracteres se codifican como ASCII, entiéndase caracter y byte como a la misma unidad básica para esta explicación.
Entiéndase por n como el nombre de una cadena de caracteres temporal.
Entiéndase por [] como índice del elemento al cual queremos accesar (adentro se coloca el equivalente a un número entero, inicia en cero).
Entiéndase por Serial a la referencia del objeto que manipula el puerto serial del Arduino.
Entiéndase por readBytesUntil a la función que recupera una secuencia de bytes desde un flujo ("stream" en inglés), y las almacena en un espacio contiguo de memoria llamado "vector" (a veces erróneamente llamado "arreglo" debido a la similitud en el nombre en inglés: "array"). Esta función se detiene cuando alguna de las siguientes se cumple:
- El último valor recuperado coincide con el del primer parámetro (en este caso al caracter del espacio en blanco, con un valor decimal de 32).
- La cantidad de bytes recuperados alcanzó el valor del tercer parámetro.
- El flujo ya no tiene más bytes para leer y además se superó el tiempo de espera ("timeout" en inglés). Para efectos del programa, esto no debería ocurrir durante la lectura o de lo contrario se nos convierten números incompletos.
Retorna, en forma de int, la cantidad de bytes que realmente fueron leídos. Dicho valor es aprovechado para determinar un índice.
Entiéndase por ' ' como al caracter que debería poner fin a readBytesUntil. El delimitador se excluye del resultado.
Entiéndase por sizeof a la "función del compilador" que retorna, en bytes, el espacio de memoria que ocupa una estructura de datos. El espacio por cantidad de elementos, es relativo al tipo de dato que maneja.
Se dice "del compilador" debido a que la secuencia de instrucciones que ejecuta, nunca es parte del código compilado; sino que el resultado se coloca implícitamente como reemplazo donde fue llamada. Por ejemplo:
Lo que en el código fuente se ve:
n[Serial.readBytesUntil(' ', n, sizeof(n) - 1)] = 0; // Leo la primera cifra
Lo que el compilador ve (en parte):
n[Serial.readBytesUntil(' ', n, 3)] = 0;
Eso último fue una ligera simplificación ya que el compilador no ve estructuras de datos, sino punteros de memoria. Lo más realista es que lo vea así:
*(n + Serial.readBytesUntil(' ', n, 3)) = 0;
Entiéndase por = 0 como al valor que se le va a asignar a esa posición. Estamos hablando del terminador de cadenas de caracteres ('\0' == 0); sin este, quien sabe cuanta "basura" llega a formar parte de la cadena.
Se utiliza sizeof(n) - 1 debido a la obligatoriedad del terminador, y de que además es mala práctica modificar valores fuera de un vector. Si n es de tamaño 4, es por eso que advertí sobre de que los números tengan máximo tres dígitos y sean positivos.
En este ejemplo puntual, no se pueden permitir negativos por tres razones:
- Tu sabes que para representar negativos necesitamos un caracter adicional: el guión ('-'); por lo tanto, no alcanza para el vector.
- atoi aunque pueda manejar números negativos, juntarlos con variables unsigned no es la mejor idea. ¿Valores entre 32768 y 65535 son válidos son para tu programa?
- De todas formas por contexto ni siquiera son necesarios los números negativos.
En resumen: recupera las partes que nos interesan (descartando los delimitadores), para luego convertirlos en variables.
Perdona que te haya inundado de tanta información, asimílala lento y con calma. Si te quedaste perdido en alguna parte, no dudes en preguntar por acá 