anchor.diff:  [NOTE]
   TODO: Replace with 'whitewashed' product picture?
   
  -I wrote and programmed custom firmware based on http://www.chibios.org/[ChibiOS 2.6.8] and http://savannah.nongnu.org/projects/lwip/[lwIP 1.4.1] to isolate the network stack. The relevant code pieces can be found https://gist.github.com/ennerf/36a57d432bcff20a58efcdee10f91bd9[here]. The elapsed time is measured using a hardware counter that was set to a 250ns resolution.
  -
  -Since storing multiple Gigabytes of data on an embedded device is challenging, I setup a https://gist.github.com/ennerf/0ddc4396d15852d28e4eca4a8a923eb7[UDP server (Java)] that receives measurement data and persists the data to disk. The main socket handler writes incoming packets into a double buffered structure that can be persisted by a background thread without halting the packet handler. The synchronization between the threads is done using a http://stuff-gil-says.blogspot.com/2014/11/writerreaderphaser-story-about-new.html[WriterReaderPhaser], which is a synchronization primitive that is very useful for persisting events that are represented by a small amount of data.
  +In order to isolate the network stack I wrote and programmed custom firmware based on http://www.chibios.org/[ChibiOS 2.6.8] and http://savannah.nongnu.org/projects/lwip/[lwIP 1.4.1]. The relevant code pieces can be found https://gist.github.com/ennerf/36a57d432bcff20a58efcdee10f91bd9[here]. The elapsed time was measured using a hardware counter with a resolution of 250ns. Since there was no way to store multiple Gigabytes of data on the devices, I needed a different solution for data logging.
  +
  +I decided store data remotely using a UDP service (see  https://gist.github.com/ennerf/0ddc4396d15852d28e4eca4a8a923eb7[code]) that can receive measurement data and persist to disk. To avoid stalling the main socket handler in disk I/O, I had it write into a double buffered structure that got persisted by a background thread. The synchronization between the threads was done using a http://stuff-gil-says.blogspot.com/2014/11/writerreaderphaser-story-about-new.html[WriterReaderPhaser], which is a synchronization primitive that is very useful for persisting events that are represented by small amounts of data. It allows readers to flip buffers while keeping writers wait-free.
  +
  +// Since storing multiple Gigabytes of data on an embedded device is challenging, I also setup a https://gist.github.com/ennerf/0ddc4396d15852d28e4eca4a8a923eb7[(Java) UDP server] that can receive measurement data and persist to disk. The main socket handler writes incoming packets into a double buffered structure that can be persisted by a background thread without halting the packet handler. The synchronization between the threads is done using a http://stuff-gil-says.blogspot.com/2014/11/writerreaderphaser-story-about-new.html[WriterReaderPhaser], which is a synchronization primitive that is very useful for persisting events that are represented by a small amount of data.
   
   // Alternatively: oscilloscope and logic analyzer
   
  -The resulting binary data was loaded into MATLAB(C) for analysis and to generate the plots. The code can be found https://gist.github.com/ennerf/19b48406a066f6e946a0567a1a4de1ed[here].
  -
  -== Ethernet Packet Structure
  +The step by step flow is as follows:
  +
  +1. Sender wakes up in fixed intervals
  +2. Sender measures time and sends packet to receiver
  +3. Receiver echoes packet back to sender
  +4. Sender receives packet and measures round trip time
  +5. Sender sends measurement to logging server
  +6. Logging server receives measurement and persists to disk
  +
  +The resulting binary data was loaded into MATLAB(C) for analysis and visualization. The code for reading a file can be found https://gist.github.com/ennerf/19b48406a066f6e946a0567a1a4de1ed[here].
  +
  +== UDP Datagram Structure
   
   UDP datagrams include various types of overhead in addition to the actual payload. The minimum overhead is 66 bytes. Additionally, Ethernet Frames have a minimum size of 84 bytes, which makes the minimum payload for a UDP Datagram 18 bytes.
   
  
positive.code: 
  == Benchmark Setup
  
  A common way to benchmark networks is to setup two computers and have a sender transmit a message to a receiver that echoes it back. That way the sender can measure the round trip time and gather statistics of the network. This works well, but there is a lot of 'magic' that happens in the underlying operating system and it's device drivers.
  
  In order to mitigate this potential source of jitter, I setup a benchmark that measures the round trip time between two dedicated embedded systems. The overall approach remains the same, i.e.,
  
  1. Sender sends packet to receiver in fixed intervals
  2. Receiver echoes packet back to sender
  3. Sender measures the round trip time
  4. Measurement gets persisted to disk
  
  As the sender and receiver devices I'm using two HEBI Robotics I/O Boards. It's a product that we typically don't advertise, but customers often use it to integrate actuators with external devices or to get various sensor input into MATLAB. It has 48 pins that serve a variety of functions (analog/digitial I/O, PWM, Encoder input, etc.) that can be accessed remotely via network. It contains a 168MHz ARM microcontroller (STM32f407) and a 100 Mbit network port.
  
  [.text-center]
  .HEBI Robotics IO Board
  
negative.code: 
  |====================
  
  For these benchmarks I chose to measure the round-trip time for a payload of 200 bytes. For comparison, the feedback packets of HEBI Robotic's X-Series actuators currently require 185-215 bytes. Returning the state of all pins of an I/O board currently requires about 300 bytes.
  
  While the size is representative of a typical feedback packet, the round trip times in production will be slightly faster because the outgoing packets (commands) tend to be significantly smaller than response packets (feedback).
  
  After including all overhead, the actual Ethernet frame size on the wire is 266 bytes. The theoretical time it takes to transfer 266 bytes over 100 Mbit/s and 1Gbit/s Ethernet is 20.3us and 2.03us respectively.
  
  