I'm trying to read a text file in an Arduino SD card reader and copy its text into a string variable, but the function .read always returns -1. How can I solve this problem?
Here's the code:
#include <SPI.h>
#include <SD.h>
File mappa;
String text;
void setup() {
Serial.begin(9600);
while (!Serial) {
;
}
Serial.print("Initializing SD card...");
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
// open the file. note that only one file can be open at a time,
// so you have to close this one before opening another.
mappa = SD.open("map.txt");
// if the file opened okay, write to it:
if (mappa) {
Serial.println("File aperto");
} else {
// if the file didn't open, print an error:
Serial.println("error opening map.txt");
}
Serial.println("map.txt:");
// read from the file until there's nothing else in it:
while (mappa.available()) {
Serial.write(mappa.read());
// text = parseInt(mappa.read());
}
Serial.println(text);
// close the file:
mappa.close();
}
void loop() {
// nothing happens after setup
}
I know that .read() returns an array of integers, but I don't know how to access them separately.
After further research, I got how .read works: It reads the character its cursor is pointing at while advancing the cursor.
So, in order to read the entirety of the file you have to remove the Serial.write portion and convert the characters into char:
String finalString = "";
while (mappa.available())
{
finalString += (char)mappa.read();
}
Related
I want to get Processing to read Strings from Arduino.
I send two Strings massages from the arduino and I want to store them in two different variables on Processing.
I tried to do it, but the two Strings are passed to the first variable and the second variable remains empty. I don't understand why this is the case. Can someone help?
Regards
Arduino Code
void setup() {
Serial.begin(9600);
delay(1000);
Serial.println("1.first message");
Serial.println("2.second message");
delay(100);
}
void loop() {
}
Processing Code
import processing.serial.*;
Serial myPort;
void setup() {
myPort=new Serial(this, "COM3", 9600);
}
void draw() {
String s1=myPort.readStringUntil('\n');
String s2=myPort.readStringUntil('\n');
// printing variables
if(s1!=null){
print("s1:",s1);
}
if(s2!=null){
println("s2:",s2);
}
}
The following works on my Mac system. The incoming strings are placed in a string array as they arrive. The string at index[0] then becomes s1 and the string at index[1] is s2. I also added a delay(100); between the two strings on the Arduino side, but this may not be necessary; you can try it both ways.
import processing.serial.*;
Serial myPort;
String[] s; // Array to hold two strings.
int counter = 0;
void setup() {
printArray(Serial.list()); // List of serial ports
// Enter appropriate number for your system
myPort = new Serial(this, Serial.list()[2], 9600);
s = new String[2];
println("===========");
}
void draw() {
String str = myPort.readStringUntil('\n');
if(str != null) {
s[counter] = str;
if(counter == 0){
println("s1 = ",s[0]);
} else {
println("s2 = ",s[1]);
}
counter++;
}
}
I have some position data continually coming in and I am currently printing it to the serial.
Say I have the string "5" and want to print that to a text file, "myTextFile", what would I need to do to achieve this? To be clear, the text file would be saved on my computer not on an SD card on the Arduino.
Also, is their a way to create a text file within the program before I start saving to it?
You can create a python script to read the serial port and write the results into a text file:
##############
## Script listens to serial port and writes contents into a file
##############
## requires pySerial to be installed
import serial # sudo pip install pyserial should work
serial_port = '/dev/ttyACM0';
baud_rate = 9600; #In arduino, Serial.begin(baud_rate)
write_to_file_path = "output.txt";
output_file = open(write_to_file_path, "w+");
ser = serial.Serial(serial_port, baud_rate)
while True:
line = ser.readline();
line = line.decode("utf-8") #ser.readline returns a binary, convert to string
print(line);
output_file.write(line);
U have to Use serial-lib for this
Serial.begin(9600);
Write your sensor values to the serial interface using
Serial.println(value);
in your loop method
on the processing side use a PrintWriter to write the data read from the serial port to a file
import processing.serial.*;
Serial mySerial;
PrintWriter output;
void setup() {
mySerial = new Serial( this, Serial.list()[0], 9600 );
output = createWriter( "data.txt" );
}
void draw() {
if (mySerial.available() > 0 ) {
String value = mySerial.readString();
if ( value != null ) {
output.println( value );
}
}
}
void keyPressed() {
output.flush(); // Writes the remaining data to the file
output.close(); // Finishes the file
exit(); // Stops the program
}
I am using arduino to develop a small IoT project. Till now everything is working fine.
The steps of the projects are:
Create an XML String from sensor reading
Send the XML as POST to the server.
The odd thing is that the first three trials work perfectly. However, after that, the string holding the XML becomes empty.
Below is a portion of the code:
void loop()
{
while (Serial3.available()>0)
{
char c = Serial3.read();
if (gps.encode(c)){
createXML();
delay(1000);
if(seconds_passed==10000 && !IsXMLEmpty)
{
XML+="\n</start>";
Serial.print(XML);
Serial.print(F("Send to serveR"));
seconds_passed=0;
IsXMLEmpty=true;
String temp ="";
temp = "XML="+XML;
char *param = new char[temp.length()+1];
temp.toCharArray(param,temp.length());
Serial.println(param);
if(!postPage(serverName,serverPort,pushPage,"XML=123")) Serial.print(F("Fail "));
else Serial.print(F("Pass "));
XML="";
XML="<start>\n\t";
}
}
}
// if(data==false){ Serial.println("No data"); }
}
I thing the problem is with the String object. It might be a memory issue. Any idea?
I'm currently experimenting with sending a string to my Arduino Yun and trying to get it to reply back depending on what I send it.
I picked up a framework of some code here and have been experimenting with it but apart from the serial monitor displaying 'ready' I can't make it go any further.
The code is:
//declace a String to hold what we're inputting
String incomingString;
void setup() {
//initialise Serial communication on 9600 baud
Serial.begin(9600);
while(!Serial);
//delay(4000);
Serial.println("Ready!");
// The incoming String built up one byte at a time.
incomingString = "";
}
void loop () {
// Check if there's incoming serial data.
if (Serial.available() > 0) {
// Read a byte from the serial buffer.
char incomingByte = (char)Serial.read();
incomingString += incomingByte;
// Checks for null termination of the string.
if (incomingByte == '\0') {
// ...do something with String...
if(incomingString == "hello") {
Serial.println("Hello World!");
}
incomingString = "";
}
}
}
Can anyone point me in the right direction?
Thanks
I suspect the problem is that you're adding the null terminator onto the end of your string when you do: incomingString += incomingByte. When you're working with string objects (as opposed to raw char * strings) you don't need to do that. The object will take care of termination on its own.
The result is that your if condition is effectively doing this: if ("hello\0" == "hello") .... Obviously they're not equal, so the condition always fails.
I believe the solution is just to make sure you don't append the byte if it's null.
Try This:
String IncomingData = "";
String Temp = "";
char = var;
void setup()
{
Serial.begin(9600);
//you dont have to use it but if you want
// if(Serial)
{
Serial.println("Ready");
}
//or
while(!Serial)
{delay(5);}
Serial.println("Ready");
void loop()
{
while(Serial.available())
{
var = Serial.read();
Temp = String(var);
IncomingData+= Temp;
//or
IncomingData.concat(Temp);
// you can try
IncomindData += String(var);
}
Serial.println(IncomingData);
IncomingData = "";
}
I have a text file, for example : file.txt, I want to read a line, for example line 7, have any way to read directly line 7 without reading other lines? I want to save memory from this work.
Because of the way JME been cut down you cannot do this. You would have to read whole file. Only other way, but may not be well suitable is to read the file , store it in RecordStore new entry per line, but is it really worth...
I think it is possible however you need to use a hashtable which might result to more heap usage.
Anyway, first, the contents of the text file should be stored in a char array. Then, second, the contents of the char array must be moved to the hashtable.
Each line in the text file is separated by a new line. In the char array, the new line (maybe) is translated to '\n'. Concatenate the characters in the array until the new line character is reached. The concatenated characters (minus '\n') will form the string in the first line. There should also be a counter here which should have been initialized to 0 (or 1, whatever you prefer). Save the text to the hashtable; The value will be the string that has been created and the key will be the counter. Increment the counter afterwards. Repeat this process for the remainder of the array until the end of file is reached.
With the hashtable, you can now get the string at line 7 without going through the other lines. Well, basically, each line has been read once. But, at least, you don't have to traverse each line once they have been stored in the hashtable.
Like what I have said earlier, doing this might increase heap usage especially if the text file is very large.
[And, by the way, sorry for the very late response. This is my first time here (I mean I just registered and answered this question) :D ]
Common Code
private String readLine(InputStream _inStream, int lineNum)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (lineNum < 0) {
return ("Cannot read line a number " + lineNum);
}
final StringBuffer buf = new StringBuffer();
byte c;
int curLine = 1;
while (((c = (byte) _inStream.read()) != -1)) {
//System.out.println((char)c);
if (c == '\n') {
++curLine;
if (curLine > lineNum) {
break;
} else if (curLine < lineNum) {
continue;
}
} else if (curLine != lineNum) {
continue;
}
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
private String readLineWithSkip(InputStream _inStream, long skipCharacters)
throws IOException {
if (null == _inStream) {
throw new IOException("Inputstream null.");
}
if (skipCharacters < 1) {
return ("Cannot skip stream of " + skipCharacters + " characters");
}
final StringBuffer buf = new StringBuffer();
byte c;
_inStream.skip(skipCharacters);
while ((c = (byte) _inStream.read()) != '\n') {
//System.out.println((char)c);
buf.append((char) c);
}
if (0 == buf.length()) {
return null;
} else {
return buf.toString().trim();
}
}
.
InputStream inStream = null;
int fileLength = 39;
int skipCharacters = 10;
int lineNumber = 3;
String myLine = "No line read.";
try {
inStream = Class.class.getResourceAsStream("/test.txt");
if (null != inStream) {
inStream.mark(fileLength);
//For Approach II
myLine = readLine(inStream, lineNumber);
inStream.reset();
//For Approach I
myLine = readLineWithSkip(inStream, skipCharacters);
}
} catch (SecurityException se) {
se.printStackTrace();
} catch (IOException ioe) {
ioe.printStackTrace();
} finally {
try {
inStream.close();
} catch (IOException ex) {
ex.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
}
inStream = null;
System.out.println(myLine);
}
.
Approach I: Map the line number with no of cumulative characters
Run the file through a code that maps the line number with the last of charater in that line from the 0th position of the file (to be used as skip() value) all +2 ('\r\n\') for each line. You can store this Mapping table either at the start or at the end of the same file.
The run the above common code with method readLineWithSkip(inStream,
skipCharacters); ONLY and judiciously commenting other method calls.
Points to Consider:
Skips to the desired position in the inputstream
Has an overhead of parsing the file and storing the mapping table.
.
Approach II: Read each line till the Nth line is read
The run the above common code with method readLine(inStream,
lineNumber); ONLY and judiciously commenting other method calls.
Points to Consider:
Slow since it has to read each character till it reaches the desired line
No overhead of parsing the file and no storing of the mapping table.
I would like to further simplify the problem of reading the chars without requiring any mapping of characters with line numbers.
...
Form form=new Form("filename");
InputStream fin=fconn.openDataInputStream();
StringBuffer buf =new StringBuffer();
int c;
int counter=-1;
while((c=fin.read())!=-1)
{
counter++;
if(counter==23)
{
form.append(buf.toString());
buf=null;counter=0;
continue;
}
buf.append((char)c);
}
if(counter<23 && counter>=0) // write the skipped chars between the last number read and the end of file
{
form.append(buf.toString());
buf=null;counter=0;
}
fin.close();
...
Hope this would help others.