Fare una FOTO e mandarla ad un PC - Vari problemi soprattutto di memoria

Sto cercando di afre in modo che Arduino faccia una foto e la mandi ad un Pc.
Ho una cam seriale Adafruit compatibile e un ethernet shield originale.

Allora sto cercando di mettere insieme un po' di pezzi che da soli funzionavano.
La foto sono riuscito a farla e salvarla sulla SD.
Unendo altre librerie ho problemi di memoria e non va piu niente

Fino a questo punto l'unica cosa che sono riuscito a fare e farla al massimo in 320x240 e mandarla ad un server FTP.
Già facendola 640x480 la connessione con l'FTP cade.
Ho provato a fare un POST su un web serve ma non sono riuscito.

Qualcuno ha idee o sugerimenti?
Sotto il codice.

Ciao
Nic

#include <Adafruit_VC0706.h>
#include <SoftwareSerial.h>    
#include <SPI.h>
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

SoftwareSerial cameraconnection = SoftwareSerial(6, 7);
Adafruit_VC0706 cam = Adafruit_VC0706(&cameraconnection);

char serverName[] = "web1.ogilvy.it";

EthernetClient client;

void setup() {
  Serial.begin(38400);

  pinMode(10, OUTPUT); 
  digitalWrite(10, HIGH);

  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    while(true);
  }   
   
  delay(1000);
   
  Serial.println("VC0706 Camera snapshot test");

  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

  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!");
    
  Serial.println("Server connecting...");   

//  if (client.connect(mioserver, 8080)) {

   
  if (client.connect(serverName, 80)) {
    Serial.println("connected");
    // Make a HTTP request:
    
    
    // Get the size of the image (frame) taken  
    uint16_t jpglen = cam.frameLength();
    Serial.print("Storing ");
    Serial.print(jpglen, DEC);
    Serial.print(" byte image.");
    uint32_t len = jpglen + 177; // 177 is the content without the image data  
    
    //client.println(F("POST /path/to/script.php HTTP/1.0"));
    client.println(F("POST /ARDUINO/savepicture.cfm HTTP/1.1"));
    //client.println(F("POST /ARDUINO/savepicture.cfm"));
    client.println(F("Host: web1.ogilvy.it"));
    client.println(F("Content-type: multipart/form-data, boundary=UH3xBZZtzewr09oPP"));
    client.print(F("Content-Length: "));
    client.println(len);
    client.println();
    client.println(F("--UH3xBZZtzewr09oPP"));
    client.println(F("content-disposition: form-data; name=\"picture\"; filename=\"cam.jpg\""));
    client.println(F("Content-Type: image/jpeg"));
    client.println(F("Content-Transfer-Encoding: binary"));
    client.println();
  
  
  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);
    
    //Scrittura
//    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;
  }
//  imgFile.close();

client.println();
client.println(F("--UH3xBZZtzewr09oPP--"));


  time = millis() - time;
  Serial.println("done!");
  Serial.print(time); Serial.println(" ms elapsed");
    
  } 
  else {
    // kf you didn't get a connection to the server:
    Serial.println("connection failed");
  }   
   
  // Get the size of the image (frame) taken  
  uint16_t jpglen = cam.frameLength();
  Serial.print("Storing ");
  Serial.print(jpglen, DEC);
  Serial.print(" byte image.");

   
}



// This is where all the magic happens...
void loop() {

  
  
  //Preso da DnsWebClient
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
  }

  // if the server's disconnected, stop the client:
  if (!client.connected()) {
    Serial.println();
    Serial.println("disconnecting.");
    client.stop();

    // do nothing forevermore:
    while(true);
  }  
  
}

Mi ero dimenticato
Uso Arduino Uno rev 3 e l'IDE 1.0.1

Nic

Io la butto li stupidamente:

Quanto e' grande il file ???
Potresti far "spezzare il jpg" in diversi file da pochi kB.
Poi li invii uno alla volta.
Lato PC prendi i vari file, li unisci.....

Allora detto che sono già in crisi di memoria.
E veramnete vedo che aggiungendo una riga di codice tocco il fondo
Volevo evitare di scrivere sulla SD.

N

acik:
Io la butto li stupidamente:

Quanto e' grande il file ???
Potresti far "spezzare il jpg" in diversi file da pochi kB.
Poi li invii uno alla volta.
Lato PC prendi i vari file, li unisci.....

o piu semplicemente prendi un arduino mega :grin:

Infatti mi sa che devo andare sul Mega
Il file comunque è 47kb

N

Beh, se devi comprarti un Mega... Per gli stessi soldi ti compri una webcam motorizzata con Ethernet e WiFi...

Riuscire a far funzionare la tua telecamera su un UNO ti darebbe la soddisfazione di dire cel' ho fatta !!!

Potresti postare i messaggi di debug che spedisci alla seriale sia nel caso di foto 320x240 che nel caso di foto 640x480?
Almeno per capire qual è il punto in cui dà problemi e se c'è un modo per aggirarlo

Beh, se devi comprarti un Mega... Per gli stessi soldi ti compri una webcam motorizzata con Ethernet e WiFi...

Riuscire a far funzionare la tua telecamera su un UNO ti darebbe la soddisfazione di dire cel' ho fatta !!!

Ma devo far fare anche altre cose.

Potresti postare i messaggi di debug che spedisci alla seriale sia nel caso di foto 320x240 che nel caso di foto 640x480?
Almeno per capire qual è il punto in cui dà problemi e se c'è un modo per aggirarlo

Adesso non ce l'ho sotto mano ma cose senza senso. Tipo magari cicla sul primo messaggio di errore all'infinito.
O si blocca ad un punto.
e solo cambiando una lettera nel debug cambia l'effetto, come se veramente non riuscisse a seguire il flusso.

Immagino che il file sia "parcheggiato" sulla SD.

Potresti far "spezzare il jpg" in diversi file da pochi kB.

questo avviene di già:

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);
    
    //Scrittura
//    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;
  }

però c'è già un grosso errore: non vedo nessuna free()! se è così, se inviassi due (o più) foto poccile di fila noteresti lo stesso problema che sull'immagine grossa.

poi un altro fatto, che però il fatto che la foto piccola funzioni mi da l'impressione che ti sia andata di culo:
se la client.write() NON è bloccante, e se la lettura da SD è più veloce della scrittura su TCP, allora incapperesti nello stesso problema di cui sopra, o nel caso di una concatenazione in buffer circolare (caso della Serial dall'ide 1.0) perderesti parte dei dati inviati.
Ma a quanto pare è bloccante (ovvero la funzione non ritorna finchè tutti i dati non sono stati scritti), quindi ti sei salvato.

In realtà questo ciclo legge da cam via seriale e cercava di mandare immediatamente al POST.

Su cosa faresti il free ad esempio?

Però sistematicamente con le piccole va (12kb) e con le grande da errore, ma poi la foto è visualizzabile (47kb)
In realtà dopo du po' di prove mi capita che non vada piu niente e non capsico perchè dopo un po ricomincia...

Cosa intendi con bloccante?
N

quando tu fai
uint8_t *buffer;
uint8_t bytesToRead = min(32, jpglen); // change 32 to 64 for a speedup but may not work with all setups!

viene allocato un buffer di una certa dimensione, che però non viene dritrutto con una free (viene distrutto il puntatore, non l'aria di memoria punatata)

per le funzioni bloccanti:
http://www.ce.unipr.it/didattica/siselab/Tesine/mpichG2/bloccanti.html

Quindi tu dici ad ogni ciclo lo ricreo?
Quindi sarebbe meglio crearlo prima del ciclo e nel ciclo riutilizzarlo solo?
Oppure consigli così e fare un free ogni ciclo?
Come si fa il free?

Grazie
N

E come faccio a sapere se una funzione è bloccante o no?
Tipo dove vedo che delay lo è e millis no?

N

ahhh minchiata mia, buffer = cam.readPicture(bytesToRead);
buffer è il valore di ritorno di una funzione, quindi se ricordo bene ha la stessa visibilità di una variabile.. prova comunque a fare una free quando hai finito di usare buffer, giusto per.

per sapoere se una funzione è loccante o è nelel specifiche, oppure lo devi capire da solo

M dicevo, come si chiama la funzione free?
N

free(*ptr)

Ah quella standard.
Non l'ho mai vista usata nei progetti di Arduino.
Proverò

N

Ciao contecavour
com'è andata a finire? Ci sei riuscito? Hai trovato il problema?

E' un argomento che interessa anche me :grin:

Ciao

PS - Comunque la free non è necessaria, il buffer restituito dal metodo readPicture è relativo ad un array privato della classe :wink:

Si ce l'ho fatta con un POST su una pagina PHP.
Come al solito il problema è mettere un po insieme tutto.

Ho usato un'altra libreria che era compatibile con la mia fotocamera e poi ci sono riuscito.
Nel frattempo sono anche passato al Mega perchè l'UNO era un po' limitato per altre cose che dovevo usare.

Chiedi...

N