Reliability Test: Seeduino Ethernet UDP

Written by  on April 30, 2014 

* A log of reliability tests and subsequent findings when working with the Seeduino Ethernet *

————————–
Hardware:
Seeduino Ethernet V1.0
Uart Sbee V4.0 (note it says 4.0 on the board but the most recent Seeed wiki is for v3.1. Still worked for me)
Grove Base Shield v1.3
Grove 3-Axis Digital Accelerometer(±16g) ADLX345 v1.2b – connected via i2c
24 x Grove Chainable RGB LED v1.0 – connected on digital pins 2 and 3 (d2 socket on Grove)
NOTE: I had two power sources to the seeduino during these tests – an external 9v power supply and the FTDI connection which supplied power over USB. Due to the 24 LEDs When I disconnected the FTDI and was only powering the seeduino via the 9v it got incredibly hot and I had to disconnect it. Any longer and I’m sure I would have melted something. I would reccomend a smaller qty of LEDs or a different power arrangement if you are going to try this at home. You just can’t pull too much current (aprox 700ma at 5v) through the seeduino board.

—————————

Programming the Seeduino Ethernet:
As the Seeduino Ethernet has no usb port you need to use an external USB>FTDI programmer to send sketches to it. I’m using the Uart Sbee.
An overview of connecting the Sbee can be found here.
Install the drivers from here so that when you connect the Sbee it appears as a serial port.
On Win7 open Device Manager and look under Ports (COM & LPT). The interface will appear as USB Serial Interface (Com#). Note the Com number.
In the Arduino IDE select Tools > board > Duemilanove,
There will be a new entry in the tools menu for processor. Select Tools > Processor > Atmega328.
Finally go to Tools > Port and select the com port that corresponds to your FTDI interface.
After that it should work like a regular Uno for programming purposes. The serial monitor will also work as normal.

————————–

Test A – First thing I’m going to do is make sure the Seeduino works fine doing ‘normal’ Uno activities before I even try the ethernet port.
I’m running the last test sketch that I used with my Uno for these peripherals (LEDs + ADXL345)



// Acc declarations
#include <Wire.h>
#include <ADXL345.h>


// RGB declarations
#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long int
#define NUM_LEDS  24 
int Clkpin = 2;
int Datapin = 3;
int i = 1;
byte q = 1; 

ADXL345 adxl; //variable adxl is an instance of the ADXL345 library


// Debug declarations
long runcount = 0;

// Clock function (RGB) 
void ClkProduce(void) {
  digitalWrite(Clkpin, LOW);
  delayMicroseconds(20);
  digitalWrite(Clkpin, HIGH);
  delayMicroseconds(20);   
}

// 32 bits zero (initialization and update function (RGB)
void Send32Zero(void) {
    unsigned char i;
    for (i=0; i<32; i++) {
          digitalWrite(Datapin, LOW);
          ClkProduce();
    }
}

// Calibration bits function (RGB) 
uint8 TakeAntiCode(uint8 dat) {
    uint8 tmp = 0;
    if ((dat & 0x80) == 0) {
        tmp |= 0x02;
    }
    if ((dat & 0x40) == 0) {
        tmp |= 0x01;
    }
    return tmp;
}
 
// Gray scale data function (RGB) 
void DatSend(uint32 dx) {
    uint8 i;
    for (i=0; i<32; i++) {
        if ((dx & 0x80000000) != 0) {
               digitalWrite(Datapin, HIGH);
        }
        else {
               digitalWrite(Datapin, LOW);
        }
        dx <<= 1;
        ClkProduce();
    }
}
 
// data processing function (RGB) 
void DataDealWithAndSend(uint8 r, uint8 g, uint8 b)
{
    uint32 dx = 0;
 
    dx |= (uint32)0x03 << 30;  // highest two bits 1,flag bits
    dx |= (uint32)TakeAntiCode(b) << 28;
    dx |= (uint32)TakeAntiCode(g) << 26;    
    dx |= (uint32)TakeAntiCode(r) << 24;
 
    dx |= (uint32)b << 16;
    dx |= (uint32)g << 8;
    dx |= r;
 
    DatSend(dx);
}
 
void setup()  {
  //debug setup
  Serial.begin(19200);
  
  //RGB setup
  pinMode(Datapin, OUTPUT);
  pinMode(Clkpin, OUTPUT);
  
  //rest is Acc setup
  //acc setup 
  adxl.powerOn();

  //set activity/ inactivity thresholds (0-255)
  adxl.setActivityThreshold(75); //62.5mg per increment
  adxl.setInactivityThreshold(75); //62.5mg per increment
  adxl.setTimeInactivity(10); // how many seconds of no activity is inactive?
 
  //look of activity movement on this axes - 1 == on; 0 == off 
  adxl.setActivityX(1);
  adxl.setActivityY(1);
  adxl.setActivityZ(1);
 
  //look of inactivity movement on this axes - 1 == on; 0 == off
  adxl.setInactivityX(1);
  adxl.setInactivityY(1);
  adxl.setInactivityZ(1);
 
  //look of tap movement on this axes - 1 == on; 0 == off
  adxl.setTapDetectionOnX(0);
  adxl.setTapDetectionOnY(0);
  adxl.setTapDetectionOnZ(1);
 
  //set values for what is a tap, and what is a double tap (0-255)
  adxl.setTapThreshold(50); //62.5mg per increment
  adxl.setTapDuration(15); //625us per increment
  adxl.setDoubleTapLatency(80); //1.25ms per increment
  adxl.setDoubleTapWindow(200); //1.25ms per increment
 
  //set values for what is considered freefall (0-255)
  adxl.setFreeFallThreshold(7); //(5 - 9) recommended - 62.5mg per increment
  adxl.setFreeFallDuration(45); //(20 - 70) recommended - 5ms per increment
 
  //setting all interrupts to take place on int pin 1
  //I had issues with int pin 2, was unable to reset it
  adxl.setInterruptMapping( ADXL345_INT_SINGLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_DOUBLE_TAP_BIT,   ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_FREE_FALL_BIT,    ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_ACTIVITY_BIT,     ADXL345_INT1_PIN );
  adxl.setInterruptMapping( ADXL345_INT_INACTIVITY_BIT,   ADXL345_INT1_PIN );
 
  //register interrupt actions - 1 == on; 0 == off  
  adxl.setInterrupt( ADXL345_INT_SINGLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_DOUBLE_TAP_BIT, 1);
  adxl.setInterrupt( ADXL345_INT_FREE_FALL_BIT,  1);
  adxl.setInterrupt( ADXL345_INT_ACTIVITY_BIT,   1);
  adxl.setInterrupt( ADXL345_INT_INACTIVITY_BIT, 1);
}
 
void loop()  {

  //acc actions
	int x,y,z;  
	adxl.readXYZ(&x, &y, &z); //read the accelerometer values and store them in variables  x,y,z
	// Output x,y,z values 
	Serial.print("values of X , Y , Z: ");
	Serial.print(x);
	Serial.print(" , ");
	Serial.print(y);
	Serial.print(" , ");
	Serial.println(z);
	
	double xyz[3];
	double ax,ay,az;
	adxl.getAcceleration(xyz);
	ax = xyz[0];
	ay = xyz[1];
	az = xyz[2];
	Serial.print("X=");
	Serial.print(ax);
    Serial.println(" g");
	Serial.print("Y=");
	Serial.print(ay);
    Serial.println(" g");
	Serial.print("Z=");
	Serial.println(az);
    Serial.println(" g");
	Serial.println("**********************");

  
  // debug
  runcount = runcount ++; 
  Serial.print("Runcount = ");
  Serial.println(runcount);
  
  //rgb 
       
      if (i > 256) q = -1; 
      if (i < 0) q = 1;
      i = i + q; 
      Serial.println(i);
       
      Send32Zero(); // Initialization
      
      for (byte n = 0; n<NUM_LEDS; n++){
      DataDealWithAndSend(i, 0, 0); 
      }
      
      Send32Zero();  // Update datas 
    
    
    // all hail the delay
    delay(10);
      

}

– Results 1
It works well, seems stable and judging by the serial monitor it gives me the impression of running faster. Possibly not though. Chainable leds appear to all be in perfect sync.

QUESTION: Is the Seeduino Ethernet faster than an Uno? chip is Atmega328p vs Atmega328. I thought the only real difference was that one was replacable and one wasn’t. My impresssion was that performance should be pretty much the same. Hmm, look into it.

Working fine to 5000 runcount. Aprox 5 minutes.

– Results 2
Ran fine for 24 minutes, 18000 runcount.

==== Conclusion ====
Seeduino ethernet handles arduino uno programming as it should. It’s reliable for at least a 30 min period.

———————-

Test B – Let’s test the UDP functionality. Had problems with sending packets at fast intervals to wifi shield so check to see what happens here.
The sketch is the ethernet version of the UDP call/response one used back in the wifi shield tests. Modified to give me a runcount.
Using a vvvv patch to send the packets.

/*
  
  Reliability testing sketch for Seeeduino ethernet. 
   Added runcount and some setup status messages printing to serial
  
  Based on UDPSendReceive.pde:
   by Michael Margolis
   
  

 */


#include <SPI.h>         // needed for Arduino versions later than 0018
#include <Ethernet.h>
#include <EthernetUdp.h>         // UDP library from: bjoern@cs.stanford.edu 12/30/2008

long runcount = 0; 

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
};
IPAddress ip(192, 168, 1, 204);

unsigned int localPort = 8888;      // local port to listen on

// buffers for receiving and sending data
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //buffer to hold incoming packet,
char  ReplyBuffer[] = "acknowledged";       // a string to send back

// An EthernetUDP instance to let us send and receive packets over UDP
EthernetUDP Udp;

void setup() {
  
   Serial.begin(9600);
  // start the Ethernet and UDP:
  Serial.println("Beginning ethernet");
  Ethernet.begin(mac, ip);
  Serial.println("Ethernet begun");
  Serial.println("Beginning UDP");
  Udp.begin(localPort);
  Serial.println("UDP Begun");


 
}

void loop() {
  // if there's data available, read a packet
  runcount = runcount ++;
  Serial.print("Runcount = ");
  Serial.println(runcount);
  
  int packetSize = Udp.parsePacket();
  if (packetSize)
  {
    Serial.print("Received packet of size ");
    Serial.println(packetSize);
    Serial.print("From ");
    IPAddress remote = Udp.remoteIP();
    for (int i = 0; i < 4; i++)
    {
      Serial.print(remote[i], DEC);
      if (i < 3)
      {
        Serial.print(".");
      }
    }
    Serial.print(", port ");
    Serial.println(Udp.remotePort());

    // read the packet into packetBufffer
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE);
    Serial.println("Contents:");
    Serial.println(packetBuffer);

    // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
    Udp.write(ReplyBuffer);
    Udp.endPacket();
  }
  delay(10);
}

– Results 1
Sending a packet every 0.25s, seems stable. Wireshark sees response packet but vvvv doesn’t. Something to do with port numbers? Need to close before receiving? Didn’t think that applied to UDP. At least it’s stable.
Another issue I had with the wifi shield was it would never receive packets if any arrived while the unit was resetting. No such issue here.

NOTE: if vvvv sends a packet every frame they queue up, so when you stay stop sending a bunch still sit in the pipe and send. Could cause problems. 0.1 sec seems to be roughly the fastest. Something to do with the computer or vvvv though, appears from serial monitor the arduino has spare cycles to tackle more data.

– Results 2
Sending a packet every 0.1 sec, 5 bytes.
Still working after 4 hours, 85000 plus runcount.

– Results 3
Sending a larger packet, 1000 bytes, every 0.1 second.
Seems to be stable but data is being truncated when displayed, presumably limited by the UDP buffer size. Looking at the software that seems to be limited in the ethernet udp library. (UDP_TX_PACKET_MAX_SIZE)
Also seems to have slowed down, still running several times a second but def some lag.

LEARNING THE HARD WAY: Did some research on the max UDP packet size with Arduino ethernet udp library.
By default it is 24 bytes. However you can raise it. See here http://forum.arduino.cc/index.php/topic,103502.0.html

– Results 4
Medium packet size, 50 byres, every 0.1s
Still displays only 24 bytes but much faster. The 1000 bytes were slowing it down even though it wasn’t accepting the whole lot.

LEARNING THE HARD WAY: Be aware that sending large packets to the Seeduino Ethernet (and possibly Uno + Ethernet Shield) will slow it down even though it will only process the first 24 bytes (or max buffer size)

==== Conclusion ====
Seeduino ethernet seems to have reliable and robust udp receive operation, at least with simple example sketches. At least 4 hours+ stability on one test. Bear in mind buffer size is limited by default.

What next: Let’s see how the Seeduino Ethernet goes talking to the ADXL accelerometer, the LEDs and sending/receiving via UDP. Check it out here.