Go Down

Topic: Webserver from SD card and picture problem (Read 5282 times) previous topic - next topic

alda

Jun 29, 2012, 08:05 am Last Edit: Jun 29, 2012, 10:28 am by alda Reason: 1
I'm using webserver from SD card :

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
byte mac[] = {
 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10,20,90,66);
File htmlFile;
EthernetServer server(80);

void setup()
{
   Serial.begin(9600);
 Ethernet.begin(mac, ip);
 server.begin();
 if (!SD.begin(4)) { return; }
}
void loop()
{
 EthernetClient client = server.available();
 if (client) {
   boolean currentLineIsBlank = true;
   while (client.connected()) {
     if (client.available()) {
       char c = client.read();
       if (c == '\n' && currentLineIsBlank) {
         client.println("HTTP/1.1 200 OK");
         client.println("Content-Type: text/html");
         client.println();
         Serial.print("OteviRm index.htm");
         htmlFile = SD.open("index.htm");
         if (htmlFile) {
           while (htmlFile.available()) {
             client.write(htmlFile.read());
           }
           // close the file:
           htmlFile.close();
         }
         break;
       }
       if (c == '\n') {
         currentLineIsBlank = true;
       }
       else if (c != '\r') {
         currentLineIsBlank = false;
       }
     }
   }
   delay(1);
   client.stop();
 }
}


Into index.htm I can write my HTML code, but question is how display on webserver also jpg picture from SD card.
If I will write into index.htm : <img src="picture.jpg"> and file picture.jpg I will copy to root of SD card, webserver will not show this picture - only square with cross.

What's wrong ?

Thanks for help

Alda

pylon

You don't even read what the client is sending to you so you cannot parse it too. In the client's request it specifies what resource (file) it wants, you don't care and just send the HTML file. You have to parse the client's request, at least the first line, else you won't be able to serve more than the current HTML file.

If you search for Webduino on Google you'll find a webserver for Arduino that is probably doing what you wanna do.

alda

Yes, I made a update to :

Quote
#include <SPI.h>
#include <SD.h>
#include <SdFatUtil.h>
#include <Ethernet.h>

/************ ETHERNET STUFF ************/
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(10,20,90,66);
char rootFileName[] = "index.htm";
EthernetServer server(80);

/************ SDCARD STUFF ************/
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))

void error_P(const char* str) {
  PgmPrint("error: ");
  SerialPrintln_P(str);
  if (card.errorCode()) {
    PgmPrint("SD error: ");
    Serial.print(card.errorCode(), HEX);
    Serial.print(',');
    Serial.println(card.errorData(), HEX);
  }
  while(1);
}

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

  PgmPrint("Free RAM: ");
  Serial.println(FreeRam()); 
 
  // initialize the SD card at SPI_HALF_SPEED to avoid bus errors with
  // breadboards.  use SPI_FULL_SPEED for better performance.
  pinMode(10, OUTPUT);                       // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH);                    // but turn off the W5100 chip!

  if (!card.init(SPI_HALF_SPEED, 4)) error("card.init failed!");
 
  // initialize a FAT volume
  if (!volume.init(&card)) error("vol.init failed!");

  PgmPrint("Volume is FAT");
  Serial.println(volume.fatType(),DEC);
  Serial.println();
 
  if (!root.openRoot(&volume)) error("openRoot failed");

  // list file in root with date and size
  PgmPrintln("Files found in root:");
  root.ls(LS_DATE | LS_SIZE);
  Serial.println();
   
  // Recursive list of all directories
  PgmPrintln("Files found in all dirs:");
  root.ls(LS_R);
 
  Serial.println();
  PgmPrintln("Done");
   
  // Debugging complete, we start the server!
  Ethernet.begin(mac, ip);
  server.begin();
}

// How big our line buffer should be. 100 is plenty!
#define BUFSIZ 100

void loop()
{

  char clientline[BUFSIZ];
  char *filename;
  int index = 0;
  int image = 0;
 
  EthernetClient client = server.available();
    if (client) {
    // an http request ends with a blank line
    boolean current_line_is_blank = true;
   
    // reset the input buffer
    index = 0;
   
      while (client.connected()) {
        if (client.available()) {
          char c = client.read();
         
        // If it isn't a new line, add the character to the buffer
        if (c != '\n' && c != '\r') {
          clientline[index] = c;
          index++;
          // are we too big for the buffer? start tossing out data
          if (index >= BUFSIZ)
            index = BUFSIZ -1;
           
          // continue to read more data!
          continue;
        }
         
        // got a \n or \r new line, which means the string is done
        clientline[index] = 0;
        filename = 0;
       
        // Print it out for debugging
        Serial.println(clientline);
       
        // Look for substring such as a request to get the root file
        if (strstr(clientline, "GET / ") != 0) {
          filename = rootFileName;
        }
        if (strstr(clientline, "GET /") != 0) {
          // this time no space after the /, so a sub-file
         
          if (!filename) filename = clientline + 5; // look after the "GET /" (5 chars)
          // a little trick, look for the " HTTP/1.1" string and
          // turn the first character of the substring into a 0 to clear it out.
          (strstr(clientline, " HTTP"))[0] = 0;
         
          // print the file we want
          Serial.println(filename);
         
          if (! file.open(&root, filename, O_READ)) {
            client.println("HTTP/1.1 404 Not Found");
            client.println("Content-Type: text/html");
            client.println();
            client.println("<h2>File Not Found!</h2>");
            break;
          }
         
          Serial.println("Opened!");
         
          client.println("HTTP/1.1 200 OK");
          if (strstr(filename, ".htm") != 0)
             client.println("Content-Type: text/html");
         else if (strstr(filename, ".css") != 0)
             client.println("Content-Type: text/css");
         else if (strstr(filename, ".png") != 0)
             client.println("Content-Type: image/png");
          else if (strstr(filename, ".jpg") != 0)
             client.println("Content-Type: image/jpeg");
         else if (strstr(filename, ".gif") != 0)
             client.println("Content-Type: image/gif");
         else if (strstr(filename, ".3gp") != 0)
             client.println("Content-Type: video/mpeg");
         else if (strstr(filename, ".pdf") != 0)
             client.println("Content-Type: application/pdf");
         else if (strstr(filename, ".js") != 0)
             client.println("Content-Type: application/x-javascript");
         else if (strstr(filename, ".xml") != 0)
             client.println("Content-Type: application/xml");
         else
             client.println("Content-Type: text");

          client.println();
         
          int16_t c;
          while ((c = file.read()) >= 0) {
              // uncomment the serial to debug (slow!)
              //Serial.print((char)c);
              client.print((char)c);
          }
          file.close();
        } else {
          // everything else is a 404
          client.println("HTTP/1.1 404 Not Found");
          client.println("Content-Type: text/html");
          client.println();
          client.println("<h2>File Not Found!</h2>");
           }
        break;
      }
    }
    // give the web browser time to receive the data
    delay(1);
    client.stop();
  }
}


Now I can see also picture from SDcard, but my next question is - is possible insert into this webserver any line which will show me actual values ( analog values ) of andruino ?

Thanks

Alda

sbright33

I have seen examples which do that.  Sorry I can't find link now I'm traveling.

This works to display JPG?  Great!  I want to do this too!  Please let me know if you have any problems with this code you provided.  Because I would like to use it soon.  Will you update it here with any improvements?
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

alda

It's working for me without problems, now I can have all stored on SDcard, also pictures, but show picture on the webserver is quite slow.
You can also click on three places on the picture which will open other page....

But I'm still looking for improvements ( see values on the screen with picture and speed up loading )

Alda

sbright33

What 3 places on picture?  What is the other page?  I cannot test it today.
If you fall... I'll be there for you!
-Floor

Skype Brighteyes3333
(262) 696-9619

rokitz

Hello Alda,

i have downloaded your update code and turned it into a wifi shield code. It functions so somewhat with my modifications.

I don t know how do you call pictures from the sd card. Please tell me.

Many Greetings.

Rokitz.
Thank you for all help!

mohamed66

Thanks for your advice ,,, but pictures downloading slowly when i open the webpage do u know why ?

zoomkat


Thanks for your advice ,,, but pictures downloading slowly when i open the webpage do u know why ?


The arduino is slow compared to computer based servers.
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

pylon

Quote
but pictures downloading slowly when i open the webpage do u know why ?


Additionally to zoomkat's explanation there's another reason:

Code: [Select]
          int16_t c;
          while ((c = file.read()) >= 0) {
              // uncomment the serial to debug (slow!)
              //Serial.print((char)c);
              client.print((char)c);
          }


You're reading the file byte by byte and then hand it over to the Ethernet library using the print() method. This way you create a packet for every byte you want to send. This is highly inefficient. It's a drawback of the Ethernet library but there is a reason for this: the lack of memory in the Arduino forced that decision. If you create a buffer of let's say 256 bytes and read that quarter kB from the card and send it using the write() method you will get faster (but not fast) responses.

zoomkat

Some discussion of interest below.

http://arduino.cc/forum/index.php/topic,134868.0.html
Google forum search: Use Google Advanced Search and use Http://forum.arduino.cc/index in the "site or domain:" box.

Touf2638

Je mets le code complet (Je débute donc c'est peut être pas très propre   :smiley-red:) mais ce qui me surprend c'est que ce code "allegé" ne marche pas tout de suite. Il faut le transferer 2 ou 3 fois avant que ca remarche...juste transferer 2 ou 3 fois sans rien modifier...

Code: [Select]
//**********************************************************************************************************************************
//**********************************************************************************************************************************



#include <Ethernet.h>
#include <SD.h> // crée automatiquement un objet racine SD représentant la carte mémoire SD
#include <SPI.h>



/* Détails technique de la connexion ethernet */
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = {
  192,168,1, 177 };
byte gateway[] = {
  192,168,1, 1 };

// Attachement d'un objet "server" sur le port 1337
EthernetServer server(80);






//**********************************************************************************************************************************
//**********************************************************************************************************************************

void setup()
{

  // Variables d'Usage
  int Resultat_fct = false;
 
  // Initialisation port serie
  Serial.begin(115200);
 
  // Affichage de la SRAM utilisée
//  Serial.print(F("Memoire SRAM restante :"));
//  Serial.println(freeRam());

  // Affectation des directions pins
  pinMode(53, OUTPUT); // broche de selection WIZNET
  pinMode(4, OUTPUT); // broche de selection SD card
  digitalWrite(4,LOW);
  digitalWrite(53,HIGH);

  // Initialisation de la carte SD avec broche 4 en tant que CS
  Resultat_fct=SD.begin(4);
  if (Resultat_fct!=true)
  {
    Serial.println(F("Echec initialisation SD!"));
  }
 
  delay(1000);
 
  // Initialisation de la librairie ethernet
  Ethernet.begin(mac, ip, gateway);
  server.begin();

}

//**********************************************************************************************************************************
//          MAIN
//**********************************************************************************************************************************

void loop()
{
      // Scrutation reseau
      Com_reseau();
}

//**********************************************************************************************************************************
//          FONCTION COMMUNICATION RESEAU
//**********************************************************************************************************************************

void Com_reseau()
{

   //_____________________________________________________________________________________
 
   // Variables d'usage
   String chaineRecue="";           // réception chaine requete
   int comptChar=0;                 // comptage des caractères reçus
   int resultat_SD=0;               // resultat fonction lecture carte SD
   int index_paquet=0;              // numéro de ligne à lire dans la carte SD
   int datas[150];               // ligne lue dans la carte SD
   char c;                          // caractère récupéré par Ethernet
   
  //_____________________________________________________________________________________

   // Crée un objet client basé sur le client connecté au serveur
   EthernetClient client = server.available();
 
  // si l'objet client n'est pas vide
  if (client)
  {
      // si le client est connecté
      if (client.connected())
      {
           
            //_____________________________________________________________________________________
           
            // Initialisation variables
            comptChar = 0;
            chaineRecue = "";
           
            // Boucle sur reception client
            while (client.available())
            {
             
              // l'octet suivant reçu du client est mis dans la variable c
              c = client.read();
             
              // incrémente le compteur de caractère reçus
              comptChar=comptChar+1;

              // Concatenation caractere dans une chaine dans une limite de 50 caracteres
              if (comptChar<50)
              {
                  chaineRecue=chaineRecue+c;
              }
             
            }
           
             //_____________________________________________________________________________________
           
             // Chaine reçue est une requete GET alors affichage page Web
             if (chaineRecue.startsWith("GET / HTTP"))
             {
                  // Lecture carte SD et affichage page Web
                  while (resultat_SD!=1 && resultat_SD<100) // Tant que pas fin de fichier texte et pas d'erreur
                  {
                      resultat_SD = Lecture_ligne_SD(index_paquet,"/Web/Image.txt",datas);
                      int idx=0;
                      while(idx<150 && datas[idx]>0)
                      {
                          if (datas[idx]>0)
                          {
                            client.print((char)datas[idx]);
                            idx++;
                          }
                      }
                      index_paquet++;
                  }             
             }
         
           
            //_____________________________________________________________________________________
                   
            // Attente et libération client     
            delay(1);
            client.stop();

            //_____________________________________________________________________________________
                       
      } 
   
  }     
     
     
}

//**********************************************************************************************************************************
//          FONCTION DE RECUPERATION D'UNE LIGNE DANS UN FICHIER TXT D'UNE CARTE SD
//**********************************************************************************************************************************

int Lecture_ligne_SD(int index_paquet,char path[20], int tableau[150])
{

    //_____________________________________________________________________________________
 
    // Variables d'Usage
    int File_exist=0;
    File myFile; // objet file

    //_____________________________________________________________________________________
   
    // Selection de la SD Card
    digitalWrite(53,HIGH);
    digitalWrite(4,LOW);
   
    //_____________________________________________________________________________________
   
    // Test si le fichier existe - renvoie true/false
    File_exist=SD.exists(path);

     // Si fichier n'existe pas   
     if (File_exist!=true) 
     {
       return 100;
     }
     // Si fichier existe
     else
     {
         
          // Ouverture du fichier en lecture
          myFile=SD.open(path,FILE_READ);
          myFile.seek(index_paquet*150);

          for (int index=0;index<=150;index++)
          {
             tableau[index] = 0;
          }
         
          for (int index_c_ec=0;index_c_ec<150;index_c_ec++)
          {
             tableau[index_c_ec] = myFile.read();

             if (tableau[index_c_ec]<0)
             {
                 //tableau[index_c_ec]=0;
                 return 1;
             }
          }
          return 2;
   
     }           

     
    //_____________________________________________________________________________________

    // Selection du Wiznet
    digitalWrite(53,LOW);
    digitalWrite(4,HIGH); 
   
    //_____________________________________________________________________________________
   
}


//**********************************************************************************************************************************
//          FONCTION LECTURE SRAM UTILISEE
//**********************************************************************************************************************************

//int freeRam ()
//{
//  extern int __heap_start, *__brkval;
//  int v;
//  return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
//}



Touf2638


sakis2323

I have tried the code but it doesn't show the picture from sd.
In which directory a jpg picture must be placed?

enrico_ecarduino

As far as I can understand, the web server as it is, is rather minimal, yet enough for many simple applications.
For an application I am working on (on Mega and Ethernet shield) I preferred to develop something more systematic and complete. You can find it at http://forum.arduino.cc/index.php?topic=203450.0, where I posted what I have done.
If you are working on UNO, it needs to be downsized a bit, anyway you may take it as a starting point.
HTH,
eca

Go Up