Hi,
I'm using a Raspberry pi to issue a get request to my arduino web server. The get request is issued via PhP (on my pi's apache server), which then takes a photo and returns the photo over the ethernet back.
This works great! --- Except for one thing. It's slow. A 640x480 image is almost 20 seconds to transfer.
Is there a way I can speed it up? Here's my code below. I've tried to change the uint8_t buffer to uint64_t buffer but the ethernet client complains in (EthernetClient.h) that it expects an 8 bit unsigned buffer, not 64.
So how do I get it to go faster? Overclock the arduino? Would a mega board be faster? Something else? Any suggestions would be appreciated. I hope to get it to about 1 second delay if not faster.
Thanks!
#include <Adafruit_VC0706.h>
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
#include <SoftwareSerial.h>
#define chipSelect 4
#define REQ_BUF_SZ 20
// Using SoftwareSerial (Arduino 1.0+) or NewSoftSerial (Arduino 0023 & prior):
#if ARDUINO >= 100
SoftwareSerial cameraconnection = SoftwareSerial(2, 3);
#else
NewSoftSerial cameraconnection = NewSoftSerial(2, 3);
#endif
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 101);
EthernetServer server(80);
File webFile;
char HTTP_req[REQ_BUF_SZ] = {0}; // buffered HTTP request stored as null terminated string
char req_index = 0; // index into HTTP_req buffer
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
pinMode(7, OUTPUT);
//Try to locate the camera
if (cam.begin()) {
Serial.println("Camera Found!");
} else {
Serial.println("No camera found?");
return;
}
/*
// see if the card is present and can be initialized:
if (!SD.begin(chipSelect)) {
Serial.println("Card failed, or not present");
//don't do anything more:
return;
}else{
Serial.println("Card Found!");
}
*/
// start the Ethernet connection and the server:
Ethernet.begin(mac, ip);
server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}
void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
if (req_index < (REQ_BUF_SZ - 1)) {
HTTP_req[req_index] = c; // save HTTP request character
req_index++;
}
Serial.write(c);
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: image/jpeg");
client.println("Connection: close"); // the connection will be closed after completion of the response
//client.println("Refresh: 15"); // refresh the page automatically every 5 sec
client.println();
Serial.println("VC0706 Camera snapshot test");
cam.reset();
cam.begin();
// 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);
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");
if (!cam.takePicture())
Serial.println("Failed to snap!");
else{
Serial.println("Picture taken! -- Let's go!");
/*
//Remove the file if it's already saved
char filename[13];
strcpy(filename, "IMAGE00.JPG");
Serial.print("Storing to:");
Serial.println(filename);
if(SD.exists(filename)){
Serial.println("Removing file!");
SD.remove(filename);
}
//Save the image to the SD card!
File imgFile = SD.open(filename, FILE_WRITE);
if(imgFile){
Serial.println("File successfully opened");
}else{
Serial.println("File not opened!");
}
*/
// 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
digitalWrite(7,HIGH);
while (jpglen > 0) {
// read 32 bytes at a time;
uint8_t *buffer;
uint8_t bytesToRead = min(64, jpglen);
//uint64_t *buffer;
//uint64_t bytesToRead = min(256, jpglen);
buffer = cam.readPicture(bytesToRead);
//imgFile.write(buffer, bytesToRead);
client.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;
}
digitalWrite(7,LOW);
//imgFile.close();
time = millis() - time;
Serial.println("Image Saved!");
Serial.print(time); Serial.println(" ms elapsed");
}
req_index = 0;
StrClear(HTTP_req, REQ_BUF_SZ);
break;
}
if (c == '\n') {
// last character on line of received text
// starting new line with next character read
currentLineIsBlank = true;
}
else if (c != '\r') {
// a text character was received from client
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
Ethernet.maintain();
}
}
// sets every element of str to 0 (clears array)
void StrClear(char *str, char length)
{
for (int i = 0; i < length; i++) {
str[i] = 0;
}
}