Pages: 1 2 3 [4] 5 6 ... 9   Go Down
Author Topic: Thumbs way down for Arduino WiFi shield. Read before you buy  (Read 21766 times)
0 Members and 1 Guest are viewing this topic.
Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks to PaulS, I will have a wifi shield arriving at the end of this week. Thanks, Paul. You do more than your share here on the forum.

The first code I plan on running is this. It is a firmware version check. I would like some input from those whose shields work, and those whose shields fail. Which version do you have and does it work?
Code:
#include <WiFi.h>

int status = WL_IDLE_STATUS;     // the Wifi radio's status

void setup() {
  //Initialize serial and wait for port to open:
  Serial.begin(9600);
  
  // check for the presence of the shield:
  if (WiFi.status() == WL_NO_SHIELD) {
    Serial.println(F("WiFi shield not present"));
    // don't continue:
    while(true);
  }

  // check firmware version
  Serial.print(F("Firmware version: "));
  Serial.println(WiFi.firmwareVersion());
}

void loop() {
}

edit: From another post here on the forum, that should return V1.1.0 if you have completed the firmware upgrade included with IDE v1.0.5.

« Last Edit: November 19, 2013, 08:36:40 am by SurferTim » Logged

Emsworth, UK
Offline Offline
Full Member
***
Karma: 8
Posts: 199
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote from: SurferTim
You correct about fast and loose. But I am working with very limited resources, so...
So.  You could respond with HTTP/1.0 and conform with the HTTP protocol standards using no more resources.  It takes more resource to conform with HTTP/1.1 and the protocol offers no benefits (I can think of) for low powered devices.

Quote
If the w5100 is sending smaller packets than it should, that would be in the firmware. The SD page uploads should load the tx buffer with 64 bytes, then send the w5100 an exec command to send that packet. ??
The single character packets are down to your use of println when you could be using write.

For a few days only, you can reach my Arduino Ethernet shield on
http://212.159.25.45
If you look at the response in Wireshark, you will see it arrives in a single packet.  I am short of time tonight but I will post the sketch tomorrow.

Great news on the WiFi Shield donation by the way.

I have two WiFi shields, both R3.
They worked OK with the firmware they shipped with and reported V1.0.0
They went flaky when I upgraded to the firmware development snapshot on Github and continued to report V1.0.0
They worked reliably again when I upgraded to the firmware in the Arduino master branch on Github but continued to report V1.0.0
They stopped working when I upgraded to Arduino IDE 1.0.5
They are working OK again since I upgraded them using the firmware files shipped with the IDE [edit] and they report V1.1.0

When I say, work OK, I mean they work within the limitations that they have.  Learning what those limitations are has taken me quite some time though.

« Last Edit: November 20, 2013, 01:52:20 am by MattS-UK » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The client.println() calls should not be sending single character packets. Only client.write(char) should do that. The client.write(char*,int) calls should send int number of characters (64 for my code) per packet (edit: except the last one if the file was not an even multiple of 64).

I will consider switching to HTTP/1.0 tho. That makes sense.

So you never show v1.1.0 on the wifi shield firmware?

edit: I tried you server. It works ok through the PuTTY test. It responds like zoomkat's code. It does not wait for the blank line, only the first line feed, and disregards the rest of the request.

I gotta know how you are servicing more than one socket at a time. Would you be ok with posting your server code?
edit: Never mind. I just found out by testing mine. I just learned something about the w5100 and ethernet library.
« Last Edit: November 19, 2013, 06:29:56 pm by SurferTim » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
For a few days only, you can reach my Arduino Ethernet shield on
http://xx.xx.xx.xx
Did you terminate your test early? Or did I get all your sockets? I can crash mine too.  smiley-sad
Logged

Emsworth, UK
Offline Offline
Full Member
***
Karma: 8
Posts: 199
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The client.println() calls should not be sending single character packets.

:smile:  Wireshark is your friend.  Whatever println should do, here is what it is doing.
Code:
//This is the result of a println()
    00000000  48                                               H
    00000001  54                                               T
    00000002  54                                               T
    00000003  50                                               P
    00000004  2f                                               /
    00000005  31                                               1
    00000006  2e                                               .
    00000007  31                                               1
//...snip...
//And this is what a write() looks like
    0000003F  3c 48 54 4d 4c 3e 0a 3c  48 45 41 44 3e 3c 6c 69 <HTML>.< HEAD><li
    0000004F  6e 6b 20 72 65 6c 3d 22  73 74 79 6c 65 73 68 65 nk rel=" styleshe
    0000005F  65 74 22 20 74 79 70 65  3d 22 74 65 78 74 2f 63 et" type ="text/c
    0000006F  73 73 22 20 68 72 65 66  3d 22 64 65 66 63 73 73 ss" href ="defcss
    0000007F  2e 63 73 73 22 3e 3c 2f  48 45 41 44 3e 0a 0a 3c .css"></ HEAD>..<
    //...snip

Quote
I will consider switching to HTTP/1.0 tho. That makes sense.
You would not be the first developer I had to try to explain HTTP version numbers to.  Outside of HTTP, version numbers typically refer to compatibility.  e.g. V2 may not be compatible with V1.  HTTP was designed to be inherently backwards compatible.  So a V1.1 request remains compatible with a V1.0 response.  HTTP/1.0, infers fewer expectations.  For instance, a server declaring a V1.0 response may still support pipelining but does not have to.  A server declaring a HTTP/1.1 response, should support pipelining.

Quote
So you never show v1.1.0 on the wifi shield firmware?
An oversight, corrected.   My shields are reporting V1.1.0 since the latest upgrade.  The latest firmware version is the most stable and complete, in my opinion.   People appear to be having issues upgrading and that appears to have created some myth and legend about earlier versions being better.  

The latest firmware version still has issues though.  The 2 second latency between transmit cycles  being the most serious, in my view.
http://mssystems.emscom.net/helpdesk/knowledgebase.php?article=51
I would love to have a crack at the WiFi shield's MCU firmware but would not know where to start with compiling and debugging.

Quote
edit: I tried you server. It works ok through the PuTTY test. It responds like zoomkat's code. It does not wait for the blank line, only the first line feed, and disregards the rest of the request.
My server is not really a server.  It's a couple house spend on a proof of concept.  The sketch started out as a simple client throughput test.  I added just enough server code to send a response to a browser.

Quote
I gotta know how you are servicing more than one socket at a time.
I didn't know I was!  This is the first time I have tried to do anything with the Ethernet shield and I am still trying to fathom the relationship between the library and the socket structures it is abstracting.  To be honest, I would be more comfortable working directly with the sockets.

Quote
Would you be ok with posting your server code?
edit: Never mind. I just found out by testing mine. I just learned something about the w5100 and ethernet library.
My sketch will be in the next post but the server code is non-existent.  Please do share what you know about the library.

« Last Edit: November 20, 2013, 03:03:47 am by MattS-UK » Logged

Emsworth, UK
Offline Offline
Full Member
***
Karma: 8
Posts: 199
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Sketch as promised.  
It is intended to be a demonstration of using Client.write() to avoid using Client.println().
It started as a throughput test with the sendData() function.  
Naturally progressed to utilising program memory to send HTML over HTTP.
Then I had a what the heck, can I send this to a browser moment.

Code:
#include <avr/pgmspace.h>
#include <stdio.h>
#include <stdlib.h>
#include <Streaming.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetClient.h>
#include <EthernetServer.h>
#include <Dns.h>
#include <Time.h>

byte mac[] = { 0x00, 0xAA, 0xBB, 0xCC, 0xDE, 0x02 };

//EthernetClient client;
EthernetServer server(80);

void setup()
{
Serial.begin(9600);
Serial << F("Setup...\r\n");

Ethernet.begin(mac);

IPAddress ip = Ethernet.localIP();

Serial << F("Arduino IP ");
for (uint8_t i =0; i <4; i++) {
Serial << ip[i] << ".";
}
Serial << "\r\n";

server.begin();
}

uint16_t responseCount = 0;
uint16_t timeoutCount = 0;
boolean idle;

void loop()
{
if (!idle) {
Serial << F("Responses ") << responseCount
<< F("\tTimeouts ") << timeoutCount
<< F("\tFree Ram ") << ramTest()
<< F("\r\nListening\r\n");
idle = true;
};

EthernetClient client = server.available();
if (client.connected()) {
idle = false;
char* page = getPageM(0);

uint16_t bytes = sendResponse(&client, 200, page);
Serial << "\r\nSent " <<  bytes << " bytes to host\r\n";
free(page);

boolean wait = true;
uint16_t startWait = millis();
do {
client.flush();
wait =(millis() - startWait) < 2000;
} while(client.connected() && wait);
client.stop();
responseCount++;
if (!wait) timeoutCount++;
}
}

char* getPageM(uint8_t pageNumber) {
char* page = NULL;

switch(pageNumber) {
case 0:
page = (char*) malloc(95);
sprintf_P(page,
(char*) F("<HTML><BODY><h1>Matt's Arduino</h1><p>Up Time %02d:%02d:%02d</p><p>Ram Free = %d</p></BODY></HTML>"),
hour(), minute(), second(),
ramTest()
);
}
return page;
}

uint16_t sendResponse(Client* client, uint16_t status, char* page) {
uint16_t sent = 0;
char* response = (char*) malloc(64);

switch (status) {
case 200:
sprintf_P(response,
(char*) F("http/1.1 %d OK\r\ncontent-length:%d\r\ncontent-type:text/html\r\nconnection:close\r\n\r\n"),
200,
strlen(page)
);
strcat(response, page);   //probably not safe!
break;
}
sent = client->write((byte*) response, strlen(response));

Serial << response;
free(response);
return sent;
}

uint16_t sendData (Client* client, uint16_t dataLen, uint8_t maxLoop ){

byte* data = NULL;
uint32_t bytesSent = 0;

data = (byte*) malloc(dataLen);
for (uint16_t i = 0; i < dataLen; i++) {
data[i] = 'A';
}

for (uint8_t l = 0; l < maxLoop; l++) {
bytesSent += client->write(data, dataLen);
}
free(data);
return bytesSent;
}

IPAddress hostByName(char* hostName) {
IPAddress hostIP;
DNSClient resolver;
resolver.begin(Ethernet.dnsServerIP());
resolver.getHostByName(hostName, hostIP);
return hostIP;
};

uint16_t ramTest() {

uint16_t freeRam = 0;
byte* buffer = NULL;

do {
buffer = (byte*) malloc(++freeRam);
if (buffer != NULL) {
free(buffer);
}
} while (buffer != NULL);

return freeRam + sizeof(byte*) + sizeof(uint16_t);
}
« Last Edit: November 20, 2013, 06:58:27 am by MattS-UK » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

@MattS-UK: Thanks for that update on client.println(). I had checked it before several IDE versions ago, and I am almost certain it was not breaking up the packets then. So you use client.write(char*) and it doesn't break up the packets into single bytes?

But that is not my big problem today. I can crash my server code. I must find a way to fix that.
http://forum.arduino.cc/index.php?topic=197103.0

edit: I tried client.write(char*) and it does not like the F() function. So I guess my choice is single character packets or run out of SRAM.  smiley-sad

Update on the client.write(char*).  It apparently does not move program memory strings into SRAM like client.print() does, at least that is the result of my preliminary tests. I use less SRAM with client.write(char*) than client.print(F(char*)). ??

BTW, thanks for your input. This is what I was looking for.  smiley
« Last Edit: November 20, 2013, 06:17:19 am by SurferTim » Logged

Emsworth, UK
Offline Offline
Full Member
***
Karma: 8
Posts: 199
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Ethernet Shield conversation moved
http://forum.arduino.cc/index.php?topic=197103.msg1475328#new
Reply #67
« Last Edit: November 20, 2013, 06:48:15 am by MattS-UK » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I read your code. I tried client.write(char*) compared to client.print(F(char*)) and found that the write uses less SRAM than the print. See the server thread. This part belongs there. I have been "thread hopping" (wish the Arduino could thread hop!).

Thanks for that!
Logged

Central MN, USA
Offline Offline
Tesla Member
***
Karma: 72
Posts: 7171
Phi_prompt, phi_interfaces, phi-2 shields, phi-panels
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The FLASH string helper F() uses String object to allocate memory so it takes more SRAM. The write(char*) simply calls write(char) repeatedly.
Logged


North Queensland, Australia
Offline Offline
Edison Member
*
Karma: 64
Posts: 2101
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The FLASH string helper F() uses String object to allocate memory so it takes more SRAM. The write(char*) simply calls write(char) repeatedly.

No it does not!

F(), uses PSTR
Code:
class __FlashStringHelper;
#define F(string_literal) (reinterpret_cast<const __FlashStringHelper *>(PSTR(string_literal)))

This writes byte by byte to 'write'.
Code:
size_t Print::print(const __FlashStringHelper *ifsh)
{
  const char PROGMEM *p = (const char PROGMEM *)ifsh;
  size_t n = 0;
  while (1) {
    unsigned char c = pgm_read_byte(p++);
    if (c == 0) break;
    n += write(c);
  }
  return n;
}
Logged


Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just an update. I received the wifi shield from PaulS yesterday. He does more than average for this forum. Thanks, PaulS!

I have a R2 Mega and a R3 wifi shield. For those not familiar with interfacing these two, you must jumper 5v to the IOREF pin, or the wifi shield will not respond, and the test code shows "wifi shield not present".

It is using firmware v1.0.0 as I suspected. However, I found this morning that I do not have a mini-usb cable to program the wifi shield with the new firmware. That will probably be Saturday before I can get one.

edit: I found a cable and updated the firmware to v1.1.0. It was not as easy as I thought it would be. It connected to my wifi network right away and got an ip. So far, so good.

Don't have time today, but will try a sketch or two tomorrow.
« Last Edit: November 22, 2013, 08:29:45 am by SurferTim » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

So much for 2 second delays between sends. My first try was my basic UDP packet send. I have it set to 48 byte packets at 10 packets per second, and it is doing fine!  smiley

Next will be TCP client.
Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I converted my playground web client sketch for the ethernet shield to wifi. It took only a few minutes and it is working fine.

BTW, all these are "Perfect World" sketches so far. I will move them to "Real World" (start torturing them and add fail recovery) when I determine they work ok.

Next is web server.

edit: I just finished converting my new web server code for the ethernet shield to the wifi shield. It works ok, but is a bit more sluggish than the ethernet shield. It takes about twice as long to download the images.

The email client code has been completed for a while.
« Last Edit: November 23, 2013, 07:21:34 am by SurferTim » Logged

Miramar Beach, Florida
Offline Offline
Faraday Member
**
Karma: 138
Posts: 5846
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I found a bug in the wifi library while using the tcp client sketch. If the wifi radio connection fails and the client code tries to make a client connection and it fails (which it will because the radio connection failed), the socket is not released. If that happens 4 times, you are out of sockets.

This will show the status of all the wifi sockets.
Code:
void ShowSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    Serial.print(F("Socket #"));
    Serial.print(x,DEC);
    if(WiFi._state[x] == -1) Serial.println(F(": available"));
    else Serial.println(F(": used"));
  }
}

FYI: If you disable the wifi router radio (my test), wait a bit, then turn it on again, the wifi shield reconnects to the radio without a problem. No need to reconnect manually. The only problem is the failed TCP connections depleting the sockets.

I am using this as a temporary "shotgun" patch. If the connection to the server fails, I call this to reset the sockets.
Code:
void SetSockStatus() {
  for(int x = 0; x < MAX_SOCK_NUM; x++) {
    WiFi._state[x] = -1;
  }
}
« Last Edit: November 23, 2013, 04:51:48 pm by SurferTim » Logged

Pages: 1 2 3 [4] 5 6 ... 9   Go Up
Jump to: