M7E Hecto not working with Arduino

I am attempting to use the SparkFun M7E RFID reader, with basic assembly and the library provided onsite.

The module works perfectly fine with the USB connection via ThingMagic Universal Reader Assistant.

But when it comes to UART, I only receive “Module failed to respond. Please check the wiring.

  • I have tried the example codes on Uno R3 (RX/TX, as well as SoftSerial) and Mega 2560 (RX1/TX1, etc). None works. (yes the switch was on SER).

  • I tried powering the module via USB (while the switch was still on SER), while reading data through UART. same error.

  • doubting maybe my serial pins are defective, I checked the hardware, and the UART pins seem to function fine.

  • After placing costume lines in the code, it returned the error code 1, which is defined as:

ERROR_COMMAND_RESPONSE_TIMEOUT.

  • After lots of effort, I checked the provided library. It (only) checks for the " _moduleType == ThingMagic_M6E_NANO" in some lines, but no checking for “M7E_HECTO”.

This is while M7E_HECTO has been initially defined in the library, but no further command corresponds to it.

I am not sure if the problem is related to the library.

Has anyone used M7E Hecto using Arduino?

Any possible help or insight is greatly appreciated.

Since you mentioned that the library checks for ThingMagic_M6E_NANO but not for M7E_HECTO, you might need to modify the library to support your module explicitly. If you think about switching to a different RFID reader, you can switch to MFRC522.

https://www.theengineeringprojects.com/ … duino.html

Make sure to use the latest library. (1.2.0) That has been updated for work with the M7E_HECTO, check one of the examples to see how to set it for M7E-HECTO. This setting will only impact the correct frequency setting in NA in case of the M6E-NANO.

else It should work as it is. Pictures ? which board ? ?connected to 5v?

aliarifat794:
Since you mentioned that the library checks for ThingMagic_M6E_NANO but not for M7E_HECTO, you might need to modify the library to support your module explicitly. If you think about switching to a different RFID reader, you can switch to MFRC522.

https://www.theengineeringprojects.com/ … duino.html

Thanks for the advice. I was mistaken with the library. The problem seems to be in the procedure of initiating the module.

paulvha:
Make sure to use the latest library. (1.2.0) That has been updated for work with the M7E_HECTO, check one of the examples to see how to set it for M7E-HECTO. This setting will only impact the correct frequency setting in NA in case of the M6E-NANO.

That's right, thanks. The problem was not with the the library, since, as you mentioned, the check was only for the M6E-NANO configs.

paulvha:
else It should work as it is. Pictures ? which board ? ?connected to 5v?

I tried to reset the module with connecting EN to GND, when it was on serial mode but connected to USB for the power. (a small note here: It seems like it doesn’t reset when it is connected to Arduino.)

It has started working for now, although some times I need to reset it to work again.

This specifically happens when the Baud Rate changes within the code (e.g., changing thee protocol from SoftSerial to RX/TX). Here I need to cut the power of the module so it starts responding with the new BR.

good to hear there is progress. Which board do you connect to?

paulvha:
good to hear there is progress. Which board do you connect to?

I have tried it on UNO R3 and MEGA 2560, but UNO is of my interest.

I need to re-initiate the M7E board some times to respond to a changed BR, with cutting the power. However, I don’t know how to do it properly, since I have other modules connected to the UNO board (HC05 and Easy Driver).

For now I have placed this to re-start the serial pins at the beginning, but I am not sure if this even helps. Do you have any suggestions? Do you think it is even necessary ?

SoftwareSerial softSerial(12, 13); //RX, TX
....
void setup() {
              digitalWrite(12, LOW);
              digitalWrite(13, LOW);
              Serial.begin(115200);
              digitalWrite(12, HIGH);
              digitalWrite(13, HIGH);
              while (!Serial); // Wait for the serial port to come online

It should not be necessary. Can you share:

Which wires and how they are connected between the UNO and the M7E?

The complete sketch you use?

paulvha:
It should not be necessary. Can you share:

Which wires and how they are connected between the UNO and the M7E?

The complete sketch you use?

Here is the image of the connections, as well as the complete sketch.

The connections to the M7E are quite solid.

https://app.gemoo.com/share/image-annot … lgenerator

#include "SparkFun_UHF_RFID_Reader.h"
#include <SoftwareSerial.h>
SoftwareSerial softSerial(12, 13); //RX, TX



RFID rfidModule;
//#define rfidSerial Serial3
#define rfidSerial softSerial // Serial3
#define rfidBaud 38400

#define moduleType ThingMagic_M7E_HECTO

long hc05_baudrate = 38400;
int ledPin = 8;
int button_pin = 7;
const long nchan = 6;
long pinout[nchan] = {7, 8, 9, 10, 11};

#define stp 2
#define dir 3
#define MS1 4
#define MS2 5
#define EN 6

int x;
unsigned long duration;
int rotation_counter = 0;

byte lastUID[24]; // To store the last read UID, assuming maximum EPC length
byte lastUIDLength = 0; // Length of the last read UID

void setup() {
  
  digitalWrite(12, LOW);
  digitalWrite(13, LOW);
  Serial.begin(115200);
  digitalWrite(12, HIGH);
  digitalWrite(13, HIGH);

  while (!Serial); // Wait for the serial port to come online

  if (setupRfidModule(rfidBaud) == false) {
    Serial.println(F("Module failed to respond. Please check wiring."));
    while (1); // Freeze!
  }

  //.....M7E-HECTO configs..................................................................
  rfidModule.setRegion(REGION_NORTHAMERICA); // Set to North America
  rfidModule.setReadPower(500); // 5.00 dBm. Higher values may cause USB port to burn out
  //rfidModule.enableDebugging(); // Turns on commands sent to and heard from RFID module
  rfidModule.startReading(); // Begin scanning for tags

  //....Bluetooth and Motor Control Initialization...
  for (size_t m = 0; m < nchan; m++) {
    pinMode(pinout[m], OUTPUT);
    digitalWrite(pinout[m], LOW);
  }
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(ledPin, OUTPUT);
  pinMode(button_pin, INPUT_PULLUP);

  Serial.begin(hc05_baudrate);
  pinMode(stp, OUTPUT);
  pinMode(dir, OUTPUT);
  pinMode(MS1, OUTPUT);
  pinMode(MS2, OUTPUT);
  pinMode(EN, OUTPUT);
  resetEDPins();
}

void loop() {
  if (rfidModule.check() == true) { // Check to see if any new data has come in from the module
    byte responseType = rfidModule.parseResponse(); // Break response into tag ID, RSSI, frequency, and timestamp

    if (responseType == RESPONSE_IS_KEEPALIVE) {
      Serial.println(F("Scanning"));
    } else if (responseType == RESPONSE_IS_TAGFOUND) {
      handleTagFound();
    } else if (responseType == ERROR_CORRUPT_RESPONSE) {
      Serial.println("Bad CRC");
    } else if (responseType == RESPONSE_IS_HIGHRETURNLOSS) {
      Serial.println("High return loss, check antenna!");
    } else {
      // Unknown response
      Serial.println("Unknown error");
    }
  }

  // Manual activation of reward with button press
  if (digitalRead(button_pin) == LOW) {
    digitalWrite(EN, LOW); // Pull enable pin low to allow motor control
    digitalWrite(ledPin, HIGH);
    SmallStepMode(30); // Set the size of the steps in the function below. Added duration input
    resetEDPins(); // Reset pins to save power
    digitalWrite(ledPin, LOW);
  }

  if (0 < Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    cmd.trim();
    if (0 == cmd.length()) return;

    String result = "P1"; // Command not understood
    switch (cmd.charAt(0)) {
      case 'Q': // Query current state
        result = "READY";
        break;

      case 'R': // Reset
        result = "OK";
        break;

      case 'Y': { // Deliver reward, Y<juice line>,<duration>,<num reward>,<pause time between multiple rewards>
        long comma1 = cmd.indexOf(',', 1);
        long comma2 = cmd.indexOf(',', comma1 + 1);
        long comma3 = cmd.indexOf(',', comma2 + 1);
        if (comma1 < 1 || comma2 < 1 | comma3 < 1) {
          result = "P3"; // Parameter error
          break;
        }

        unsigned long juiceline = cmd.substring(1, comma1).toInt() - 1; // 0-based
        unsigned long duration = cmd.substring(comma1 + 1, comma2).toInt(); // Coming from timing script of monkeylogic.
        unsigned long numreward = cmd.substring(comma2 + 1, comma3).toInt();
        unsigned long pausetime = cmd.substring(comma3 + 1).toInt();
        if (nchan <= juiceline) {
          result = "P2"; // Solenoid does not exist
          break;
        }
     for (size_t m = 1; m <= numreward; m++) {
          digitalWrite(LED_BUILTIN, HIGH);
          digitalWrite(ledPin, HIGH);
          digitalWrite(EN, LOW); // Pull enable pin low to allow motor control
          SmallStepMode(duration); // Set the size of the steps in the function below. Added duration input
          resetEDPins(); // Reset pins to save power
          digitalWrite(LED_BUILTIN, LOW);
          digitalWrite(ledPin, LOW);
          if (m < numreward) delay(pausetime); // Pause between rewards set in ML
        }
        result = "OK";
        break;
      }
    }
    Serial.write((result + '\n').c_str());
  }
}

// Reset Easy Driver pins to default states
void resetEDPins() {
  digitalWrite(stp, LOW);
  digitalWrite(dir, LOW);
  digitalWrite(MS1, LOW);
  digitalWrite(MS2, LOW);
  digitalWrite(EN, HIGH); // Saves power!
}

// 1/8th microstep forward mode function
void SmallStepMode(int duration) {
  rotation_counter++;
  digitalWrite(dir, LOW); // Pull direction pin low to move "forward"
  digitalWrite(MS1, HIGH); // Pull MS1, and MS2 high to set logic to 1/8th microstep resolution
  digitalWrite(MS2, HIGH);

  for (x = 0; x < duration; x++) { // Loop the forward stepping enough times for a pellet to fall in
    digitalWrite(stp, HIGH); // Trigger one step forward
    delay(1);
    digitalWrite(stp, LOW); // Pull step pin low so it can be triggered again
    delay(1);
  }
}

void handleTagFound() {
  // If we have a full record we can pull out the fun bits
  int rssi = rfidModule.getTagRSSI(); // Get the RSSI for this tag read
  long freq = rfidModule.getTagFreq(); // Get the frequency this tag was detected at
  long timeStamp = rfidModule.getTagTimestamp(); // Get the time this was read, (ms) since last keep-alive message
  byte tagEPCBytes = rfidModule.getTagEPCBytes(); // Get the number of bytes of EPC from response

  byte currentUID[24]; // To store the current UID
  for (byte x = 0; x < tagEPCBytes; x++) {
    currentUID[x] = rfidModule.msg[31 + x]; // Extract EPC
  }

  Serial.print(F(" rssi["));
  Serial.print(rssi);
  Serial.print(F("]"));

  Serial.print(F(" freq["));
  Serial.print(freq);
  Serial.print(F("]"));

  Serial.print(F(" time["));
  Serial.print(timeStamp);
  Serial.print(F("]"));

  Serial.print(F(" epc["));
  for (byte x = 0; x < tagEPCBytes; x++) {
    if (currentUID[x] < 0x10) Serial.print(F("0")); // Pretty print
    Serial.print(currentUID[x], HEX);
    Serial.print(F(" "));
  }
  Serial.print(F("] "));

  if (isNewTag(currentUID, tagEPCBytes)) {
    Serial.println("New UID read!");
    memcpy(lastUID, currentUID, tagEPCBytes);
    lastUIDLength = tagEPCBytes;

    // Operate motor and LED for new tag
    digitalWrite(ledPin, HIGH);
    digitalWrite(EN, LOW);
    SmallStepMode(30);
    resetEDPins();
    digitalWrite(ledPin, LOW);
  } else {
    Serial.println("Already read");
  }
}

boolean setupRfidModule(long baudRate) {
  rfidModule.begin(rfidSerial, moduleType); // Tell the library to communicate over serial port
  // Test to see if we are already connected to a module
  rfidSerial.begin(baudRate); // For this test, assume module is already at our desired baud rate
  delay(100); // Wait for port to open

  // About 200ms from power on the module will send its firmware version at 115200. We need to ignore this.
  while (rfidSerial.available())
    rfidSerial.read();

  rfidModule.getVersion();

  if (rfidModule.msg[0] == ERROR_WRONG_OPCODE_RESPONSE) {
    // This happens if the baud rate is correct but the module is doing a continuous read
    rfidModule.stopReading();

    Serial.println(F("Module continuously reading. Asking it to stop..."));
    delay(1500);
  } else {
    // The module did not respond so assume it's just been powered on and communicating at 115200bps
    rfidSerial.begin(115200); // Start serial at 115200

    rfidModule.setBaud(baudRate); // Tell the module to go to the chosen baud rate. Ignore the response msg

    rfidSerial.begin(baudRate); // Start the serial port, this time at user's chosen baud rate

    delay(250);
  }
  // Test the connection
  rfidModule.getVersion();
  if (rfidModule.msg[0] != ALL_GOOD)
    return false; // Something is not right

  // The module has these settings no matter what
  rfidModule.setTagProtocol(); // Set protocol to GEN2
  rfidModule.setAntennaPort(); // Set TX/RX antenna ports to 1

  return true; // We are ready to rock
}

boolean isNewTag(byte* currentUID, byte currentUIDLength) {
  if (currentUIDLength != lastUIDLength) {
    return true; // Different length means different tag
  }

  for (byte i = 0; i < currentUIDLength; i++) {
    if (currentUID[i] != lastUID[i]) {
      return true; // Different UID means different tag
    }
  }

  return false; // Same UID means same tag
}

it is hard to see in the picture, but there is an unused connection between VCC and GND on the M7E. DId you skip that ?

Setting pin 12/13 to HIGH is already done by SoftwareSerial during creating the instance. It should not have an impact.

Are you sure there is NOTHING else connected on Pin 12 /13 from the board in between? Maybe remove it for test and use a standard RFID example?

Is the power provided to the M7E 5V ?

enable RFID debug and share what you see

else you can set the Serial speed to ‘hc05_baudrate’ from the start.

Spend more time looking at the M7E and there are important differences between the M6E and M7E. I documented my first findings (attached).

One aspect that could be important in this case is that the M6E has an onboard level shifter (TXB0104) to make RX and TX 5V compatible. The M7E does not have a level shifter and looks 3v3 compatible. The M7E datasheet indicates this also: UART; 3.3V logic levels 9.6 to 921.6 kbps.

  1. Try to connect a level shifter on the RX/TX lines

  2. OR try a resistor voltage divider on the M7E RX line. There is no need to do that on the M7E TX line.

diff_M6e-M7E.zip (338 KB)

Hi Paul,

I’ve spent some time playing with the module, but the problem persists and it’s driving me crazy! :frowning:

So far, I have observed the following:

  • With a direct USB connection, the module works perfectly.

  • If you program the module with a specific baud rate, it will initiate communication with that baud rate on subsequent startups (and not 115700).

  • When using the serial connection (SoftSerial on pins 11 & 12), the response is unstable. Most of the time, or from code to code, it fails to start a serial connection and sends a “check the wiring” message. The connections are solid.

Initially, I was powering the RFID module with the +5V from the Arduino. I then switched to 3.3V using a breadboard power supply connected to a 12V DC battery pack for the RFID, while the Arduino remained connected to the PC. The instability persists.

paulvha:

  1. Try to connect a level shifter on the RX/TX lines.

  2. OR try a resistor voltage divider on the M7E RX line. There is no need to do that on the M7E TX line.

I haven’t tried these yet, as I’m not sure how to approach this. I will try these in the upcoming days. I hope it resolves the issue because otherwise, I have no clue what could be causing the problem!

Best,

Shiin

Hi Paul,

.

paulvha:
The M7E does not have a level shifter and looks 3v3 compatible. The M7E datasheet indicates this also: UART; 3.3V logic levels 9.6 to 921.6 kbps.

I measured the pin voltages on my M7E , and whether it was connected to a 5V or 3.3V power supply (via a breadboard power supply module with 12V DC input) or directly to the Arduino’s 5V (connected to PC), the RX and TX lines both are 2.49V.

Additionally, I observed the following current measurements:

between Vcc and Gnd: 1 µA

RX and Gnd: 0.48 µA

TX and Gnd: 1 µA

What do you think could be the problem? If it is the internal pull-up resistor, could it be fixed?

it is getting a long issue.

What do you think could be the problem? If it is the internal pull-up resistor, could it be fixed?

Nothing can be done about the internal pull-up nor should it.

If you program the module with a specific baud rate, it will initiate communication with that baud rate on subsequent startups (and not 115700).

I expect only after you remove the power and re-apply it will reset to the default 115200. Else it would stay on the latest selected power. (as with the M6E)

For test I would propose to go back to the basics: remove all the other hardware boards only keep the UNO and M7E. Connect directly to the UNO with software serial pin 2 and 3 and use example1. Connect power 5V and GND. Does that work?

I cant get this to connect on the Universal Reader software. Did you need to install any drivers?

you will need te Ch340 drivers on windows. see How to Install CH340 Drivers - SparkFun Learn