Olá, pessoal.
Estou começando a usar o módulo para leitura e escrita em cartão SD. Já consegui gravar e ler mas não estou conseguindo achar na documentação como somente substituir a linha no arquivo txt. Saberiam como posso fazer isto?
Tipo, com Files.println, grava novo dado na linha abaixo dando pulos de linha, eu precisava apagar o conteúdo e regravar o novo sem precisar ficar removendo o arquivo txt, recriando ele e depois gravar no txt.
Estou montando um código para leitura de hidrômetro e a contagem dos pulsos é que vou gravar no SD. Assim, gravando tipo 52010 pulsos, na próxima gravação, queria apagar o 52010 e gravar 52500 por exemplo no mesmo arquivo sem pular linha e nem colocar ao lado.
Isso somente será possível apagando o arquivo txt e criando novamente?
Usando as tags devidas, publique seu codigo para que posamos entender melhor seu projeto e então ajuda-lo.
Informe também qual arduino e qual biblioteca voce está usando. (e o link dela).
Usando as tags devidas, publique seu codigo para que posamos entender melhor seu projeto e então ajuda-lo.
É possível gravar sempre no inicio do arquivo, sem a necessidade de deletar e criar novo arquivo.
Dessa forma não funciona. Nas pesquisas que fiz orientava-se a abrir e fechar em seguida o arquivo para limpá-lo, mas o dados anteriores não foram apagados.
Vou tentar alguma solução em código C puro, pois acho que a biblioteca não tem essa funcionalidade.
Há, só não está documentada, o que dificulta a vida de todo mundo.
ao invés de usar
myFile = SD.open(arquivoTxt, FILE_WRITE);
use
myFile = SD.open(arquivoTxt, O_RDWR);
Isso vai permitir que você sobrescreva o conteúdo. Agora, se você não quiser substituir o conteúdo todo, será necessário saber exatamente a posição do arquivo onde você quer começar a substituir o valor e o seu tamanho, o que não será tão simples dado que a quantidade de pulsos deve variar bastante.
Obrigado pela resposta.
Vou testar aqui e dou retorno. Sim, preciso substituir todo o conteúdo. O SD é caso fique sem energia e, ao iniciar, pretendo pegar o valor acumulado no servidor, pegar o valor acumulado no SD e comparar qual é o maior, no qual teria sido o ultimo a ser processado, e recomeçar a partir da comparação.
Nos testes, surgiu uma dificuldade. Uma coisa são simples mas que a biblioteca parece não estar deixando aplicar é o colocar o valor lido do cartão em uma variável, para que possa somar o próximo pulso. Saberia dizer como fazer o valor printado pelo while em uma variável?
Se o que vai ser gravado no arquivo é somente o número de pulsos, creio que é suficiente fazer:
while (myFile.available()) {
leitura += myFile.read();
}
onde a variável leitura é um array de caracteres. Depois você usa toInt() para transformar em um número do tipo long (variáveis do tipo int no Arduino vão somente até 32.767).
Fui olhar com mais calma o exemplo que o @ruilviana fez no wokwi e quando tentei usar a abordagem que eu propus (criar um array de char) ela não funcionou porque o compilador diz que a função myFile.read() está retornando um int e não um char.
Eu mexi então no programa, simplesmente atribuindo uma variável long e parece ter funcionado.
Teste essa versão aqui:
#include <SPI.h>
#include <SD.h>
#define CS_PIN 15
File gravarCartaoSd;
File lerCartaoSd;
long randNumber;
String arquivoTxt = "testeafa.txt";
long pulsosSd;
void setup() {
Serial.begin(115200);
SD.begin(CS_PIN);
randNumber = random(100, 300);
gravarCartaoSd = SD.open(arquivoTxt, FILE_WRITE);
if (gravarCartaoSd) {
Serial.println(" ");
Serial.println("Gravando randomicamente...");
gravarCartaoSd.print(randNumber);
gravarCartaoSd.close();
Serial.println("ok.");
} else {
Serial.print("erro ao abrir o arquivo ");
Serial.println(arquivoTxt);
}
lerCartaoSd = SD.open(arquivoTxt, O_RDWR);
if (lerCartaoSd) {
Serial.print("lendo o arquivo ");
Serial.println(arquivoTxt);
while (lerCartaoSd.available()) {
pulsosSd = lerCartaoSd.read();
}
Serial.print("Pulsos: ");
Serial.write(pulsosSd);
lerCartaoSd.close();
} else {
Serial.print("erro ao ler o arquivo ");
Serial.println(arquivoTxt);
}
}
void loop() {
delay(1000);
}
Consegui resolver. Agora, inserindo o seek e abrir o aquivo como O_RDWR, o ponteito é posicionado para gravar a partir da posição 0(zero) e, assim, passou a reescrever sem precisar apagar o arquivo txt de criá-lo novamente. Para colocar o valor que está no arquivo txt em uma variável, cada caractere fica em uma variável char e depois concateno cada caractere em outra variável do tipo String e depois passo a string para int.
Obrigado ruilviana e Brazilino pela ajuda.
#include <SPI.h>
#include <SD.h>
File myFile;
File myFileRead;
long randNumber;
String pulsosSd = "";
char ler;
long pulsosInt;
long somaPulsos;
void setup() {
Serial.begin(115200);
if (!SD.begin(15)) {
Serial.println("Erro ao iniciar o cartão SD!");
return;
}
Serial.println(" ");
Serial.println("Cartão SD iniciado.");
randNumber = random(1000, 3000);
myFile = SD.open("testeafa.txt", O_RDWR);
if (myFile) {
Serial.print("Gravando randomicamente...");
myFile.seek(0);
myFile.print(randNumber);
myFile.close();
Serial.println("ok.");
} else {
Serial.println("erro ao abrir o arquivo testeafa.txt");
}
myFileRead = SD.open("testeafa.txt", FILE_READ);
if (myFileRead) {
Serial.println("Lendo o arquivo testeafa.txt...");
while (myFileRead.available()) {
ler = myFileRead.read();
pulsosSd.concat(ler);
}
Serial.print("Pulsos: ");
Serial.println(pulsosSd);
myFileRead.close();
} else {
Serial.println("erro ao ler o arquivo testeafa.txt");
}
pulsosInt = pulsosSd.toInt();
somaPulsos = pulsosInt + 1;
Serial.print("Soma dos pulsos: ");
Serial.println(somaPulsos);
}
void loop() {
// nothing happens after setup
}