Post Go back to editing

MAX22200 Serial-Controlled Solenoid and Motor Driver SPI Communication Problem

Category: Software
Product Number: MAX22200ETJ+
Software Version: stm32h747

Hello,

I am trying to read MAX22200 Serial-Controlled Solenoid and Motor Driver data with spi communication. I ran into a few problems and frankly, I couldn't find many examples on the internet so I wanted to ask here.

When I examined the datasheet, I read that I had to send the Command Register to the sensor first and then write data or read data.

For example, when I energize, I want to read the STATUS Register Address(0x00) data of the sensor. I am sending 0x80 by SDI as Command Register. 

In order to be able to read 32-bit data after the data, I send 0x00 by SDI, since no information is given on the datasheet side, I read 0x00 by SDO.

The question mark point stuck in my head here is actually when I change any bit of the STATUS Register, I still read 0x00.

Topics on my mind,

  •  While the command register is sending 8-bit data, only the CMD pin will be made HIGH-LOW, then it should always stay LOW, right?
  • The bit 0x02 status referred to as STATUS[0:7] is understood as FAULT, but what is the status it returns by default?
  • Can you share sample code that I can review on this topic?



naming error fixed.
[edited by: aemiroglu at 6:19 AM (GMT -4) on 14 Jul 2023]
  • I had some difficulties understanding controlling this solenoid driver myself, but I created the following sketch in Arduino and I was able to turn solenoids on and off. It is very basic, and I just created this to make sure I understand the operating sequence. Next, I have to create some functions to clean this up, but I hope this helps to understand the sequence:

    #include <SPI.h>

    #define pin_csb 7 // Change this to your chip select pin
    #define pin_en 8 // Change this to your enable pin
    #define pin_cmd 9 // Change this to your command pin

    byte response;

    void setup() {
    Serial.begin(115200);
    delay(500); // delay required to connect to Serial
    Serial.println("Initiated");

    pinMode(pin_csb, OUTPUT);
    pinMode(pin_en, OUTPUT);
    pinMode(pin_cmd, OUTPUT);

    digitalWrite(pin_csb, HIGH); // Keep CS high till SPI is required (chip select)
    digitalWrite(pin_en, HIGH); // Enable the device
    digitalWrite(pin_cmd, LOW);

    SPI.begin();
    SPI.beginTransaction(SPISettings(5000000, MSBFIRST, SPI_MODE0));

    Serial.print("\nInitiated\nResponse from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    delayMicroseconds(50);
    digitalWrite(pin_csb, LOW);
    response = (SPI.transfer(0x00), BIN); // Read = 0, Status register 0x00, use 8MSB = 0
    digitalWrite(pin_csb, HIGH);
    delayMicroseconds(50);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    delay(100);

    Serial.print("Response from STATUS register: ");
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x00);
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN); // Read the status register

    Serial.println("\nWrite status register to device activation");
    Serial.print("Response from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x80); // write = 1, Status register 0x00, use 8MSB = 1
    digitalWrite(pin_csb, HIGH);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    Serial.print("Response from writting to STATUS register: ");
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x01); // Read the status register
    SPI.transfer(0x00);
    SPI.transfer(0x00);
    SPI.transfer(0x00);
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN);

    delay(100);

    Serial.println("\nRead status register for UVM");
    Serial.print("Response from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x00); // Read = 0, Status register 0x00, use 8MSB = 0
    digitalWrite(pin_csb, HIGH);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    Serial.print("Response from STATUS register: ");
    digitalWrite(pin_csb, LOW);
    SPI.transfer(0x00); // Read the status register (32 bits)
    SPI.transfer(0x00); // Read the status register (32 bits)
    SPI.transfer(0x00); // Read the status register (32 bits)
    response = SPI.transfer(0x00); // Read the status register (32 bits), and safe status
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN);

    delay(100);

    Serial.println("\nRead again status register to clear UVM");
    Serial.print("Response from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x00); // Read = 0, Status register 0x00, use 8MSB = 0
    digitalWrite(pin_csb, HIGH);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    Serial.print("Response from STATUS register: ");
    digitalWrite(pin_csb, LOW);
    SPI.transfer(0x00); // Read the status register (32 bits)
    SPI.transfer(0x00); // Read the status register (32 bits)
    SPI.transfer(0x00); // Read the status register (32 bits)
    response = SPI.transfer(0x00); // Read the status register (32 bits), and safe status
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN);
    }

    void loop() {
    delay(1000);

    Serial.println("\nTurn on the solenoid on channel 0&1");
    Serial.print("Response from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x80); // write = 1, Status register 0x00, use 8MSB = 0
    digitalWrite(pin_csb, HIGH);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    Serial.print("Response from STATUS register: ");
    digitalWrite(pin_csb, LOW);
    SPI.transfer(0x01); // Write the status register active
    SPI.transfer(0x00); // Read the status register
    SPI.transfer(0x00); // Read the status register
    response = SPI.transfer(0x03); // Write the status register with Channel 0&1
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN);

    delay(1000);

    Serial.println("\nTurn off the solenoid on channel 0&1");
    Serial.print("Response from COMMAND register: ");
    digitalWrite(pin_cmd, HIGH);
    digitalWrite(pin_csb, LOW);
    response = SPI.transfer(0x80); // write = 1, Status register 0x00, use 8MSB = 0
    digitalWrite(pin_csb, HIGH);
    digitalWrite(pin_cmd, LOW);
    Serial.println(response, BIN);

    Serial.print("Response from STATUS register: ");
    digitalWrite(pin_csb, LOW);
    SPI.transfer(0x01); // Write the status register with active
    SPI.transfer(0x00);
    SPI.transfer(0x00);
    response = SPI.transfer(0x00); // Write the status register with 0 to turn off all channels
    digitalWrite(pin_csb, HIGH);
    Serial.println(response, BIN);
    }

  • Some comments:

    • The CMD pin should only be pulled high right before writing to the command register, otherwise that line should be pulled low.
    • The bits returned by STATUS[7:0] depend on whether you have initialized the part or not. Figure 6 in the MAX22200 IC datasheet shows the programming flow chart. On the first read of the status register, STATUS[7:0] will show 0x02. After the status register is set and the channels are configured, reading STATUS[7:0] will show 0x03. A final read will show 0x01, which means the channels can now be turned on and certain on-the-fly actions can be performed. For normal operation, STATUS[7:0] will read 0x01 (no fault flags triggered and device is active).
    • The Pmod board for the MAX22200 IC (which is used with the TMCM-0960-MotionPy V21) will be out soon, but for now here are the links to the Python driver which is used for that board. The max22200pmb.py file is an example script that initializes the board and sets up Channel 0. You can see that the initialization follows the programming flowchart from the datasheet. The max22200.py file provides all the functions used in the example script.


    You wrote that you sent 0x80 to the command register to read the status register, but you should be sending 0x00 instead. Sending 0x80 tells the command register that your next action is writing to the status register. Can you confirm that when you are writing to the status register, the command register is set up properly?

  • Hi!

    I also spent a lot of time getting the communication between a stm32 nucleo board and the MAX22200 to work. I found a project on github with drivers for the chip and used them as a starting point. Basically I just adapted the style and functions to suit my project and added and removed functions as needed. Maybe it can help others too.

    Here is the link: https://github.com/mentee-robotics/Hand6Motors/blob/main/Core/Src/max22200_driver.c

    Regards

    Lars

  • Have you managed to get proper return values from the MAX chip? I'm using an stm32 controller and can also turn channels on and off but can't seem to get real return values. I also just tried your arduino sketch since I had an ESP32 board here but then I also only get a UVM flag at start and aftere that only zeroes or ffff.

    Regards

    Lars

  • Apparently since last week there is an official driver available here: https://github.com/analogdevicesinc/no-OS/tree/master/drivers/digital-io/max22200

    A bit annoying that it's still not mentioned anywhere else on the site.

  • If you can write to the IC but the read data is not available, one reason could be that you did not connect a pull-up resistor (300-360 ohm) to 3.3v  from the MISO pin of the eval board. You need to do this as the pin is open-drain.

    BR.

  • Hi!

    Yes that turned out to be the problem. The reason was that when using an stm32 nucleo board doing the setup in CubeMX, it can often happen that when changing something in the CubeIDE and then generating the code again, the internal pullups or pulldowns disappear. 

    So always check this or as you said, use external pullups.

    Regards

    Lars