0

I've got an Adafruit Bluefruit NRF52 hooked up to the Adafruit BNO055 9-axis orientation sensor, but when I use Serial.write to send the data, serial monitor displays blank values only. The scroll bar drops so something I definitely appearing, it just seems to be empty.

Serial.print works fine, but I cannot use this for my application, as it uses too much memory.

I'm gathering 3 axis of absolute orientation plus 3 axis of acceleration (6 floats in total) plus a three digit number representing the calibration of each sensor.

Each line should look something like

303 68.69   4.19    -2.19   -0.12   0.14    -0.40

My code:

void displayCalStatus(void)
{

  uint8_t system, gyro, accel, mag;
  system = gyro = accel = mag = 0;
  bno.getCalibration(&system, &gyro, &accel, &mag);

  /* Display the individual values */
  Serial.write(gyro);
  Serial.write(accel);
  Serial.write(mag);
  Serial.write("\t");
}

void loop()
{
  imu::Vector<3> accel = bno.getVector(Adafruit_BNO055::VECTOR_LINEARACCEL);

  /* Get a new sensor event */
  sensors_event_t event;
  bno.getEvent(&event);

  displayCalStatus();

  /* Display the floating point data */
  Serial.write(event.orientation.x);
  Serial.write("\t");
  Serial.write(event.orientation.y);
  Serial.write("\t");
  Serial.write(event.orientation.z);
  Serial.write("\t");

    /* Display the floating point data for Linear Acceleration */
  Serial.write(accel.x());
  Serial.write("\t");
  Serial.write(accel.y());
  Serial.write("\t");
  Serial.write(accel.z());
  Serial.write("\n");
}
  • write transfers a byte, you want print text. replace all write with print – Juraj Jan 9 at 18:53
  • As mentioned, I cannot use print because it uses too much memory. I'm using Serial for debug but am sending over bleuart in prototype. I'm recording high speed, high fidelity movement and so I need the ble connection interval down to 20ms minimum, which means getting the transfer size down. Do you know if there are workable alternatives to print? – dookie Jan 9 at 18:58
  • This is not good coding: system = gyro = accel = mag = 0; Instead, explicitly set each one to zero. – jose can u c Jan 9 at 18:58
  • but you want see the number as text or not? if you write(5) you send a nonprintable byte. if you print(5) it will print "5". imu::Vector takes much more space then C array – Juraj Jan 9 at 19:00
  • system = gyro = accel = mag = 0; is from the example provided by Adafruit, not my own. Either way that doesn't solve the problem of printing blank values. – dookie Jan 9 at 19:03
1

Problem 1:

You wish to send/display on the Serial Monitor the int and float values generated by your sensor, but Serial.print() uses too much memory.

Solution 1:

Optimize your sketch to use less memory.


Problem 2:

Serial.write() doesn't cause the values to show up on Serial Monitor, but something is getting sent, because I see scrolling activity.

Solution 2:

Serial.write() sends raw bytes, whereas Serial.print() converts a variable to a string (or series of ASCII bytes) and sends that string. For example, Serial.write(65) sends A to the Serial Monitor because the ASCII value of A is 65; Serial.print(65) sends 65 to the Serial Monitor because it converts the numeric value 65 into a string containing the character 6 and the character 5, and sends that string to Serial Monitor.

The Serial Monitor expects only ASCII data. You are using Serial Monitor for development/debugging, but your final application does not require ASCII, only to transmit the numbers.

Serial.write() comes in a few forms. One is Serial.write(val) which sends a single byte (named val, of type byte or compatible). Another is Serial.write(buf, len) which sends a series of len bytes, starting at the address of memory pointed by by buf. (This is often when buf is an array of bytes, so buf points to the first element of the array.)

If you wanted to send the 4 bytes of a float using Serial.write(), you could call:

Serial.write(&(event.orientation.x), sizeof(event.orientation.x);

As an alternative, you can use bit shifting to send one byte at a time of the 4-byte float:

Serial.write((byte)((event.orientation.x & 0xFF000000) >> 24);
Serial.write((byte)((event.orientation.x & 0x00FF0000) >> 16);
Serial.write((byte)((event.orientation.x & 0x0000FF00) >>  8);
Serial.write((byte)((event.orientation.x & 0x000000FF)      );

On the receiving end, you need to reconstruct your float by doing the reverse.

But you have multiple 4-byte values to send, in rapid repeating loop, so what happens if your receiver and transmitter get out of sync? Then you might want to put in a "flag" value to indicate the start of a sequence of data and a different flag for the stop of a sequence of data. What happens if your start or stop "flag" value actually shows up as one of the bytes you send as part of a real data byte? Then you need to find some way to modify the "real" data so that it's not to be construed as a flag.

This looks to be getting complicated now? Fortunately, these problems have existed and been solved for decades. Unfortunately, there is no consensus on the best or right way.

I did a quick search and found this arduino library that facilitates packet-based serial communication:

https://github.com/bakercp/PacketSerial

Perhaps that can help you take a bundle of numbers and send them reliably to some other system. I don't know that library in particular, and there are probably others that do something similar. This one claims to be compatible with the PySerial, COBS, and SLIP modules for dealing with packetized serial data communications.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.