What happens when the arduino cannot send any more data?

I am adding serial functionality to a programming language and have been running some tests using an SEPP Uno R3 and the OSEPP compass module. I’m using a sketch for the compass on the Arduino that sends compass data over the serial line to the COM port on Windows. My software reads and fills up a buffer. until I do something with it. After about 15 seconds if I am not pulling data out of the buffer, the Arduino stops sending messages until I take some of the data out of the buffer. Anyways, at some point, I am losing part of a line. I am just trying to figure out if the Arduino may stop sending midline if the buffer is full. Is that possible?

You can see the cut off line in the output below:

>> s: open serial://com11/115200
>> buffer: to string! read s
>> print buffer
X: 272   Y: 346   Z: -186   Xs: 155   Ys: 470   Zs: -171   H: 1.32   A: 75.76
X: 272   Y: 345   Z: -188   Xs: 155   Ys: 469   Zs: -172   H: 1.32   A: 75.73
X: 271   Y: 344   Z: -187   Xs: 154   Ys: 468   Zs: -172   H: 1.32   A: 75.80
X: 272   Y: 345   Z: -189   Xs: 155   Ys: 469   Zs: -173   H: 1.32   A: 75.73
X: 271   Y: 344   Z: -189   Xs: 154   Ys: 468   Zs: -173   H: 1.32   A: 75.80
X: 271   Y: 343   Z: -190   Xs: 154   Ys: 467   Zs: -174   H: 1.32   A: 75.77
X: 271   Y: 344   Z: -189   Xs: 154   Ys: 468   Zs: -173   H: 1.32   A: 75.80
X: 273   Y: 339   Z: -194   Xs: 156   Ys: 463   Zs: -178   H: 1.32   A: 75.40
X: 273   Y: 339   Z: -193   Xs: 156   Ys: 463   Zs: -177   H: 1.32   A: 75.40
X: 274   Y: 338   Z: -194   Xs: 157   Ys: 462   Zs: -178   H: 1.31   A: 75.25
X: 273   Y: 339   Z: -194   Xs: 156   Ys: 463   Zs: -178   H: 1.32   A: 75.40
X: 272   Y: 339   Z: -195   Xs: 155   Ys: 463   Zs: -179   H: 1.32   A: 75.51
X: 274   Y: 339   Z: -194   Xs: 157   Ys: 463   Zs: -178   H: 1.31   A: 75.28
X: 273   Y: 339   Z: -192   Xs: 156   Ys: 463   Zs: -176   H: 1.32   A: 75.40
X: 273   Y: 338   Z: -193   Xs: 156   Ys: 462   Zs: -177   H: 1.32   A: 75.36
X: 273   Y: 337   Z: -193   Xs: 156   Ys: 461   Zs: -177   H: 1.31   A: 75.32
X: 272   Y: 339   Z: -193   Xs: 155   Ys: 463   Zs: -177   H: 1.32   A: 75.51
X: 272   Y: 338   Z: -193   Xs: 155   Ys: 462   Zs: -177   H: 1.32   A: 75.47
X: 272   Y: 339   Z: -194   Xs: 155   Ys: 463   Zs: -178   H: 1.32   A: 75.51
X: 272   Y: 339   Z: -194   Xs: 155   Ys: 463   Zs: -178   H: 1.32   A: 75.51
X: 271   Y: 338   Z: -194   Xs: 154   Ys: 462   Zs: -178   H: 1.32   A: 75.58
X: 272   Y: 339   Z: -192   Xs: 155   Ys: 463   Zs: -176   H: 1.32   A: 75.51
X: 272   Y: 340   Z: -194   Xs: 155   Ys: 464   Zs: -178   H: 1.32   A: 75.54
X: 271   Y: 339   Z: -193   Xs: 154   Ys: 463   Zs: -177   H: 1.32   A: 75.62
X: 272   Y: 340   Z: -194   Xs: 155   Ys: 464   Zs: -178   H: 1.32   A: 75.54
X: 271   Y: 340   Z: -194   Xs: 154   Ys: 464   Zs: -178   H: 1.32   A: 75.66
X: 272   Y: 341   Z: -193   Xs: 155   Ys: 465   Zs: -177   H: 1.32   A: 75.58
X: 271   Y: 341   Z: -195   Xs: 154   Ys: 465   Zs: -179   H: 1.32   A: 75.69
X: 271   Y: 341   Z: -193   Xs: 154   Ys: 465   Zs: -177   H: 1.32   A: 75.69
X: 272   Y: 340   Z: -193   Xs: 155   Ys: 464   Zs: -177   H: 1.32   A: 75.54
X: 272   Y: 340   Z: -194   Xs: 155   Ys: 464   Zs: -178   H: 1.32   A: 75.54
X: 272   Y: 340   Z: -193   Xs: 155   Ys: 464   Zs: -177   H: 1.32   A: 75.54
X: 272   Y: 340   Z: -194   Xs: 155   Ys: 464   Zs: -178   H: 1.32   A: 75.54
X: 271   Y: 342   Z: -194   Xs: 154   Ys: 466   Zs: -178   H: 1.32   A: 75.73
X: 271   Y: 340   Z: -193   Xs: 154   Ys: 464   Zs: -177   H: 1.32   A: 75.66
X: 271   Y: 341   Z: -195   Xs: 154   Ys: 465   Zs: -179   H: 1.32   A: 75.69
X: 271   Y: 341   Z: -195   Xs: 154   Ys: 465   Zs: -179   H: 1.32   A: 75.69
X: 271   Y: 341   Z: -194   Xs: 154   Ys: 465   Zs: -178   H: 1.32   A: 75.69
X: 271   Y: 340   Z: -195   Xs: 154   Ys: 464   Zs: -179   H:1.32   A: 75.66
>> print to string! read s
X: 273   Y: 340   Z: -195   Xs: 156   Ys: 464   Zs: -179   H: 1.32   A: 75.43
X: 271   Y: 339   Z: -195   Xs: 154   Ys: 463   Zs: -179   H: 1.32   A: 75.62
X: 271   Y: 339   Z: -195   Xs: 154   Ys: 463   Zs: -179   H: 1.32   A: 75.62
X: 272   Y: 339   Z
X: 272   Y: 337   Z: -195   Xs: 155   Ys: 461   Zs: -179   H: 1.32   A: 75.43
X: 272   Y: 337   Z: -195   Xs: 155   Ys: 461   Zs: -179   H: 1.32   A: 75.43
X: 273   Y: 339   Z: -195   Xs: 156   Ys: 463   Zs: -179   H: 1.32   A: 75.40
X: 272   Y: 337   Z: -194   Xs: 155   Ys: 461   Zs: -178   H: 1.32   A: 75.43
X: 272   Y: 338   Z: -195   Xs: 155   Ys: 462   Zs: -179   H: 1.32   A: 75.47
X: 272   Y: 338   Z: -194   Xs: 155   Ys: 462   Zs: -178   H: 1.32   A: 75.47
X: 272   Y: 339   Z: -195   Xs: 155   Ys: 463   Zs: -179   H: 1.32   A: 75.51

Arduino Sketch:

// OSEPP Compass Sensor Example Sketch
// by OSEPP <http://www.osepp.com>
// Modifications by Chris W. to accommodate declination, scaling and origin adjustment 2013-02-13
// This sketch demonstrates interactions with the Compass Sensor

#include <Wire.h>

const uint8_t sensorAddr = 0x1E;   // Sensor address (non-configurable)
const float xOffset = 103.0;      // Offset required to adjust x coordinate to zero origin
const float yOffset = -165.0;       // Offset required to adjust y coordinate to zero origin
const float declination = 70.1;    // Enter magnetic declination mrads here (local to your geo area) 

// One-time setup
void setup()
{
   // Start the serial port for output
   Serial.begin(115200);

   // Join the I2C bus as master
   Wire.begin();

   // Configure the compass to default values (see datasheet for details)
   WriteByte(sensorAddr, 0x0, 0x70);
   
   WriteByte(sensorAddr, 0x1, 0x20); // +1.3Ga

   // Set compass to continuous-measurement mode (default is single shot)
   WriteByte(sensorAddr, 0x2, 0x0);
}

// Main program loop
void loop()
{
   uint8_t x_msb;   // X-axis most significant byte
   uint8_t x_lsb;   // X-axis least significant byte
   uint8_t y_msb;   // Y-axis most significant byte
   uint8_t y_lsb;   // Y-axis least significant byte
   uint8_t z_msb;   // Z-axis most significant byte
   uint8_t z_lsb;   // Z-axis least significant byte

   int x;
   int y;
   int z;
  
   // Get the value from the sensor
    if ((ReadByte(sensorAddr, 0x3, &x_msb) == 0) &&
       (ReadByte(sensorAddr, 0x4, &x_lsb) == 0) &&
       (ReadByte(sensorAddr, 0x5, &z_msb) == 0) &&
       (ReadByte(sensorAddr, 0x6, &z_lsb) == 0) &&
       (ReadByte(sensorAddr, 0x7, &y_msb) == 0) &&
       (ReadByte(sensorAddr, 0x8, &y_lsb) == 0))
    {
    x = x_msb << 8 | x_lsb;
    y = y_msb << 8 | y_lsb;
    z = z_msb << 8 | z_lsb;
      
    int xs;
    int ys;
    int zs;

    float gScale = .92;  // Scale factor for +1.3Ga setting
    
    float adjx = x - xOffset;
    float adjy = y - yOffset;

    xs = adjx * gScale; 
    ys = adjy * gScale;
    zs = z * gScale;    
    
    float heading = atan2(ys, xs);
    heading += declination / 1000; // Declination for geo area
      
      if (heading < 0);
        heading += 2*PI;
        
      if (heading > 2*PI)
        heading -= 2*PI;

      float angle = heading * 180/M_PI;
      
      Serial.print("X: ");
      Serial.print(x);
      Serial.print("   Y: ");
      Serial.print(y);
      Serial.print("   Z: ");
      Serial.print(z);
      Serial.print("   Xs: ");
      Serial.print(xs);
      Serial.print("   Ys: ");
      Serial.print(ys);
      Serial.print("   Zs: ");
      Serial.print(zs);
      Serial.print("   H: ");
      Serial.print(heading);
      Serial.print("   A: ");
      Serial.println(angle);
   }
   else
   {
      Serial.println("Failed to read from sensor");
   }

   // Run again in 1 s (1000 ms)
   delay(500);
}

// Read a byte on the i2c interface
int ReadByte(uint8_t addr, uint8_t reg, uint8_t *data)
{
   // Do an i2c write to set the register that we want to read from
   Wire.beginTransmission(addr);
   Wire.write(reg);
   Wire.endTransmission();

   // Read a byte from the device
   Wire.requestFrom(addr, (uint8_t)1);
   if (Wire.available())
   {
      *data = Wire.read();
   }
   else
   {
      // Read nothing back
      return -1;
   }

   return 0;
}

// Write a byte on the i2c interface
void WriteByte(uint8_t addr, uint8_t reg, byte data)
{
   // Begin the write sequence
   Wire.beginTransmission(addr);

   // First byte is to set the register pointer
   Wire.write(reg);

   // Write the data byte
   Wire.write(data);

   // End the write sequence; bytes are actually transmitted now
   Wire.endTransmission();
}

As far as I know if the Arduino output buffer is full it just discards any other data that you try to send.

I have a sketch running for months with nothing connected to read the output. If I do connect my PC it just shows data from that point onwards.

...R

Thank you for the response. Makes sense. It looks like Windows will accept around 4090 bytes and Linux around 3980 bytes before they are full (at least on the configuration of my computers). Just looking at edge cases to see how they are handled.

Yep, without flow control (hardware using RTS/CTS) or by monitoring in software,
Serial.print/println/write etc will just keep blasting out data.
Up to receiver to not choke on it.

Include code in your application to process the onset and offset of data sent from arduino. When arduino cannot send any more data, signify so with a data delimiter (you can use special characters) which you would check for in your application.

Thank you for the advice. :slight_smile: Could you give me an example or more details of how that would work?

You mean to frame the data in some kind of structure beyond newlines? How could one send a data delimiter if one can't send anything?