Problemi trasmissione Ethernet schield e web server

Ciao a tutti :slight_smile:
seguo il forum da un po' ed ora per la maturità devo creare un progetto con arduino, ma siccome sono le miei prime volte sto incontrando difficoltà
ho un arduino uno con un Ethernet Shield e SD da 2gb ... Io devo prendere in input dei dati di misura ( presi da sensori di temperatura, sensori di fumo), ed accendere delle luci ( dei led) per simulare una casa domotica... per fare questo volevo utilizzare l'arduino come web server, inserire li sopra ( sulla sd ) un sito html che quando lo richiedo inserendo l'ip dell'arduino, mi permette di vedere i dati e di accendere e spegnere le luci ... per ora mi accontento di questo, poi se avrò ancora tempo proverò a fare qualcosa con il php
Il mio problema è che l'arduino non comunica con il mio pc attraverso la ethernet ( ho windows 7) ... di fatti non mi funzionano nemmeno i file di esempio, perchè lampeggia solo il led rx ( e infatti il computer non riceve pacchetti ma invia solo). Con gli esempi client lampeggiano entrambi, però lo scambio di pacchetti è solo in ricezione e non funziona lo sketch
Curiosando sul forum ho trovato un file di un utente molto semplice, che dovrebbe funziuonare senza problemmi:

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

//Creao un array di byte per specificare il mac address
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
//creo un array di byte per specificare l'indirizzo ip
byte ip[] = {192, 168, 1, 127};

char Data_RX;

//creao un oggetto server che rimane in ascolto sulla porta
//specificata
EthernetServer ArduinoServer(80);

void setup()
{
  //inizializza lo shield con il mac e l'ip  
  Ethernet.begin(mac, ip);
  //inizializza l'oggetto server
  ArduinoServer.begin();
  
  Serial.begin(9600);
}

void loop()
{

    EthernetClient pc_client = ArduinoServer.available();

    //controllo se pc_client è true
    if (pc_client != false)
    {
        //controllo continuamente che il client sia connesso
        while (pc_client.connected())
        {
            //Controllo se ci sono byte disponibili per la lettura
            if (pc_client.available())
            {
                //leggo i byte disponibili
                //provenienti dal client
                Data_RX = pc_client.read();

                //Attendo che tutti i byte siano letti
                //quando Data_RX contiene il carattere
                //di nuova line capisco tutti i byte sono
                //stati letti
                if (Data_RX == '\n')
                {
                    //Invio la risposta al client
                    //invio lo status code
                    pc_client.println("HTTP/1.1 200 OK");
                    //imposto il data type
                    pc_client.println("Content-Type: text/html");
                    pc_client.println();
                    //invio codice html
                    pc_client.print("<html><body><h1>Hello world Arduino Web Server</h1></body></html>");
                    //aspetto 1 ms affinche la risposta giunga al browser del client
                    delay(1);
                    //esco dal ciclo while una volta completato l'invio della risposta
                    break;
                }
            }
        }
        //chiudo la connessione
        pc_client.stop();
    }
}

Ma anche con questo ( una volta settato il MAC) non funziona nulla, dal browser non vedo nulla mi dice impossibile trovare il server, e il tx non lampeggia e non ho scambi

Come posso risolvere?
Grazie mille a tutti :slight_smile:

Ho provato questo sketch e funziona.
Lo hai collegato al pc diretto, passi da uno switch, un router?
Sicuro che l'ip impostato appartenga allo stesso gruppo della tua rete?
{192, 168, 1, xxx};

ciao

l'ho collegato diretto al mio pc portatile. Il computer l'ho messo con il wi fi spento, e non è connesso a internet.
da windows mi dice che la rete è settata male, ma questo discorso me lo fa anche su altri pc.
La porta è sempre 80 e l'ip ho lasciato quello perchè non avendo connessioni non vedo come non possa funzionare
mmi sembra strano che l'aurduino non trasmetta nulla...

Si ma bisogna strapparti le parole....
Usi un cavo cross?

devi assegnare l'ip alla tua scheda di rete (del pc alla voce tcp/ip proprietà) ad esempio 192.168.1.100 subnet 255.255.255.0 gateway e DNS puoi tralasciarli e non rileva automaticamente l'ip.

l'importante è che la sottorete sia la stessa
192.168.1.xxx pc
192.168.1.xxx arduino

certo che se tu collegassi arduino al router del tuo gestore di rete e telefonia sarebbe più semplice

Scusa, cercherò di essere più preciso, se ti servono altre info chiedimi pure
Si ho usato un cavo cross, che ho testato e so di per certo che funziona
Ho prvato diversi ip e diverse porte, nulla da fare

Ho letto ora la modifica
Ora provo a modificare e mettere l'ip statico e ti dico
Non lo posso fare in rete poichè nella mia scuola durante la maturità la rete non funzionerà e mi mandarebbe tutto all'aria
Grazie

Sullo sketch lascia quello che c'era prima, sono le impostazioni della scheda di rete del tuo pc da cambiare , come ti ho scritto prima

Allora, ho fatto come hai detto ed ora funziona.
Il problema che ho ora è sulla SD, poichè non riesco a visualizzare un file html dalla scheda
è possibile prendere i dati dai sensori, salvare i parametri in un file txt e visualizzarli sul sito presente sulla sd? c'è una via più veloce? Grazie per l'aiuto
mi sto basando su questo sketch che ho trovato

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

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,1, 127 };
File htmlFile;
EthernetServer server(80);



void setup () 
{
  
  Ethernet.begin(mac, ip);
  server.begin();
  if (!SD.begin(4)) { return; }
  
  Serial.begin(9600);
  
}



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("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();
  }
}

Pure a me funziona lo sketch, prova con un cavo incrociato collegato direttamente al PC senza passare per lo switch..

Ora mi funziona.... Vorrei prendere tutti i dati relativi ai sensori ( le temp che rilevano etc) e salvarli in un txt, e poi con un sito html messo sulla SD visualizzarli.. inoltre vorrei poter accendere ogni led utilizzando un pulsante html, è possibile farlo? ho guardato i file esempio datalogger e tutti gli altri ma non sono riuscito
Grazie per la disponibilità

Questo non usa la SD però forse può aiutarti...

#include <SPI.h>
#include <Ethernet.h>
//Funzioni Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 0, 2 };	         
Server server(80);                                 
int ledPin = 2;  
String readString = String(30); 
boolean LEDON = false; 

//Funzioni per la misura della temperatura
void termometro();
#define LM35_TEMP 3
#define LM35_REF 2 
double temperatura;



void setup(){
  Ethernet.begin(mac, ip);
  pinMode(ledPin, OUTPUT);  
}


void loop(){
Client client = server.available();
  if (client) {
    while (client.connected()) {
   if (client.available()) {
    char c = client.read();
    if (readString.length() < 30) 
      {
        readString +=c;
      }  
          if (c == '\n') {          
  if(readString.startsWith("L=LED_ON", 6))
           {
             digitalWrite(ledPin, HIGH); 
             LEDON = true;
           }else{
             digitalWrite(ledPin, LOW);
             LEDON = false;             
           }           
          client.println("HTTP/1.1 200 OK");
          client.println("META HTTP-EQUIV=REFRESH CONTENT =5");
          client.println();
          client.print("<body style=background-color:#F5F5F5>");
          client.println("<font color='red'><h1>Piccolo esempio di web server in rete locale</font></h1>");
          client.println("<hr />");
          client.println("<font color='blue' size='5'>Temperatura attuale del laboratorio: ");        
          termometro();
          client.print(temperatura);
          client.println("<form><input type=submit value=AGGIORNA ></form>"); 
          client.println("<hr />");
          client.println("<font color='blue' size='5'>Laboratorio di Sistemi Informatici ed Elettronica/Telecomunicazioni"); 
          client.println("
");           
          client.println("<hr />");
          client.println("<form><input type=submit name=L value=LED_ON> </form>");                       
          client.println("<hr />");
          client.println("<form><input type=submit name=L value=LED_OFF ></form>");                       
          client.println("<hr />");   
          client.print("<font size='5'>Stato LED: ");
          if (LEDON)
              client.println("<font color='green' size='5'>ON"); 
          else
              client.println("<font color='red' size='5'>OFF"); 
          client.print("<hr /><font color='black' size='4'><p>Questa pagina e' stata creata in HTML usando i Form, risiede in web server minimale basato sull' integrato W5100,");
          client.print("e' gestita da una (MCU micro controller unit) sostanzilmente micro computer programmato in C, ATmega 328P-PU (Pico-Power-Unit)..a risparmio energetico");
          client.println("</body></html>");
          readString="";
          client.stop();
            }
          }
       }
    }
 }     



void termometro(){
  int cont,ref,sensoreTemperatura;
  int ref_medio = 0; 
  int sensoreTemperatura_medio = 0; 
  float prev_temperatura = 0; 
  
  for( cont = 0; cont < 10; cont++)
  {
    sensoreTemperatura = analogRead(LM35_TEMP); 
    sensoreTemperatura_medio += sensoreTemperatura;
    ref = analogRead(LM35_REF);
    ref_medio += ref; 
    delay(50);
  } 
  if(cont == 10)
  {
    cont = 0;
    sensoreTemperatura_medio = sensoreTemperatura_medio / 10;
    ref_medio = ref_medio / 10;
    temperatura = (sensoreTemperatura_medio - ref_medio) * 100/2.56;
    temperatura = temperatura * 5/1024;
    prev_temperatura = temperatura; 
    sensoreTemperatura_medio = 0;
    ref_medio = 0;
  }
  else{
    temperatura = prev_temperatura;
  }
}

Grazie per l'aiuto,
Però da quello che vedo il sito è nella Flash di arduino, e quando inserisco l'ip nel browser mi da tutte le misure. Invece io vorrei fare lo stesso ma con un sito caricato da SD, ma non so come fare comunicare il sito con le variabili del codice di arduino... inoltre devo poter accendere dei led con un pulsante o un collegamento ipertestuale in html ( sempre nel sito presente sulla SD)
Grazie ancora

Devi usare il tiny web server di ovidou o qualcosa di simile, provai ad usarla tempo fà però non mi è mai funzionata la libreria che gestisce la SD..

Allora, con tiny non mi funziona nulla... Ho guardato veramente ogni sorta di topic di questo forum, ma mi trovo ora a riuscire ad aprire il file index.htm da SD, ma non riesco ad aprire altri file htm presenti sulla scheda dai link ipertestuali che ho messo nella pagina html. Qualche idea? inoltre per i led l'unico modo che ho trovato è usare il GET e POST, ma funzionano anche solo con le normali librerie?
Grazie ancora

icarus93:
Allora, con tiny non mi funziona nulla... Ho guardato veramente ogni sorta di topic di questo forum, ma mi trovo ora a riuscire ad aprire il file index.htm da SD

La libreria tiny funziona benissimo sia con la 0022-23 (ormai abbandonate) che con la 1.0, non spieghi però che cosa hai provato, che IDE usi, che errori hai nell'usarla, che post hai letto, che browser usi perchè ad esempio la tiny funziona solo con firefox.
Puoi anche vedere la webduino.h che è molto simile.

icarus93:
inoltre per i led l'unico modo che ho trovato è usare il GET e POST, ma funzionano anche solo con le normali librerie?

Si funziona anche con le normali librerie, il princio di funzionamento delle librerie webduino, tinywebserver è quello di fare il parsing dettagliato delle richieste del client e/o delle sue risposte, analizzano anche il Path (quello che vai a scrivere nel link HTTP://.......
Analizzando i messaggi puoi riconoscere se sono GET, POST, le authentication, i file richiesti, ecc. Non tutte le librerie che trovi lo fanno in automatico, lo devi fare tu a mano.

ciao

uso la 1.0 e ora provo con firefox, prima ho usato IE 9 e Chrome.
Ma se io ho un sito index.htm da SD posso prendere i dati delle variabili che ho nello sketch e visualizzarli nel sito presente su SD o devo usare l'html direttamente nel codice sketch? non so se mi sono espresso bene
Quello che voglio alla fine è un sito caricato su scheda SD con pulsanti che mi facciano cambiare i valori delle variabili ( quindi accendere i led) e delle textbox che mi dicono la temperature dai sensori vari
è fattibile?
grazie mille ancora

Certo che si può fare, con quella libreria che tra l'altro è stata corretta per la 1.0 puoi fare tutto quello che vuoi. Restano solo i limiti di velocità di arduino quindi non dargli files troppo pesanti da caricare. Se vuoi utilizzare altri browser devi usare nel js il json invece che ajax.
Quindi ti consiglio di far girare l'esempio originale e poi andare a modificarlo cercando di capire come funziona, tutto questo se hai un po' di esperienza js e html altrimenti ti butti in una cosa molto complicata.

ciao

Allora, con questo sketch

// -*- c++ -*-
//
// Copyright 2010 Ovidiu Predescu <ovidiu@gmail.com>
// Date: December 2010
//

#include <SPI.h>
#include <Ethernet.h>
#include <Flash.h>
#include <SdFat.h>
#include <SdFatUtil.h>
#include <TinyWebServer.h>
#include <SD.h>

// The LED attached in PIN 13 on an Arduino board.
const int ledPin = 7;

// The initial state of the LED
int ledState = LOW;

void setLedEnabled(boolean state) {
  ledState = state;
  digitalWrite(ledPin, ledState);
}

inline boolean getLedState() { return ledState; }

boolean file_handler(TinyWebServer& web_server);
boolean blink_led_handler(TinyWebServer& web_server);
boolean led_status_handler(TinyWebServer& web_server);
boolean index_handler(TinyWebServer& web_server);

TinyWebServer::PathHandler handlers[] = {
  // Work around Arduino's IDE preprocessor bug in handling /* inside
  // strings.
  //
  // `put_handler' is defined in TinyWebServer
  {"/", TinyWebServer::GET, &index_handler },
  {"/upload/" "*", TinyWebServer::PUT, &TinyWebPutHandler::put_handler },
  {"/blinkled", TinyWebServer::POST, &blink_led_handler },
  {"/ledstatus" "*", TinyWebServer::GET, &led_status_handler },
  {"/" "*", TinyWebServer::GET, &file_handler },
  {NULL},
};

const char* headers[] = {
  "Content-Length",
  NULL
};

TinyWebServer web = TinyWebServer(handlers, headers);

boolean has_filesystem = true;
Sd2Card card;
SdVolume volume;
SdFile root;
SdFile file;

static uint8_t mac[] = { 0x90, 0xA2, 0xDA, 0x00, 0x8B, 0xD2 };

// Don't forget to modify the IP to an available one on your home network
byte ip[]  = { 192,168,1,115 };                  // IP-Adresse

void send_file_name(TinyWebServer& web_server, const char* filename) {
  if (!filename) {
    web_server.send_error_code(404);
    web_server << F("Could not parse URL");
  } else {
    TinyWebServer::MimeType mime_type
      = TinyWebServer::get_mime_type_from_filename(filename);
    web_server.send_error_code(200);
    web_server.send_content_type(mime_type);
    web_server.end_headers();
    if (file.open(&root, filename, O_READ)) {
      Serial << F("Read file "); Serial.println(filename);
      web_server.send_file(file);
      file.close();
    } else {
      web_server << F("Could not find file: ") << filename << "\n";
    }
  }
}

boolean file_handler(TinyWebServer& web_server) {
  char* filename = TinyWebServer::get_file_from_path(web_server.get_path());
  send_file_name(web_server, filename);
  free(filename);
  return true;
}

boolean blink_led_handler(TinyWebServer& web_server) {
  web_server.send_error_code(200);
  web_server.send_content_type("text/plain");
  web_server.end_headers();
  // Reverse the state of the LED.
  setLedEnabled(!getLedState());
  Client& client = web_server.get_client();
  if (client.available()) {
    char ch = (char)client.read();
    if (ch == '0') {
      setLedEnabled(false);
    } else if (ch == '1') {
      setLedEnabled(true);
    }
  }
}

boolean led_status_handler(TinyWebServer& web_server) {
  web_server.send_error_code(200);
  web_server.send_content_type("text/plain");
  web_server.end_headers();
  Client& client = web_server.get_client();
  client.println(getLedState(), DEC);
}

boolean index_handler(TinyWebServer& web_server) {
  send_file_name(web_server, "index.htm");
  return true;
}

void file_uploader_handler(TinyWebServer& web_server,
			    TinyWebPutHandler::PutAction action,
			    char* buffer, int size) {
  static uint32_t start_time;
  static uint32_t total_size;

  switch (action) {
  case TinyWebPutHandler::START:
    start_time = millis();
    total_size = 0;
    if (!file.isOpen()) {
      // File is not opened, create it. First obtain the desired name
      // from the request path.
      char* fname = web_server.get_file_from_path(web_server.get_path());
      if (fname) {
	 Serial << F("Creating ") << fname << "\n";
	 file.open(&root, fname, O_CREAT | O_WRITE | O_TRUNC);
	 free(fname);
      }
    }
    break;

  case TinyWebPutHandler::WRITE:
    if (file.isOpen()) {
      file.write(buffer, size);
      total_size += size;
    }
    break;

  case TinyWebPutHandler::END:
    file.sync();
    Serial << F("Wrote ") << file.fileSize() << F(" bytes in ")
	    << millis() - start_time << F(" millis (received ")
           << total_size << F(" bytes)\n");
    file.close();
  }
}

void setup() {
  Serial.begin(115200);
  Serial << F("Free RAM: ") << FreeRam() << "\n";

  pinMode(ledPin, OUTPUT);
  setLedEnabled(false);

  // initialize the SD card
  Serial << F("Setting up SD card...\n");
  pinMode(10, OUTPUT); // set the SS pin as an output (necessary!)
  digitalWrite(10, HIGH); // but turn off the W5100 chip!
  if (!card.init(SPI_FULL_SPEED, 4)) {
    Serial << F("card failed\n");
    has_filesystem = false;
  }
  // initialize a FAT volume
  if (!volume.init(&card)) {
    Serial << F("vol.init failed!\n");
    has_filesystem = false;
  }
  if (!root.openRoot(&volume)) {
    Serial << F("openRoot failed");
    has_filesystem = false;
  }

  if (has_filesystem) {
    // Assign our function to `upload_handler_fn'.
    TinyWebPutHandler::put_handler_fn = file_uploader_handler;
  }

  Serial << F("Setting up the Ethernet card...\n");
  Ethernet.begin(mac, ip);

  // Start the web server.
  Serial << F("Web server starting...\n");
  web.begin();

  Serial << F("Ready to accept HTTP requests.\n");
}

void loop() {
  if (has_filesystem) {
    web.process();
  }
}

che ho trovato qui in un 3d sul forum, non riesco a compilarlo, mi dice che la libreria SDfat.h non è presente( no such file or directory) quando invece è presente nella cartella di librerie di arduino... come posso fare? devo per forza usare il tiny per fare quello che mi serve? perchè siccome devo finire il lavoro entro domani mattina preferirei utilizzare qualcosa di più semplice che so già
Grazie

infatti non si usa più quella lib per la SD quello sketch non è .ino
qui trovi i file per la 1.0 https://github.com/Hardcore-fs/TinyWebServer/zipball/master

impossibile finire per domani, non trovi pezzi già fatti con pulsanti come vuoi tu su questo tipo di lib, c'è pochissimo in giro proprio perchè ci vuole molto tempo per comprendere e modificarle
guarda anche questo treath però è sulla vecchia IDE
http://arduino.cc/forum/index.php/topic,63747.0.html

Ho usato quella, ho fatto una prova con il file Blinked, però mi dice che non può trovare il file html quando clicco nel link... io ho messo una pagina html chiamata form.html nella SD e nel file index ho messo un link che dovrebbe aprirmi il form.html ( classico con href) ... devo metterlo in qualche luogo specifico?

La SD va formattata in fat16, i file hanno estensioni a 3 lettere essendo in fat 16 .... quindi si deve chiamare xxxxxx.htm e i nomi dei file non devono superare gli 8 caratteri, non sei su win 7 :slight_smile: