Problem in sending bytes from arduino help needed ASAP Thanks!!!

Hello everyone,
Im doing a arduino project where a JPEG camera will be connected to arduino along with the SD card. I found a library named adafruit which captures the jpg image and saves the JPG file in the SD card much faster compared to other libraries. Now i need to send this JPG image out as BYTES using serial comm. Can anyone help me how to send the saved JPG image as bytes using Serial.write function, Ill post the sample code that i used for capturing and saving. Thanks.

#include <Adafruit_VC0706.h>
#include <SD.h>
#include <SoftwareSerial.h>         
#define chipSelect 10

#if ARDUINO >= 100

SoftwareSerial cameraconnection = SoftwareSerial(2, 3);

#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);



void setup() {


#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
  if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif

  Serial.begin(9600);
  Serial.println("VC0706 Camera snapshot test");
  
  
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }  
  
  // Try to locate the camera
  if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

 
  
  cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  //cam.setImageSize(VC0706_160x120);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

  Serial.println("Snap in 3 secs...");
  delay(3000);

  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

  int32_t time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");
}

void loop() {
}

You were a bit quick to bump this thread weren't you ?

Your code presumably works and when complete there is a jpg file on the SD card. Now you want to send it to the PC.

In principle what you want is simple.
open the file to read it
read a byte (or bytes) from the file
write a byte (or bytes) to the Serial port
continue until all bytes have been read and sent
close the file

What is running on the PC to receive and store the bytes as they arrive ?

Can anyone help me how to send the saved JPG image as bytes using Serial.write function

What have you tried? There is nothing in that code (except a lot of clues) that tries to read from the SD card or write to the serial port.

Thanks for the comment. I actually wanted to send the bytes to an android phone where it actually recieves the byte and undergoes a process to retrieve the jpg image from bytes. The android code to receive the bytes and to convert back to jpg is given below

 //This thread runs during a connection with a remote device. It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
		private final BluetoothSocket mmBTSocket;
		private final InputStream mmBTInStream;
		private final OutputStream mmBTOutStream;

		public ConnectedThread(BluetoothSocket socket) {
			Log.d(BTTAG, "create ConnectedThread");
			mmBTSocket = socket;
			InputStream tmpIn = null;
			OutputStream tmpOut = null;

			// Get the BluetoothSocket input and output streams
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) {
				Log.e(BTTAG, "temp sockets not created", e);
			}

			mmBTInStream = tmpIn;
			mmBTOutStream = tmpOut;
		}

		public void run() {
			Log.i(BTTAG, "BEGIN mBTConnectedThread");
			byte[] inBTBuffer = new byte[1024];
			boolean BTFileEndOne = false;
			// byte[] mBTimageBuffer = new byte[15360]; // 15KB reserved
			int bytes;
			// long start= System.currentTimeMillis() ;

			// Keep listening to the InputStream while connected
			while (true) {
				try {
					// Read from the InputStream
					bytes = mmBTInStream.read(inBTBuffer);

					for (int i = 0; i < bytes; i++) {
						mBTimageBuffer[mBTfileIndex] = inBTBuffer[i];
						mBTfileIndex++;
						// start = System.currentTimeMillis();
						// Log.i(BTTAG, bytes+"="+String.format("%02X",
						// inBTBuffer[i]));
						if (i > 0) {
							if (inBTBuffer[i] == (byte) 0xD9) {
								// BTFileEndOne = true;
								// Log.i(BTTAG, "BTFileEndOne = true");

								if (inBTBuffer[i - 1] == (byte) 0xFF) {
									if (SaveImagetoSD() == true) {
										mBTHandler
												.obtainMessage(
														MainCameraActionActivity.BT_MESSAGE_READ,
														bytes, -1, inBTBuffer)
												.sendToTarget();

									}

									// Log.i(BTTAG, "FileEndTwo = true");
								}
							}
						}
					}

					// if(System.currentTimeMillis() - start > 1000)
					// SaveImagetoSD();

					// Log.i(BTTAG, "mBTfileIndex="+mBTfileIndex);

					// nTotalReceiveBytes = nTotalReceiveBytes + bytes;
					// SaveImagetoSD(inBTBuffer, bytes);
					// if(nTotalReceiveBytes >= 1024)
					// {
					// Send the obtained bytes to the UI Activity
					// mHandler.obtainMessage(MainCameraActionActivity.BT_MESSAGE_READ, bytes, -1,
					// inBTBuffer).sendToTarget();
					// }
				} catch (IOException e) {
					Log.e(BTTAG, "Disconnected", e);
					connectionLost();
					break;
				}
			}
		}

		/**
		 * Write to the connected OutStream.
		 * 
		 * @param buffer
		 *            The bytes to write
		 */
		public void write(byte[] outBuffer) {
			try {
				mmBTOutStream.write(outBuffer);

				// Share the sent message back to the UI Activity
				mBTHandler.obtainMessage(
						MainCameraActionActivity.BT_MESSAGE_WRITE, -1, -1,
						outBuffer).sendToTarget();
			} catch (IOException e) {
				Log.e(BTTAG, "Exception during write", e);
			}
		}

		public void cancel() {
			try {
				if (DIVICE)
					Log.d(BTTAG, "ConnectThread : mmBTSocket.close() ...");
				mmBTSocket.close();
				if (DIVICE)
					Log.d(BTTAG, "ConnectThread : mmBTSocket.close() ...");
			} catch (IOException e) {
				Log.e(BTTAG, "close() of connect socket failed", e);
			}
		}

	}

	public boolean checkSDCard() {
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean SaveImagetoSD() {
		Log.i(BTTAG, "SaveImagetoSD ");

		String extStorage = Environment.getExternalStorageDirectory()
				.toString();
		File file = new File(extStorage, "motoduino.jpg");
		if (checkSDCard() == false)
			return false;

		try {
			mBTImageOutStream = new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			mBTImageOutStream.write(mBTimageBuffer, 0, mBTfileIndex);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Log.i(BTTAG, "Save file size = " + mBTfileIndex);
		return true;
	}

	public static String hexadecimal(String input, String charsetName)
			throws UnsupportedEncodingException {
		if (input == null)
			throw new NullPointerException();
		return asHex(input.getBytes(charsetName));
	}

	private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

	public static String asHex(byte[] buf) {
		char[] chars = new char[2 * buf.length];
		for (int i = 0; i < buf.length; ++i) {
			chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
			chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
		}
		return new String(chars);
	}
}

Can anyone post me a sample code for reading bytes from a jpg file in SD card and send the bytes through serial. It would be a great help. Thanks.

Can anyone post me a sample code for reading bytes from a jpg file in SD card and send the bytes through serial.

Have you read Reply #2? There are examples provided with the SD class that do exactly what you are asking us to write code to do.

Yes there are examples but in my case i need to send arduino output as bytes of a jpeg file. Where i will have to create a loop for that to read the whole image and then send it one by one. Isnt it?

Has anyone sent bytes of a jpeg file to serial port? If so please help me. Thanks:)

Ashuk:
Has anyone sent bytes of a jpeg file to serial port? If so please help me. Thanks:)

The Arduino will not care what type of file it is. It is just a series of bytes as far as it is concerned. Have you tried reading bytes from a file and sending them to the Serial port ? If you create a plain text file on the card you could then read it and send it to the Serial monitor so that you can see it working as a proof of the concept.

Ashuk:
i will have to create a loop for that to read the whole image and then send it one by one. Isnt it?

That sounds about right - and I'm sure you'll find SD examples demonstrating that approach. Writing a byte to the serial port is obviously trivial. However, you will need to have some scheme for the device reading from the far end of the connection to know when the file data starts and ends. How are you going to do that?

It actually starts capturing when i send a char 'a' from the phone via bluetooth and then it starts the process. Now my problem is how do i read all the bytes of the JPG file. Thanks

Thanks for the comment. Definitely ill try that way :slight_smile:

How does your phone know when it has received the end of the image? Are you just going to time out the incoming serial stream, or do you have some other scheme in mind?

I actually know the starting and the ending incoming byte for that particular camera. Using that im detecting the end of pic at the receiving point.

The modified arduino code,

#include <Adafruit_VC0706.h>
#include <SD.h>
#include <SoftwareSerial.h>         
#define chipSelect 10
File myFile;



#if ARDUINO >= 100

SoftwareSerial cameraconnection = SoftwareSerial(2, 3);

#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif

Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
char val;



void setup() {


#if !defined(SOFTWARE_SPI)
#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  if(chipSelect != 53) pinMode(53, OUTPUT); // SS on Mega
#else
  if(chipSelect != 10) pinMode(10, OUTPUT); // SS on Uno, etc.
#endif
#endif

  Serial.begin(9600);
  Serial.println("VC0706 Camera snapshot test");
  
  
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }  
  
  // Try to locate the camera
} 

void loop() {
  
  if(Serial.available())
  {
    val = Serial.read();
    if(val=='a')
    {
    if (cam.begin()) {
    Serial.println("Camera Found:");
  } else {
    Serial.println("No camera found?");
    return;
  }
  // Print out the camera version information (optional)
  char *reply = cam.getVersion();
  if (reply == 0) {
    Serial.print("Failed to get version");
  } else {
    Serial.println("-----------------");
    Serial.print(reply);
    Serial.println("-----------------");
  }

 
  
  //cam.setImageSize(VC0706_640x480);        // biggest
  //cam.setImageSize(VC0706_320x240);        // medium
  cam.setImageSize(VC0706_160x120);          // small

  // You can read the size back from the camera (optional, but maybe useful?)
  uint8_t imgsize = cam.getImageSize();
  Serial.print("Image size: ");
  if (imgsize == VC0706_640x480) Serial.println("640x480");
  if (imgsize == VC0706_320x240) Serial.println("320x240");
  if (imgsize == VC0706_160x120) Serial.println("160x120");

  Serial.println("Snap in 3 secs...");
  delay(3000);

  if (! cam.takePicture()) 
    Serial.println("Failed to snap!");
  else 
    Serial.println("Picture taken!");
  
  // Create an image with the name IMAGExx.JPG
  char filename[13];
  strcpy(filename, "IMAGE00.JPG");
  for (int i = 0; i < 100; i++) {
    filename[5] = '0' + i/10;
    filename[6] = '0' + i%10;
    // create if does not exist, do not open existing, write, sync after write
    if (! SD.exists(filename)) {
      break;
    }
  }
  
  // Open the file for writing
  File imgFile = SD.open(filename, FILE_WRITE);

  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

  int32_t time = millis();
  pinMode(8, OUTPUT);
  // Read all the data up to # bytes!
  byte wCount = 0; // For counting # of writes
  while (jpglen > 0) {
    // read 32 bytes at a time;
    uint8_t *buffer;
    uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!
    buffer = cam.readPicture(bytesToRead);
    imgFile.write(buffer, bytesToRead);
    if(++wCount >= 64) { // Every 2K, give a little feedback so it doesn't appear locked up
      Serial.print('.');
      wCount = 0;
    }
    //Serial.print("Read ");  Serial.print(bytesToRead, DEC); Serial.println(" bytes");
    jpglen -= bytesToRead;
  }
  imgFile.close();

  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");
  
   myFile = SD.open("IMAGE00.JPG");
   
   if (myFile) {
    while (myFile.available()) {
      Serial.write(myFile.read());
    }
    myFile.close();
  } else {
  	// if the file didn't open, print an error:
    Serial.println("error opening test.txt");
  }
 
}
//Serial.println("No BT connections");
}
  }

And the response i get in serial monitor is,

Im getting the output as this when i try to output the bytes of JPG image. If anyone could explain me why am i getting this it would be a great help. Thanks

Were you expecting to get an image on the Serial monitor ?

You should not expect to be able to make sense of a JPEG file on a byte by byte basis. It needs to be read by a program that can interpret the bytes as an image and display it. The Serial monitor cannot do that. I asked earlier in this thread what program would be running on the PC to receive the image file,

Thanks for the comment:)
Im sending those bytes to an android phone not for a pc and i have already posted the android code to retrieve the image. Il post it again.

//This thread runs during a connection with a remote device. It handles all incoming and outgoing transmissions.
private class ConnectedThread extends Thread {
		private final BluetoothSocket mmBTSocket;
		private final InputStream mmBTInStream;
		private final OutputStream mmBTOutStream;

		public ConnectedThread(BluetoothSocket socket) {
			Log.d(BTTAG, "create ConnectedThread");
			mmBTSocket = socket;
			InputStream tmpIn = null;
			OutputStream tmpOut = null;

			// Get the BluetoothSocket input and output streams
			try {
				tmpIn = socket.getInputStream();
				tmpOut = socket.getOutputStream();
			} catch (IOException e) {
				Log.e(BTTAG, "temp sockets not created", e);
			}

			mmBTInStream = tmpIn;
			mmBTOutStream = tmpOut;
		}

		public void run() {
			Log.i(BTTAG, "BEGIN mBTConnectedThread");
			byte[] inBTBuffer = new byte[1024];
			boolean BTFileEndOne = false;
			// byte[] mBTimageBuffer = new byte[15360]; // 15KB reserved
			int bytes;
			// long start= System.currentTimeMillis() ;

			// Keep listening to the InputStream while connected
			while (true) {
				try {
					// Read from the InputStream
					bytes = mmBTInStream.read(inBTBuffer);

					for (int i = 0; i < bytes; i++) {
						mBTimageBuffer[mBTfileIndex] = inBTBuffer[i];
						mBTfileIndex++;
						// start = System.currentTimeMillis();
						// Log.i(BTTAG, bytes+"="+String.format("%02X",
						// inBTBuffer[i]));
						if (i > 0) {
							if (inBTBuffer[i] == (byte) 0xD9) {
								// BTFileEndOne = true;
								// Log.i(BTTAG, "BTFileEndOne = true");

								if (inBTBuffer[i - 1] == (byte) 0xFF) {
									if (SaveImagetoSD() == true) {
										mBTHandler
												.obtainMessage(
														MainCameraActionActivity.BT_MESSAGE_READ,
														bytes, -1, inBTBuffer)
												.sendToTarget();

									}

									// Log.i(BTTAG, "FileEndTwo = true");
								}
							}
						}
					}

					// if(System.currentTimeMillis() - start > 1000)
					// SaveImagetoSD();

					// Log.i(BTTAG, "mBTfileIndex="+mBTfileIndex);

					// nTotalReceiveBytes = nTotalReceiveBytes + bytes;
					// SaveImagetoSD(inBTBuffer, bytes);
					// if(nTotalReceiveBytes >= 1024)
					// {
					// Send the obtained bytes to the UI Activity
					// mHandler.obtainMessage(MainCameraActionActivity.BT_MESSAGE_READ, bytes, -1,
					// inBTBuffer).sendToTarget();
					// }
				} catch (IOException e) {
					Log.e(BTTAG, "Disconnected", e);
					connectionLost();
					break;
				}
			}
		}

		/**
		 * Write to the connected OutStream.
		 * 
		 * @param buffer
		 *            The bytes to write
		 */
		public void write(byte[] outBuffer) {
			try {
				mmBTOutStream.write(outBuffer);

				// Share the sent message back to the UI Activity
				mBTHandler.obtainMessage(
						MainCameraActionActivity.BT_MESSAGE_WRITE, -1, -1,
						outBuffer).sendToTarget();
			} catch (IOException e) {
				Log.e(BTTAG, "Exception during write", e);
			}
		}

		public void cancel() {
			try {
				if (DIVICE)
					Log.d(BTTAG, "ConnectThread : mmBTSocket.close() ...");
				mmBTSocket.close();
				if (DIVICE)
					Log.d(BTTAG, "ConnectThread : mmBTSocket.close() ...");
			} catch (IOException e) {
				Log.e(BTTAG, "close() of connect socket failed", e);
			}
		}

	}

	public boolean checkSDCard() {
		if (android.os.Environment.getExternalStorageState().equals(
				android.os.Environment.MEDIA_MOUNTED)) {
			return true;
		} else {
			return false;
		}
	}

	public boolean SaveImagetoSD() {
		Log.i(BTTAG, "SaveImagetoSD ");

		String extStorage = Environment.getExternalStorageDirectory()
				.toString();
		File file = new File(extStorage, "motoduino.jpg");
		if (checkSDCard() == false)
			return false;

		try {
			mBTImageOutStream = new FileOutputStream(file);
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		try {
			mBTImageOutStream.write(mBTimageBuffer, 0, mBTfileIndex);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		Log.i(BTTAG, "Save file size = " + mBTfileIndex);
		return true;
	}

	public static String hexadecimal(String input, String charsetName)
			throws UnsupportedEncodingException {
		if (input == null)
			throw new NullPointerException();
		return asHex(input.getBytes(charsetName));
	}

	private static final char[] HEX_CHARS = "0123456789abcdef".toCharArray();

	public static String asHex(byte[] buf) {
		char[] chars = new char[2 * buf.length];
		for (int i = 0; i < buf.length; ++i) {
			chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
			chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
		}
		return new String(chars);
	}
}