Reliability Test: Seeduino Ethernet UDP + Grove Accelerometer(±16g) ADXL345r + Grove Chainable RGB LED

Written by  on April 30, 2014 

* A log of reliability tests and subsequent findings when working with the Seeduino Ethernet, Grove ADXL345 Accelerometer and Grove Chainable RGB LEDs *

————————–
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.

—————————

Test A: Send the ADXL accelerometer data over Ethernet to a computer. Test reliability.

Each UDP packet consists of X, Y and Z each sent as a 4 byte float, followed by a lowecase “x” (Ascii Hex 78) for a total of 13 bytes.

QUESTION: How do you implement checksums? Or does the arduino UDP stack already do this? Does the windows UDP stack do it?

LEARNING THE HARD WAY: Need to declare destination ip and port in this sketch. All the UDP demos this is based on use udp.remoteip() as the destination, which will return the ip of the last INCOMING connection. This is only useful if there was an incoming packet to start with and you want to send back to that address. Not useful if you are setting up a send only sketch. The best way to define a port is using the ipaddress object, eg
At Declaration:
IPAddress destinationip(192, 168, 1, 201); //remote address
unsigned int destinationPort = 4444; //remote port
In the Loop:
Udp.beginPacket(destinationip, destinationPort);

NOTE TO SELF: The example code under the arduino.cc reference pages at EthernetUDPBeginPacket and EthernetUDPWrite confusingly uses udp.remoteIP() as the send address and udp.remotePort() as the send port. This would be appropriate for an echo sketch where you would talk back to someone who talked to you first. It is weird in the context of a sketch that only sends, as it would make more sense to define an arbitrary destination.

QUESTION: It would be good if destination IP could be set remotely, other than by an echo method. Is there a way to use bonjour or something clever to discover dynamically?

LEARNING THE HARD WAY: For both the serial and client (TCP) libraries there is a .print() function that takes care of converting values for transmission as ASCII chars. UDP library only comes with a .write() function which only takes bytes or chars. It won’t convert values. In any case we don’t want to waste time spelling out the whole value as chars like .print() does. If the data is a 4 byte float we only want to send 4 bytes. So we need a way to convert in Arduino from values (floats, doubles etc) to their raw bytes for transmission.
The best way I’ve found is here http://forum.arduino.cc/index.php?topic=112597.0
Basically you create a ‘union’ where the float and byte array reference the same memory. This union is then an object that needs to be instanced. This allows you to assign the float to the float part of the object, and then you can pull the bytes off the byte part of the same object. No messy converting. A float is just 4 bytes after all.
Like this:
At Declaration:
typedef union {
float floatingPoint;
byte binary[4];
} twowayFloat;

In the Loop:
twowayFloat fx; //create a twowayfloat called fx
fx.floatingPoint = 1.35; //set fx by accessing the floatingpoint part
Udp.beginPacket(destinationip, destinationPort);
Udp.write(fx.binary, 4); //recall fx by accessing the binary part
Udp.endPacket();

Sketch: ADXL_UDPSend_Test. Prints the acc data to serial AND sends it over ip.

/*
  
  Reliability testing sketch for Seeeduino ethernet. 
  Config: Grove ADXL345 on I2C bus, via Grove shield 1.3
    
  Uses code from:
  EthernetUDP examples by Michael Margolis. Included in Arduino IDE 1.5.6-r2
  ADXL345 examples from Seeed Studios.

 */

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

// ethernet includes
#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

// debug declares
long runcount = 0; 

// acc declares
ADXL345 adxl;
typedef union {
  float floatingPoint;
  byte binary[4];
} twowayFloat;

//ethernet declares
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
}; //don't know if this is actually its mac address.
IPAddress ip(192, 168, 1, 204); //local address 
unsigned int localPort = 8888; //local port 
IPAddress destinationip(192, 168, 1, 201); //remote address
unsigned int destinationPort = 4444;  //remote port 
// 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 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");

  //adxl start and calibrate
 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() {
  //debug
  runcount = runcount ++;
  Serial.print("Runcount = ");
  Serial.print(runcount);
  
  //acc 
  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.print(" g");
	Serial.print(" Y=");
	Serial.print(ay);
    Serial.print(" g");
	Serial.print(" Z=");
	Serial.println(az);
    Serial.print(" g");
	//Serial.println("**********************");

  /* receiving UDP stuff, don't need it for this test. 
  
  int packetSize = Udp.parsePacket();
  if (packetSize) //if packetsize is greater than 0 evalutates to true
  {
    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);
    
  }
  */
  
    twowayFloat fx; 
    twowayFloat fy;
    twowayFloat fz;
    
    fx.floatingPoint = ax;
    fy.floatingPoint = ay;
    fz.floatingPoint = az;
  
     // send a reply, to the IP address and port that sent us the packet we received
    Udp.beginPacket(destinationip, destinationPort);
    Udp.write(fx.binary, 4);
    Udp.write(fy.binary, 4);
    Udp.write(fz.binary, 4);
    Udp.write("x"); //check byte
    Udp.endPacket();
    
  delay(10);
}


Results 1:
Moved the accelerometer around intermittently.
The sketch ran well for 20 minutes, runcount of 26500.
Good result.

Conclusion: Seeduino Ethernet with Grove ADXL345 sending UDP data over ethernet every 0.1 of a second is stable for at least 20 minutes.

———————————

Test B: Getting Seeduino Ethernet to do two things simultaneously:
1) Getting Grove ADXL345 Accelerometer data and sending it via UDP
2) Receiving UDP data and individually controlling 24 x Grove Chainable RGB LED.
I wrote a patch in vvvv to do the sending and receiving.
The protocol is:
Accelerometer (Arduino sending) protocol: One packet with 13 bytes via UDP.
The first 4 bytes are a float (Single?) of the current x acceleration value
The next 4 bytes are a float (Single?) of the current y acceleration value
The next 4 bytes are a float (Single?) of the current z acceleration value
The last (13th byte) is a verification byte, a lowercase “x” (ASCII Dec 120, Hex 78)

RGB Data (Arduino receiving) protocol: One packet with 74 bytes via UDP
The first byte is a verification start byte, a lowercase “a” (ASCII Dec 97, Hex 61)
The next 72 bytes are RGB Colour data, each byte is 0 – 255 controlling one colour
eg RGBRGBRGBRGBRGB etc….
The final (74th) byte is a vertication end byte, a lowercase z (ASCII Dec 120, Hex 7A)

LEARNING THE HARD WAY: I’ll have to increase the max packet size out to cover the 72 bytes required to send individual R, G and B values for each LED. To increase max UDP packet size beyond the default 24 bytes put this line in with the definitions
#define UDP_TX_PACKET_MAX_SIZE 90
. (see here http://forum.arduino.cc/index.php/topic,103502.0.html)

QUESTION: So is that method how you override constants from libraries? By just redefining them in the main sketch?

QUESTION: What if we want to print the incoming bytes as hex to the serial monitor? Bear in mind packetBuffer is an array of chars. Serial.println(packetBuffer); prints the first byte (‘a’) correctly but then the next 72 (which I know are values) come up as a couple of gibberish chars and then nothing, probably means Arduino is interpreting them as ASCII and interpreting a value as a carriage return or similar which stops the stream printing.
The solution to this one should be easy:
Serial.println(packetBuffer, HEX);
See here http://arduino.cc/en/Serial/Print.
However this doesn’t work. It seems specifying base doesn’t work when printing arrays. NOTE TO SELF: Ask arduino.cc to include this limitation on the print() reference page? It doesn’t say anything about how print treats arrays.

LEARNING THE HARD WAY: Once UDP bytes are received, how do we apply them to our RGB Leds? First thing we’re going to do is parse them to check the first and last bytes are the check bytes, using if statements.
We run into a problem with the Char array packetBuffer, In the loop, after the packetbuffer is filled, we ask
if (packetBuffer[0] = "a")
to verify that the first char in the buffer is ‘a’, however I get:
error: invalid conversion from 'const char*' to 'char'
After some research http://forum.arduino.cc/index.php/topic,208834.0.html. and http://stackoverflow.com/questions/2263681/c-compile-error-iso-c-forbids-comparison-between-pointer-and-integer
This one has a really dumb answer, a couple of simple things I’ve forgotten.
The types are correct (comparing a single char to a single char) but I’ve used the wrong operator. In the c language you use = to assign and == for a relational test.
a = b | ‘assign b’s value to a’
a == b | ‘does a equal b?’
There is one more issue. Double quotes indicate a string of chars, single quotes indicate a single char constant.
Original:
if (packetBuffer[0] = "a")
Correction:
if (packetBuffer[0] == 'a')

LEARNING THE HARD WAY: Another dumb problem. In trying to verify the last char in the packet using
if (packetBuffer[packetSize] == 'z')
where packetSize is the length of the packet and therefore should be the index of the last char in the packet. Except I’m
wrong. The first index is 0, not 1, therefore the last char’s index is (packetSize – 1)
Original:
if (packetBuffer[packetSize] == 'z')
Correction:
if (packetBuffer[(packetSize - 1)] == 'z')

LEARNING THE HARD WAY: More dumbness on my part. When using a for loop the increment statement is usually just x++ to increase by 1 each loop. If you want to do something else (like increase by 3) you need to put the full statement like this x = x + 3, not just x + 3
Original:
for (byte n = 0; n < 3; n + 3)
will compile but will create a neverending loop, with n remaining 0 forever.
Correction
for (byte n = 0; n < 3; n = n + 3)
will increase n by 3 each loop.

/*
  
  Reliability testing sketch for Seeeduino ethernet, sending and receing UDP.
  
  Config: 
  Grove ADXL345 on I2C bus, via Grove shield 1.3
  24 x Grove Chainable RGB LED in a single chain on digital pins 2 and 3
  
  Accelerometer (Arduino sending) protocol: One packet with 13 bytes via UDP. 
  The first 4 bytes are a float (Single?) of the current x acceleration value
  The next 4 bytes are a float (Single?) of the current y acceleration value
  The next 4 bytes are a float (Single?) of the current z acceleration value
  The last (13th byte) is a verification byte, a lowercase "x" (ASCII Dec 120, Hex 78)

  RGB Data (Arduino receiving) protocol: One packet with 74 bytes via UDP
  The first byte is a verification start byte, a lowercase "a" (ASCII Dec 97, Hex 61) 
  The next 72 bytes are RGB Colour data, each byte is 0 - 255 controlling one colour
  eg RGBRGBRGBRGBRGB etc.... 
  The final (74th) byte is a vertication end byte, a lowercase z (ASCII Dec 120, Hex 7A) 

   Uses code from:
  EthernetUDP examples by Michael Margolis. Included in Arduino IDE 1.5.6-r2
  Chainable RGB LED (non library) example version by Seeed Studios, found at 
http://www.evola.fr/en/chainable-rgb-led-p-163.html?osCsid=o8kfiok52urd5it8uoc6hfrq1l5h34a1
  ADXL345 examples from Seeed Studios.

 */

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

// ethernet includes and defines
#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
#define UDP_TX_PACKET_MAX_SIZE 90 //Overwrite UDP max packet size

//rgb defines
#define uint8 unsigned char
#define uint16 unsigned int
#define uint32 unsigned long int
#define NUM_LEDS  24 

// debug declares
long runcount = 0; 

// acc declares
ADXL345 adxl;
typedef union {
  float floatingPoint;
  byte binary[4];
} twowayFloat;

//ethernet declares
byte mac[] = {
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED
}; //don't know if this is actually its mac address.
IPAddress ip(192, 168, 1, 204); //local address 
unsigned int localPort = 8888; //local port 
IPAddress destinationip(192, 168, 1, 201); //remote address
unsigned int destinationPort = 4444;  //remote port 
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;

//rgb declares and functions
int Clkpin = 2;
int Datapin = 3;


// 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() {
  //serial setup
   Serial.begin(115200);
   
     //RGB setup
  pinMode(Datapin, OUTPUT);
  pinMode(Clkpin, OUTPUT);
   
  // 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");

  //adxl start and calibrate
 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() {
 
 //receive UDP packet
 int packetSize = Udp.parsePacket();
 Serial.print("Incoming Packetsize =");
 Serial.println(packetSize);
  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);
    
    // Debug, this prints the buffer in HEX but is pretty slow
    /*
    Serial.println("Contents:");
    for (int i = 0; i < packetSize; i++)
    {
      Serial.println(packetBuffer[i], HEX); // 
    }
    */ 
    
   // verify incoming packet has correct start and end bytes 
   if (packetBuffer[0] == 'a')
      {
        Serial.println("Start byte verified");
        if (packetBuffer[(packetSize - 1)] == 'z') 
           {
             Serial.println("Finish byte verified");
             
             // RGB set Data
              Send32Zero(); // Initialization
      
              for (byte n = 1; n < ((NUM_LEDS * 3) + 1); n = n+3){
              DataDealWithAndSend(packetBuffer[n], packetBuffer[n+1], packetBuffer[n+2]);
              // Note: n starts at 1 rather than 0 because we are skipping 
              // the first byte in the buffer, it's a check byte
               //Serial.print("N count = "); // Debug statement
               //Serial.println(n); //Debug statement
              }
              
              Send32Zero();  // Update datas 
              Serial.println("RGB LEDs set");
           }
       }
        

   }


    
    //acc
	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.print(" g");
	Serial.print(" Y=");
	Serial.print(ay);
    Serial.print(" g");
	Serial.print(" Z=");
	Serial.print(az);
    Serial.println(" g");
        
          // Sending acc stuff
    twowayFloat fx; 
    twowayFloat fy;
    twowayFloat fz;
    fx.floatingPoint = ax;
    fy.floatingPoint = ay;
    fz.floatingPoint = az;
 
    Udp.beginPacket(destinationip, destinationPort);
    Udp.write(fx.binary, 4);
    Udp.write(fy.binary, 4);
    Udp.write(fz.binary, 4);
    Udp.write("x"); //check byte
    Udp.endPacket();
    
    // all important delay
  delay(10);
  
   //debug
  runcount = runcount ++;
  Serial.print("Runcount = ");
  Serial.println(runcount);
  
}
     


Results 1:
Working reasonably well. But getting hot. Time to splice usb power supply in for LEDs. Remember 5v only!
Getting too hot for further testing, need to solve this power problem.

NOTE: The current draw of 24 RGB Grove LEDs is theoretically 480mA (at 20mA each, as listed here). I measures it at closer to 700mA with cables on full white.

What next:
Solving the power problem!