https://arduwiki.perut.org/api.php?action=feedcontributions&user=Lucario448&feedformat=atomArduWiki - Contribuciones del usuario [es]2024-03-28T17:02:10ZContribuciones del usuarioMediaWiki 1.27.7https://arduwiki.perut.org/index.php?title=File.name()&diff=4584File.name()2019-07-02T06:34:32Z<p>Lucario448: Página creada con «== Descripción == Retorna el nombre del archivo o directorio. == Sintaxis == <pre> archivo.name(); </pre> == Parámetros == Nada. == Retorna == El nombre del archivo o...»</p>
<hr />
<div>== Descripción ==<br />
Retorna el nombre del archivo o directorio.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.name();<br />
</pre><br />
<br />
== Parámetros ==<br />
Nada.<br />
<br />
== Retorna ==<br />
El nombre del archivo o directorio, o una cadena vacía si la instancia representa un archivo que nunca se abrió ([[char]]* o [[string]]).<br />
<br />
== Advertencias ==<br />
* El retorno debe considerarse como una cadena de sólo lectura, de lo contrario se corre el riesgo de corromper la instancia (o incluso más allá todavía).<br />
<br />
== Comentarios ==<br />
* Cerrar el archivo no borra esta información; por lo tanto, permanece accesible aún después de explícitamente haber ordenado el cierre. Cabe aclarar que si el archivo no se logró abrir desde el principio, este dato se halla vacío.<br />
* Si la instancia fue creada mediante [[SD.open()]], se retornará una copia (truncada a 12 caracteres) del nombre ingresado en el primer parámetro (la ruta no forma parte del nombre).<br />
* Si la instancia fue creada mediante [[File.openNextFile()]], se retornará la versión 8.3 del nombre del archivo/directorio en cuestión. Si el archivo/directorio fue creado mediante un sistema con soporte para LFN (ej.: un PC), el nombre retornado aquí podría parecer extraño si se violó alguna regla de los nombres 8.3. Por ejemplo: '''Mis frases favoritas.txt''' podría aparecer como '''MISFRA~1.TXT'''.<br />
* La versión mejorada de esta librería ('''SdFat''') hace esta función "obsoleta", sugiriendo que se utilice '''getName()''' en su lugar (por la añadida compatibilidad con LFN).<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
void setup() {<br />
// Inicializaciones<br />
<br />
File raiz = SD.open("/");<br />
<br />
if (!raiz) {<br />
Serial.println("Error de apertura");<br />
return;<br />
}<br />
<br />
Serial.println("Archivos en la raiz:");<br />
File actual;<br />
<br />
while ((actual = raiz.openNextFile())) {<br />
Serial.print(actual.name());<br />
Serial.print("\t\t\t");<br />
<br />
if (actual.isDirectory()) {<br />
Serial.println("Directorio");<br />
} else {<br />
Serial.print(actual.size());<br />
Serial.println(" bytes");<br />
}<br />
<br />
actual.close();<br />
}<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Libreria SD</categorytree><br />
<br />
== Referencias ==<br />
[[Category:Libreria SD]]</div>Lucario448https://arduwiki.perut.org/index.php?title=File.size()&diff=4583File.size()2019-07-02T05:26:36Z<p>Lucario448: Página creada con «== Descripción == Retorna el tamaño del archivo. Su valor inicia en cero cuando se abre uno recién creado o con la opción '''O_TRUNC'''. == Sintaxis == <pre> archivo.s...»</p>
<hr />
<div>== Descripción ==<br />
Retorna el tamaño del archivo. Su valor inicia en cero cuando se abre uno recién creado o con la opción '''O_TRUNC'''.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.size();<br />
</pre><br />
<br />
== Parámetros ==<br />
Nada.<br />
<br />
== Retorna ==<br />
El tamaño en bytes del archivo, o 0 si la instancia representa un directorio/carpeta o archivo sin abrir. ([[unsigned long]]).<br />
<br />
== Advertencias ==<br />
* Ya que el valor cero también se retorna en archivos sin contenido, se recomienda verificar directamente lo de estar abierto y si es un directorio/carpeta, con tal de evitar confusión.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
unsigned long tamanioEnElementos() {<br />
return archivo.size() / sizeof(Registro);<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Libreria SD</categorytree><br />
<br />
== Referencias ==<br />
[[Category:Libreria SD]]</div>Lucario448https://arduwiki.perut.org/index.php?title=File.position()&diff=4579File.position()2019-07-01T02:05:52Z<p>Lucario448: Página creada con «== Descripción == Retorna la posición actual del "cursor" del archivo. Si retorna '''0''' significa que se encuentra al inicio; si retorna el mismo valor de File.size()...»</p>
<hr />
<div>== Descripción ==<br />
Retorna la posición actual del "cursor" del archivo. Si retorna '''0''' significa que se encuentra al inicio; si retorna el mismo valor de [[File.size()]] significa que se encuentra al final.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.position();<br />
</pre><br />
<br />
== Parámetros ==<br />
Nada.<br />
<br />
== Retorna ==<br />
La posición actual en bytes del "cursor", o -1 si la instancia representa un directorio/carpeta o archivo sin abrir. ([[unsigned long]]).<br />
<br />
== Advertencias ==<br />
* -1 en [[unsigned long]] equivale a 4294967295, lo cual puede resultar confuso si se está interactuando con un archivo cuyo tamaño alcanza el límite. En ese caso, se recomienda verificar directamente el tamaño y el estar abierto, con tal de salir de dicha confusión.<br />
<br />
== Comentarios ==<br />
Se habla de un "cursor" posicionado en bytes porque la librería trata internamente los archivos como vectores/matrices de tipo [[byte]], y con la posibilidad de crecer automáticamente según la necesidad.<br />
<br />
Lo que hace esta función es retornar el índice (como el de un vector/matriz) actualmente en uso para la próxima lectura ([[File.read()]] o [[File.peek()]]) o escritura ([[File.write()]]/[[File.print()]]).<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
// Así es como se retrocede una línea de texto<br />
void retrocederLinea() {<br />
<br />
if (!archivo.position()) return; // No se puede retroceder si estamos al principio del archivo<br />
<br />
retrocede();<br />
if (archivo.peek() == '\r') retrocede(); // Esto se hace cuando el salto de línea se compone de dos caracteres<br />
<br />
while (archivo.position() && archivo.peek() != '\n') retrocede(); // Así es como se retrocede<br />
<br />
if (archivo.position()) archivo.read(); // Esto sucede solo si el comienzo de la línea NO es también el comienzo del archivo.<br />
}<br />
<br />
// Asumiendo que 'archivo' sea una variable global<br />
bool retrocede() {<br />
return archivo.seek(archivo.position() - 1);<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Libreria SD</categorytree><br />
<br />
== Referencias ==<br />
[[Category:Libreria SD]]</div>Lucario448https://arduwiki.perut.org/index.php?title=File.seek()&diff=4440File.seek()2019-06-15T18:12:12Z<p>Lucario448: Página creada con «== Descripción == Coloca el "cursor" del archivo en la posición dada. '''0''' para volver al inicio, File.size() para colocarse al final. == Sintaxis == <pre> archiv...»</p>
<hr />
<div>== Descripción ==<br />
Coloca el "cursor" del archivo en la posición dada. '''0''' para volver al inicio, [[File.size()]] para colocarse al final.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.seek(pos);<br />
</pre><br />
<br />
== Parámetros ==<br />
;pos: la posición (en bytes) que se desea establecer en el "cursor" ([[unsigned long]]).<br />
<br />
== Retorna ==<br />
'''true''' si fue posible cambiar dicha posición; '''false''' en caso contrario ([[bool]]). Puede fallar si el valor ingresado no comprende el rango entre cero y el tamaño actual del archivo.<br />
<br />
== Advertencias ==<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta; o si el archivo no está abierto.<br />
<br />
== Comentarios ==<br />
Se habla de un "cursor" posicionado en bytes porque la librería trata internamente los archivos como vectores/matrices de tipo [[byte]], y con la posibilidad de crecer automáticamente según la necesidad.<br />
<br />
Lo que hace esta función es cambiar el índice (como el de un vector/matriz) al cuál se quiere acceder la próxima vez; para así recuperar ([[File.read()]] o [[File.peek()]]) el valor almacenado en dicho lugar, o modificarlo ([[File.write()]]/[[File.print()]]).<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
bool leerRegistro(Registro* r, unsigned int posicion) {<br />
<br />
if (archivo.seek(posicion * sizeof(r))) {<br />
return archivo.read(r, sizeof(r)); // Si se logra leer algo, equivale a retornar true<br />
}<br />
<br />
return false;<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Libreria SD</categorytree><br />
<br />
== Referencias ==<br />
[[Category:Libreria SD]]</div>Lucario448https://arduwiki.perut.org/index.php?title=File.flush()&diff=4014File.flush()2019-05-26T01:46:44Z<p>Lucario448: Página creada con «== Descripción == Fuerza la actualización de los datos en la tarjeta SD (y el atributo del tamaño del archivo en caso de que haya crecido). == Sintaxis == <pre> archivo...»</p>
<hr />
<div>== Descripción ==<br />
Fuerza la actualización de los datos en la tarjeta SD (y el atributo del tamaño del archivo en caso de que haya crecido).<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.flush();<br />
</pre><br />
<br />
== Parámetros ==<br />
Nada.<br />
<br />
== Retorna ==<br />
Nada.<br />
<br />
== Advertencias ==<br />
* No se recomienda abusar de esta función, no solo por tema de rendimiento sino por tema de desgaste en la tarjeta SD.<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta; o el archivo no fue abierto para escritura.<br />
<br />
== Comentarios ==<br />
Esta es una opción ya que, como en la [[SD|página principal de esta librería]] se mencionó, es un flujo de datos por bloques; lo que quiere decir que escribir datos no lo hace inmediatamente al medio físico (por cuestiones de rendimiento), sino que primero los registra en [[SRAM]] mediante una caché. Cuando esta se llene, automáticamente debe escribir esos datos al medio físico (la tarjeta SD) para así poder seguir con la escritura.<br />
<br />
Este proceso de actualización ocurre en alguna de las siguientes situaciones:<br />
<br />
* Al llamar esta función (manualmente).<br />
* Al cambiar de bloque de datos (cada 512 bytes) si el que está en caché ha cambiado su contenido tras su lectura.<br />
* Al cerrar el archivo (aplica la misma regla de la anterior).<br />
* En cada intento de escritura si el archivo se abre con la opción '''O_SYNC'''.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
// Pendiente<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD.open()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.println()&diff=4013File.println()2019-05-26T00:39:52Z<p>Lucario448: Página creada con «== Descripción == Cumple exactamente la misma función que File.print(), salvo que además agrega un salto de línea (el caracter de retorno del carro y nueva línea,...»</p>
<hr />
<div>== Descripción ==<br />
Cumple exactamente la misma función que [[File.print()]], salvo que además agrega un salto de línea (el caracter de retorno del carro y nueva línea, o el literal '''"\r\n"''').<br />
<br />
Si el [[File.position()|"cursor"]] está posicionado al final del archivo (o alcanza dicho punto en el proceso), esta función lo hará crecer lo necesario para que todos los datos sean escritos. El tope de este crecimiento está en el espacio libre del "volumen" o al alcanzar los 4 GB (4294967295 bytes) de tamaño.<br />
<br />
Si este "cursor" no está posicionado al final del archivo, entonces esta función sobrescribirá datos existentes (a partir de la posición actual); lo que hace un tanto difícil editar de esta manera texto en el archivo (imagínalo como un editor de texto dónde la tecla de retroceso no funciona, siempre en modo sobrescribir sin que se pueda cambiar al típico modo insertar, y que cada salto de línea en medio de algo borre dos caracteres en la nueva línea).<br />
<br />
{{Nota|ya que es una implementación de [[Stream]], los detalles mencionados en [[Stream.print()]] y [[Serial.print()]] también aplican aquí.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.println();<br />
archivo.println(cadena);<br />
archivo.print(variable[, formato]);<br />
</pre><br />
{{Nota|La primera sintaxis se utiliza para agregar solamente el salto de línea.}}<br />
<br />
== Parametros ==<br />
;cadena: Un [[string]] o [[String]]. También se valen literales (texto entrecomillado) y constantes [[F()]].<br />
;variable: variable a evaluar. Esta variable puede ser de cualquier tipo.<br />
;formato: por defecto es '''DEC''', pero puedes también usar '''HEX''', '''OCT''' o '''BIN'''. También puede ser un valor del 0 al 7 si '''variable''' es un punto flotante, representaría la cantidad de cifras decimales a imprimir (2 por defecto).<br />
<br />
== Retorna ==<br />
La cantidad de caracteres que se llegaron a escribir en el proceso ([[int]]). Puede fallar si el archivo no puede crecer, si no está abierto o no fue abierto para escritura.<br />
<br />
== Advertencias ==<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
// Loggear lecturas analógicas<br />
while (!digitalRead(boton)) {<br />
archivo.println(analogRead(A0));<br />
}<br />
archivo.close();<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[File.print()]]<br />
* [[File.write()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.print()&diff=3902File.print()2019-05-13T01:36:12Z<p>Lucario448: Página creada con «== Descripción == Escribe (al archivo) un dato mediante la representación textual de su valor, haciendo esta función útil para archivos de texto plano (ej.: .txt, .csv)...»</p>
<hr />
<div>== Descripción ==<br />
Escribe (al archivo) un dato mediante la representación textual de su valor, haciendo esta función útil para archivos de texto plano (ej.: .txt, .csv).<br />
<br />
Si el [[File.position()|"cursor"]] está posicionado al final del archivo (o alcanza dicho punto en el proceso), esta función lo hará crecer lo necesario para que todos los datos sean escritos. El tope de este crecimiento está en el espacio libre del "volumen" o al alcanzar los 4 GB (4294967295 bytes) de tamaño.<br />
<br />
Si este "cursor" no está posicionado al final del archivo, entonces esta función sobrescribirá datos existentes (a partir de la posición actual); lo que hace un tanto difícil editar de esta manera texto en el archivo (imagínalo como un editor de texto dónde la tecla de retroceso no funciona, siempre en modo sobrescribir sin que se pueda cambiar al típico modo insertar, y que cada salto de línea en medio de algo borre dos caracteres en la nueva línea).<br />
<br />
{{Nota|ya que es una implementación de [[Stream]], los detalles mencionados en [[Stream.print()]] y [[Serial.print()]] también aplican aquí.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.print(cadena);<br />
archivo.print(variable[, formato]);<br />
</pre><br />
<br />
== Parametros ==<br />
;cadena: Un [[string]] o [[String]]. También se valen literales (texto entrecomillado) y constantes [[F()]].<br />
;variable: variable a evaluar. Esta variable puede ser de cualquier tipo.<br />
;formato: por defecto es '''DEC''', pero puedes también usar '''HEX''', '''OCT''' o '''BIN'''. También puede ser un valor del 0 al 7 si '''variable''' es un punto flotante, representaría la cantidad de cifras decimales a imprimir (2 por defecto).<br />
<br />
{{Nota|Equivaldría al [[File.write()]] de un solo byte si '''variable''' es de tipo [[char]].}}<br />
<br />
== Retorna ==<br />
La cantidad de caracteres que se llegaron a escribir en el proceso ([[int]]). Puede fallar si el archivo no puede crecer, si no está abierto o no fue abierto para escritura.<br />
<br />
== Advertencias ==<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
// Loggear lecturas analógicas<br />
while (!digitalRead(boton)) {<br />
archivo.println(analogRead(A0)); // Ya sé que no es print() exactamente, pero se usa de la misma manera.<br />
}<br />
archivo.close();<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[File.println()]]<br />
* [[File.write()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.write()&diff=3901File.write()2019-05-13T00:56:43Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Escribe datos binarios ("crudos") al archivo, haciendo esta función útil para archivos binarios (con contenido diferente al texto plano).<br />
<br />
Si el [[File.position()|"cursor"]] está posicionado al final del archivo (o alcanza dicho punto en el proceso), esta función lo hará crecer lo necesario para que todos los datos sean escritos. El tope de este crecimiento está en el espacio libre del "volumen" o al alcanzar los 4 GB (4294967295 bytes) de tamaño.<br />
<br />
Si este "cursor" no está posicionado al final del archivo, entonces esta función sobrescribirá datos existentes (a partir de la posición actual); lo que hace un tanto difícil reemplazar valores en registros de longitud variable.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.write(val);<br />
archivo.write(str);<br />
archivo.write(buf, len);<br />
</pre><br />
<br />
== Parametros ==<br />
;val: Valor como un solo [[byte]] o variable (el byte menos significativo en caso de ser más grande).<br />
;str: Cadena como una serie de bytes ([[string]]).<br />
;buf: Matriz enviada como una serie de bytes ([[byte]]*).<br />
;len: Largo de la matriz '''en bytes''' ([[int]]).<br />
<br />
== Retorno ==<br />
La cantidad real de bytes que se escribieron con éxito ([[int]]). Puede fallar si el archivo no puede crecer, si no está abierto o no fue abierto para escritura.<br />
<br />
== Advertencias ==<br />
* Para escribir los caracteres que representan los dígitos de un número, use la función [[File.print()]] en su lugar.<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
while (Serial.available()) {<br />
archivo.write(Serial.read()); // Vuelca el contenido "crudo" o binario del puerto serial, al archivo<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD.open()]]<br />
* [[File.print()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.write()&diff=3900File.write()2019-05-13T00:48:31Z<p>Lucario448: Página creada con «== Descripción == Escribe datos binarios ("crudos") al archivo. Si el "cursor" está posicionado al final del archivo (o alcanza dicho punto en el pro...»</p>
<hr />
<div>== Descripción ==<br />
Escribe datos binarios ("crudos") al archivo.<br />
<br />
Si el [[File.position()|"cursor"]] está posicionado al final del archivo (o alcanza dicho punto en el proceso), esta función lo hará crecer lo necesario para que todos los datos sean escritos. El tope de este crecimiento está en el espacio libre del "volumen" o al alcanzar los 4 GB (4294967295 bytes) de tamaño.<br />
<br />
Si este "cursor" no está posicionado al final del archivo, entonces esta función sobrescribirá datos existentes (a partir de la posición actual); lo que hace un tanto difícil reemplazar valores en registros de longitud variable.<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.write(val);<br />
archivo.write(str);<br />
archivo.write(buf, len);<br />
</pre><br />
<br />
== Parametros ==<br />
;val: Valor como un solo [[byte]] o variable (el byte menos significativo en caso de ser más grande).<br />
;str: Cadena como una serie de bytes ([[string]]).<br />
;buf: Matriz enviada como una serie de bytes ([[byte]]*).<br />
;len: Largo de la matriz '''en bytes''' ([[int]]).<br />
<br />
== Retorno ==<br />
La cantidad real de bytes que se escribieron con éxito ([[int]]). Puede fallar si el archivo no puede crecer, si no está abierto o no fue abierto para escritura.<br />
<br />
== Advertencias ==<br />
* Para escribir los caracteres que representan los dígitos de un número, use la función [[File.print()]] en su lugar.<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
while (Serial.available()) {<br />
archivo.write(Serial.read()); // Vuelca el contenido "crudo" o binario del puerto serial, al archivo<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD.open()]]<br />
* [[File.print()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.available()&diff=3871File.available()2019-05-11T21:10:28Z<p>Lucario448: Página creada con «== Descripción == Obtiene el número de bytes disponibles para leer en el archivo (antes de llegar al final de este). == Sintaxis == <pre> archivo.available(); </pre> =...»</p>
<hr />
<div>== Descripción ==<br />
Obtiene el número de bytes disponibles para leer en el archivo (antes de llegar al final de este). <br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.available();<br />
</pre><br />
<br />
== Parámetros ==<br />
Nada.<br />
<br />
== Retorno ==<br />
La cantidad de bytes/caracteres disponibles para lectura ([[int]]). <br />
<br />
== Comentarios ==<br />
Si hay más de 32 KB para leer, esta función siempre retornará 32767 hasta que ocurra lo contrario. Por lo tanto, esta no es la forma más certera de hacerlo si se necesitara de un valor exacto; y mucho menos para determinar el tamaño de archivo.<br />
<br />
En ese caso, el cálculo más adecuado sería:<br />
<syntaxhighlight lang="c++"><br />
unsigned long bytesRestantes = archivo.size() - archivo.position();<br />
</syntaxhighlight><br />
<br />
== Ejemplo ==<br />
Alternativa al ejemplo en [[File.read()]]:<br />
<syntaxhighlight lang="c++"><br />
void setup(){<br />
Serial.begin(9600);<br />
// Tarjeta inicializada y archivo abierto para lectura<br />
<br />
while (archivo.available()){<br />
Serial.write((archivo.read());<br />
}<br />
archivo.close();<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[File.size()]]<br />
* [[File.position()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.peek()&diff=3870File.peek()2019-05-11T20:50:07Z<p>Lucario448: Página creada con «== Descripción == Devuelve el siguiente byte (carácter) del archivo, sin avanzar al siguiente. Es decir, las llamadas sucesivas a '''peek()''' devolverán el mismo carác...»</p>
<hr />
<div>== Descripción ==<br />
Devuelve el siguiente byte (carácter) del archivo, sin avanzar al siguiente. Es decir, las llamadas sucesivas a '''peek()''' devolverán el mismo carácter, al igual que la próxima llamada a [[File.read()]].<br />
<br />
El valor recuperado es relativo a la [[File.position()|posición del "cursor"]].<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.peek();<br />
</pre><br />
<br />
== Retorno ==<br />
El valor recuperado, o -1 si no hay datos para leer ([[int]]). Esto último puede deberse a que se alcanzó el final del archivo, porque está cerrado o porque no fue abierto para lectura.<br />
<br />
== Advertencias ==<br />
* Si por error no se verifica de antemano si hay datos disponibles, '''peek()''' retornará 255 para [[byte]] en el caso que el valor real sea -1 (nada).<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
// Pendiente de hacer<br />
void setup() {<br />
}<br />
void loop() {<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[File.read()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=File.read()&diff=3869File.read()2019-05-11T20:42:22Z<p>Lucario448: Página creada con «== Descripción == Lee un byte/caracter del archivo, y además avanza al siguiente. El valor recuperado es relativo a la posición del "cursor". == Sin...»</p>
<hr />
<div>== Descripción ==<br />
Lee un byte/caracter del archivo, y además avanza al siguiente. El valor recuperado es relativo a la [[File.position()|posición del "cursor"]].<br />
<br />
== Sintaxis ==<br />
<pre><br />
archivo.read()<br />
archivo.read(buffer, tamanio);<br />
</pre><br />
<br />
== Parametros ==<br />
;buffer: una matriz de cualquier tipo, aunque usualmente de tipo [[byte]] o [[char]] (en la implementación se declara como puntero de tipo [[void]]).<br />
;tamanio: el tamaño de dicha matriz '''en bytes'''. ([[unsigned int]]).<br />
<br />
== Retorno ==<br />
* Para la primera, el valor recuperado, o -1 si no hay datos para leer ([[int]]). Esto último puede deberse a que se alcanzó el final del archivo, porque está cerrado o porque no fue abierto para lectura.<br />
* Para la segunda, la cantidad de bytes leídos exitosamente ([[unsigned int]]). Si retorna cero, es porque no logró leer nada.<br />
<br />
== Advertencias ==<br />
* Si por error no se verifica de antemano si hay datos disponibles, '''read()''' retornará 255 para [[byte]] en el caso que el valor real sea -1 (nada).<br />
* Esta función siempre fallará si la instancia representa un directorio o carpeta.<br />
<br />
== Comentarios ==<br />
A pesar de que la segunda sintaxis hace lo mismo que [[Stream.readBytes()|readBytes()]] (y que además se puede utilizar con normalidad), se recomienda la aquí mencionada debido a que es más eficiente para la obtención de múltiples bytes que su contraparte "genérica".<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
void setup(){<br />
Serial.begin(9600);<br />
// Tarjeta inicializada y archivo abierto para lectura<br />
<br />
int dato;<br />
while ((dato = archivo.read()) >= 0){<br />
Serial.write(dato); //Imprime caracter leído<br />
}<br />
archivo.close();<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
*[[File.position()]]<br />
*[[File.close()]]<br />
*[[SD.open()]]<br />
*[[SD]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3868SD2019-05-11T20:00:17Z<p>Lucario448: Tengo pensado hacer la página de cada método</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
#include <SPI.h><br />
#include <SD.h><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Método !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usarla.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| [[SD.exists()]] || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| [[SD.remove()]] || Elimina un archivo.<br />
|-<br />
| [[SD.mkdir()]] || Crea un directorio (carpeta).<br />
|-<br />
| [[SD.rmdir()]] || Elimina un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| [[File.read()]] || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| [[File.peek()]] || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| [[File.available()]] || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| [[File.write()]] || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| [[File.print()]] || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| [[File.println()]] || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| [[File.flush()]] || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| [[File.seek()]] || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| [[File.position()]] || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| [[File.size()]] || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| [[File.name()]] || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| [[File.isDirectory()]] || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| [[File.openNextFile()]] || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| [[File.rewindDirectory()]] || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| [[File.close()]] || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
* [https://www.luisllamas.es/tarjeta-micro-sd-arduino/ Leer y escribir en tarjeta SD] - Luis Llamas<br />
* [https://naylampmechatronics.com/blog/38_Tutorial-Arduino-y-memoria-SD-y-micro-SD-.html Memorias SD y microSD] - Naylamp<br />
* [https://aprendiendoarduino.wordpress.com/category/sd/ SD] - Enrique Crespo<br />
* [http://manueldelgadocrespo.blogspot.com/p/biblioteca-sd.html Biblioteca SD] - Manuel Delgado<br />
* [https://www.prometec.net/sdcard/ SDcard] - Prometec<br />
* [https://naylampmechatronics.com/blog/38_tutorial-arduino-y-memoria-sd-y-micro-sd-.html Tutorial SD] - Naylamp<br />
* [https://eldesvandejose.com/2016/05/12/la-libreria-sd/ Libreria SD] - El desvan de José<br />
<br />
[[Category:Librerias]]<br />
[[Category:Libreria SD]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3420SD2019-05-05T19:58:57Z<p>Lucario448: /* Metodos */</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Método !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usarla.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| [[SD.exists()]] || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| [[SD.remove()]] || Elimina un archivo.<br />
|-<br />
| [[SD.mkdir()]] || Crea un directorio (carpeta).<br />
|-<br />
| [[SD.rmdir()]] || Elimina un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.mkdir()&diff=3419SD.mkdir()2019-05-05T19:57:47Z<p>Lucario448: Página creada con «== Descripción == Crea un directorio (carpeta) o toda una ruta (jerarquía). Para esto último, automáticamente se crea cualquier directorio faltante que la conforma. ==...»</p>
<hr />
<div>== Descripción ==<br />
Crea un directorio (carpeta) o toda una ruta (jerarquía). Para esto último, automáticamente se crea cualquier directorio faltante que la conforma.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.mkdir(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: carpeta o ruta que se pretende crear ([[string]] o [[String]]). Esta siempre será relativa a la raíz; en otras palabras, siempre será absoluta para efectos del sistema de archivos.<br />
<br />
== Retorna ==<br />
'''true''' si se pudo crear, '''false''' en caso contrario ([[bool]]). Si falla, es por error de hardware o porque el "volumen" está lleno.<br />
<br />
== Advertencias ==<br />
Nada.<br />
<br />
== Ejemplo ==<br />
Creamos una separación (en carpetas) de imágenes según el año de obtención, desde el 1990 hasta el año que se creó esta página (2019). Cada año estará separado por sus meses.<br />
<br />
<syntaxhighlight lang="c++"><br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
char ruta[50];<br />
<br />
// Algunos nombres fueron recortados para respetar el límite de 8 caracteres. Si fuera el caso, se podrían abreviar por las tres primeras letras.<br />
char mes[12][] = {"Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio", "Julio", "Agosto", "Setiembr", "Octubre", "Noviembr", "Diciembr"};<br />
<br />
for (unsigned int anio = 1990; anio <= 2019; anio++) {<br />
<br />
for (byte m = 0; i < 12; i++) {<br />
sprintf(ruta, "Imagenes/%d/%s", anio, mes[m]);<br />
<br />
if (SD.mkdir(ruta)) {<br />
Serial.print("La ruta ");<br />
Serial.print(ruta);<br />
Serial.print(" se ha creado con éxito!");<br />
} else {<br />
Serial.print("La ruta ");<br />
Serial.print(ruta);<br />
Serial.print(" no se ha podido crear!");<br />
} // Fin if-else<br />
} // Fin del segundo for<br />
} // Fin del primer for<br />
<br />
} // Fin de la función<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.open()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.rmdir()&diff=3418SD.rmdir()2019-05-05T18:19:27Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Elimina el directorio (carpeta) en la ruta dada.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.rmdir(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia la carpeta que se pretende eliminar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si se pudo eliminar, '''false''' en caso contrario ([[bool]]). Si falla, es porque el directorio no existe en esa ubicación, existe pero no está vacío, o la ruta apunta a un archivo regular.<br />
<br />
== Advertencias ==<br />
* Asegúrate de que dicha carpeta no esté abierta antes de intentar eliminarla.<br />
* Por razones obvias, la "raíz" nunca se puede eliminar.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
const char[] nombre = "Imagenes"; // Debe ser una carpeta, por eso no lleva extensión<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
if (SD.rmdir(nombre)) {<br />
Serial.print("La carpeta ");<br />
Serial.print(nombre);<br />
Serial.println(" se ha logrado eliminar.");<br />
} else {<br />
Serial.print("La carpeta ");<br />
Serial.print(nombre);<br />
Serial.println(" no se puede eliminar porque no existe o no esta vacia.");<br />
}<br />
<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.remove()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.exists()&diff=3417SD.exists()2019-05-05T18:17:07Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Verifica si la ruta hacia cierto elemento (archivo o carpeta) realmente existe.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.exists(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia el archivo o carpeta que se pretende verificar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si el elemento existe en dicha ubicación, '''false''' en caso contrario ([[bool]]).<br />
<br />
== Advertencias ==<br />
Nada.<br />
<br />
== Ejemplo ==<br />
Similar al ejemplo 2 de [[SD.open()]], solo que utilizando esta función.<br />
<syntaxhighlight lang="c++"><br />
File archivo;<br />
<br />
void setup() {<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
char nombre[13];<br />
unsigned int contador = 0;<br />
<br />
sprintf(nombre, "DATA%04d.CSV", contador);<br />
<br />
while (SD.exists(nombre)) {<br />
<br />
if (++contador > 9999) { // Si ya se agotaron los cuatro dígitos, no queda de otra que sobrescribir desde la 0000. Lo malo es que esto siempre lo haría si llegara a suceder.<br />
contador = 0;<br />
sprintf(nombre, "DATA%04d.CSV", contador); <br />
break;<br />
}<br />
<br />
sprintf(nombre, "DATA%04d.CSV", contador);<br />
<br />
}<br />
archivo = SD.open(nombre, FILE_WRITE | O_TRUNC);<br />
// A este punto ya es cuestión de solamente usar la instancia.<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.open()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.remove()&diff=3416SD.remove()2019-05-05T18:16:01Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Elimina el archivo en la ruta dada.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.remove(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia el archivo que se pretende eliminar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si se pudo eliminar, '''false''' en caso contrario ([[bool]]). Si falla, es porque el archivo no existe en esa ubicación, o la ruta apunta a un directorio/carpeta.<br />
<br />
== Advertencias ==<br />
* Asegúrate de que dicho archivo no esté abierto antes de intentar eliminarlo.<br />
* Esta función no puede eliminar carpetas; para eso, usa [[SD.rmdir()]] en su lugar.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
const char[] nombre = "Borrame.txt";<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
if (SD.remove(nombre)) {<br />
Serial.print(nombre);<br />
Serial.println(" se ha logrado eliminar.");<br />
} else {<br />
Serial.print(nombre);<br />
Serial.println(" no se puede eliminar porque no existe.");<br />
}<br />
<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.rmdir()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.rmdir()&diff=3415SD.rmdir()2019-05-05T18:13:56Z<p>Lucario448: Página creada con «== Descripción == Elimina el directorio (carpeta) en la ruta dada. == Sintaxis == <pre> SD.rmdir(ruta); </pre> == Parametros == ;ruta: ruta hacia la carpeta que se prete...»</p>
<hr />
<div>== Descripción ==<br />
Elimina el directorio (carpeta) en la ruta dada.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.rmdir(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia la carpeta que se pretende eliminar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si se pudo eliminar, '''false''' en caso contrario ([[bool]]). Si falla, es porque el directorio no existe en esa ubicación, existe pero no está vacío, o la ruta apunta a un archivo regular.<br />
<br />
== Advertencias ==<br />
Asegúrate de que dicha carpeta no esté abierta antes de intentar eliminarla.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
const char[] nombre = "Imagenes"; // Debe ser una carpeta, por eso no lleva extensión<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
if (SD.rmdir(nombre)) {<br />
Serial.print("La carpeta ");<br />
Serial.print(nombre);<br />
Serial.println(" se ha logrado eliminar.");<br />
} else {<br />
Serial.print("La carpeta ");<br />
Serial.print(nombre);<br />
Serial.println(" no se puede eliminar porque no existe o no esta vacia.");<br />
}<br />
<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.remove()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.remove()&diff=3414SD.remove()2019-05-05T18:03:28Z<p>Lucario448: Página creada con «== Descripción == Elimina el archivo en la ruta dada. == Sintaxis == <pre> SD.remove(ruta); </pre> == Parametros == ;ruta: ruta hacia el archivo que se pretende eliminar...»</p>
<hr />
<div>== Descripción ==<br />
Elimina el archivo en la ruta dada.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.remove(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia el archivo que se pretende eliminar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si se pudo eliminar, '''false''' en caso contrario ([[bool]]). Si falla, es porque el archivo no existe en esa ubicación.<br />
<br />
== Advertencias ==<br />
Asegúrate de que dicho archivo no esté abierto antes de intentar eliminarlo.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
const char[] nombre = "Borrame.txt";<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
if (SD.remove(nombre)) {<br />
Serial.print(nombre);<br />
Serial.println(" se ha logrado eliminar.");<br />
} else {<br />
Serial.print(nombre);<br />
Serial.println(" no se puede eliminar porque no existe.");<br />
}<br />
<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.rmdir()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3407SD2019-05-05T17:46:06Z<p>Lucario448: Si estás "vigilando" esta página, perdona el spam</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Método !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| [[SD.exists()]] || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| [[SD.remove()]] || Elimina un archivo.<br />
|-<br />
| [[SD.mkdir()]] || Crea un directorio (carpeta).<br />
|-<br />
| [[SD.rmdir()]] || Elimina un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3406SD2019-05-05T17:43:42Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Método !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| [[SD.exists()]] || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| [[SD.remove()]] || Elimina un archivo.<br />
|-<br />
| [[SD.mkdir()]] || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.exists()&diff=3405SD.exists()2019-05-05T17:42:08Z<p>Lucario448: Y esta página si me dejó crearla, que rayos?</p>
<hr />
<div>== Descripción ==<br />
Verifica si la ruta hacia cierto elemento (archivo o carpeta) realmente existe.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.exists(ruta);<br />
</pre><br />
<br />
== Parametros ==<br />
;ruta: ruta hacia el archivo o carpeta que se pretende verificar, o sólo el nombre para ubicarlo en la "raíz" ([[string]] o [[String]]).<br />
<br />
== Retorna ==<br />
'''true''' si el elemento existe en dicha ubicación, '''false''' en caso contrario.<br />
<br />
== Advertencias ==<br />
Nada.<br />
<br />
== Ejemplo ==<br />
Similar al ejemplo 2 de [[SD.open()]], solo que utilizando esta función.<br />
<syntaxhighlight lang="c++"><br />
File archivo;<br />
<br />
void setup() {<br />
// Inicializamos la tarjeta por supuesto<br />
<br />
char nombre[13];<br />
unsigned int contador = 0;<br />
<br />
sprintf(nombre, "DATA%04d.CSV", contador);<br />
<br />
while (SD.exists(nombre)) {<br />
<br />
if (++contador > 9999) { // Si ya se agotaron los cuatro dígitos, no queda de otra que sobrescribir desde la 0000. Lo malo es que esto siempre lo haría si llegara a suceder.<br />
contador = 0;<br />
sprintf(nombre, "DATA%04d.CSV", contador); <br />
break;<br />
}<br />
<br />
sprintf(nombre, "DATA%04d.CSV", contador);<br />
<br />
}<br />
archivo = SD.open(nombre, FILE_WRITE | O_TRUNC);<br />
// A este punto ya es cuestión de solamente usar la instancia.<br />
}<br />
<br />
void loop() {}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD]]<br />
* [[SD.open()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3404SD2019-05-05T17:16:45Z<p>Lucario448: PD: la página con open no la puedo crear por el famoso 403</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Métodos !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| [[SD.exists()]] || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| SD.remove() || Elimina un archivo.<br />
|-<br />
| SD.mkdir() || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3403SD2019-05-05T17:12:08Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Métodos !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| SD.exists() || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| SD.remove() || Elimina un archivo.<br />
|-<br />
| SD.mkdir() || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield, o cambiar según corresponda.<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\r\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3402SD2019-05-05T17:07:58Z<p>Lucario448: Traducir los demás strings</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Métodos !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| SD.exists() || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| SD.remove() || Elimina un archivo.<br />
|-<br />
| SD.mkdir() || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero. Es el mismo ejemplo de '''CardInfo''', solo que los mensajes se han traducido al español.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Tipo de tarjeta: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Desconocido");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuentro particion FAT16/FAT32. La tarjeta esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusteres: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Sectores por Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total de sectores: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("El tipo de volumen es: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; // Bloques (sectores) de una SD son de 512 bytes (2 bloques abarcan 1 KB o 1024 bytes)<br />
Serial.print("Tamanio del volumen (KB): ");<br />
Serial.println(volumesize);<br />
Serial.print(Tamanio del volumen (MB): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Tamanio del volumen (GB): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\nArchivos en SD (nombre, fecha y tamanio en bytes): ");<br />
root.openRoot(volume);<br />
<br />
// Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
// Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3399SD2019-05-05T16:46:55Z<p>Lucario448: La hora por defecto en realidad es 1 am</p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Métodos !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| SD.exists() || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| SD.remove() || Elimina un archivo.<br />
|-<br />
| SD.mkdir() || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 1:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Card type: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Unknown");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuantro particion: FAT16/FAT32.\nSD esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusters: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Blocks x Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total Blocks: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("Volume type is: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; //Bloques SD son de 512 bytes (2 blocks are 1KB)<br />
Serial.print("Volume size (Kb): ");<br />
Serial.println(volumesize);<br />
Serial.print("Volume size (Mb): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Volume size (Gb): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\nArchivos en SD (name, date and size in bytes): ");<br />
root.openRoot(volume);<br />
<br />
//Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
//Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=3398SD2019-05-05T16:42:54Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
La librería [https://github.com/arduino-libraries/SD SD.h] de SparkFun habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que usa [[SPI]], la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Sintaxis ===<br />
<pre><br />
SD.begin(CS);<br />
</pre><br />
<br />
=== Parametros ===<br />
;CS:Puerto 4 si es Aduino Shield.<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metodos de la clase SD<br />
|-<br />
! Métodos !! Descripción<br />
|-<br />
| [[SD.begin()]] || Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a usar.<br />
|-<br />
| [[SD.end()]] || Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
|-<br />
| [[SD.open()]] || Abre un archivo o una carpeta.<br />
|-<br />
| SD.exists() || Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
|-<br />
| SD.remove() || Elimina un archivo.<br />
|-<br />
| SD.mkdir() || Crea un directorio (carpeta).<br />
|}<br />
<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
=== Sintaxis ===<br />
<pre><br />
File variable = SD.open(nombre, modo);<br />
</pre><br />
<br />
=== Parámetros ===<br />
;variable:Nombre de variable a instanciar.<br />
;nombre:Nombre de archivo SFN (8.3). Ejemplo log12345.txt.<br />
;modo:Puede ser FILE_WRITE o FILE_READ<br />
<br />
=== Metodos ===<br />
{| class="wikitable"<br />
|+Metrodos de la clase File<br />
|-<br />
!Método!!Descripción<br />
|-<br />
| File.read() || Lee un byte/caracter o varios del archivo.<br />
|-<br />
| File.peek() || Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
|-<br />
| File.available() || Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
|-<br />
| File.write() || Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
|-<br />
| File.print() || Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
|-<br />
| File.println() || Igual al anterior, excepto que agrega una nueva línea de texto.<br />
|-<br />
| File.flush() || Fuerza la actualización de los datos en la tarjeta SD.<br />
|-<br />
| File.seek() || Posiciona el "cursor" del archivo hacia una posición dada.<br />
|-<br />
| File.position() || Retorna la posición actual del "cursor" del archivo.<br />
|-<br />
| File.size() || Retorna el tamaño del archivo (en bytes).<br />
|-<br />
| File.name() || Retorna el nombre del archivo/carpeta.<br />
|-<br />
| File.isDirectory() || Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
|-<br />
| File.openNextFile() || Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.rewindDirectory() || Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
|-<br />
| File.close() || Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
|}<br />
<br />
{{Nota|Prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
=== Formato de la ruta de acceso ===<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<br />
<pre><br />
datos.txt<br />
ruta/hacia/el/archivo/que/buscamos.txt<br />
</pre><br />
<br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
{{Nota|Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 carácter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
=== Caracteres permitidos ===<br />
En el nombre puede venir cualquier carácter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El carácter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el carácter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer carácter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente usa, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
=== Comentarios ===<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan usar.<br />
<br />
{{Nota|a partir de la versión 1.0 del [[IDE]] de Arduino, se permite tener múltiples archivos abiertos a la vez.}}<br />
<br />
{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}<br />
<br />
{{Nota|Este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Cómo agregar fecha y hora a los archivos ===<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 12:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
<br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|word o uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br />
<br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
== Advertencias ==<br />
* Para efectos del sistema de archivos, los nombres '''NO SON''' sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Ejemplo 1 ==<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
<br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br />
<br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Ejemplo 2 ==<br />
Este ejemplo muestra como conectar SD mediante [[SPI]], con MOSI, MISO, CLK, CS (11,12,13,4). CS puede variar segun si es Arduino Shield (4), Adafuit (19, Sparkfun(8) o MKRZero.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
Sd2Card card;<br />
SdVolume volume;<br />
SdFile root;<br />
<br />
const int chipSelect = 4; //Arduino Ethernet shield<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!card.init(SPI_HALF_SPEED, chipSelect)) {<br />
Serial.println("Error con SD:");<br />
Serial.println("* la trajeta SD esta puesta ?");<br />
Serial.println("* los cables estan correctos ?");<br />
Serial.println("* pin de chipSelect es correcto segun modelo ?");<br />
while (1);<br />
} else {<br />
Serial.println("Conexiones correctas y tarjeta SD en su lugar.");<br />
}<br />
<br />
Serial.println();<br />
Serial.print("Card type: ");<br />
switch (card.type()) {<br />
case SD_CARD_TYPE_SD1:<br />
Serial.println("SD1");<br />
break;<br />
case SD_CARD_TYPE_SD2:<br />
Serial.println("SD2");<br />
break;<br />
case SD_CARD_TYPE_SDHC:<br />
Serial.println("SDHC");<br />
break;<br />
default:<br />
Serial.println("Unknown");<br />
}<br />
<br />
if (!volume.init(card)) {<br />
Serial.println("No encuantro particion: FAT16/FAT32.\nSD esta formateada ?");<br />
while (1);<br />
}<br />
<br />
Serial.print("Clusters: ");<br />
Serial.println(volume.clusterCount());<br />
Serial.print("Blocks x Cluster: ");<br />
Serial.println(volume.blocksPerCluster());<br />
Serial.print("Total Blocks: ");<br />
Serial.println(volume.blocksPerCluster() * volume.clusterCount());<br />
Serial.println();<br />
uint32_t volumesize;<br />
Serial.print("Volume type is: FAT");<br />
Serial.println(volume.fatType(), DEC);<br />
<br />
volumesize = volume.blocksPerCluster();<br />
volumesize *= volume.clusterCount();<br />
volumesize /= 2; //Bloques SD son de 512 bytes (2 blocks are 1KB)<br />
Serial.print("Volume size (Kb): ");<br />
Serial.println(volumesize);<br />
Serial.print("Volume size (Mb): ");<br />
volumesize /= 1024;<br />
Serial.println(volumesize);<br />
Serial.print("Volume size (Gb): ");<br />
Serial.println((float)volumesize / 1024.0);<br />
<br />
Serial.println("\nArchivos en SD (name, date and size in bytes): ");<br />
root.openRoot(volume);<br />
<br />
//Mostrar contenido<br />
root.ls(LS_R | LS_DATE | LS_SIZE);<br />
}<br />
<br />
void loop(void) {<br />
//Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 3 ==<br />
Data logger.<br />
<br />
<syntaxhighlight lang="c++"><br />
#include <SPI.h><br />
#include <SD.h><br />
<br />
const int chipSelect = 4;<br />
<br />
void setup() {<br />
Serial.begin(9600);<br />
Serial.print("Inicializando SD...");<br />
if (!SD.begin(chipSelect)) {<br />
Serial.println("SD fallo, esta puesta ?");<br />
while (1);<br />
}<br />
Serial.println("SD lista.");<br />
}<br />
<br />
void loop() {<br />
String data = "";<br />
for (byte analogPin=0; analogPin<3; analogPin++) {<br />
int sensor = analogRead(analogPin);<br />
data += String(sensor);<br />
if (analogPin < 2) {<br />
data += ",";<br />
}<br />
}<br />
File File = SD.open("datalog.txt", FILE_WRITE);<br />
if (File) {<br />
File.println(data);<br />
File.close();<br />
Serial.println(data);<br />
}else{<br />
Serial.println("Error abriendo datalog.txt");<br />
}<br />
}<br />
</syntaxhighlight><br />
<br />
== Ejemplo 4 ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
<categorytree mode=all>Librerias</categorytree><br />
<br />
== Referencias externas ==<br />
* [https://www.arduinolibraries.info/libraries All Libraries]<br />
* [http://www.arduino.cc/en/Reference/SD SD]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.end()&diff=3156SD.end()2019-05-01T21:19:54Z<p>Lucario448: Página creada con «== Descripción == Devuelve la librería al estado inicial, usualmente para mantener la consistencia ante eventos como la remoción de la tarjeta mientras el programa está...»</p>
<hr />
<div>== Descripción ==<br />
Devuelve la librería al estado inicial, usualmente para mantener la consistencia ante eventos como la remoción de la tarjeta mientras el programa está corriendo.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.end();<br />
</pre><br />
<br />
== Parametros ==<br />
Nada.<br />
<br />
== Retorna ==<br />
Nada.<br />
<br />
== Advertencias ==<br />
Antes de llamar esta función, asegúrate primero de [[File.close()|cerrar]] cualquier archivo previamente abierto.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
void setup() {<br />
Serial.begin(9600);<br />
<br />
if (!SD.begin(4)) Serial.println("Fallo en la tarjeta");<br />
else Serial.println("Tarjeta iniciada");<br />
<br />
// Hacer algo más con la tarjeta<br />
<br />
SD.end();<br />
Serial.println("Ahora se puede retirar la tarjeta con seguridad");<br />
}<br />
<br />
void loop(){}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD.begin()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD.begin()&diff=3155SD.begin()2019-05-01T20:57:39Z<p>Lucario448: Página creada con «== Descripción == Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a utilizarla. Aunque llamar esta funció...»</p>
<hr />
<div>== Descripción ==<br />
Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a utilizarla.<br />
<br />
Aunque llamar esta función cuando la tarjeta ya había sido inicializada no la perjudica (y prácticamente no tendría efecto alguno en el programa), de todas formas sería un desperdicio de tiempo ya que ejecutar esta función puede tardar hasta un segundo. Donde sí valdría la pena sería al dar soporte de remoción "en caliente", porque cada vez que una tarjeta SD pierda energía, hay que pasar por este proceso al reinsertarse.<br />
<br />
== Sintaxis ==<br />
<pre><br />
SD.begin([velocidad, ]pinCS);<br />
</pre><br />
<br />
== Parametros ==<br />
;velocidad: frecuencia del reloj SPI en Hertz ([[unsigned long]]). Si excede el máximo soportado por el microcontrolador, dicho máximo se utilizará en su lugar. El valor máximo absoluto es de 20000000 (20 MHz).<br />
;pinCS: el número del pin utilizado para la línea "Chip Select" (o "Slave Select"/SS) de la tarjeta ([[byte]]).<br />
<br />
== Retorna ==<br />
'''true''' si la tarjeta pudo ser inicializada con éxito, '''false''' en caso contrario ([[bool]]).<br />
<br />
== Comentarios ==<br />
Este proceso de inicialización sigue tres pasos:<br />
<br />
* Poner la tarjeta en modo SPI mediante el envío de cierto comando una cantidad determinada de veces. Si no se da la respuesta esperada en alguno de los intentos, el proceso falla inmediatamente. Esta etapa esencialmente verifica el hardware (lo físico); en otras palabras, puede fallar por mala alimentación (de la tarjeta), mala conexión, o incluso por tarjeta defectuosa o que de pleno no soporta SPI.<br />
* Leer la tabla de particiones (también llamados "volúmenes") para así encontrar alguna con el sistema de archivos FAT (16 o 32). Si se falla en esta etapa, es posible que la tarjeta no esté formateada al sistema FAT.<br />
* Abrir el directorio raíz una vez encontrada la partición FAT. Si falla, podría ser problema de hardware (ej.: desconexión de la tarjeta antes de llegar a esta etapa) o el sistema de archivos está dañado (reparable mediante formateo o el comando '''chkdsk''' en Windows).<br />
<br />
<br />
En el momento que alguno fracase, es dónde la función retorna '''false'''. Ya que el dato de retorno no es muy específico para diagnosticar posibles problemas con la tarjeta, se recomienda subir y ejecutar el ejemplo '''CardInfo''' para dicha tarea. Ese programa imprime (en el monitor serial) un mensaje de error dependiendo de en cuál de las dos primeras etapas ha fallado; si llega a imprimir una lista del contenido (archivos y carpetas) de la tarjeta, significa que todo está en orden.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
void setup() {<br />
Serial.begin(9600);<br />
<br />
if (!SD.begin(4)) Serial.println("Fallo en la tarjeta");<br />
else Serial.println("Tarjeta iniciada");<br />
}<br />
<br />
void loop(){}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[SD.end()]]<br />
<br />
== Referencias ==</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=2771SD2019-03-23T06:05:10Z<p>Lucario448: Agregué una pequeña guía de cómo aprovechar los atributos de fecha y hora usando esta librería</p>
<hr />
<div>== Descripción ==<br />
Es una librería que habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que utiliza SPI, la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
== Formato de la ruta de acceso ==<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<pre>ruta/hacia/el/archivo/que/buscamos.txt</pre><br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<pre>datos.txt</pre><br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}{{Nota|para efectos del sistema de archivos, los nombres no son sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 caracter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
==== Caracteres permitidos ====<br />
En el nombre puede venir cualquier caracter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El caracter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el caracter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer caracter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente utiliza, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
* [[SD.begin()]] - Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a utilizarla.<br />
* [[SD.end()]] - Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
* [[SD.open()]] - Abre un archivo o una carpeta.<br />
* [[SD.exists()]] - Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
* [[SD.remove()]] - Elimina un archivo.<br />
* [[SD.mkdir()]] - Crea un directorio (carpeta).<br />
* [[SD.rmdir()]] - Elimina un directorio (carpeta).<br />
<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan utilizar.<br />
<br />
{{Nota|a partir de la versión 1.0 de la IDE de Arduino, se permite tener múltiples archivos abiertos a la vez.}}{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}{{Nota|este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
* [[File.read()]] - Lee un byte/caracter o varios del archivo.<br />
* [[File.peek()]] - Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
* [[File.available()]] - Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
* [[File.write()]] - Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
* [[File.print()]] - Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
* [[File.println()]] - Igual al anterior, excepto que agrega una nueva línea de texto.<br />
* [[File.flush()]] - Fuerza la actualización de los datos en la tarjeta SD.<br />
* [[File.close()]] - Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
* [[File.seek()]] - Posiciona el "cursor" del archivo hacia una posición dada.<br />
* [[File.position()]] - Retorna la posición actual del "cursor" del archivo.<br />
* [[File.size()]] - Retorna el tamaño del archivo (en bytes).<br />
* [[File.name()]] - Retorna el nombre del archivo/carpeta.<br />
* [[File.isDirectory()]] - Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
* [[File.openNextFile()]] - Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
* [[File.rewindDirectory()]] - Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
<br />
== Cómo agregar fecha y hora a los archivos ==<br />
Todo archivo/fichero y directorio/carpeta tiene por atributos, además del nombre, la fecha y hora de creación, último acceso y última modificación (datos que se pueden mirar en las "propiedades" o "detalles" del elemento, en el explorador de archivos de tu PC). La librería por defecto no tiene definido cómo obtener dicha información; pero cuando es requerido, por defecto coloca el '''01/01/2000 12:00:00 am''' aunque haya transcurrido un tiempo desde que el sistema ha arrancado.<br />
<br />
<br />
Para definir la obtención de esos datos, primero debes crear una función con la siguiente "firma" (declaración):<br />
<pre>void nombreFuncion(uint16_t* fecha, uint16_t* hora)</pre><br />
'''Quiere decir que dicha función DEBE retornar [[void]] y DEBE tener dos parámetros de tipo [[word|uint16_t]][[asterisco|*]]. El nombre no es importante.'''<br><br />
En dicha función, programarás la obtención de la fecha y hora actualizados; que pueden provenir de un reloj generado por software, un reloj NTP o un RTC.<br />
<br />
<br />
Luego, en el [[setup()]], colocas esta línea para así otorgarle dicha definición a la librería:<br />
<pre>SdFile::dateTimeCallback(nombreFuncion);</pre><br />
<br />
<br />
Un ejemplo de aplicación sería el siguiente:<br />
<syntaxhighlight lang="c++"><br />
void obtenerFechaHora(uint16_t* fecha, uint16_t* hora) {<br />
// Aquí llamas al reloj para que actualice los datos<br />
<br />
*fecha = FAT_DATE(anio, mes, dia);<br />
*hora = FAT_TIME(hora, minuto, segundo);<br />
}<br />
<br />
void setup() {<br />
// Todas las demás inicializaciones<br />
SdFile::dateTimeCallback(obtenerFechaHora);<br />
}<br />
<br />
void loop() {<br />
// El resto del programa<br />
}<br />
</syntaxhighlight><br />
Siendo '''anio''' una variable de tipo [[unsigned int]], mientras que el resto de componentes son de tipo [[byte]]. El año se agrega con un valor que tenga los cuatro dígitos.<br><br />
El rango de fecha y hora válido es del '''01/01/1980 12:00:00 am''' al '''31/12/2107 11:59:59 pm'''.<br />
<br />
<br />
Una vez "adjuntada", esta función se utiliza de manera similar a como ocurre en las [[attachInterrupt()|interrupciones]]: implícitamente cuando la librería la necesite.<br />
<br />
<br />
La fecha/hora de creación se aplica únicamente al momento de crear un archivo/carpeta que antes no existía; la de acceso con el simple hecho de lograr abrirla; y la de modificación cuando se cierra un archivo regular que fue abierto para escritura, o cuando una subcarpeta adquiere o pierde contenido.<br />
<br />
== Advertencias ==<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Vea también ==<br />
* [[SPI]]<br />
* [[Stream]]<br />
<br />
== Referencias externas ==<br />
* [https://www.arduino.cc/en/Reference/SD Documentación oficial de la librería (en inglés)]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=2690SD2019-03-13T19:54:26Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Es una librería que habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que utiliza SPI, la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
== Formato de la ruta de acceso ==<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<pre>ruta/hacia/el/archivo/que/buscamos.txt</pre><br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<pre>datos.txt</pre><br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}{{Nota|para efectos del sistema de archivos, los nombres no son sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 caracter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
==== Caracteres permitidos ====<br />
En el nombre puede venir cualquier caracter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El caracter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el caracter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer caracter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente utiliza, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
* [[SD.begin()]] - Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a utilizarla.<br />
* [[SD.end()]] - Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
* [[SD.open()]] - Abre un archivo o una carpeta.<br />
* [[SD.exists()]] - Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
* [[SD.remove()]] - Elimina un archivo.<br />
* [[SD.mkdir()]] - Crea un directorio (carpeta).<br />
* [[SD.rmdir()]] - Elimina un directorio (carpeta).<br />
<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan utilizar.<br />
<br />
{{Nota|a partir de la versión 1.0 de la IDE de Arduino, se permite tener múltiples archivos abiertos a la vez.}}{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}{{Nota|este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
* [[File.read()]] - Lee un byte/caracter o varios del archivo.<br />
* [[File.peek()]] - Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
* [[File.available()]] - Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
* [[File.write()]] - Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
* [[File.print()]] - Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
* [[File.println()]] - Igual al anterior, excepto que agrega una nueva línea de texto.<br />
* [[File.flush()]] - Fuerza la actualización de los datos en la tarjeta SD.<br />
* [[File.close()]] - Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
* [[File.seek()]] - Posiciona el "cursor" del archivo hacia una posición dada.<br />
* [[File.position()]] - Retorna la posición actual del "cursor" del archivo.<br />
* [[File.size()]] - Retorna el tamaño del archivo (en bytes).<br />
* [[File.name()]] - Retorna el nombre del archivo/carpeta.<br />
* [[File.isDirectory()]] - Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
* [[File.openNextFile()]] - Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
* [[File.rewindDirectory()]] - Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
<br />
<br />
== Advertencias ==<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
== Vea también ==<br />
* [[SPI]]<br />
* [[Stream]]<br />
<br />
== Referencias externas ==<br />
* [https://www.arduino.cc/en/Reference/SD Documentación oficial de la librería (en inglés)]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=F()&diff=2689F()2019-03-13T19:33:33Z<p>Lucario448: /* Descripción */</p>
<hr />
<div>== Descripción ==<br />
La macro '''F()''' permite guardar la cadena a mostrar en monitor serie con [[Serial.print()]] o [[Serial.println()]] en la memoria [[flash]] en lugar de la [[SRAM]].<br />
<br />
{{Nota|Si en el boceto tienes un montón de cosas que mostrar en el monitor serie, puedes llenar fácilmente la memoria [[SRAM]], por eso es aconsejable usar esta macro para guardar esos textos en la memoria [[flash]]}}{{Nota|Cualquier clase que "herede" de [[Print]] o [[Stream]] (ej.: [[Serial]]), tendrá acceso a las funciones '''print'''; las cuales siempre serán compatibles con esta macrofunción.}}{{Nota|Es posible crear una función o método personalizado que acepte esta macro, el tipo de dato es '''const __FlashStringHelper*''' (puntero); sin embargo cabe recordar que la memoria [[flash]] es de sólo lectura para efectos de ejecución, las modificaciones sólo son posibles si los datos se copian a [[SRAM]] de antemano (mediante variables o vectores/matrices).}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
Serial.print(F("texto a mostrar"));<br />
</pre><br />
<br />
== Advertencias ==<br />
* '''F()''' al ser una macrofunción, solo se ejecuta en tiempo de compilación. Esto quiere decir que de parámetros se aceptan únicamente literales (entrecomillados) y cadenas de caracteres declarados como '''[[const]] [[char]]*'''; nada de vectores/matrices [[string]], ni siquiera objetos [[String]]. En resumen, '''solamente texto invariable se acepta'''.<br />
<br />
== Ejemplos ==<br />
<syntaxhighlight lang="c++"><br />
Serial.println(F("Escribe algo en el monitor serie que se almacena en FLASH"));<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[Serial]]<br />
* [[Serial.begin()]]<br />
* [[Serial.available()]]<br />
* [[Serial.read()]]<br />
* [[Serial.print()]]<br />
* [[Serial.println()]]<br />
* [[Serial.write()]]<br />
* [[Serial.peek()]]<br />
* [[Serial.end()]]<br />
<br />
== Referencias ==<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=bitshift_left&diff=2688bitshift left2019-03-13T19:20:00Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Desplaza hacia la izquierda (hacia el bit más significativo) una cantidad determinada de bits de una variable o constante; rellenando con ceros.<br />
<br />
== Sintaxis ==<br />
<pre><br />
valor = valor <nowiki><<</nowiki> nBits;<br />
valor <nowiki><<</nowiki>= nBits;<br />
</pre><br />
;valor: Constante o variable a trabajar.<br />
;nBits: Cantidad de bits a desplazar. '''Debe ser un valor entero positivo'''.<br />
<br />
== Advertencias ==<br />
* Esta operación desplaza bits descartando los que hayan quedado fuera, no los rota de posición. Por lo tanto, desplazar la cantidad suficiente de bits puede resultar en un valor cero.<br />
<br />
== Ejemplo ==<br />
Partiendo del valor 1, se puede obtener el resultado de una potencia con base 2.<br />
<syntaxhighlight lang="c++"><br />
unsigned long resultado = 1;<br />
<br />
for (byte potencia = 0; potencia < sizeof(unsigned long) * 8; potencia++) {<br />
Serial.print("2^");<br />
Serial.print(potencia);<br />
Serial.print(" = ");<br />
resultado <<= 1; // Se desplaza una vez cada iteración de este ciclo.<br />
Serial.println(resultado);<br />
}<br />
</syntaxhighlight><br />
Imprime los resultados desde 2 a la 0 hasta 2 a la 31.<br />
<br />
== Vea también ==<br />
* [[not]]<br />
* [[and]]<br />
* [[or]]<br />
* [[bitshift right]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/bitwise-operators/bitshiftleft/ Artículo oficial de Arduino sobre el tema (en inglés)]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=SD&diff=2682SD2019-03-13T07:04:05Z<p>Lucario448: Página creada con «== Descripción == Es una librería que habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([...»</p>
<hr />
<div>== Descripción ==<br />
Es una librería que habilita un Arduino para la interacción con tarjetas SD (Secure Digital) mediante el protocolo '''Serial Peripheral Interface''' ([[SPI]]). A pesar de que existen tres tamaños distintos, todos operan exactamente de la misma manera (a determinada capacidad); por lo tanto, esta librería funciona con todos los tamaños.<br />
<br />
Debido a que utiliza SPI, la conexión debe realizarse hacia los respectivos pines del Arduino; salvo SS/CS, este puede conectarse en cualquier pin digital libre.<br />
<br />
{{Nota|la librería soporta tarjetas SD del estándar '''SC''' y '''HC'''; por esta razón, la capacidad máxima soportada es de '''32 GB'''.}}{{Nota|la librería está preinstalada junto con la IDE de Arduino, no es necesario descargarla.}}{{Nota|debido a limitaciones de la librería y sistema de archivos compatibles, el tamaño máximo por archivo es de 4 GB o 4294967295 bytes.}}<br />
<br />
== Formato de la ruta de acceso ==<br />
Esta librería utiliza el formato de rutas de UNIX/Linux: el nombre de las carpetas involucradas se separa con '''/''' (barra inclinada o slash), siendo el destino final el último nombre de la secuencia. Por ejemplo:<br />
<pre>ruta/hacia/el/archivo/que/buscamos.txt</pre><br />
Siendo '''ruta''', '''hacia''', '''el''', '''archivo''' y '''que''' las carpetas que nos llevan al archivo '''buscamos.txt'''<br />
<br />
Ese destino no tiene que ser solamente un archivo regular, también podría ser otra carpeta.<br />
<br />
<br />
Si es algo que queremos colocar o ubicar en la "raíz", basta con simplemente colocar el nombre del elemento. Por ejemplo:<br />
<pre>datos.txt</pre><br />
Esto hará que el archivo '''datos.txt''' sea creado o buscado en el directorio raíz; en otras palabras, fuera de toda carpeta.<br />
<br />
<br />
{{Nota|ya que el directorio de trabajo de la librería siempre es la raíz, da igual que la ruta sea absoluta (con '''/''' al comienzo) o relativa (sin '''/''' al comienzo).}}{{Nota|para efectos del sistema de archivos, los nombres no son sensibles a las mayúsculas; por lo tanto, '''datos.txt''', '''Datos.txt''' y '''DATOS.TXT''' hacen referencia al mismo archivo. Lo mismo aplica para directorios/carpetas.}}<br />
<br />
=== Nombres SFN (8.3) ===<br />
Parte de la escritura de rutas también involucra respetar el formato SFN (Short File Name o nombre corto de archivo), el cuál sigue estas reglas:<br />
<br />
* El nombre del elemento debe tener como mínimo 1 caracter, y como máximo 8 caracteres.<br />
* Si es un archivo regular, debe haber un único punto ('''.''') justo después del nombre.<br />
* Si es un archivo regular, deben haber de 1 a 3 caracteres después del antes mencionado punto. Esto es lo que se conoce como la "extensión", una forma burda (pero muy usada en Windows) de etiquetar archivos por su contenido (ej.: '''txt''' para texto plano, '''jpg''' para imágenes codificadas en JPEG, '''mp3''' para audio codificado en MPEG capa 3, etc.).<br />
<br />
{{Nota|deduciendo de las reglas anteriores, los directorios/carpetas solo deben cumplir la primera; no debe haber punto ('''.''') ni extensión en el nombre.}}<br />
<br />
==== Caracteres permitidos ====<br />
En el nombre puede venir cualquier caracter, excepto los siguientes:<br />
<br />
* <code>" * + , / : ; < = > ? \ [ ] | </code><br />
* Los que tienen un valor decimal del 0 al 31<br />
* El caracter de valor decimal 127<br />
* El punto ('''.''') sólo si no es antecedido por al menos un caracter permitido.<br />
<br />
Técnicamente se permite el caracter espaciador y los del ASCII extendido (valor decimal del 128 al 255), sin embargo el primero no se recomienda porque puede hacer más complicado programar la generación de rutas; y lo segundo tampoco ya que la codificación no es estándar entre regiones geográficas (lo que puede llevar a una interpretación errónea del nombre en cuestión), eso sin contar que si el primer caracter es de valor '''0xE5''' (229 decimal), la librería podría después mal interpretarlo como un archivo eliminado (que no existe).<br />
<br />
Curiosamente, las letras minúsculas están prohibidas; sin embargo esto no es cierto al crear e ingresar la ruta, ya que la librería automáticamente utiliza, en su lugar, las respectivas contrapartes mayúsculas al procesarla.<br />
<br />
<br />
== La clase SD ==<br />
Es un objeto preinstanciado que se utiliza para iniciar la tarjeta y realizar operaciones generales sobre el sistema de archivos ([https://es.wikipedia.org/wiki/Tabla_de_asignaci%C3%B3n_de_archivos FAT] en sus versiones de 16 y 32 bits; '''exFAT''' no es compatible).<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún otro método funcionará si no se inicializa de antemano la tarjeta SD.}}<br />
<br />
* [[SD.begin()]] - Intenta inicializar la tarjeta SD al modo SPI, para así obtener de esta la información necesaria para empezar a utilizarla.<br />
* [[SD.end()]] - Devuelve la librería al estado inicial; útil para remover, "en caliente" y de forma segura, la tarjeta.<br />
* [[SD.open()]] - Abre un archivo o una carpeta.<br />
* [[SD.exists()]] - Verifica si determinado archivo o carpeta realmente existe en la tarjeta.<br />
* [[SD.remove()]] - Elimina un archivo.<br />
* [[SD.mkdir()]] - Crea un directorio (carpeta).<br />
* [[SD.rmdir()]] - Elimina un directorio (carpeta).<br />
<br />
<br />
== La clase File ==<br />
Es un objeto que representa la instancia de un fichero (archivo) o directorio (carpeta) dentro de la tarjeta SD; con este se interactúa directamente sobre ellos. Se crea mediante las funciones [[SD.open()]] o [[File.openNextFile()]].<br />
<br />
Hereda de la clase [[Stream]], lo que quiere decir que prácticamente comparte la mayoría de métodos (y funcionalidad) de incluso la clase [[Serial]]. Que algunos no sean mencionados en esta página, no quiere decir que no se puedan utilizar.<br />
<br />
{{Nota|a partir de la versión 1.0 de la IDE de Arduino, se permite tener múltiples archivos abiertos a la vez.}}{{Nota|El flujo de entrada y salida de esta clase se categorizan como '''por bloques'''.}}{{Nota|este objeto se puede introducir directamente en un contexto booleano (ej.: como condición de un [[if... else]]); se evaluará como verdadero o '''true''' si el archivo/carpeta que representa está abierto/a en dicha instancia, falso o '''false''' en el caso contrario.}}<br />
<br />
=== Métodos ===<br />
{{Nota|prácticamente ningún método funcionará si la instancia es "vacía" o representa un archivo/carpeta sin abrir.}}<br />
<br />
* [[File.read()]] - Lee un byte/caracter o varios del archivo.<br />
* [[File.peek()]] - Lee un byte/caracter del archivo sin avanzar al siguiente.<br />
* [[File.available()]] - Retorna la cantidad de bytes/caracteres disponibles para leer (antes de llegar al final del archivo).<br />
* [[File.write()]] - Escribe un byte/caracter o varios al archivo. Suele usarse para archivos binarios.<br />
* [[File.print()]] - Escribe una representación textual de un dato (o una cadena de caracteres) al archivo. Suele usarse para archivos de texto plano.<br />
* [[File.println()]] - Igual al anterior, excepto que agrega una nueva línea de texto.<br />
* [[File.flush()]] - Fuerza la actualización de los datos en la tarjeta SD.<br />
* [[File.close()]] - Cierra el archivo (o carpeta) para liberar correctamente cualquier recurso que esté siendo utilizado por esta instancia.<br />
* [[File.seek()]] - Posiciona el "cursor" del archivo hacia una posición dada.<br />
* [[File.position()]] - Retorna la posición actual del "cursor" del archivo.<br />
* [[File.size()]] - Retorna el tamaño del archivo (en bytes).<br />
* [[File.name()]] - Retorna el nombre del archivo/carpeta.<br />
* [[File.isDirectory()]] - Verifica si esta instancia realmente representa un directorio (carpeta) y no un archivo regular.<br />
* [[File.openNextFile()]] - Abre el siguiente archivo de la lista (válido si esta instancia representa un directorio/carpeta).<br />
* [[File.rewindDirectory()]] - Devuelve la iteración de archivos al comienzo (válido si esta instancia representa un directorio/carpeta).<br />
<br />
<br />
== Advertencias ==<br />
* Atento al uso de la [[SRAM]], esta librería suele ser intensiva en ese recurso. Inicialmente consume alrededor de 700 bytes de este tipo de memoria.<br />
* La tarjeta debe estar formateada en FAT16 o FAT32 con [https://www.sdcard.org/downloads/formatter_4/ SDFormatter] ('''NUNCA CON LOS UTILITARIOS DEL SISTEMA OPERATIVO'''), de lo contrario no funcionará con la librería o podría tener un bajo rendimiento.<br />
<br />
<br />
== Ejemplo ==<br />
<br />
<br />
== Vea también ==<br />
* [[SPI]]<br />
* [[Stream]]<br />
<br />
== Referencias externas ==<br />
* [https://www.arduino.cc/en/Reference/SD Documentación oficial de la librería (en inglés)]<br />
* [https://en.wikipedia.org/wiki/8.3_filename Artículo de Wikipedia sobre los nombres SFN (en inglés)]<br />
<br />
[[Category:Librerias]]</div>Lucario448https://arduwiki.perut.org/index.php?title=Librerias&diff=2394Librerias2019-01-13T22:07:55Z<p>Lucario448: /* Almacenamiento de memoria */</p>
<hr />
<div>Esta página incluye una lista de librerías contribuidas por la comunidad para Arduino.<br />
<br />
== Paginas huerfanas ==<br />
* [[ChatServer]]<br />
* [[UDPSendReceiveString]]<br />
* [[WebClient]]<br />
* [[WebClientRepeating]]<br />
* [[WebServer]]<br />
<br />
== Audio ==<br />
* [[Rttl]] - Ejecuta melodias Rttl<br />
* [[MusicWithoutDelay]] - Un algoritmo para tocar notas musicales más fácil, con la ayuda de la biblioteca de tonos de Bhagman, sin demora.<br />
* [[SinpleSDAudio]]<br />
* [[TMRpcm]] - Reproducción de audio PCM/WAV.<br />
* [[AudioFrequencyMeter]] - Obtener el tono fundamental de una señal de audio<br />
<br />
== Nube ==<br />
* [[JustWifi]] - Administrador Wifi para ESP8266 (Xose Pérez)<br />
<br />
== Comunicaciones ==<br />
* [[Ethernet]] para conectarse a Internet usando Arduino Ethernet Shield, Arduino Ethernet Shield 2 y Arduino Leonardo ETH<br />
* [[GSM]] para conectarse a una red GSM/GRPS con la protección GSM.<br />
* [[SPI]] para comunicarse con dispositivos que utilizan el bus de Interfaz Periférica Serial (SPI)<br />
* [[WiFi]] para conectarse a internet usando el escudo Arduino WiFi.<br />
* [[Wire]] Interfaz de dos hilos (I2C) para enviar y recibir datos a través de una red de dispositivos o sensores.<br />
* [[OneWire]] Acceda a sensores de temperatura de 1 cable, memoria y otros chips.<br />
* [[ArduinoMqtt]] Libreria de cliente MQTT para Arduino basada en el proyecto Eclipse Paho.<br />
* [[Conector CMMC MQTT]] Libreria de conetctores MQTT<br />
* [[MQTT]] Libreria MQTT para Arduino<br />
* [[ESP32 BLE Arduino]] Funciones BLE para ESP32.<br />
<br />
== Criptografía ==<br />
<br />
== Estructura de datos y algoritmos ==<br />
<br />
== Gráficos de datos ==<br />
<br />
== Domótica e IoT (Internet de las cosas) ==<br />
<br />
== De entrada y salida ==<br />
=== Botones y Debouncing ===<br />
=== Control LED ===<br />
=== Control LED múltiple ===<br />
=== Otra entrada / salida ===<br />
<br />
== Control LED ==<br />
<br />
== Control LED multiple ==<br />
<br />
== Otra entrada / salida ==<br />
<br />
== Interrupciones ==<br />
<br />
== LCD ==<br />
=== Textuales LCD ===<br />
=== Gráficos / LCD a color ===<br />
<br />
== Matemáticas ==<br />
<br />
== Menú ==<br />
* [[LCDMenuLib]] - Una librería con la que puedes generar un menú basado en el modelo de conjunto anidado con múltiples capas.<br />
* [[MD_Menu]] - Una librería para mostrar y administrar menús en pantallas con hasta 2 líneas.<br />
<br />
== Control de movimiento ==<br />
<br />
== Controladores de motor ==<br />
<br />
== Robotica ==<br />
<br />
== Control de poder ==<br />
<br />
== Procesamiento de señales ==<br />
<br />
== Programadores y pseudo sistemas operativos ==<br />
<br />
== Sensores ==<br />
<br />
== Almacenamiento de memoria ==<br />
[[SD]] - Para la interacción con tarjetas SD (Secure Digital) y la manipulación de archivos (ficheros) y directorios (carpetas) que hay en ellas.<br />
<br />
== Instrumentos de cuerda ==<br />
<br />
== Pruebas, utilidades y ahorro de energia ==<br />
<br />
== Sincronización ==<br />
* [[Time]] - reloj de software en tiempo real.<br />
* [[Metro]] - implementación de eventos temporizados recurrentes, como LED parpadeantes o control del servomotor.<br />
* [[Chronos]] - Fácilmente manipular los tiempos de fecha para realizar la programación, calendarios de configuración y encontrar puntos en el tiempo que sean de su interés.<br />
<br />
== Vea también ==<br />
<br />
== Referencias externas ==<br />
* [http://arduino.cc/en/Reference/Libraries Bibliotecas oficiales de Arduino]<br />
* [https://playground.arduino.cc/Main/LibraryList Libreries for Arduino]<br />
* [https://www.arduinolibraries.info/libraries Arduino libraries]<br />
<br />
[[Category:Arduino]]</div>Lucario448https://arduwiki.perut.org/index.php?title=Librerias&diff=2393Librerias2019-01-13T22:07:09Z<p>Lucario448: /* Almacenamiento de memoria */</p>
<hr />
<div>Esta página incluye una lista de librerías contribuidas por la comunidad para Arduino.<br />
<br />
== Paginas huerfanas ==<br />
* [[ChatServer]]<br />
* [[UDPSendReceiveString]]<br />
* [[WebClient]]<br />
* [[WebClientRepeating]]<br />
* [[WebServer]]<br />
<br />
== Audio ==<br />
* [[Rttl]] - Ejecuta melodias Rttl<br />
* [[MusicWithoutDelay]] - Un algoritmo para tocar notas musicales más fácil, con la ayuda de la biblioteca de tonos de Bhagman, sin demora.<br />
* [[SinpleSDAudio]]<br />
* [[TMRpcm]] - Reproducción de audio PCM/WAV.<br />
* [[AudioFrequencyMeter]] - Obtener el tono fundamental de una señal de audio<br />
<br />
== Nube ==<br />
* [[JustWifi]] - Administrador Wifi para ESP8266 (Xose Pérez)<br />
<br />
== Comunicaciones ==<br />
* [[Ethernet]] para conectarse a Internet usando Arduino Ethernet Shield, Arduino Ethernet Shield 2 y Arduino Leonardo ETH<br />
* [[GSM]] para conectarse a una red GSM/GRPS con la protección GSM.<br />
* [[SPI]] para comunicarse con dispositivos que utilizan el bus de Interfaz Periférica Serial (SPI)<br />
* [[WiFi]] para conectarse a internet usando el escudo Arduino WiFi.<br />
* [[Wire]] Interfaz de dos hilos (I2C) para enviar y recibir datos a través de una red de dispositivos o sensores.<br />
* [[OneWire]] Acceda a sensores de temperatura de 1 cable, memoria y otros chips.<br />
* [[ArduinoMqtt]] Libreria de cliente MQTT para Arduino basada en el proyecto Eclipse Paho.<br />
* [[Conector CMMC MQTT]] Libreria de conetctores MQTT<br />
* [[MQTT]] Libreria MQTT para Arduino<br />
* [[ESP32 BLE Arduino]] Funciones BLE para ESP32.<br />
<br />
== Criptografía ==<br />
<br />
== Estructura de datos y algoritmos ==<br />
<br />
== Gráficos de datos ==<br />
<br />
== Domótica e IoT (Internet de las cosas) ==<br />
<br />
== De entrada y salida ==<br />
=== Botones y Debouncing ===<br />
=== Control LED ===<br />
=== Control LED múltiple ===<br />
=== Otra entrada / salida ===<br />
<br />
== Control LED ==<br />
<br />
== Control LED multiple ==<br />
<br />
== Otra entrada / salida ==<br />
<br />
== Interrupciones ==<br />
<br />
== LCD ==<br />
=== Textuales LCD ===<br />
=== Gráficos / LCD a color ===<br />
<br />
== Matemáticas ==<br />
<br />
== Menú ==<br />
* [[LCDMenuLib]] - Una librería con la que puedes generar un menú basado en el modelo de conjunto anidado con múltiples capas.<br />
* [[MD_Menu]] - Una librería para mostrar y administrar menús en pantallas con hasta 2 líneas.<br />
<br />
== Control de movimiento ==<br />
<br />
== Controladores de motor ==<br />
<br />
== Robotica ==<br />
<br />
== Control de poder ==<br />
<br />
== Procesamiento de señales ==<br />
<br />
== Programadores y pseudo sistemas operativos ==<br />
<br />
== Sensores ==<br />
<br />
== Almacenamiento de memoria ==<br />
[[SD]] - Para la interacción con tarjetas SD (Secure Digital) y la manipulación de archivos (ficheros) y directorios (carpetas) que hay en él.<br />
<br />
== Instrumentos de cuerda ==<br />
<br />
== Pruebas, utilidades y ahorro de energia ==<br />
<br />
== Sincronización ==<br />
* [[Time]] - reloj de software en tiempo real.<br />
* [[Metro]] - implementación de eventos temporizados recurrentes, como LED parpadeantes o control del servomotor.<br />
* [[Chronos]] - Fácilmente manipular los tiempos de fecha para realizar la programación, calendarios de configuración y encontrar puntos en el tiempo que sean de su interés.<br />
<br />
== Vea también ==<br />
<br />
== Referencias externas ==<br />
* [http://arduino.cc/en/Reference/Libraries Bibliotecas oficiales de Arduino]<br />
* [https://playground.arduino.cc/Main/LibraryList Libreries for Arduino]<br />
* [https://www.arduinolibraries.info/libraries Arduino libraries]<br />
<br />
[[Category:Arduino]]</div>Lucario448https://arduwiki.perut.org/index.php?title=delayMicroseconds()&diff=2392delayMicroseconds()2018-12-02T05:27:29Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Pausa la ejecución del programa durante la cantidad de microsegundos especificada. Al igual que [[delay()]], no interfiere en las salidas PWM ni en las tareas en segundo plano (interrupciones).<br />
<br />
Este retraso lo realiza con la mayor exactitud posible que pueda ofrecer el sistema; tanto así que para ciertas frecuencias de reloj, utiliza instrucciones en lenguaje ensamblador para mantener la sincronía.<br />
<br />
== Sintaxis ==<br />
<pre><br />
delayMicroseconds(tiempo);<br />
</pre><br />
<br />
== Parámetros ==<br />
;tiempo: el lapso (en microsegundos) en el que el programa se detiene ([[unsigned int]]).<br />
<br />
== Retornos ==<br />
Nada.<br />
<br />
== Advertencias ==<br />
* Debido a que esta función no interfiere con las interrupciones, estas podrían comprometer fuertemente la exactitud del retraso (lo prolongan más de lo que debería). A menos que las deshabilites con [[noInterrupts()]] o lo hagas dentro de una rutina de este tipo, no se recomienda utilizar esta función para generar (o leer) trenes de pulsos cuyo margen de error sea muy pequeño.<br />
<br />
== Comentarios ==<br />
* A diferencia de [[delay()]], [[millis()]] y [[micros()]], esta función no depende de temporizador alguno; lo que lo vuelve utilizable sin interrupciones o dentro de una rutina de interrupción (aunque en la mayoría de casos se desaconseja su uso).<br />
* A pesar de ser algo inusual (y en cierto modo hasta absurdo pensar), debido al tipo de parámetro, es posible realizar un retraso de 65535 microsegundos (casi como hacer '''delay(66)''') o 4294967296 microsegundos (4295 segundos o 1 hora y 12 minutos); dependiendo de la arquitectura del microcontrolador.<br />
* Colocar un cero de parámetro es prácticamente el equivalente a colocar un uno; solamente el proceso que "por debajo" conlleva invocar una función y salir de esta, ya genera un retraso de esa duración. Dicho efecto se vuelve despreciable en microcontroladores que trabajan a 40 MHz o más.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
while (true) {<br />
digitalWrite(pin, HIGH);<br />
delayMicroseconds(500);<br />
digitalWrite(pin, LOW);<br />
delayMicroseconds(500);<br />
}<br />
// Genera una señal cuadrada de más o menos 1 KHz. El sobrecargo del ciclo hace este proceso un tantito más lento, y además las ocasionales interrupciones hacen que dicha frecuencia no se mantenga estable.<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[delay()]]<br />
* [[millis()]]<br />
* [[micros()]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]<br />
<br />
<br />
[[Category:Funciones]]</div>Lucario448https://arduwiki.perut.org/index.php?title=bitshift_right&diff=2389bitshift right2018-10-06T19:15:22Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Desplaza hacia la derecha (hacia el bit menos significativo) una cantidad determinada de bits de una variable o constante; rellenando con ceros.<br />
<br />
== Sintaxis ==<br />
<pre><br />
valor = valor >> nBits;<br />
valor >>= nBits;<br />
</pre><br />
;valor: Constante o variable a trabajar.<br />
;nBits: Cantidad de bits a desplazar. '''Debe ser un valor entero positivo'''.<br />
<br />
== Advertencias ==<br />
* Esta operación desplaza bits descartando los que hayan quedado fuera, no los rota de posición. Por lo tanto, desplazar la cantidad suficiente de bits puede resultar en un valor cero.<br />
<br />
== Ejemplo ==<br />
Sirve para realizar una división entera con un cociente potencia de base 2<br />
<pre><br />
analogWrite(pin, analogRead(A0) >> 2);<br />
// Mucho más rápido que map() o una división.<br />
</pre><br />
'''analogRead(A0) >> 2''' equivale a '''analogRead(A0) / 4'''<br />
<br />
== Vea también ==<br />
* [[not]]<br />
* [[and]]<br />
* [[or]]<br />
* [[bitshift left]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=random()&diff=2359random()2018-08-10T02:24:53Z<p>Lucario448: /* Vea también */</p>
<hr />
<div>== Descripción ==<br />
La función random devuelve un número aleatorio entero de un intervalo de valores especificado entre los valores min (inclusive) y max (hasta max-1).<br />
{{Nota|Si quiere realmente generar un número aleatorio entre una ejecución y otra, debe cambiar el valor de la "semilla" con [[randomSeed()]].}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
random(max);<br />
random(min, max);<br />
</pre><br />
<br />
== Parámetros ==<br />
;max: numero maximo pero no lo incluye. Hasta max-1<br />
;min: numero minimo incluido (cero cuando no se especifica este parámetro).<br />
<br />
== Retornos ==<br />
Retorna un número aleatorio entero tipo [[long]], cuyo valor oscilará entre '''min''' y '''max'''-1.<br />
<br />
== Advertencias ==<br />
Es un generador pseudo-aleatorio, lo que quiere decir que si la semilla (valor de iniciación) permanece constante, la secuencia de valores generados también lo será. Hay dos formas de obtener la semilla en tiempo de ejecución y con relativa aleatoriedad:<br />
# El valor retornado por [[analogRead()]] sobre un pin analógico "flotante" (libre, sin conectar a nada), aunque la semilla estaría limitada a la resolución del ADC.<br />
# Una técnica que involucra aprovechar el desfase natural entre el oscilador principal y el del temporizador "watchdog", pulsar [https://gist.github.com/endolith/2568571 aquí] para leer sobre el tema (en inglés y aplica únicamente para arquitecturas AVR).<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte n = random(0,256); //Genera un numero entre 0~255 (max-1)<br />
int n = random(1024); //Genera un numero entre 0~1023<br />
</pre><br />
<br />
== Vea también ==<br />
* [[randomSeed()]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]<br />
<br />
<br />
[[Category:Funciones]]</div>Lucario448https://arduwiki.perut.org/index.php?title=randomSeed()&diff=2358randomSeed()2018-08-10T02:22:02Z<p>Lucario448: /* Advertencias */</p>
<hr />
<div>== Descripción ==<br />
Establece un valor, o semilla, como punto de partida para la función [[random()]]. En realidad inicializa el generador de números pseudoaleatorios, haciendo que comience en un punto arbitrario en su secuencia aleatoria. Esta secuencia, aunque es muy larga y aleatoria, siempre es la misma.<br />
<br />
<pre><br />
void setup(){<br />
randomSeed(semilla);<br />
}<br />
</pre><br />
<br />
== Parámetros ==<br />
;semilla: un numero tipo [[unsigned long]] que define la semilla.<br />
<br />
== Retorno ==<br />
Nada.<br />
<br />
== Advertencias ==<br />
* Si llamas esta función con un numero [[unsigned long]] fijo la secuencia [[random()]] siempre se repetira.<br />
<br />
== Comentarios ==<br />
* Si el pin A0 esta al aire producirá ruido que es perfecto para usar de semilla.<br />
<br />
== Ejemplos ==<br />
<syntaxhighlight lang="c++"><br />
void setup(){<br />
randomSeed(analogRead(A0));<br />
}<br />
void loop(){<br />
int aleatorio = random(1024); //Numero entre 0~1023 <br />
}<br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[random()]]<br />
<br />
== Referencias ==<br />
<br />
[[Category:Funciones]]</div>Lucario448https://arduwiki.perut.org/index.php?title=return&diff=2357return2018-08-10T02:19:39Z<p>Lucario448: </p>
<hr />
<div>== Descripción ==<br />
Termina una función, devuelve el control y opcionalmente un valor desde una función a la función que la llamó.<br />
<br />
{{Nota|Lo que escribamos por debajo de '''return''' en la función donde lo usemos, no se ejecutará nunca. Ya que, cuando llega a '''return''', vuelve a la función que lo llamó.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
return [variable];<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable: variable, constante que contiene o valor es lo que se retornara.<br />
<br />
En caso de que la función sea de retorno [[void]], no se coloca más que la palabra reservada y el ''';'''<br />
<br />
== Retorno ==<br />
Valor de la variable o constante a la función invocadora (si no es de retorno [[void]]).<br />
<br />
== Advertencias ==<br />
Nada.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
int checkSensor(){ <br />
if (analogRead(0) > 400) {<br />
return 1; <br />
}else{ <br />
return 0; <br />
} <br />
} <br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[if... else]]<br />
* [[switch... case]]<br />
* [[for]]<br />
* [[while]]<br />
* [[do... while]]<br />
* [[break]]<br />
* [[continue]]<br />
* [[goto]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/es/language/functions/time/millis/ Guia de referencia de Arduino]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=asterisco&diff=2356asterisco2018-08-09T02:11:10Z<p>Lucario448: /* Parámetros */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''asterisco''' <nowiki>(*)</nowiki> tiene dos funciones:<br />
<br />
# Declarar variables como punteros de cierto tipo de dato.<br />
# Desreferenciar; dicho en otras palabras, trabajar con el valor apuntado en vez del puntero en sí. Dicho valor dependerá del tipo de dato del puntero (es "interpretado" segun la posición de memoria dada).<br />
<br />
{{Nota|A menos que el microcontrolador tenga más de 32 KB de [[SRAM]], los punteros siempre serán variables enteras de 16 bits (el equivalente a [[word]]) independientemente del tipo que interpreten. De hecho también se pueden realizar las típicas operaciones matemáticas en punteros como cualquier otro tipo número-entero de variable conocido.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
tipo* puntero; // Así se declara un puntero. La diferencia a una variable normal radica en el * después de declarar el tipo de dato y antes del nombre.<br />
variable1 = *variable2 // Asigne el valor apuntado por variable2. Cuando no es en una declaración, se usa para desreferenciar. El * va antes del nombre del puntero.<br />
</pre><br />
<br />
== Parámetros ==<br />
;puntero: Una variable que se utiliza como puntero, y que la posición apuntada será interpretada como si fuera un dato de tipo '''tipo'''.<br />
;variable1: Una variable normal (que solamente almacena un dato del tipo declarado).<br />
;<nowiki>*</nowiki>variable2: Puntero del cuál se quiere obtener el valor de la posición a la que apunta.<br />
<br />
== Comentarios ==<br />
Los punteros son uno de los temas más complicados para los principiantes de Arduino y es posible escribir la gran mayoría de [[bocetos]] sin tener que encontrarse con los punteros. Sin embargo, para la manipulación de ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en la propia caja de herramientas.<br />
<br />
Bien usados, los punteros son excepcionalmente útiles para resolver cierto tipo de problemas, pero aprender a manejarlos puede provocar serios dolores de cabeza, especialmente cuando tratas de depurar un programa que se niega a funcionar como debe.<br />
<br />
En primer lugar debemos entender que la memoria del Arduino está numerada en posiciones. Cada posición de memoria tiene una dirección única, que debe ser especificada cuando queremos leer o escribir su valor. Si miramos el tipo de memoria de los distintos Arduinos, vemos que, por ejemplo, el [[UNO]] dispone de 32 K de memoria [[flash]] para almacenamiento de programas y de 2 K de [[SRAM]] para almacenar de variables.<br />
<br />
Cuando definimos una variable en el [[boceto]], el compilador le asigna una posición en la memoria [[SRAM]]. Si la variables es del tipo [[char]] o [[byte]] asigna un byte de memoria, si es del tipo [[int]] o [[unsigned int]] le asigna dos posiciones de memoria y si es un tipo [[long]] o [[unsigned long]] le asigna 4 posiciones de memoria.<br />
<br />
<pre><br />
int numero; //Declaramos variable<br />
numero = 123; //Definimos variable<br />
</pre><br />
<br />
{|class="wikitable"<br />
!Nombre!!Dirección de memoria!!Contenido<br />
|-<br />
|numero||2050||123<br />
|}<br />
<br />
Esto nos da una idea de lo que puede suceder si escribimos un valor long en una dirección de memoria que corresponde a un int. Como el tipo long ocupa 4 bytes, cuando intentemos meterlos en una dirección a la que se ha asignado 2 bytes, va a ocupar el contenido de las siguientes posiciones de memoria, que pueden estar usadas por otros satos. Prueba esto:<br />
<br />
<pre><br />
void setup(){<br />
Serial.begin(115200);<br />
int numero;<br />
long n = 100000;<br />
numero = n; //Estas intentando guardar 4 byte donde solo reservaste 2 bytes<br />
Serial.println(numero); //-31072<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</pre><br />
<br />
<br />
Cuando declaras una matriz, en realidad estás declarando un puntero. De hecho es posible utilizar '''[]''' en cualquier puntero, aunque este no se haya declarado explícitamente como una matriz.<br><br />
La diferencia entre declarar un puntero y una matriz, está en lo que ocurre implícitamente: declarar un puntero es igual que declarar cualquier otra variable simple; mientras que declarar una matriz es más que asignar 2 bytes, es asignar otro espacio según el tipo de dato y el número ingresado entre los '''[]''' (o en su defecto, la cantidad de elementos que aparece entre los '''{}'''), inicializarlo con ceros o con los valores preestablecidos, y finalmente asignarle al respectivo puntero la posición del primer byte de ese espacio que tuvo que asignar.<br />
<br />
El acceso a un elemento es más amigable hacerlo con los '''[]''', sin embargo existen dos formas de realizar la misma acción:<br />
<pre><br />
matriz[i] = 4;<br />
*(matriz + i) = 4;<br />
// Ambos hacen exactamente lo mismo<br />
</pre><br />
De las dos formas es válido ya que una matriz es un puntero, y en cierto modo también se puede decir que al revés.<br />
<br />
== Advertencias ==<br />
* Errores de '''overflow''' de registro no son advertidos por el compilador, ya que el puntero puede apuntar en cualquier posición arbitraria de la memoria. Tanto así que puede apuntarse a sí mismo, a otro puntero, e incluso a cualquier variable, matriz u objeto existente en el momento.<br />
* '''Un gran poder conlleva una gran responsabilidad'''. Debido a que el puntero tiene el "superpoder" de meterse en cualquier parte de la memoria de ejecución ([[SRAM]]), existe el riesgo de corromperla sin previo aviso y colgar el programa en cuestión.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p; i=5, resultado;<br />
p = &i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria de p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[ampersan]] - <nowiki>(&)</nowiki><br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/dereference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=ampersan&diff=2355ampersan2018-08-09T02:03:22Z<p>Lucario448: /* Descripción */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''ampersand''' <nowiki>(&)</nowiki> se usa para obtener la dirección de memoria (puntero) de una variable individual.<br />
<br />
El tipo de puntero obtenido es igual al tipo de dato del operando; en caso de que el valor apuntado requiera "reinterpretación" (que no es lo mismo que la conversión explícita o casting), el tipo de puntero debe ser convertido explícitamente. Este truco es útil para directamente leer o modificar cualquier variable como una simple matriz de [[byte|bytes]].<br />
<br />
{{Nota|Es incluso válido obtener el puntero de otro puntero, y el de un elemento de una matriz.}}<br />
<br />
== Sintexis ==<br />
<pre><br />
variable1 = &variable2;<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable1:<br />
;variable2:<br />
<br />
== Advertencias ==<br />
Los punteros son uno de los temas más complicados para los principiantes en el aprendizaje de C, y es posible escribir la gran mayoría de los bocetos de Arduino sin encontrar punteros. Sin embargo, para manipular ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en el kit de herramientas.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p, i=5, resultado;<br />
p=&i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[asterisco]] - <nowiki>(*)</nowiki><br />
<br />
== Referencia ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/reference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=asterisco&diff=2354asterisco2018-08-09T01:09:43Z<p>Lucario448: /* Comentarios */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''asterisco''' <nowiki>(*)</nowiki> tiene dos funciones:<br />
<br />
# Declarar variables como punteros de cierto tipo de dato.<br />
# Desreferenciar; dicho en otras palabras, trabajar con el valor apuntado en vez del puntero en sí. Dicho valor dependerá del tipo de dato del puntero (es "interpretado" segun la posición de memoria dada).<br />
<br />
{{Nota|A menos que el microcontrolador tenga más de 32 KB de [[SRAM]], los punteros siempre serán variables enteras de 16 bits (el equivalente a [[word]]) independientemente del tipo que interpreten. De hecho también se pueden realizar las típicas operaciones matemáticas en punteros como cualquier otro tipo número-entero de variable conocido.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
tipo* puntero; // Así se declara un puntero. La diferencia a una variable normal radica en el * después de declarar el tipo de dato y antes del nombre.<br />
variable1 = *variable2 // Asigne el valor apuntado por variable2. Cuando no es en una declaración, se usa para desreferenciar. El * va antes del nombre del puntero.<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable1:<br />
;<nowiki>*</nowiki>variable2:<br />
<br />
<br />
== Comentarios ==<br />
Los punteros son uno de los temas más complicados para los principiantes de Arduino y es posible escribir la gran mayoría de [[bocetos]] sin tener que encontrarse con los punteros. Sin embargo, para la manipulación de ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en la propia caja de herramientas.<br />
<br />
Bien usados, los punteros son excepcionalmente útiles para resolver cierto tipo de problemas, pero aprender a manejarlos puede provocar serios dolores de cabeza, especialmente cuando tratas de depurar un programa que se niega a funcionar como debe.<br />
<br />
En primer lugar debemos entender que la memoria del Arduino está numerada en posiciones. Cada posición de memoria tiene una dirección única, que debe ser especificada cuando queremos leer o escribir su valor. Si miramos el tipo de memoria de los distintos Arduinos, vemos que, por ejemplo, el [[UNO]] dispone de 32 K de memoria [[flash]] para almacenamiento de programas y de 2 K de [[SRAM]] para almacenar de variables.<br />
<br />
Cuando definimos una variable en el [[boceto]], el compilador le asigna una posición en la memoria [[SRAM]]. Si la variables es del tipo [[char]] o [[byte]] asigna un byte de memoria, si es del tipo [[int]] o [[unsigned int]] le asigna dos posiciones de memoria y si es un tipo [[long]] o [[unsigned long]] le asigna 4 posiciones de memoria.<br />
<br />
<pre><br />
int numero; //Declaramos variable<br />
numero = 123; //Definimos variable<br />
</pre><br />
<br />
{|class="wikitable"<br />
!Nombre!!Dirección de memoria!!Contenido<br />
|-<br />
|numero||2050||123<br />
|}<br />
<br />
Esto nos da una idea de lo que puede suceder si escribimos un valor long en una dirección de memoria que corresponde a un int. Como el tipo long ocupa 4 bytes, cuando intentemos meterlos en una dirección a la que se ha asignado 2 bytes, va a ocupar el contenido de las siguientes posiciones de memoria, que pueden estar usadas por otros satos. Prueba esto:<br />
<br />
<pre><br />
void setup(){<br />
Serial.begin(115200);<br />
int numero;<br />
long n = 100000;<br />
numero = n; //Estas intentando guardar 4 byte donde solo reservaste 2 bytes<br />
Serial.println(numero); //-31072<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</pre><br />
<br />
<br />
Cuando declaras una matriz, en realidad estás declarando un puntero. De hecho es posible utilizar '''[]''' en cualquier puntero, aunque este no se haya declarado explícitamente como una matriz.<br><br />
La diferencia entre declarar un puntero y una matriz, está en lo que ocurre implícitamente: declarar un puntero es igual que declarar cualquier otra variable simple; mientras que declarar una matriz es más que asignar 2 bytes, es asignar otro espacio según el tipo de dato y el número ingresado entre los '''[]''' (o en su defecto, la cantidad de elementos que aparece entre los '''{}'''), inicializarlo con ceros o con los valores preestablecidos, y finalmente asignarle al respectivo puntero la posición del primer byte de ese espacio que tuvo que asignar.<br />
<br />
El acceso a un elemento es más amigable hacerlo con los '''[]''', sin embargo existen dos formas de realizar la misma acción:<br />
<pre><br />
matriz[i] = 4;<br />
*(matriz + i) = 4;<br />
// Ambos hacen exactamente lo mismo<br />
</pre><br />
De las dos formas es válido ya que una matriz es un puntero, y en cierto modo también se puede decir que al revés.<br />
<br />
== Advertencias ==<br />
* Errores de '''overflow''' de registro no son advertidos por el compilador, ya que el puntero puede apuntar en cualquier posición arbitraria de la memoria. Tanto así que puede apuntarse a sí mismo, a otro puntero, e incluso a cualquier variable, matriz u objeto existente en el momento.<br />
* '''Un gran poder conlleva una gran responsabilidad'''. Debido a que el puntero tiene el "superpoder" de meterse en cualquier parte de la memoria de ejecución ([[SRAM]]), existe el riesgo de corromperla sin previo aviso y colgar el programa en cuestión.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p; i=5, resultado;<br />
p = &i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria de p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[ampersan]] - <nowiki>(&)</nowiki><br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/dereference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=asterisco&diff=2353asterisco2018-08-09T00:39:38Z<p>Lucario448: /* Advertencias */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''asterisco''' <nowiki>(*)</nowiki> tiene dos funciones:<br />
<br />
# Declarar variables como punteros de cierto tipo de dato.<br />
# Desreferenciar; dicho en otras palabras, trabajar con el valor apuntado en vez del puntero en sí. Dicho valor dependerá del tipo de dato del puntero (es "interpretado" segun la posición de memoria dada).<br />
<br />
{{Nota|A menos que el microcontrolador tenga más de 32 KB de [[SRAM]], los punteros siempre serán variables enteras de 16 bits (el equivalente a [[word]]) independientemente del tipo que interpreten. De hecho también se pueden realizar las típicas operaciones matemáticas en punteros como cualquier otro tipo número-entero de variable conocido.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
tipo* puntero; // Así se declara un puntero. La diferencia a una variable normal radica en el * después de declarar el tipo de dato y antes del nombre.<br />
variable1 = *variable2 // Asigne el valor apuntado por variable2. Cuando no es en una declaración, se usa para desreferenciar. El * va antes del nombre del puntero.<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable1:<br />
;<nowiki>*</nowiki>variable2:<br />
<br />
<br />
== Comentarios ==<br />
Los punteros son uno de los temas más complicados para los principiantes de Arduino y es posible escribir la gran mayoría de [[bocetos]] sin tener que encontrarse con los punteros. Sin embargo, para la manipulación de ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en la propia caja de herramientas.<br />
<br />
Bien usados, los punteros son excepcionalmente útiles para resolver cierto tipo de problemas, pero aprender a manejarlos puede provocar serios dolores de cabeza, especialmente cuando tratas de depurar un programa que se niega a funcionar como debe.<br />
<br />
En primer lugar debemos entender que la memoria del Arduino está numerada en posiciones. Cada posición de memoria tiene una dirección única, que debe ser especificada cuando queremos leer o escribir su valor. Si miramos el tipo de memoria de los distintos Arduinos, vemos que, por ejemplo, el [[UNO]] dispone de 32 K de memoria [[flash]] para almacenamiento de programas y de 2 K de [[SRAM]] para almacenar de variables.<br />
<br />
Cuando definimos una variable en el [[boceto]], el compilador le asigna una posición en la memoria [[SRAM]]. Si la variables es del tipo [[char]] o [[byte]] asigna un byte de memoria, si es del tipo [[int]] o [[unsigned int]] le asigna dos posiciones de memoria y si es un tipo [[long]] o [[unsigned long]] le asigna 4 posiciones de memoria.<br />
<br />
<pre><br />
int numero; //Declaramos variable<br />
numero = 123; //Definimos variable<br />
</pre><br />
<br />
{|class="wikitable"<br />
!Nombre!!Dirección de memoria!!Contenido<br />
|-<br />
|numero||2050||123<br />
|}<br />
<br />
Esto nos da una idea de lo que puede suceder si escribimos un valor long en una dirección de memoria que corresponde a un int. Como el tipo long ocupa 4 bytes, cuando intentemos meterlos en una dirección a la que se ha asignado 2 bytes, va a ocupar el contenido de las siguientes posiciones de memoria, que pueden estar usadas por otros satos. Prueba esto:<br />
<br />
<pre><br />
void setup(){<br />
Serial.begin(115200);<br />
int numero;<br />
long n = 100000;<br />
numero = n; //Estas intentando guardar 4 byte donde solo reservaste 2 bytes<br />
Serial.println(numero); //-31072<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</pre><br />
<br />
== Advertencias ==<br />
* Errores de '''overflow''' de registro no son advertidos por el compilador, ya que el puntero puede apuntar en cualquier posición arbitraria de la memoria. Tanto así que puede apuntarse a sí mismo, a otro puntero, e incluso a cualquier variable, matriz u objeto existente en el momento.<br />
* '''Un gran poder conlleva una gran responsabilidad'''. Debido a que el puntero tiene el "superpoder" de meterse en cualquier parte de la memoria de ejecución ([[SRAM]]), existe el riesgo de corromperla sin previo aviso y colgar el programa en cuestión.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p; i=5, resultado;<br />
p = &i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria de p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[ampersan]] - <nowiki>(&)</nowiki><br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/dereference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=asterisco&diff=2352asterisco2018-08-09T00:25:54Z<p>Lucario448: /* Sintaxis */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''asterisco''' <nowiki>(*)</nowiki> tiene dos funciones:<br />
<br />
# Declarar variables como punteros de cierto tipo de dato.<br />
# Desreferenciar; dicho en otras palabras, trabajar con el valor apuntado en vez del puntero en sí. Dicho valor dependerá del tipo de dato del puntero (es "interpretado" segun la posición de memoria dada).<br />
<br />
{{Nota|A menos que el microcontrolador tenga más de 32 KB de [[SRAM]], los punteros siempre serán variables enteras de 16 bits (el equivalente a [[word]]) independientemente del tipo que interpreten. De hecho también se pueden realizar las típicas operaciones matemáticas en punteros como cualquier otro tipo número-entero de variable conocido.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
tipo* puntero; // Así se declara un puntero. La diferencia a una variable normal radica en el * después de declarar el tipo de dato y antes del nombre.<br />
variable1 = *variable2 // Asigne el valor apuntado por variable2. Cuando no es en una declaración, se usa para desreferenciar. El * va antes del nombre del puntero.<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable1:<br />
;<nowiki>*</nowiki>variable2:<br />
<br />
<br />
== Comentarios ==<br />
Los punteros son uno de los temas más complicados para los principiantes de Arduino y es posible escribir la gran mayoría de [[bocetos]] sin tener que encontrarse con los punteros. Sin embargo, para la manipulación de ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en la propia caja de herramientas.<br />
<br />
Bien usados, los punteros son excepcionalmente útiles para resolver cierto tipo de problemas, pero aprender a manejarlos puede provocar serios dolores de cabeza, especialmente cuando tratas de depurar un programa que se niega a funcionar como debe.<br />
<br />
En primer lugar debemos entender que la memoria del Arduino está numerada en posiciones. Cada posición de memoria tiene una dirección única, que debe ser especificada cuando queremos leer o escribir su valor. Si miramos el tipo de memoria de los distintos Arduinos, vemos que, por ejemplo, el [[UNO]] dispone de 32 K de memoria [[flash]] para almacenamiento de programas y de 2 K de [[SRAM]] para almacenar de variables.<br />
<br />
Cuando definimos una variable en el [[boceto]], el compilador le asigna una posición en la memoria [[SRAM]]. Si la variables es del tipo [[char]] o [[byte]] asigna un byte de memoria, si es del tipo [[int]] o [[unsigned int]] le asigna dos posiciones de memoria y si es un tipo [[long]] o [[unsigned long]] le asigna 4 posiciones de memoria.<br />
<br />
<pre><br />
int numero; //Declaramos variable<br />
numero = 123; //Definimos variable<br />
</pre><br />
<br />
{|class="wikitable"<br />
!Nombre!!Dirección de memoria!!Contenido<br />
|-<br />
|numero||2050||123<br />
|}<br />
<br />
Esto nos da una idea de lo que puede suceder si escribimos un valor long en una dirección de memoria que corresponde a un int. Como el tipo long ocupa 4 bytes, cuando intentemos meterlos en una dirección a la que se ha asignado 2 bytes, va a ocupar el contenido de las siguientes posiciones de memoria, que pueden estar usadas por otros satos. Prueba esto:<br />
<br />
<pre><br />
void setup(){<br />
Serial.begin(115200);<br />
int numero;<br />
long n = 100000;<br />
numero = n; //Estas intentando guardar 4 byte donde solo reservaste 2 bytes<br />
Serial.println(numero); //-31072<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</pre><br />
<br />
== Advertencias ==<br />
* Errores de '''overflow''' de registro no son advertidos por el compilador.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p; i=5, resultado;<br />
p = &i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria de p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[ampersan]] - <nowiki>(&)</nowiki><br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/dereference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=asterisco&diff=2351asterisco2018-08-09T00:19:20Z<p>Lucario448: /* Descripción */</p>
<hr />
<div>== Descripción ==<br />
El operador de '''asterisco''' <nowiki>(*)</nowiki> tiene dos funciones:<br />
<br />
# Declarar variables como punteros de cierto tipo de dato.<br />
# Desreferenciar; dicho en otras palabras, trabajar con el valor apuntado en vez del puntero en sí. Dicho valor dependerá del tipo de dato del puntero (es "interpretado" segun la posición de memoria dada).<br />
<br />
{{Nota|A menos que el microcontrolador tenga más de 32 KB de [[SRAM]], los punteros siempre serán variables enteras de 16 bits (el equivalente a [[word]]) independientemente del tipo que interpreten. De hecho también se pueden realizar las típicas operaciones matemáticas en punteros como cualquier otro tipo número-entero de variable conocido.}}<br />
<br />
== Sintaxis ==<br />
<pre><br />
variable1 = *variable2<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable1:<br />
;<nowiki>*</nowiki>variable2:<br />
<br />
<br />
== Comentarios ==<br />
Los punteros son uno de los temas más complicados para los principiantes de Arduino y es posible escribir la gran mayoría de [[bocetos]] sin tener que encontrarse con los punteros. Sin embargo, para la manipulación de ciertas estructuras de datos, el uso de punteros puede simplificar el código, y el conocimiento de la manipulación de punteros es útil para tener en la propia caja de herramientas.<br />
<br />
Bien usados, los punteros son excepcionalmente útiles para resolver cierto tipo de problemas, pero aprender a manejarlos puede provocar serios dolores de cabeza, especialmente cuando tratas de depurar un programa que se niega a funcionar como debe.<br />
<br />
En primer lugar debemos entender que la memoria del Arduino está numerada en posiciones. Cada posición de memoria tiene una dirección única, que debe ser especificada cuando queremos leer o escribir su valor. Si miramos el tipo de memoria de los distintos Arduinos, vemos que, por ejemplo, el [[UNO]] dispone de 32 K de memoria [[flash]] para almacenamiento de programas y de 2 K de [[SRAM]] para almacenar de variables.<br />
<br />
Cuando definimos una variable en el [[boceto]], el compilador le asigna una posición en la memoria [[SRAM]]. Si la variables es del tipo [[char]] o [[byte]] asigna un byte de memoria, si es del tipo [[int]] o [[unsigned int]] le asigna dos posiciones de memoria y si es un tipo [[long]] o [[unsigned long]] le asigna 4 posiciones de memoria.<br />
<br />
<pre><br />
int numero; //Declaramos variable<br />
numero = 123; //Definimos variable<br />
</pre><br />
<br />
{|class="wikitable"<br />
!Nombre!!Dirección de memoria!!Contenido<br />
|-<br />
|numero||2050||123<br />
|}<br />
<br />
Esto nos da una idea de lo que puede suceder si escribimos un valor long en una dirección de memoria que corresponde a un int. Como el tipo long ocupa 4 bytes, cuando intentemos meterlos en una dirección a la que se ha asignado 2 bytes, va a ocupar el contenido de las siguientes posiciones de memoria, que pueden estar usadas por otros satos. Prueba esto:<br />
<br />
<pre><br />
void setup(){<br />
Serial.begin(115200);<br />
int numero;<br />
long n = 100000;<br />
numero = n; //Estas intentando guardar 4 byte donde solo reservaste 2 bytes<br />
Serial.println(numero); //-31072<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</pre><br />
<br />
== Advertencias ==<br />
* Errores de '''overflow''' de registro no son advertidos por el compilador.<br />
<br />
== Ejemplo ==<br />
<pre><br />
byte *p; i=5, resultado;<br />
p = &i; //5<br />
resultado = *p; //resultado toma el valor de la posicion de memoria de p<br />
</pre><br />
<br />
== Vea también ==<br />
* [[ampersan]] - <nowiki>(&)</nowiki><br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/structure/pointer-access-operators/dereference/ Guia de referencia]<br />
<br />
[[Category:Estructura]]</div>Lucario448https://arduwiki.perut.org/index.php?title=sizeof()&diff=2350sizeof()2018-08-08T23:40:38Z<p>Lucario448: /* Advertencias */</p>
<hr />
<div>== Descripción ==<br />
Evalúa el tamaño en bytes de una variable o matriz. Acepta cualquier tipo de datos: [[char]], [[byte]], [[int]], [[long]], [[float]], etc.<br />
<br />
== Sintexis ==<br />
<pre><br />
sizeof(variable);<br />
</pre><br />
<br />
== Parámetros ==<br />
;variable: nombre de variable o matriz a evaluar, que puede ser tipo: [[char]], [[byte]], [[int]], [[long]], [[float]].<br />
<br />
== Retorna ==<br />
Número de bytes ocupados por variable o matriz.<br />
<br />
== Advertencias ==<br />
'''sizeof()''' al contar en bytes, no necesariamente lo hace en cantidad de elementos; esto depende del tipo de dato. Lo más correcto sería:<br />
<pre><br />
sizeof(matriz) / sizeof(matriz[0])<br />
</pre><br />
Para así obtener el tamaño en cantidad de elementos y no en bytes.<br />
<br />
== Ejemplo 1 ==<br />
Creamos una matriz de caracteres con cierto valor y luego mostramos carácter a carácter.<br />
<br />
<syntaxhighlight lang="c++"><br />
const byte matriz[]="Esto es una matriz";<br />
void setup(){<br />
Serial.begin(115200);<br />
for (byte i=0; i<sizeof(matriz)-1; i++{<br />
Serial.write(matriz[i]); //Caracter<br />
Serial.print(" = ");<br />
Serial.println(matriz[i]); //Codigo ASCII<br />
delay(100);<br />
}<br />
}<br />
void loop(){<br />
//Nada<br />
}<br />
</syntaxhighlight><br />
<br />
== Vea tambien ==<br />
* [[tone()]]<br />
* [[noTone()]]<br />
* [[pulseln()]]<br />
* [[pulselnLong()]]<br />
* [[shiftIn()]]<br />
* [[shiftOut()]]<br />
<br />
== Referencias ==<br />
<br />
[[Category:Funciones]]</div>Lucario448https://arduwiki.perut.org/index.php?title=objeto.c_str()&diff=2104objeto.c str()2018-07-17T23:45:44Z<p>Lucario448: /* Advertencias */</p>
<hr />
<div>== Descripción ==<br />
Convierte el contenido de una cadena como una cadena terminada en nulo al estilo C ([[string]]). Tenga en cuenta que esto le da acceso directo a la memoria intermedia interna [[String]] y se debe usar con cuidado.<br />
<br />
== Sintaxis ==<br />
<pre><br />
objeto.c_str()<br />
</pre><br />
<br />
== Parámetros ==<br />
;objeto: nombre de la instanciado de clase [[String]].<br />
<br />
== Retorna ==<br />
Un puntero al estilo C de la cadena invocadora ([[const]] [[char]]*).<br />
<br />
== Advertencias ==<br />
* Cuando modifica el objeto [[String]], o cuando se destruye, cualquier puntero devuelto previamente por '''c_str()''' deja de ser válido y no debe seguir usandose.<br />
* En particular, nunca debe modificar la cadena a través del puntero devuelto; de lo contrario, podrían ocurrir discrepancias con los contadores internos, y por ende, comportamiento indefinido al operar con el objeto.<br />
<br />
== Ejemplo ==<br />
<syntaxhighlight lang="c++"><br />
</syntaxhighlight><br />
<br />
== Vea también ==<br />
* [[String]]<br />
<br />
== Referencias ==<br />
* [https://www.arduino.cc/reference/en/language/variables/data-types/string/functions/c_str/ Guia de referencia de Arduino]<br />
<br />
[[Category:Funciones]]</div>Lucario448