Pages: [1]   Go Down
Author Topic: Bluetooth + microSD = Sending Image  (Read 1400 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello,

Currently I'm saving an image (as a txt file with pixel values) on the microSD. Now When i try to transfer the image to my computer (and catch it with Processing) not all the pixels are being recieved. So my question is whats the issue? Atm this is my arduino code:

Code:
#include <SD.h>

File myFile;

void setup() {
  Serial.begin(9600);
  Serial2.begin(115200);
  pinMode(53, OUTPUT);
  SD.begin(53);
  myFile = SD.open("im300.txt", FILE_WRITE);
}
void loop() {
  int code = 0;
  // lets first start a handshake
  // we first need to recieve code 101
  if(myFile) {
    if(Serial2.available() > 0) {
      code = Serial2.read();
      if(code == 101) {
        Serial2.write(102);
        long unsigned counter = 0;
        myFile.seek(0);
        while(myFile.available()) {
          uint8_t var = readNumber();
          Serial2.write(var);
          Serial2.flush();
        }
        myFile.close();
      }
    }
  }
}

uint8_t readNumber() {
  uint8_t var1 = (myFile.read()-'0')*100;
  uint8_t var2 =  (myFile.read()-'0')*10;
  return var1 + var2 + myFile.read()-'0';  
}

So the issue is that only part of the data is being recieved by processing ( a simple counter tells me only 44975 values are send instead of 300x300 = 90 000)

This is my processing code:

Code:
public void draw() {

imageArray = new int[_imageSize][_imageSize];

int startcode = 101;
// first request with code 101
myPort.write(startcode);

// unless we get crap data keep looping
if (myPort.available() > 0) {

int code = myPort.read();
print("Code: "); println(code);
int rowcount = 0;
int collcount = 0;
int counter = 0;
boolean getData = true;

if (code == 102) {
// we found the answer code lets go
// so we will loop now until we get all the data we need!
while (getData == true) {
int pixel = myPort.read();
if (pixel != -1) {
counter++;

imageArray[rowcount][collcount] = pixel;
if (collcount > _imageSize-1) {
collcount = 0;
getData = false;
}
if (rowcount == _imageSize-1) {
rowcount = 0;
collcount++;

if(collcount == _imageSize) getData = false;
} else {
rowcount++;
}
print("rowcount: "); println(rowcount);
print("collcount: "); println(collcount);

}
//print("Counter: "); println(counter);
}
// sending has been completed,  send the shut down signal
drawImage();

}

}
« Last Edit: December 10, 2011, 11:25:52 am by dan_fritz » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

What version of the IDE are you using? In 0023 and earlier, the Serial.flush() function operates on the input stream. It did nothing with the output stream. In 1.0 and later, the Serial.flush() function blocks until the last byte has been sent. Since you are only sending one byte at a time, and since the PC has a much larger serial buffer than the Arduino, it really isn't necessary to flush anything except porcelain fixtures.

Code:
  uint8_t var1 = (myFile.read()-'0')*100;
  uint8_t var2 =  (myFile.read()-'0')*10;
  return var1 + var2 + myFile.read()-'0'; 
You are adding three bytes, and returning a single byte. Does that make sense?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Right now im using 1.0.

That part is used for a simple reason. Every pixel is saved in a txt file as a number with 3 values (so 9 will be saved as 009 and 127 will be saved as 127). If I want to read back, then i multiply the first number with 100, then the second with 10 and then at last add the last one, so basicly I'm reading 1, 2, 7 and that function will make 127 of it. (makes sense i hope).

I've done this so I could read a single value from an image pixel (for example if i want to read pixel at position 50,50), so for the example I need only to multiply ((50*AMOUNT_ROWS)+50)*3 and I can read the exact pixel at an location.

I hope this makes things clear, I'll remove the unneaded flush command (I hoped this would solve the issue anyway).

EDIT: This code does work for images of 10x10 (or 100 numbers) up till 200x200. If I'm using an image of 300x300 it only read till 250 pixels, if i use an image of 500x500 I can read till up 400 pixels (WIERD)
« Last Edit: December 10, 2011, 06:22:26 pm by dan_fritz » Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I hope this makes things clear,
Yes, it does. I hadn't looked all that closely at that code. Now that I have, it makes sense.

However, we'd still need to know something about how the data was written to the file. No carriage returns after so many pixels?

More observations.
Code:
  myFile = SD.open("im300.txt", FILE_WRITE);
Why are you opening the file for write?

Code:
        while(myFile.available()) {
available() is not a boolean function. You shouldn't treat is as such. If what you mean is "do this if there is at least one more byte to read", make that clearer.
Code:
        while(myFile.available() > 0) {

On the other hand, the File class has a size() method. You could use that to determine how many reads to perform, and read the data in a for loop.

Quote
a simple counter tells me only 44975 values are send instead of 300x300 = 90 000)
Where is this counter? What type is it? How does that counter value match with myFile.size()?

Does the number of bytes sent match the number of bytes received?
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

However, we'd still need to know something about how the data was written to the file. No carriage returns after so many pixels?
What do you mean with carriage returns?

Quote
More observations.
Code:
  myFile = SD.open("im300.txt", FILE_WRITE);
Why are you opening the file for write?
No real reason, but it allows me to read and write, this was still in place when i generated a test image with random pixels (then i would need the write property). Can this have anny affect?[/quote]

Quote
Code:
        while(myFile.available()) {
available() is not a boolean function. You shouldn't treat is as such. If what you mean is "do this if there is at least one more byte to read", make that clearer.
Code:
        while(myFile.available() > 0) {
Thanks I'll fix that one.

Quote
On the other hand, the File class has a size() method. You could use that to determine how many reads to perform, and read the data in a for loop.

Quote
a simple counter tells me only 44975 values are send instead of 300x300 = 90 000)
Where is this counter? What type is it? How does that counter value match with myFile.size()?

Does the number of bytes sent match the number of bytes received?
I had a basic counter that would just add one if a successive read was made, after that I just compared it with a counter on processing. The counter on processing was made after a pixel was read. The size function would not really help, I know that all bytes are read in correctly from the microSD, it seems there is a issue with Processing or the Easy Bluetooth Module.

Some other observations, It seems that after a while the Easy Bluetooth Module hangs and the led stays on for a while, following with new data being send. So there is like a short brake, the other data gets send continually at the same interval.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What do you mean with carriage returns?
Typically, some number of bytes are written, then a carriage return/line feed is added, so that when the file is opened in a text editor, there is not just a single record with 270000 characters in it. If the program that created the text file didn't put carriage returns in, then never mind. If it did, though, you must ignore them when reading the data.

Quote
Can this have anny affect?
Probably not. I tend to open files with the minimum capability needed, though.

Quote
The size function would not really help,
Why not?

Quote
I know that all bytes are read in correctly from the microSD, it seems there is a issue with Processing or the Easy Bluetooth Module.
Nice of you to mention this up front. I assumed that the problem was with the Arduino. But, how do you know that the data is all read correctly?

Have you added a counter to the Arduino side, to verify that the correct number of bytes is read from the file?

On the Processing side, you have some print() statements. Are rowcount and collcount printed correctly?

Have you tried the code without the bluetooth module in the picture? Just connect the Arduino and PC with the USB cable, and use Serial instead of Serial2.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 24
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Typically, some number of bytes are written, then a carriage return/line feed is added, so that when the file is opened in a text editor, there is not just a single record with 270000 characters in it. If the program that created the text file didn't put carriage returns in, then never mind. If it did, though, you must ignore them when reading the data.
There are no line brakes so its just all on 1 single line


Quote
Nice of you to mention this up front. I assumed that the problem was with the Arduino. But, how do you know that the data is all read correctly?

Have you added a counter to the Arduino side, to verify that the correct number of bytes is read from the file?

On the Processing side, you have some print() statements. Are rowcount and collcount printed correctly?

Have you tried the code without the bluetooth module in the picture? Just connect the Arduino and PC with the USB cable, and use Serial instead of Serial2.
Yes there is a counter on the Arduino that indeed checks for the correct bytes and then on Processing I do print the cols and rows.

Great i'm struggling with this issue for 1 month and I never controlled it without the Bluetooth module, doing it now!

Oke thats not working at all, it seems that the processing part isnt right, I have to use now Serial.print(var) to show the values in the console. Also it seems that my set up codes (101 and 102) are not being send right... I think that part of the code needs a complete rewrite. So changing every Serial2 to Serial and changing the com port in Processing doesnt work, rewriting all the code so it works with serial is some work and then I doubt it will work for bluetooth...
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 549
Posts: 46107
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
I have to use now Serial.print(var) to show the values in the console.
In what console? Serial.write() is how you should send the data to Processing. Processing should then be able to show the value as a string, using print() or println().

Quote
Also it seems that my set up codes (101 and 102) are not being send right.
Possibly because literals are, in the absence of any contrary direction, treated as ints. Serial.write() with an int is not what you want to to. Serial.write((byte)101) should send the value correctly.

You should not need to make a lot of changes to make the program work wired or wirelessly. The Serial instance needs to change, since only Serial is connected, via the USB to serial converter chip, to the PC.
Logged

Pages: [1]   Go Up
Jump to: