Wifly shield - SpiSerial.write too slow

Hi,

I am using the Wifly Shield with Arduino Uno (Wifly library alpha 2 from git).

I want to use the Arduino/Wifly to read a six degree of freedom force/torque sensor and stream the data as fast as possible to a wireless node (Netgear router). A labview compact Rio is connected on the ethernet port of the router and is used to collect the data.

I am sending the data as blocks of:

  • - 1 timestamp (unsigned long) = 4 bytes
    • 6 force values (integer)= 6x 2 bytes


    • For a total of 16 bytes per data block.

    To be more precise, I would like to get in the 300-500 blocks/s ball part … or 38400-64000 baud (16bytes/block x 8bits/bytes x 300blocks/s = 38400).

    Since I read about people getting the communication to work at over 115200 baud I thought the Arduino/Wifly to be able to do so (maybe someone will tell me otherwise).

    As you can guess, it doesn’t work. Trying to debug, I found interesting things about SpiSerial.write delay.

    Here’s the code:

    #include <SPI.h>
    #include <WiFly.h>
    //#include <SoftwareSerial.h>
    
    // Change the prescale to 16 for faster analogRead()
    #define FASTADC 1
    
    // defines for setting and clearing register bits
    #ifndef cbi
    #define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
    #endif
    #ifndef sbi
    #define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
    #endif
    
    // Wifi parameters
    char passphrase[] = "passphrase";
    char ssid[] = "ssid";
    
    // Data Variables
    const int NBFORCES=6;
    int intForces[NBFORCES];
    
    // Other Variables
    String inputString="";
    unsigned long t1;
    unsigned long t2;
    unsigned long t3;
    unsigned long told=0;
    
    //////////////////////////////////////////////////////////////////
    
    void setup() {
      
      #if FASTADC
      // set prescale to 16
      sbi(ADCSRA,ADPS2) ;
      cbi(ADCSRA,ADPS1) ;
      cbi(ADCSRA,ADPS0) ;
      #endif
      
      Serial.begin(9600);
      //SpiSerial.begin(115200);
      Serial.println("");
      Serial.println("");
      Serial.println("----------------------------------------------");
      Serial.println("WiFly: Communication with cRio");
      Serial.println("----------------------------------------------");
      Serial.println("");
      
      // reserve 20 bytes for the state buffer
      inputString.reserve(20);
      
      WiFly.begin();
      
      if(!WiFly.join(ssid, passphrase)) {
        Serial.println("Association failed");
        while(1) {
          // Hang on failure
        }
      }
      
      Serial.println("Associated!");
      Serial.print("IP: ");
      Serial.println(WiFly.ip());
    
      //establishContact();  // Wait for connection to be established ... commented for debuging
      
      //ONLY FOR DEBUGING ... to be removed
      while(!Serial.available()) {
        // Wait for a character
      }
    }
    
    /////////////////////////////////////////////////////////////////
    ...
    /////////////////////////////////////////////////////////////////
    
    void loop() {
       
      //Because the time when the port is read is important
      //we read every port, then send the value
      
      t1=micros();
      readAnalogPorts();
      t2=micros();
      writeToCRio(t1);
      t3=micros();
      
      //Debug print
      Serial.print("timestamp:");
      Serial.println(t1);
      Serial.print("Read:");
      Serial.println(t2-t1);
      Serial.print("Write:");
      Serial.println(t3-t2);
      Serial.print("Period:");
      Serial.println(t1-told);
      Serial.println("");
      
      told=t1;
    
    } 
    /////////////////////////////////////////////////////////////////
    // Reads NBFORCES analog ports
    void readAnalogPorts() {
      
      for (int i=0; i<NBFORCES; i++)
      {
        intForces[i]=analogRead(i);
      }
      
    }
    
    /////////////////////////////////////////////////////////////////
    // Write every byte once at the time
    // Starting with the most significative
    void writeToCRio(unsigned long t) {
      
      //Write time as 4 bytes
      SpiSerial.write((t>>24));
      SpiSerial.write((t>>16));
      SpiSerial.write((t>>8));
      SpiSerial.write(t);
      
      //Write each forces as 2 bytes
      for (int i=0; i<NBFORCES; i++)
      {
          SpiSerial.write((intForces[i]>>8));
          SpiSerial.write(intForces[i]);   
      }
        
    }
    /////////////////////////////////////////////////////////////////
    

    I am already using a ADC prescale divider of 16 for a faster analogRead()

    So when using Serial.begin(9600) and default value for SpiSerial (9600) here is the typical output I get:

    timestamp:22270288
    Read:108
    Write:624
    Period:59280
    timestamp:22329568
    Read:108
    Write:616
    Period:59280

    When I use Serial.begin(115200) and SpiSerial.begin(115200) here is what I get:

    timestamp:9036048
    Read:108
    Write:15008
    Period:16636
    timestamp:9052704
    Read:108
    Write:14984
    Period:16656

    I get that there is a lot of overhead in the while loop with all those print and micros instructions. I also get that this overhead gets lower as the baudrate goes up. The thing I don’t understand is why does my write function sudently takes more time as the baudrate goes up?? (though the first few readings gets me a 650us delay as well)

    If I keep 9600 baud, remove all the overhead and I read the timestamps on the receiver side, I still get a period of about 16000us (which is too slow).

    It looks like I am hitting the communication saturation speed… and I don’t see why.

    Thanks for the help

  • I still don’t understand why the write function takes more time as the baud rate goes up…

    I found that the while loop in the SpiUartDevice::write seems to be slowing things down:

    while (readRegister(TXLVL) == 0) {
        // Wait for space in TX buffer
      };
    

    … but also found that it is essential to ensure delivery .

    (I commented the loop and received only garbage at the other end)

    Is there a way I could send data faster?

    thx

    Really… no replies in over one month and a half.

    :frowning: