MS5611 pressure sensors not responding.

I've soldered a couple MS5611s to breakout boards (nothing fancy, just adding .1inch headers and no other circuitry on the BoB) and set them up according to the SPI reference circuit in the datasheet

All three lines have a max voltage of 2.7v, which is well within the requirements specified in the datasheet.

When the circuit powers up, SDO goes high and stays there permanently. From the looks of the datasheet, on page 10, SDO should go low after bit 6's clock goes high. SDO should then go high again 2.8 ms later. After struggling to work out why I was getting no response to requests for PROM/temp/pressure reads, I hooked up the oscilloscope to see exactly what's going on. You can see in the image that the top trace (SCLK) and the bottom trace (SDI) exactly match the datasheet. However, SDO never goes low. My first assumption was that something was wrong with CSB (chip select.) However, a quick check with the multimeter shows that it is correctly grounded. (I have it wired directly to ground since I want the MS5611 active all the time.) Similarly, protocol select (PS) is also wired to ground to select the SPI protocol.

My soldering work isn't 100% verifiable, but since pins 4 and 5 are internally wired in the MS5611, I can at least test those two solder points by checking for continuity between the legs on the breakout. Both test devices have <0.5 ohm.

I'm not using the arduino SPI library, but it's irrelevant - the scope shows an identical electrical behavior to what is shown in the datasheet.

Anyone have any thoughts on what on earth is happening here? Why is SDO never going low (during reset or any other request, for that matter?)

Thanks

Post a complete wiring diagram of your setup!

Post your code (don't forget the code tags!).

If you power the sensors with 2.7V you must use the same voltage for your SPI bus, so a level converter is needed. Ensure that MSIO goes tri-state if no 2.7V CS is selected.

Since I'm using a 2.7v arduino (the MKRZERO), the level converter isn't necessary.

I've included the code, below, though it isn't relevant since the sensor doesn't care what's going on on the processor. The clock, MISO, MOSI channels, and as you can see in the .jpg from the original post, are being driven exactly as diagrammed in the datasheet, but the sensor isn't responding. It's in an extremely experimental state, but it's driving the comms pins exactly as required (see the .jpg), so again - it's irrelevant.

The wiring diagram is, as stated in the original post, exactly as specified in the datasheet. Since I'm not using the arduino SPI library, I could be using any pins, but for the sake of self-documentation I used SCK, MOSI, and MISO. On the MKRZERO, they are 9, 8, and 10, respectively. SCLK, SDO, and SDI are pins 8, 6, and 7 on the ms5611. I've included the 100nF capacitor between V+ and GND, right at the MS5611, and as mentioned in the original post, the protocol select and chip select are permanently grounded.

I've double-checked that the datasheet is referring to "out" and "in" from the MS5611's perspective. In other words, SDO is data leaving the MS5611. (I'd hoped that my mistake had been that "out" was data out from the arduino and "in" was data entering the arduino.)

Operating on the assumption that I might have overheated the sensors while soldering them, or that I might have had a bad batch, I ordered another set from a different distributor and I have exactly the same problem. The datasheet limits soldering time/temp to 40s @ 250C. I soldered @ 250C for about 32 seconds, total, in 4s bursts... allowing the chip to cool fully between soldering each pin. I was very careful not to contaminate the vent holes with solder or flux.

#include <SPI.h>

// ASSUMES THAT SCK IS LOW TO BEGIN WITH.
void bit_out(int bit) {
  digitalWrite(MOSI, bit?HIGH:LOW);
  delayMicroseconds(50);
  digitalWrite(SCK, HIGH);
  delayMicroseconds(50);
  digitalWrite(SCK, LOW);
}

int bit_in() {
  int bit;
  digitalWrite(SCK, HIGH);
  delayMicroseconds(50);
  bit = digitalRead(MISO);
  digitalWrite(SCK, LOW);
  delayMicroseconds(50);
  return bit;
}

// SPI Mode 0. Most Significant Bit (MSB) first. Output on falling edge, capture on rising.
// I'm not using the arduino's built-in SPI library for a couple reasons;
// * The SPI lib assumes that you are receiving 8 bits for every 8 bits sent or 16 for 16.
//   This is simply not true for the ms5611. I'm not entirely sure on this, but the other
//   issues are sufficient for me to write my own comms.
// * I could possibly work around the bad 8/16 arduino lib assumption, but it would mean
//   having SCK/SCLK oscillating while conversions are being done, which causes conversion
//   noise.
// * Having 2 ms5611s on the same arduino means having them on separate busses (if I want
//   to be talking to one while the other is converting). This is, again, because I don't want
//   to be running the bus clock while a sensor is converting. I'll eventually require at least 2
//   ms5611s per arduino, so the SPI library is not an option.
long int spi_command(byte command, unsigned int wait_time, int result_len) {
  digitalWrite(SCK, LOW);
  for(int i=0; i<8; i++) {
    bit_out(((0x80>>i)&command)?HIGH:LOW);
  }
  digitalWrite(MOSI, LOW);

  delayMicroseconds(wait_time);
  
  long int result = 0;
  for(int i=0; i<result_len; i++) {
    result <<= 1;
    result |= bit_in();
  }

  return result;
}

void ms5611_reset() {
  spi_command(0x1e, 0, 0);
  // The required delay time is 2.8ms, but I've had issues w/ badly clocked arduinos, so
  // I'm giving myself some padding.
  delayMicroseconds(3500);
}

//OSR = 4096 for best resolution
unsigned long ms5611_temp() {
  spi_command(0x48, 9000, 0);
  return spi_command(0x00, 0, 24);
}

//OSR = 4096 for best resolution
unsigned long ms5611_pressure() {
  spi_command(0x58, 9000, 0);
  return spi_command(0x00, 0, 24);
}

void setup() {
  // put your setup code here, to run once:
  Serial.begin(19200);
  delay(3000);
  Serial.println("starting");
  Serial.println(HIGH);
  Serial.println(LOW);
  pinMode(SCK, OUTPUT);
  digitalWrite(SCK, LOW);
  pinMode(MOSI, OUTPUT);
  digitalWrite(MOSI, LOW);
  pinMode(MISO, OUTPUT);
  pinMode(LED_BUILTIN, OUTPUT);

  ms5611_reset();
}

void loop() {
  //ms5611_reset();
  //delay(10);
  
  // put your main code here, to run repeatedly:
  int index = 0;
    for(byte c=0xa0; c<=0xa0; c++) {
      Serial.println(spi_command(c, 500, 24));
      delay (300);
  }
}

Since I'm using a 2.7v arduino (the MKRZERO), the level converter isn't necessary.

If a poster doesn't specify the Arduino model used we always expect him to use an UNO!

And the MKR Zero runs on 3.3V, not 2.7V.

pinMode(MISO, OUTPUT);

That produces a short-circuit. MISO is an input on the master! You might have fried your sensor already.

If MISO is not connected to SDO in your setup, post a complete wiring diagram!

That's a nice catch - thank you! Though, I wouldn't expect hardware damage since OUTPUT defaults to a low state, and since I never wrote anything there, it would never have gone high. Any current placed on MISO by the sensor would have been sunk. Unless the sensor couldn't handle a low-impedance to ground on the line, there shouldn't be an issue.

The MKRZero is providing 3.3v to the V+/GND pins, and I'm currently measuring a max voltage of 3.52V on the clock pins, 3.36V on the MOSI pins, and 0.240V on MISO. All are within the limits specified in the datasheet: 4.0V. I'm not sure why I originally said 2.7v, though that is the preferred level of the sensor. I chose the MKRZero for this test specifically because it should natively work with the sensor. I will likely have to work through a converter when I scale this project up, as the Zero is ridiculously expensive compared to most arduinos.

At any rate, I uploaded the code change, disconnected the power, swapped out the sensor for a brand-new one, set the oscilloscope trigger to fire, then plugged in the arduino. The trigger fired on the first MS5611 reset, and it's exactly the same situation as in the original attached jpg. The clock fires 8 times, with the MOSI going high on the 3rd voltage drop and going low again on the 7th.

On the off chance that connecting the arduino was surging the power above 4V, I added a probe to the power rails and set the trigger to fire, on that channel, at 3.75V. After many repeated connections and disconnections, and after leaving the thing to soak for a few hours, the scope never saw a >3.75V surge, so I feel safe in concluding that I'm not frying my sensors - at least, not that way.

GRRRRRR.

foodini:
Unless the sensor couldn't handle a low-impedance to ground on the line, there shouldn't be an issue.

The moment the sensor starts transmitting something on the SDO line (like a response to your commands), it will experience a short when the line is driven high. That's bad for the sensor in any case. I forgot if SPI is idle high or low.

The voltages you measure are also suspect. It's not possible for the sensor to output higher voltages than the voltage delivered to it by your Arduino. Also 0.24V on SDO seems rather high for what I assume is supposed to be a low signal.

I agree that it's a little odd, but in the image, channel 1 is clock, 2 is MOSI, 3 is MISO, and 4 is V+/GND, and I'm seeing a max power of 3.36 and a max on clock of 3.6. All of these values are max, not sustained.

Including a current photo of the circuit.

foodini:
I agree that it's a little odd, but in the image, channel 1 is clock, 2 is MOSI, 3 is MISO, and 4 is V+/GND, and I'm seeing a max power of 3.36 and a max on clock of 3.6. All of these values are max, not sustained.

That is probably just a scope artifact. You see the little overshoot lines at the rising and falling edges. That's quite common an occurrence and should be ignored.

Any current placed on MISO by the sensor would have been sunk. Unless the sensor couldn't handle a low-impedance to ground on the line, there shouldn't be an issue.

I don't know how much current the sensor can provide but a short on that line might destroy the sensors pin driver or the Arduinos (it doesn't sink any current).

You don't follow the reset sequence! You must handle CSB actively (so pull it from high to low) to start the reset sequence. You cannot have it pulled low constantly (at least that's my interpretation of the datasheet).

For anyone who is interested, I've put together a library that drives the ms5611 on Github