How to use a motorized webcam to take pictures from different locations and post them online as if they came from different webcams? With Arduino you can do it!

In this article I explain how I realized a webcam control system using the famous Arduino microcontroller with an Ethernet module and an Apexis APM-J902-Z-WS motorized webcam.

Ingredients:

  • a panoramic position
  • the Arduino microcontroller
  • the Arduino ethernet module
  • a micro SD
  • a motorized webcam
  • a PC with the development tool for Arduino Arduino IDE
  • a usb cable to communicate with the arduino board
  • an internet connection

The goal: multiple webcams in one

Having a terrace placed in a very large panoramic position, framing only one point was really a waste. I told myself, why not take advantage of the possibility of movement of a motorized webcam to take pictures from different angles, and then post each photo on webcam sites, as if they were webcams physically placed in different places?

To do this, the webcam software was not enough. The idea of using Arduino seemed to me the simplest thing … cheaper and even fun!

Now I’ll explain how I did it.

Analysis of the status of fact: what can the webcam do alone?

webcam Apexis APM-J902-Z-WS

This is the Apexis APM-J902-Z-WS webcam. Let’s start from the actual state of what it can do.

The apexis APM-J902 first of all is a wireless network webcam so it can be remotely controlled via network (cable or wireless). The first thing to do is therefore to assign them a static IP address and configure it to the home switch or router. Via the network it is possible to configure it using the appropriate control panel.

Apexis APM-J902-Z-WS Control Panel

Vediamo duque ciò che di utile al notro progetto può fare la cam.La cam può ricevere ed eseguire comandi via http per muovere l’obiettivo a destra, sinistra, in basso e in alto

  1. Ricevere ed eseguire comandi via http per restituire l’immagine puntata dall’obiettivo in quell’istante
  2. Ricevere ed eseguire comandi via http per memorizzare fino a 8 posizioni dell’obiettivo
  3. Ricevere ed eseguire comandi via http per spostare l’obiettvo in una delle 8 posizioni memorizzate

Sfruttado i punti di cui sopra è facile capire come si possa realizzare il tutto. Basta crerare un programma che per ognuna delle posizioni da fotografare esegua in sequenza:

  1. Posizionamento obiettivo su posizione 1
  2. Scaricamenti immagine su posizione 2
  3. Posizionamento obiettivo su posizione 2
  4. Scaricamenti immagine su posizione 2
  5. Posizionamento obiettivo su posizione 2
  6. Scaricamenti immagine su posizione 3
  7. Caricare le immagini su server FTP
  8. Attendere 10 minuti (o quanto vogliamo) e poi ripetere l’intero cilo

Ora basta fare un programma che realizzi tutto questo. Il problema è che bisognerebbe lasciare acceso un pc tutto il giorno e tutta la notte solo per fare questo!! Ecco perchè mi è venuta l’idea di utilizzare Arduino, che invece di qualche decina di Watts, consuma circa 4-6 Watt.

Supponendo che l’indirizzo IP della cam sia 10.0.0.100 i comandi da inviare alla cam sono semplici url, e sono i seguenti.

Comando per ricevere l’immagine “snapshot”:

http://10.0.0.100:81/snapshot.cgi?user=NOMEUTENTE&pwd=PASSWORD

Comando per richiamare lo spostamento dell’obiettivo su una determinata posizione:

http://10.0.0.100:81/decoder_control.cgi?command=31&user=NOMEUTENTE&pwd=PASSWORD

il command=31 corrisponde alla posizione preset numero 1. Per la posizione numero 2 utilizzare command=33, mentre per la posizione 2 il commad=35. La lista completa dei comandi potete scaricarla qui: PTZ Command List

Soluzione: utilizzare Arduino + Ethernet Shield

DUE PAROLE SU ARDUINO:
Per chi non lo conoscesse, Arduino è un microcontrollore programmabile, un progetto Open Source tutto italiano. In soldoni è una scheda elettronica dotata di un microprocessore, una memoria per contenere i programmi, diversi ingressi e uscite digitali e analogiche, una interfaccia di programmazione C/C++ e una miriadi di componenti interfacciabili. Arduino è una piattaforma a basso costo ed è correntemente utilizzata sia dagli studenti per progetti sperimentali, sia dagli hobbisti appassionati di elettronica, sia per utilizzi più professionali.

Esistono diverse versioni di Arduino. Nel mio progetto ho utilizzato Arduino Mega 2560 R3:

Aarduino Mega 2560-r3

Arduino ha la possibilità di connettersi alla rete, e quindi anche a internet mediante una scheda aggiuntiva chiamata Ethernet Shield:

Arduino Ethernet Shield - Arduino Modulo Ethernet

 

Le due schede si utilizzano sovrapponendo il modulo Ethernet Shield alla scheda Arduino in modo che i pettini di collegamento sulla scheda Ethernet si infilino nel fori del connettore sulla scheda Arduino.

Del modulo Ethernet Shield sfrutteremo il lettore di memorie Micro SD integrato per memorizzare le immagini catturate prima di inviarle sul server FTP.

Utilizzando l’IDE di sviluppo apposito e le opportune librerie è possibile programmare Arduino. In questo articolo non spiegherò come installare e configurare il tool di sviluppo sul proprio pc dato che è tutto ben spiegato qui.

Il risultato Finale:

Prima di tutto vediamo il risultato finale

Questo il video che illustra il funzionamento:

E queste le tre immagini catturate:

Le tre immagini in realtà sono pulite senza la scritta dell’orario e il logo, cosa che viene poi messo da un mio codice PHP il cui funzionamento non viene trattato in questa sede. Ma il risultato finale è comunque questo, ovvero tre immagini distinte comem se provenissero da tre webcam fisse diverse.

Il programma

Essendo il codice un po lungo non spiegherò tutto passo passo ma solo alcuni dettagli importanti lasciando ai commenti nel codice la spiegazione del resto.

Le librerie che ci serviranno sono le seguenti:

#include <SPI.h>            // per la comunicazine seriale
#include <HttpClient.h>     // per inviare i comandi http alla cam
#include <Ethernet.h>       // per inviare i comandi http alla cam
#include <EthernetClient.h> // per inviare i comandi http alla cam
#include <SD.h>             // per comunicare con il lettore di micro sim SD

Passiamo alla dichiarazione delle variabili principali. In particolare va indicato il MAC ADDRESS della scheda Ethernet Shield. Questo numero lo ricavate da una etichetta sulla scheda stessa. E’ fondamentale per ottenere l’IP dal DHCP Client.

const int LED_PIN=13;                   // pin a cui collego un led opzionale per la segnalazione di programmain ciclo
const char kHostname[] = "10.0.0.100";  // INDIRIZZO IP DELLA WEBCAM
char kPath[] = "/snapshot.cgi?user=NOMEUTENTE&pwd=PASSWORD";  // url della webcam che restituisce l'immagine
IPAddress server (62, 149, 141, 10);  // IP DEL SERVER FTP
byte mac[] = { 0x90, 0xA2, 0xDA, 0x02, 0x00, 0xFF  };  // MAC ADDRESS DELLA SCHEDA ETHERNET SHIELD
const int kNetworkTimeout = 30*1000; // Numero di millisecondi da attendere renza ricevere nulla prima di rinunciare
const int kNetworkDelay = 1000;      // Numero di millisecondi da attendere prima di riprovare se non ricevo dati
File file;
char outBuf[128];
char outCount;
EthernetClient client;
EthernetClient dclient;
HttpClient http(client);
int err =0;
byte clientBuf[2048];

La funzione setup() si avvia quando alimentate la scheda e ha il compito di:

  1. Inizializzare la micro sim SD
  2. Inizializzare la comunicazione seriale con il pc per la stampa dei logs
void setup()
{
    pinMode(LED_PIN, OUTPUT); // Led che indica se è in ciclo o in attesa 
  
   // initialize serial communications at 9600 bps:
  Serial.begin(9600);  
  Serial.println("(c) Copyright 2013 Alessandro Scola"); 
  Serial.println("http://www.alessandroscola.it");
  Serial.println("Released under Apache License, version 2.0");
  Serial.println("Software da utilizzare con Arduino Mega 2560 + Ethernet Shield");
  Serial.println("Il software controlla una IP cam Apexis, muovendola in 3 posizioni \"preset\" differenti");
  Serial.println("salvando le 3 immagini su SD card,");
  Serial.println("e successivamente facendo l'upload delle immagini su Server remoto via FTP.");
  Serial.println("Il ciclo si ripete ogni 10 minuti. Ogni 10 minuti vengono acquisite le 3 immagini");
  Serial.println("********************************************");
  Serial.print("Controllo SD Card...");
     
  
  //OBBLIGATORIO per l'uso della SD. Dato che arduino comunica alla scheda SD ed alla scheda ethernet con gli stessi pin,
  //solo una delle due può essere utilizzata alla volta. Tramite il pin 53 impostato ad HIGH si disattiva la scheda ethernet
  //in modo da poter usare la scheda SD e viceversa. impostando il pin 53 a OUTPUT si fa in modo che la libreria SD abbia la capacità
  //di gestire in automatico l'attivazione e la disattivazione di questa (in modo da non doverlo fare noi ogni volta) ma questa
  //gestione automatica del pin 53 da parte della libreria SD inizia solo dopo aver inizializzato la libreria con il comando SD.begin(4)
  
   digitalWrite(53,HIGH);  // il pin 53 è solo per la scheda Arudino Mega. per le altre schede usare il pin 10 
   pinMode(53,OUTPUT);     // il pin 53 è solo per la scheda Arudino Mega. per le altre schede usare il pin 10 
  

   // set up SD
   if(SD.begin(4) == 0) 
      Serial.println("errore, non riesco ad accedere a SD");
   else
   {
     Serial.println("SD Card OK !");
   }
}

Fate attenzione al Pin 53 (per la Scheda Arduino Mega, 10 per le altre schede), deve essere impostato subito come uscita e subito a valore HIGH. Questo è spiegato nei commenti e serve a disabilitare la shceda ethernet per poter inizializzare la comunicazione con la microsim SD, dato che l’accesso alla SD è gestita dalla stessa scheda che gestisce la scheda di rete.

Il resto del codice C++ comprende la funzione loop() che rappresenta l’intero ciclco del programma e alcune funzioni per la gestione della connessione FTP.

void loop()
{
  int err =0; 
  EthernetClient c;
  HttpClient http(c);
  long bufferCount = 0;
  
  digitalWrite(LED_PIN,HIGH);
    
   Serial.println("********************************************");
   Serial.println("Sto ottendendo indirizzo IP dal router ...");
   while (Ethernet.begin(mac) != 1)
   {
    Serial.print("Errore ottendendo indirizzo IP via DHCP, provo ancora ...");
    delay(15000);
   }  
   Serial.println("Ok !");
  

 //******************************************************************************************
 
 //Da il comando per la rotazione in posizione 1
 // go tp POSIZIONE 1:  
 Serial.println("********************************************");
 Serial.println ("Muovo la cam in POSIZIONE 1 e attendo che si posizioni");
 
 char kPathPOSIZIONE1[] ="/decoder_control.cgi?command=31&user=NOMEUTENTE&pwd=PASSWORD";
 err = http.get(kHostname, 81, kPathPOSIZIONE1);
 if (err != 0)
 {
   Serial.println ("Errore muovendo a POSIZIONE 1.");
 }
 http.stop();
 delay(8000); // attendo 8 secondi che la cam si posizioni
 
 //******************************************************************************************
 
  char kPath[] ="/snapshot.cgi?user=NOMEUTENTE&pwd=PASSWORD"; 
  err = http.get(kHostname, 81, kPath);
  if (err == 0)
  {
    Serial.println("Connessione con la cam OK !");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Codice risposta http: ");
      Serial.println(err);

      // Usually you'd check that the response code is 200 or a
      // similar "success" code (200-299) before carrying on,
      // but we'll print out whatever response we get

      err = http.skipResponseHeaders();
      if (err >= 0)
      {
        int bodyLen = http.contentLength();
        Serial.print("La risposta e' lunga: ");
        Serial.print(bodyLen);
        Serial.println(" bytes");
             
        file = SD.open("cam1.jpg", FILE_WRITE);
        file.seek(0);
        if (file) Serial.print("Salvo l'immagine su SD...");
        else Serial.println("Impossibile aprire file!");
        
        // Now we've got to the body, so we can print it out
        unsigned long timeoutStart = millis();
        byte c;
        // Whilst we haven't timed out & haven't reached the end of the body
        
        bufferCount=0;
        while ( (http.connected() || http.available()) &&
               ((millis() - timeoutStart) < kNetworkTimeout) ) { if (http.available()) { //c = http.read(); clientBuf[bufferCount] = http.read(); bufferCount++; // Print out this character //Serial.print(c); //if (file) file.write(c); if(bufferCount > 2047)
                  {
                    file.write(clientBuf,2048);
                    bufferCount = 0;
                  }
                
                // We read something, reset the timeout counter
                timeoutStart = millis();
            }
            else
            {
                // We haven't got any data, so let's pause to allow some to
                // arrive
                delay(kNetworkDelay);
            }
        }// fine while
        if(bufferCount > 0) file.write(clientBuf,bufferCount);
        
        file.close();
        Serial.println ("File chiuso.");
      }
      else
      {
        Serial.print("Failed to skip response headers: ");
        Serial.println(err);
      }
    }
    else
    {    
      Serial.print("Nessuna risposta: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connect failed: ");
    Serial.println(err);
  }
  http.stop();
  
 //****************************************************************************************
 
 //Da il comando per la rotazione in posizione 2
 // go tp POSIZIONE 2:  
 
 Serial.println("********************************************");
 Serial.println ("Muovo la cam in POSIZIONE 2 e attendo che si posizioni");
 
 char kPathPOSIZIONE2[] ="/decoder_control.cgi?command=33&user=NOMEUTENTE&pwd=PASSWORD";
 err = http.get(kHostname, 81, kPathPOSIZIONE2);
 if (err != 0)
 {
   Serial.println ("Errore muovendo a POSIZIONE 2.");
 }
 http.stop();
 delay(6000);
 
 //******************************************************************************************
 
 // SALVA IMG 2

  err = http.get(kHostname, 81, kPath);
  if (err == 0)
  {
    Serial.println("Connessione con la cam OK !");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Codice risposta http: ");
      Serial.println(err);

      // Usually you'd check that the response code is 200 or a
      // similar "success" code (200-299) before carrying on,
      // but we'll print out whatever response we get

      err = http.skipResponseHeaders();
      if (err >= 0)
      {
        int bodyLen = http.contentLength();
        Serial.print("La risposta e' lunga: ");
        Serial.print(bodyLen);
        Serial.println(" bytes");
              
        file = SD.open("cam2.jpg", FILE_WRITE);
        file.seek(0);
        if (file) Serial.print("Salvo l'immagine su SD...");
        else Serial.println("Impossibile aprire file!");
        
        // Now we've got to the body, so we can print it out
        unsigned long timeoutStart = millis();
        byte c;
        // Whilst we haven't timed out & haven't reached the end of the body
        bufferCount=0;
        while ( (http.connected() || http.available()) &&
               ((millis() - timeoutStart) < kNetworkTimeout) ) { if (http.available()) { //c = http.read(); clientBuf[bufferCount] = http.read(); bufferCount++; // Print out this character //Serial.print(c); //if (file) file.write(c); if(bufferCount > 2047)
                  {
                    file.write(clientBuf,2048);
                    bufferCount = 0;
                  }
               
                // We read something, reset the timeout counter
                timeoutStart = millis();
            }
            else
            {
                // We haven't got any data, so let's pause to allow some to
                // arrive
                delay(kNetworkDelay);
            }
        }// fine while
        
        if(bufferCount > 0) file.write(clientBuf,bufferCount);
        file.close();
        Serial.println ("File chiuso.");
      }
      else
      {
        Serial.print("Failed to skip response headers: ");
        Serial.println(err);
      }
    }
    else
    {    
      Serial.print("Nessuna risposta: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connect failed: ");
    Serial.println(err);
  }
  http.stop();
 
  
  //****************************************************************************************
 
 //Da il comando per la rotazione in posizione 3
 // go tp POSIZIONE 3:  
 
 Serial.println("********************************************");
 Serial.println ("Muovo la cam in POSIZIONE 3 e attendo che si posizioni");
 
 char kPathPOSIZIONE3[] ="/decoder_control.cgi?command=35&user=NOMEUTENTE&pwd=PASSWORD";
 err = http.get(kHostname, 81, kPathPOSIZIONE3);
 if (err != 0)
 {
   Serial.println ("Errore muovendo a POSIZIONE 3.");
 }
 http.stop();
 delay(4000);
 
 //******************************************************************************************
   
 // SALVA IMG 3

  err = http.get(kHostname, 81, kPath);
  if (err == 0)
  {
    Serial.println("Connessione con la cam OK !");

    err = http.responseStatusCode();
    if (err >= 0)
    {
      Serial.print("Codice risposta http: ");
      Serial.println(err);

      // Usually you'd check that the response code is 200 or a
      // similar "success" code (200-299) before carrying on,
      // but we'll print out whatever response we get

      err = http.skipResponseHeaders();
      if (err >= 0)
      {
        int bodyLen = http.contentLength();
        Serial.print("La risposta e' lunga: ");
        Serial.print(bodyLen);
        Serial.println(" bytes");
        Serial.println("Body returned follows:");
      
        file = SD.open("cam3.jpg", FILE_WRITE);
        file.seek(0);
        if (file) Serial.print("Salvo l'immagine  su SD...");
        else Serial.println("Impossibile aprire file!");
        
        // Now we've got to the body, so we can print it out
        unsigned long timeoutStart = millis();
        byte c;
        // Whilst we haven't timed out & haven't reached the end of the body
        bufferCount=0;
        while ( (http.connected() || http.available()) &&
               ((millis() - timeoutStart) < kNetworkTimeout) ) { if (http.available()) { //c = http.read(); clientBuf[bufferCount] = http.read(); bufferCount++; // Print out this character //Serial.print(c); //if (file) file.write(c); if(bufferCount > 2047)
                  {
                    file.write(clientBuf,2048);
                    bufferCount = 0;
                  }
               
                // We read something, reset the timeout counter
                timeoutStart = millis();
            }
            else
            {
                // We haven't got any data, so let's pause to allow some to
                // arrive
                delay(kNetworkDelay);
            }
        }// fine while
        if(bufferCount > 0) file.write(clientBuf,bufferCount);        
        file.close();
        Serial.println ("File chiuso.");
      }
      else
      {
        Serial.print("Failed to skip response headers: ");
        Serial.println(err);
      }
    }
    else
    {    
      Serial.print("Nessuna risposta: ");
      Serial.println(err);
    }
  }
  else
  {
    Serial.print("Connessione fallita: ");
    Serial.println(err);
  }
  http.stop();
  
  
  //******************************************************************************************
 
 //Da il comando per la rotazione in posizione 1
 // go tp POSIZIONE 1:  
 Serial.println("********************************************");
 Serial.println ("Riporto la cam in POSIZIONE 1 e attendo che si posizioni");
 
 char kPathPOSIZIONE4[] ="/decoder_control.cgi?command=31&user=NOMEUTENTE&pwd=PASSWORD";
 err = http.get(kHostname, 81, kPathPOSIZIONE1);
 if (err != 0)
 {
   Serial.println ("Errore muovendo a POSIZIONE 1.");
 }
 http.stop();
 delay(8000); // attendo 8 secondi che la cam si posizioni
 
 //******************************************************************************************
 
  //Carico le immagini sul server FTP
  Serial.println("********************************************");
  Serial.println ("");
  Serial.println ("CARICO LE 3 IMMAGINI SU SERVER FTP");
  Serial.println ("");
  uploadFTP();
  Serial.println("********************************************");
  
  Serial.println("Attendo 10 minuti e poi ricomincero' il ciclo...");
  digitalWrite(LED_PIN, LOW);
  delay(600000);
  //Serial.println("Attendo 15 secondi ...");
  //delay(15000);
} // fine void loop()



// #################### FUNZIONI PER L'FTP: #########################
byte uploadFTP()
{
  char fileName1[13] = "CAM1.JPG";
  char fileName2[13] = "CAM2.JPG";
  char fileName3[13] = "CAM3.JPG";
  byte clientBuf[64];
  long clientCount = 0;
  
  HttpClient http(client);
  
  
  if (client.connect(server,21))
  {
    Serial.println(F("Connesso al server..."));
  }
  else 
  {
    Serial.println(F("Connessione al server fallita."));
    return 0;
  }
  
  
   if(!eRcv()) return 0;

  client.println(F("NOMEUTENTE FTP"));

  if(!eRcv()) return 0;

  client.println(F("PASSWORD FTP"));

  if(!eRcv()) return 0;

  client.println(F("SYST"));

  if(!eRcv()) return 0;

  client.println(F("PASV"));

  if(!eRcv()) return 0;

  char *tStr = strtok(outBuf,"(,");
  int array_pasv[6];
  for ( int i = 0; i < 6; i++) {
    tStr = strtok(NULL,"(,");
    array_pasv[i] = atoi(tStr);
    if(tStr == NULL)
    {
      Serial.println(F("Bad PASV Answer"));    

    }
  }

  unsigned int hiPort,loPort;

  hiPort = array_pasv[4] << 8; loPort = array_pasv[5] & 255; Serial.print(F("Data port: ")); hiPort = hiPort | loPort; Serial.println(hiPort); if (dclient.connect(server,hiPort)) { Serial.println(F("Data connected")); } else { Serial.println(F("Data connection failed")); client.stop(); return 0; } //******************************************************** client.println(F("TYPE I")); // Importante! seleziona modo BINARIO per il trasferimento !! client.println(F("CWD /www.alessandroscola.it/webcam-belluno/CAM1")); client.print(F("STOR ")); client.println(fileName1); if(!eRcv()) { dclient.stop(); return 0; } file = SD.open(fileName1, FILE_READ); if(!file) { Serial.println("Apertura SD fallita !"); return 0; } Serial.println(F("Writing")); clientCount=0; while(file.available()) { clientBuf[clientCount] = file.read(); clientCount++; if(clientCount > 63)
    {
      dclient.write(clientBuf,64);
      clientCount = 0;
    }
  }
  if(clientCount > 0) dclient.write(clientBuf,64);
  dclient.stop();
  Serial.println(F("Data disconnected"));
  file.close();
  
  //*********************************************************
  if (dclient.connect(server,hiPort)) 
  {
    Serial.println(F("Data connected"));
  }
  else 
  {
    Serial.println(F("Data connection failed"));
    client.stop();
    return 0;
  }
  
   client.println(F("CWD /www.alessandroscola.it/webcam-belluno/CAM2"));  
  client.print(F("STOR "));
  client.println(fileName2);
  
   if(!eRcv())
  {
    dclient.stop();
    return 0;
  }
  file = SD.open(fileName2, FILE_READ);
  if(!file)
  {
    Serial.println("Apertura SD fallita");
    return 0;    
  }  
  Serial.println(F("Writing"));  
  clientCount=0;
  while(file.available())
  {
    clientBuf[clientCount] = file.read();
    clientCount++;

    if(clientCount > 63)
    {
      dclient.write(clientBuf,64);
      clientCount = 0;
    }
  }
  if(clientCount > 0) dclient.write(clientBuf,clientCount);
  dclient.stop();
  Serial.println(F("Data disconnected"));
  file.close();
  
  //*********************************************************
  if (dclient.connect(server,hiPort)) 
  {
    Serial.println(F("Data connected"));
  }
  else 
  {
    Serial.println(F("Data connection failed"));
    client.stop();
    return 0;
  }
  
  client.println(F("CWD /www.alessandroscola.it/webcam-belluno/CAM3"));  
  client.print(F("STOR "));
  client.println(fileName3);
  
   if(!eRcv())
  {
    dclient.stop();
    return 0;
  }
  
  file = SD.open(fileName3, FILE_READ);
  if(!file)
  {
    Serial.println("Apertura SD fallita");
    return 0;    
  }  
  Serial.println(F("Writing"));  
  clientCount=0;
  while(file.available())
  {
    clientBuf[clientCount] = file.read();
    clientCount++;

    if(clientCount > 63)
    {
      dclient.write(clientBuf,64);
      clientCount = 0;
    }
  }
  if(clientCount > 0) dclient.write(clientBuf,clientCount);
  dclient.stop();
  Serial.println(F("Data disconnected"));
  file.close();
  //******************************************************
  dclient.stop();
  Serial.println(F("Data disconnected"));

  if(!eRcv()) return 0;

  client.println(F("QUIT"));

  if(!eRcv()) return 0;

  client.stop();
  Serial.println(F("Command disconnected"));

  file.close();
  Serial.println(F("SD Chiusa."));
  return 1;

 
} // fine doFTP()


byte eRcv()
{
  byte respCode;
  byte thisByte;

  while(!client.available()) delay(1);

  respCode = client.peek();

  outCount = 0;

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);

    if(outCount < 127) { outBuf[outCount] = thisByte; outCount++; outBuf[outCount] = 0; } } if(respCode >= '4')
  {
    efail();
    return 0;  
  }

  return 1;
}


void efail()
{
  byte thisByte = 0;

  client.println(F("QUIT"));

  while(!client.available()) delay(1);

  while(client.available())
  {  
    thisByte = client.read();    
    Serial.write(thisByte);
  }

  client.stop();
  Serial.println(F("Command disconnected"));
  file.close();
  Serial.println(F("SD Chiusa."));
}

Categories: programming