Problems communicating between microcontroller and micrometer

I want to send measurement-data from a micrometer (Insize Metal Sheet) to a microcontroller (Bluefruit nRF52 Feather) by using the protocol i got from Insize (see PDF-attachment). I don't know if I misunderstand the protocol, the Aduino-functions or the connections with to the aux. Can anyone see why I don't read any proper frames from the micrometer?

#include <bluefruit.h>

BLEDis bledis;
BLEHidAdafruit blehid;

bool hasKeyPressed = false;

// Variables for controlling buttons
byte interruptPinSend = 11;
byte interruptPinUndo = 27;
byte interruptPinRedo = 7;
volatile bool isTriggeredSend = false;
volatile bool isTriggeredUndo = false;
volatile bool isTriggeredRedo = false;

// Variables for serial UART-communication
uint8_t sequenceNumber = 0;
uint8_t data[] = {0x00, 0x00, 0x00, 0x00};
uint8_t frame[] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xB0};

// Declearing functions
void triggerSendISR();
void triggerUndoISR();
void triggerRedoISR();
uint8_t getCheckSum(char *string, uint8_t frameHeader, uint8_t command);

void setup()
{
  Serial.begin(115200);
  while ( !Serial ) delay(10);   // for nrf52840 with native usb

  Serial.println("Bluetooth HID");
  Serial.println("--------------------------------\n");

  Serial.println();
  Serial.println("Go to your Bluetooth settings to pair your device");
  Serial.println("then open an application that accepts keyboard input");

  Serial.println();
  Serial.println("Enter the character(s) to send:");
  Serial.println();

  /* Attach interrupt for trigger button
     Note: When user trigger button, report is sent to micrometer
     to ask for measured value.
  */
  pinMode(interruptPinSend, INPUT_PULLUP);
  pinMode(interruptPinUndo, INPUT_PULLUP);
  pinMode(interruptPinRedo, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(interruptPinSend), triggerSendISR, FALLING);
  attachInterrupt(digitalPinToInterrupt(interruptPinUndo), triggerUndoISR, FALLING);
  attachInterrupt(digitalPinToInterrupt(interruptPinRedo), triggerRedoISR, FALLING);

  Bluefruit.begin();
  Bluefruit.setTxPower(4);    // Check bluefruit.h for supported values
  Bluefruit.setName("XR Inspector");

  // Configure and Start Device Information Service
  bledis.setManufacturer("Adafruit Industries");
  bledis.setModel("Bluefruit Feather 52");
  bledis.begin();

  /* Start BLE HID
     Note: Apple requires BLE device must have min connection interval >= 20m
     ( The smaller the connection interval the faster we could send data).
     However for HID and MIDI device, Apple could accept min connection interval
     up to 11.25 ms. Therefore BLEHidAdafruit::begin() will try to set the min and max
     connection interval to 11.25  ms and 15 ms respectively for best performance.
  */
  blehid.begin();

  /* Set connection interval (min, max) to your perferred value.
     Note: It is already set by BLEHidAdafruit::begin() to 11.25ms - 15ms
     min = 9*1.25=11.25 ms, max = 12*1.25= 15 ms
  */
  /* Bluefruit.Periph.setConnInterval(9, 12); */

  // Set up and start advertising
  startAdv();
}

void startAdv(void)
{
  // Advertising packet
  Bluefruit.Advertising.addFlags(BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE);
  Bluefruit.Advertising.addTxPower();
  Bluefruit.Advertising.addAppearance(BLE_APPEARANCE_HID_KEYBOARD);

  // Include BLE HID service
  Bluefruit.Advertising.addService(blehid);

  // There is enough room for the dev name in the advertising packet
  Bluefruit.Advertising.addName();

  /* Start Advertising
     - Enable auto advertising if disconnected
     - Interval:  fast mode = 20 ms, slow mode = 152.5 ms
     - Timeout for fast mode is 30 seconds
     - Start(timeout) with timeout = 0 will advertise forever (until connected)

     For recommended advertising interval
     https://developer.apple.com/library/content/qa/qa1931/_index.html
  */
  Bluefruit.Advertising.restartOnDisconnect(true);
  Bluefruit.Advertising.setInterval(32, 244);    // in unit of 0.625 ms
  Bluefruit.Advertising.setFastTimeout(30);      // number of seconds in fast mode
  Bluefruit.Advertising.start(0);                // 0 = Don't stop advertising after n seconds
}

void loop()
{
  //Read frame from micrometer
  int8_t byteCount = 0;
  while (Serial.available())
  {
    frame[byteCount] = (uint8_t) Serial.read();
    ++byteCount;
    hasKeyPressed = true;
    if(byteCount == sizeof(frame)) // Reached the end of frame
    {
      byteCount = 0;
    }
  }


  if (hasKeyPressed && (frame[1] == 0x42))
  {
    data[0] = frame[2];
    data[1] = frame[3];
    data[2] = frame[4];
    data[3] = frame[5];

    blehid.keyPress(data[0]);
    blehid.keyRelease();
    delay(5);

    blehid.keyPress(data[1]);
    blehid.keyRelease();
    delay(5);

    blehid.keyPress(data[2]);
    blehid.keyRelease();
    delay(5);

    blehid.keyPress(data[3]);
    blehid.keyRelease();
    delay(5);
  }

  // Sending frame to micrometer
  if (isTriggeredSend)
  {
    isTriggeredSend = false;

    char charData[] = {data[0], data[1], data[2], data[3]};

    //Sending query to micrometer
    Serial.print(0xA0); //Frame header
    Serial.print(0x45); //Command: Query
    Serial.print(0x00); //Data
    Serial.print(0x00);
    Serial.print(0x00);
    Serial.print(0x00);
    Serial.print(0x01); //Channel
    Serial.print(0xFF); //Equipment Sequence Number
    Serial.print(0xFF);
    Serial.print(0xFF);
    Serial.print(0xFF);
    Serial.print(0x00); //Reserved
    Serial.print(sequenceNumber); //Sequence Number
    Serial.print(getCheckSum(0x00000000, 0xA0, 0x42)); //Sum Check: Frame Header + Command + Data XOR
    Serial.print(0xB0); //Frame Tail
    ++sequenceNumber;
  }
}

uint8_t getCheckSum(char *string, uint8_t frameHeader, uint8_t command) //https://forum.arduino.cc/index.php?topic=86496.0 - Rob Tillart
{
  int XOR = 0;
  for (int i = 0; i < strlen(string); i++)
  {
    XOR = XOR ^ string[i];
  }
  return XOR + frameHeader + command;
}

void triggerSendISR()
{
  /*
     Send report to micrometer.
  */
  isTriggeredSend = true;
}

void triggerUndoISR()
{
  /*
     Send report to micrometer.
  */
  isTriggeredUndo = true;
}

void triggerRedoISR()
{
  /*
     Send report to micrometer.
  */
  isTriggeredRedo = true;
}

7315-2 Multiplex Interface Wireless Communication Protocol.pdf (100 KB)

Karma for properly posting the code and data sheets on your first post! But WHICH micrometer do you have?

Post examples of what happens when trying to read the micrometer.

How does program identify the start and end of a frame when receiving it ?

I would have thought that it would read bytes until it got an 0xA0 then read the data and saved it until it got an 0xB0 before parsing the frame and using the data it contains

UKHeliBob:
How does program identify the start and end of a frame when receiving it ?

I would have thought that it would read bytes until it got an 0xA0 then read the data and saved it until it got an 0xB0 before parsing the frame and using the data it contains

Thanks for the advice! I will try that as soon as possible:D

jremington:
Karma for properly posting the code and data sheets on your first post! But WHICH micrometer do you have?

Post examples of what happens when trying to read the micrometer.

Thanks! The micrometer can be found in this link: https://www.cutwel.co.uk/measuring-tools/small-tool-instruments/micrometers/sheet-metal-micrometer/digital-sheet-metal-micrometers-insize-3539-series

The ouput I got when I tried to write out the output from Serial.Read() into the console was a lot of linebreaks and a few random ASCII-characters.

The micrometer can be found in this link: https://www.cutwel.co.uk/measuring-tools/small-tool-instruments/micrometers/sheet-metal-micrometer/digital-sheet-metal-micrometers-insize-3539-series

WHICH ONE?

Please post a link to the data sheet or instruction manual for the optional data output cable/interface. Also explain how you have connected it to the Arduino.

You need to get the hardware protocol (voltage levels, Baud rate, number of bits, parity, etc.) working first. I suggest to start over and write a simple program that just reads the micrometer, and get that working before adding anything else.

Other measuring stuff similiar to this use 3.0 volt logic as one standard. 3.3 is not recommended and 5.0 out of question.

jremington:
WHICH ONE?

Please post a link to the data sheet or instruction manual for the optional data output cable/interface. Also explain how you have connected it to the Arduino.

You need to get the hardware protocol (voltage levels, Baud rate, number of bits, parity, etc.) working first. I suggest to start over and write a simple program that just reads the micrometer, and get that working before adding anything else.

I've added the protocol as a PDF-attachment. The baud rate is 115200, number of bits is 8, stop-bit is 1 and non parity-bit. They haven't documented any voltage level, but the Bluetooth module they normally use has a 3V-battery and the micrometer has a 1.5V-battery.

Railroader:
Other measuring stuff similiar to this use 3.0 volt logic as one standard. 3.3 is not recommended and 5.0 out of question.

Thanks for advice! Looks like it uses 3V, so I'll add a voltage divider.

jremington:
WHICH ONE?

Please post a link to the data sheet or instruction manual for the optional data output cable/interface. Also explain how you have connected it to the Arduino.

You need to get the hardware protocol (voltage levels, Baud rate, number of bits, parity, etc.) working first. I suggest to start over and write a simple program that just reads the micrometer, and get that working before adding anything else.

Forgot to answer your first question: 3539-253SA

Tried to simplify the program to make it easier to figure out the protocol. I have adjusted the aux-power to 3.0V and connected the left and right aux-channel to rx and tx first, and then the opposite way.

I send the following to the micrometer using the serial monitor: 0xA0450000000000000000000000E0B0,
where the protocol is (the number in square brackets is the byte starting from zero):

  • [ 0] frame header
  • [1] command (0x45 = query, don't know if this should be 0x42 = data or anything else)
  • [2-12] data
  • [13] checksum (frame header + command + data xor, should this be "xor'ed" together or added with overflow)
  • [14] frame tail

I use the following code:

void setup() {
  Serial.begin(115200, SERIAL_8N1);
}

void loop() {
  if(Serial.available())
  {
    Serial.println(Serial.read(), HEX);
  }
}

But still I get nothing in return.

I send the following to the micrometer using the serial monitor: 0xA0450000000000000000000000E0B0,

I can't help feeling that it would be better to code this into the program rather than entering it in the Serial monitor as entering it manually will be prone to error (and tedious). Have the program work out the checksum too

You also seem to be sharing hardware serial (ie Serial) with the micrometer which is probably a bad idea. Consider using SoftwareSerial to communicate with the micrometer leaving Serial for debugging

UKHeliBob:
You also seem to be sharing hardware serial (ie Serial) with the micrometer which is probably a bad idea. Consider using SoftwareSerial to communicate with the micrometer leaving Serial for debugging

I've thought about that at some point, but didn't think about that solution. Thanks, I'll test that!

Where is the documentation for the interface cable? The protocol information is useless until you have the hardware communication problem solved.

If the voltage level on the serial line is 3V, you probably can't read it reliably with a 5V Arduino. Try using a 3.3V Arduino.

The micrometer might have been damaged by applying a 5V signal on TX.

I don't think Software Serial works at 115200 Baud. See this comparison of the alternatives: What's the difference between all the Software Serial Libraries? Which one is Arduino Nano compatible? - Arduino Stack Exchange

jremington:
Where is the documentation for the interface cable? The protocol information is useless until you have the hardware communication problem solved.

If the voltage level on the serial line is 3V, you probably can't read it reliably with a 5V Arduino. Try using a 3.3V Arduino.

The micrometer might have been damaged by applying a 5V signal on TX.

I don't think Software Serial works at 115200 Baud. See this comparison of the alternatives: What's the difference between all the Software Serial Libraries? Which one is Arduino Nano compatible? - Arduino Stack Exchange

It says in documentation that it's 115200 baud rate, 8 bit, 1 stop bit and no parity. Everything I got from the micrometer manufacturer is attached at the top if you need to have a look. I use a 3.3V Adafruit microcontroller and have stepped down the output to the aux too 3V with a potmeter.

Also, I just noticed that the icon on the micrometer display that blinks one time when the manufacturer Bluetooth-device askes for data is staying on from the moment I send 0xA0450000000000000000000000E5B0 (0x45 is the query-command and the checksum 0xE5 is calculated through an online calculator that corresponds to my hand-calculations) until I plug out my own module, plug in the manufacturer module and trigger the measurement button.

I don't know if that's because what you (jremington) said about Software Serial, so I'll check that out.

Thanks for the link!

I don't think Software Serial works at 115200 Baud.

Good point

If the interface cable is intended to connect to a PC serial port, the voltage levels (typically +12 and -12V) will be totally incompatible with Arduino.