Progetto Arduino Server

Ciao a tutti! :stuck_out_tongue:
Devo finire il mio progetto di maturità ma sono mi sono bloccato. :~
Il mio obbiettivo era, attraverso Arduino UNO, Ethernet Shield V2 + SD Card, LCD seriale, salvare e visualizzare dei dati direttamente dal dispostivo a pagina web.
La mia idea fantasiosa era usare XAMPP e MySql (visto che li ho usati a scuola) per gestire i dati ma non credo che si possa poichè ho bisogno di un client (come il pc) per startare i processi Apache e MySql. Ho anche provato a usare Altervista con il proprio db e PhpMyAdmin ma niente.
Voi cosa mi consigliate per semplificare il lavoro ma mantendo la mia idea iniziale??
Vi ringrazio in anticipo, Buona giornata :slight_smile:

Questa maturitá o quella dell anno prossimo?

Non ho capito vorresti far girare MySQL e Apache su Arduino?
Ciao Uwe

Questa..

Si l'idea era quella ma l'ho bocciata.
Vorrei salvare file sull'sd, visualizzarli sul Web e salvarli sul pc..

Ho già interfacciato SD e Web Server (separatamente), il problema è il vedere i file all'interno del SD Card sul sito Web (salvato su SD).

il problema è il vedere i file all'interno del SD Card sul sito Web (salvato su SD).

sito magari è un po' troppo, facciamo pagina web :slight_smile:

Quindi fammi capire... tu apri una pagina web che si trova dentro l'SD e all'interno di essa vuoi visualizzare un file archivio dati anch'esso dentro SD? perchè è questo che hai detto
Non fai prima ad aprire il file archivio sul browser e basta senza tante pagine?

Fare quello che hai detto ci vuole un formato riconoscito dalla pagina html tramite script, scambio di dati ajax o json ... non hai tempo per farlo

ciao

Giusto pablos. :slight_smile:
Volevo fare un interfaccia Web per considerare il tutto un Server Web..
Ajax o Json non li ho mai usati nella mia vita scolastica quindi sarebbe ancora più dura riuscire a fare il progetto..
Non c'è un modo più semplice per visualizzare i file sul web con l'HTML??

si ma ne trovi a palate su google tipo questo

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
 
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1, 177 };
File htmlFile;
EthernetServer server(80);
 
void setup()
{
  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();
 
          htmlFile = SD.open("file.txt"); 
          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();
  }
}

La mia idea iniziale era di simulare in piccolo alcuni servizi di un server di una LAN Client - Server..
Web/HTTP --> Con la grafica del piccolo sito.
DB --> Con il salvataggio dei dati.
FTP --> Con il download di un file sul client.
DHCP --> Offrendo un IP ai client che si connettevano all'ip di arduino.

Visto che devo rinunciare alla mie idea, consigli su un semplice progetto?
Ripeto, ho Arduino UNO, Ethernet Shield, SD Card, LCD Seriale..

Mi sembra che tu abbia sopravvalutato arduno UNO, non ha ne la memoria ne la potenza per fare quelle cose.

Web/HTTP --> Con la grafica del piccolo sito.

si, questo è possibile, ma molto piccolo e la paginetta web deve essere contenuta su SD a causa della scarsa ram del micro, questa dovrebbe essere in grado di inviare e ricevere dati su GET-POST tramite script nella pagina stessa, molto piccola anch'essa perchè impiega tempo ad essere caricata, quindi niente immagini e abbellimenti vari, gli esami di stato finiscono prima che tu abbia caricato.

DB --> Con il salvataggio dei dati.

un database DB non puoi farlo ne ora che hai poco tempo, ne mai, se non su un server host esterno o su un Pc come hai detto prima tu caricando Apache e MySql e realizzando poi programmi in php-html, al massimo puoi solo inviargli i char da salvare sul Db

FTP --> Con il download di un file sul client.

L'ftp è un protocollo che lavora su porta 21, quindi dovresti già differenziare nel programma server TCP/IP e server FTP oltre che alle altre cose, perciò non ti basta la ram. Il download lo puoi fare anche col tcp/ip come nell'esempio che ti ho postato prima, anche l'upload volendo (sempre cose leggere).

DHCP --> Offrendo un IP ai client che si connettevano all'ip di arduino.

Qui invece mi spiazzi, arduino non è un router capace di assegnare degli IP e fare da gateway verso la rete, è l'opposto semmai, esso non ha un sistema operativo, un client che si collega ad arduino lo fa attraverso la rete locale, aziendale, pubblica dove l'ip il clent lo possiede già, ci si limita solo a fare la negoziazione sul protocollo e al traffico dati tramite tcp/ip o udp ecc.
La libreria DHCP che avrai visto in alcuni esempi è per chiederlo l'IP non per darlo, insomma per adattarsi alla rete con i vari parametri mask, gateway, dns ecc
E' come se tu comprassi una telecamera IP, che ha un micro almeno 20 volte più potente di un 328 e la connetti in rete, quando ti colleghi ad essa mica ti da l'IP, arduino è +/- la stessa cosa, solo che invece di elaborare immagini e trasmetterle elabora segnali digitali e analogici provenienti dai suoi pin che può volendo anche inviare a fatica via web.

Ora il punto è: tu mi chiedi un consiglio su cosa portare all'esame ...... ma sinceramente anche qui mi spiazzi, perchè non hai parlato di un progetto dove c'è dell'elettronica da gestire, un controllo di led, luci, motori, temperature, sensori di ogni tipo, relay, 1000 altre cose, hai solo un display, una SD e una ethernet .... belin ma che ci fai con solo ste cose? XD

Forse la yun ti permette di fare qualcosa più simile a quello che chiedi .... ma io non la conosco bene.

ciao

Grazie di tutto e del tempo che mi stai dedicando.

Ps. Ho letto il "belin", sono anche io genovese :slight_smile:

Mi conviene lasciare questa idea da parte allora.. Credevo di riuscire a fare tutto questo, ho fatto tutto in separata sede, ma implementare tutto insieme non si può per i limiti di Arduino.
Non ho idee, ho solo a disposizione quello che ti ho detto.. Ho cercato i progetto online ma niente. Potevo fare un impianto di domotica ma un mio compagno mi ha rubato l'idea..

Okay ci sono.
Ho tirato fuori un vecchio progetto in cui controllavo una ventola tramite PWM con Arduino.

Il circuito l'ho completato, ora devo interfacciarlo con il web: volevo mostrare (e magari salvare su SD?) su una pagina web i dati rilevati (temperatura, percentuale PWM..). Lo script per il web l'ho già implementato e funziona, mi manca solo mostare i dati con l'HTML.
Nello script trovato sul web e modificato, carico la pagine da SD:

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
 
#define maxLength 25
 
byte mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x5A, 0x82 };
byte ip[] = { 192,168,1,10 };
File htmlFile;
EthernetServer server(80);
 
void setup()
{
  Ethernet.begin(mac, ip);
  server.begin();
  if (!SD.begin(4)) { return; }
}
 
void loop()
{
  char* file_to_load = "index.htm";
  String inString = String(maxLength);
 
  EthernetClient client = server.available();
  if (client) {
    boolean currentLineIsBlank = true;
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        if (inString.length() < maxLength) {
          inString += c;
        }
        if (c == '\n' && currentLineIsBlank) {
          if (inString.indexOf(".htm") > -1) {
            String new_file_load;
            int rootIndex = inString.indexOf("/");
            new_file_load = inString.substring((rootIndex+1), (rootIndex+13));
 
            int endIndex = new_file_load.indexOf(" ");
            if (endIndex > -1) {
              new_file_load = new_file_load.substring(0, endIndex);
            }
            if (new_file_load != "")  {
              new_file_load.toCharArray(file_to_load,12);
            }
          }
 
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println();
 
          // read_file( "header.htm",client );
          read_file( file_to_load,client );
          // read_file( "footer.htm",client );
 
          break;
        }
        if (c == '\n') {
          currentLineIsBlank = true;
        }
        else if (c != '\r') {
          currentLineIsBlank = false;
        }
      }
    }
    delay(1);
    client.stop();
  }
}
 
void read_file( char* page_html, EthernetClient client )
{
  htmlFile = SD.open( page_html );
  if (htmlFile) {
    while (htmlFile.available()) {
        client.write(htmlFile.read());
    }
    // close the file:
    htmlFile.close();
  }
}

io ho realizzto una cosa simile: una pagina html su SD che mostra dei dati salvati in un file su SD.
per mostrare il file dati ho utilizzato un iframe.
se ti può servire te lo mando.

Mi faresti un grandissimo favore grazie davvero :smiley:
Però scusa la mia ignoranza.. Cosa è un iframe?? :slight_smile:

un iframe è una "finestra" (non è proprio corretto chiamarla così ma rende bene l'idea) all'interno della pagina nella quale viene visualizzato un link ad una pagina "esterna". questo perchè arduino non può aprire due o più file contemporaneamente.

ho estrapolato il tutto da un mio progetto, forse ci sarà qualcosa da limare e aggiustare, ma di base è funzionante.
i dati non si aggiornano automaticamente per questo ho inserito un pulsante per aggiornare la finestra del log senza ricaricare tutta la pagina.

scketch:

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

#define REQ_BUF_SZ   60                                     // size of buffer used to capture HTTP requests

byte mac[] = { 0x90, 0xA2, 0xDA, 0x0E, 0xBF, 0x00 };        // MAC address from Ethernet shield 
IPAddress ip(192, 168, 1, 199);                             // IP address, may need to change depending on network

//WEB SERVER
EthernetServer server(80);                                  // create a server at port 80
File webFile;                                               // the web page file on the SD card
char HTTP_req[REQ_BUF_SZ] = {0};                            // buffered HTTP request stored as null terminated string
char req_index = 0;                                         // index into HTTP_req buffer
boolean LED_state[4] = {0};                                 // stores the states of the LEDs

String ServerResponse="";
EthernetClient emailClient;

void setup() {
  pinMode(4, OUTPUT);                                       // CS SD Card
  pinMode(10, OUTPUT);                                      // CS Ethernet Card
  digitalWrite(10, HIGH);                                   // disable Ethernet chip
  Serial.begin(9600);                                       // start serial monitor

  //INITIALIZE AND CHECK SD CARD
  Serial.println("Initializing SD card...");                // initialize SD card
  if (!SD.begin(4)) {
    Serial.println("ERROR - SD failed!");
    return;                                                 // init failed
  }
  else Serial.println("SUCCESS - SD OK.");

  //CHECK WEBSERVER HOME FILE
  if (!SD.exists("home.htm")) {                            // check for home.htm file
    Serial.println("ERROR - Can't find home.htm file!");
    return;                                                 // can't find index file
  }
  else{
    Serial.println("SUCCESS - Found home.htm file.");
  }

  //INITIALIZE LOG FILE
  Serial.println(F("card initialized."));
  File dataFile = SD.open("LOG.HTM", FILE_WRITE);

  Ethernet.begin(mac, ip);                                   // initialize Ethernet device
  server.begin();                                            // start to listen for clients
}


void loop() {

  EthernetClient client = server.available();                // try to get client
  if (client) {                                              // got client?
    startWebServer();
  } 
 
}

 
void startWebServer() {
  EthernetClient client = server.available();                // try to get client
  boolean currentLineIsBlank = true;
  while (client.connected()) {
    if (client.available()) {                              // client data available to read
      char c = client.read();                              // read 1 byte (character) from client
      // limit the size of the stored received HTTP request
      // buffer first part of HTTP request in HTTP_req array (string)
      // leave last element in array as 0 to null terminate string (REQ_BUF_SZ - 1)
      if (req_index < (REQ_BUF_SZ - 1)) {
        HTTP_req[req_index] = c;                           // save HTTP request character
        req_index++;
      }
      // last line of client request is blank and ends with \n
      // respond to client only after last line received
      if (c == '\n' && currentLineIsBlank) {

        client.println("HTTP/1.1 200 OK");                 // send a standard http response header
    
        if (StrContains(HTTP_req, "home.htm")) {
          client.println(F("Content-Type: text/html"));
          client.println(F("Connection: keep-alive"));
          client.println();
          webFile = SD.open("home.htm");                  // open web page file
          if (webFile) {
            while(webFile.available()) {
              client.write(webFile.read());                // send web page to client
            }
            webFile.close();
          }
        }

        if (StrContains(HTTP_req, "LOG.HTM")) {
          client.println(F("Content-Type: text/html"));
          client.println(F("Connection: keep-alive"));
          client.println();
          webFile = SD.open("LOG.HTM");                  // open web page file
          if (webFile) {
            while(webFile.available()) {
              client.write(webFile.read());                // send web page to client
            }
            webFile.close();
          }
        }      

        if (!StrContains(HTTP_req, "LOG.HTM") && !StrContains(HTTP_req, "home.htm") && !StrContains(HTTP_req, "ajax_inputs")    ) {
          client.println();
          client.println(F("<html>
<p style=\"text-align:center;padding:20px;background:red;font-size:40px;font-weight:bold;\">Error 404: page not found!</p></html>"));
        }  

        Serial.print(HTTP_req);                            // display received HTTP request on serial port
        req_index = 0;                                     // reset buffer index and all buffer elements to 0
        StrClear(HTTP_req, REQ_BUF_SZ);
        break;
      }
      if (c == '\n') {                                     // every line of text received from the client ends with \r\n
        currentLineIsBlank = true;                         // last character on line of received text starting new line with next character read
      } 
      else if (c != '\r') {                                // a text character was received from client
        currentLineIsBlank = false;
      }
    }
  }
  delay(1);                                                // give the web browser time to receive the data
  client.stop();                                           // close the connection
}



// sets every element of str to 0 (clears array)                      *** OK
void StrClear(char *str, char length)
{
  for (int i = 0; i < length; i++) {
    str[i] = 0;
  }
}

// searches for the string sfind in the string str                    *** OK
// returns 1 if string found, returns 0 if string not found
char StrContains(char *str, char *sfind) {
  char found = 0;
  char index = 0;
  char len;
  len = strlen(str);
  if (strlen(sfind) > len) {
    return 0;
  }
  while (index < len) {
    if (str[index] == sfind[found]) {
      found++;
      if (strlen(sfind) == found) {
        return 1;
      }
    }
    else {
      found = 0;
    }
    index++;
  }
  return 0;
}

home.htm

<!DOCTYPE html>
<html>
	<head>
		<title>Titolo</title>
	
		<style type="text/css">
		body {
				background: none repeat scroll 0 0 #00979C;
				font-family: arial;
				width: 100%;
		}
		h1 {
				float: left;
				margin: 0;
				text-align: center;
				width: 500px;
		}
		#header {
				border-bottom: 2px solid #FD6400;
				color: #E0E0E0;
				height: 45px;
				width: 100%;
		}
		input, button {
				background: none repeat scroll 0 0 #E0E0E0;
				border: 1px solid;
				font-size: 14px;
				font-weight: bold;
				margin-bottom: 10px;
				padding-bottom: 5px;
				padding-top: 5px;
				width: 145px;
		}
		input:hover, button:hover {
				background: none repeat scroll 0 0 #CBCBCB;
				color: #FFFFFF;
		}
		</style>
	</head>

  <body>
    <div id="header">
			<h1 style="width:100%">Titolo</h1>
  	</div>
				<p style="text-align:center">Storico Allarmi</p>
				
 
				<iframe name="framelog" src="LOG.HTM" width=100% height=200 frameborder=0 ></iframe>
	
				<button style="width:100%" onclick="var ifr=document.getElementsByName('framelog')[0]; ifr.src=ifr.src;">Aggiorna</button>
		
			<div style="clear:both;"></div> 
		
	</body>
</html>

i dati non si aggiornano automaticamente per questo ho inserito un pulsante per aggiornare la finestra del log senza ricaricare tutta la pagina.

aggiungi un refresh automatico

<html>
<head>
<script type="text/JavaScript">

function timedRefresh(timeoutPeriod) {
	setTimeout("location.reload(true);",timeoutPeriod);
}
</script>
</head>
<body onload="JavaScript:timedRefresh(3000);">
***
***
***
</body>
</html>

@pablos
avevo evitato il refresh automatico perchè avendo un file di log discretamente lungo non avevo il tempo di leggere (al refresh l'iframe torna in alto e mi tocca scrollare a tutto gas :)) ) per contro, con un tempo troppo lungo mi tocca aspettare per vedere un aggiornamento. ma ovviamente dipende dalle applicazioni. nel mio caso ho preferito il pulsante.

Ti ringrazio infinitamente!! :smiley:

L'unico problema è che non riesce a caricare il file su sd e mi da sempre l'errore:

client.println(F("<html>
<p style=\"text-align:center;padding:20px;background:red;font-size:40px;font-weight:bold;\">Error 404: page not found!</p></html>"));

Quello che visualizza il page 404 not found in rosso..
Come mai??

non ho capito il problema. chi ti da errore? il compilatore o il browser? che errore?
comunque quella riga non è fondamentale, serve solo a visualizzare un messaggio di errore nel caso che l'indirizzo nel browser non sia corretto. senza di quello avrai una pagina bianca.
come indirizzo devi dare l'ip di arduino + /home.htm

Io carico "http://"IP"/index.htm"
Come risultato ho la pagina bianca.
Ho provato a pingare sull'indirizzo e tutto ok.
Il file aperto direttamente da sd dal pc c'è.. Se lo apro attraverso Arduino pagina bianca..

se il file htm lo hai chiamato index.htm devi modificare anche lo sketch.
io l'ho chiamato home.htm.
devi modificare tutti i riferimenti nello a sketch, oppure cambi semplicemente il nome al file index.htm -> home.htm

Sisi ho modificato tutto..
Normalmente uso idex.htm per la prima pagina quindi anche qua l'ho girata così..