SPI communication MOSI not high enough

Hello,

I have been using the INA239 current sensor via SPI to a Teensy4.1 board successfully with a wire length of about 5 inches. The strange thing is that, if I extend the wire length to 12 inches, I can see on the oscilloscope that the MOSI line stops working and stays relatively low voltage around 1.8 volts when my power is 3.3V. I then get nothing from the SPI communication after that.

The datasheet for the INA239 states that the data is shifted out on the Rising edge and data is sampled on the Falling edge, and I believe I have the settings correct.

SPISettings INA239_settings(1000000, MSBFIRST, SPI_MODE1);

Any thoughts on why the MOSI line dies down after adding 7 inches to the length of the wire?

The rest of my code is below:

/*
   MCU: TEENSY 4.1
   URL:
   https://www.pjrc.com/store/teensy41.html
   LEAP: INA239 Sensor for OUTPUT power
   DATASHEET:
   https://www.ti.com/lit/ds/symlink/ina239.pdf?ts=1684330883046&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252FINA239
*/

#include <Streaming.h>
#include <SPI.h>

#define CS          10

#define POT_MAX     255



/*
   SHUNT_CAL = (819.2x10^(6))*(Current_LSB)*(Rshunt)

   CURRENT_LSB = (max Current expected)/(2^(15))

   CURRENT[A] = (CURRENT_LSB)*(CURRENT_FROM_REGISTER)

   POWER[W] = (0.2)*(CURRENT_LSB)*(POWER_FROM_REGISTER)

   R_SHUNT = 1.365 milliOhms -> 100milliV reading range

*/

//const double current_lsb = 0.001068115; // 1.365 milli ohm
const double current_lsb = 0.0000305; // 25 milli ohm

int serialCount = 0;
float v1, v2, outv1, outv2;
byte pc1, pc2, outpc1, outpc2;
float currentSum = 0;
float mappedVoltage = 0;
float voltage, current;
double power;
float outvoltage, outcurrent, outpower;

/*
    INA239 captures data on falling edge & shifts out data on rising edge.
    Therefore we need to use SPI_MODE1.
    spi settings from the spi.h online (speedMax in hz, dataOrder, dataMode)
*/

SPISettings INA239_settings(1000000, MSBFIRST, SPI_MODE1);

void setup() {

  pinMode(CS, OUTPUT);
  digitalWrite(CS, HIGH); // turn spi device 1 off initially

  Serial.begin(115200);
  SPI.begin();

//  while (!Serial) {
//    ; // wait for serial port to connect. Needed for native USB port only
//  }
}

float mapf(float x, float in_min, float in_max, float out_min, float out_max) {
  /* mapping values: analog to ____ */
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

/*
   function to write calibration value based on the shunt resistor used.
   must transder to register in hexidecimal.
*/
void writeShuntCal() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);              //turn on spi device 1
  //  SPI.transfer(0x01 << 2 | 0x00);   //ADC_CONFIG REGISTER
  //  SPI.transfer(0xB0);
  //  SPI.transfer(0x05);
  //  SPI.transfer16(0x07);
  SPI.transfer(0x02 << 2 | 0x00);  //SHUNT_CAL REGISTER; SET TO MEASURE <= 35A. OUTPUT SHUNT RESISTANCE: 1.365mOHM
  SPI.transfer(0x04);
  SPI.transfer(0xAE);
  //  SPI.transfer(0x01);
  //  SPI.transfer(0xF2);
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to read the sense voltage. register 5h
*/
void readVoltage() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);            //turn on spi device 1
  SPI.transfer(0x05 << 2 | 0x01);   //register to read
  v1 = SPI.transfer16(0);
  voltage = v1 * (0.003125);
  Serial << "Voltage: " << voltage << endl;
  digitalWrite(CS, HIGH);           // turn off spi device 1
  SPI.endTransaction();
}

/*
   function to read the sense current. register 7h
*/
void readCurrent() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x07 << 2 | 0x01);
  pc1 = SPI.transfer16(0x00);
  pc2 = SPI.transfer(0x00);
  currentSum = ((uint32_t)pc1 << 8 | pc2);
  current = (currentSum * current_lsb) * 2;
  //Serial << pc1 << " " << pc2 << endl;
  //Serial << currentSum << endl;
  Serial << "Current: " << current << endl;
//  if (current > 60) {
//    current = 0;
//    Serial << "Current: " << _FLOAT(current, 6) << endl;
//  }
//  else {
//    Serial << "Current: " << _FLOAT(current, 6) << endl;
//  }
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to manually calculate power based on the
   value read from the voltage and current reg.
*/
void readPower_ManualCalculation() {
  power = (voltage * current);
  Serial << "power: " << power << endl;
}


/*
   function to read the sense power. register 8h
*/
void readPower() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x08 << 2 | 0x01);
  byte p1 = SPI.transfer(0x00);
  byte p2 = SPI.transfer(0x00);
  byte p3 = SPI.transfer(0x00);
  power = ((uint32_t)p1 << 16 | (uint32_t)p2 << 8 | p3) * (0.2) * (0.001068115);
  Serial << "Power:   " << power << endl;
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to read the voltage drop across the shunt resistor.
   register 4h
*/
void readShuntVoltage() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x04 << 2 | 0x01);
  float shuntVoltage = SPI.transfer16(0);
  float shuntVoltageTwo = (shuntVoltage * 0.000005);
  Serial << shuntVoltage << endl;
  Serial << _FLOAT(shuntVoltageTwo, 6) << endl;
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to read the shunt calibration register.
   register 2h
*/
void readShuntCalReg() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x02 << 2 | 0x01);
  float shunt = SPI.transfer16(0);
  //byte shuntAdd1 = SPI.transfer(0x00);
  //byte shuntAdd2 = SPI.transfer(0x00);
  //Serial << shuntAdd2 << " " << shuntAdd1 << endl;
  Serial << shunt << endl;
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to read the ADC range mode. register 1h
   Two options only with the INA239.
   1. +- 163.84 mV
   2. +- 40.96 mV
*/
void readADCReg() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x01 << 2 | 0x01);
  float adcReg = SPI.transfer16(0);
  Serial << adcReg << endl;
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

/*
   function to read the manufacturer ID. register 3Eh
   should read 84 73 -> = 
*/
void readID() {
  SPI.beginTransaction(INA239_settings);
  digitalWrite(CS, LOW);
  SPI.transfer(0x3E << 2 | 0x01);
  byte m1 = SPI.transfer(0x00);
  byte m2 = SPI.transfer(0x00);
  Serial << m1 << " " << m2 << endl;
  digitalWrite(CS, HIGH);
  SPI.endTransaction();
}

void setAD5160Resistance(byte value) {
  /*--- Function to set the resistance value on the AD5160 ---*/
  digitalWrite(CS, LOW);      // Select the AD5160
  //SPI.transfer(0x11);                         // Command byte to update the resistance
  SPI.transfer(value);                        // Send the value to set the resistance (0 to POT_MAX)
  digitalWrite(CS, HIGH);     // Deselect the AD5160
}

int readAD5160Resistance() {
  /*--- Function to read the current resistance value from the AD5160 ---*/
  digitalWrite(CS, LOW);         // Select the AD5160
  SPI.transfer(0x01);                                   // Command byte to read the resistance
  byte value = SPI.transfer(0x00);                      // Dummy byte to read the response
  digitalWrite(CS, HIGH);        // Deselect the AD5160
  return map(value, 0, POT_MAX, 0, 10000); // Map to the desired resistance range
}

/*
*/
void loop() {
  delay(500);
  writeShuntCal();
  //readShuntCalReg();
  //readADCReg();
  readID();
  //readShuntVoltage();
  Serial << "----------------------------" << endl;
  readVoltage();
  readCurrent();
  //readPower();
  readPower_ManualCalculation();
  Serial << "----------------------------" << endl;
}

IDK, for a question like this, surely you should show us the wires...

Hi what do you mean? like my connections? or the type of wire?

Please read the forum introductory guidelines document about how to post a question. It explains it better than I can.

The type of wire. Thinner is better.
Basically what you encountering in the capacitance of the wire.
Capacitance is a phenomena which takes place on the surface of the metal. The wire starts to act like a capacitor (energy storage unit basically) , the more surface the more capacitance (the type of metal also is a factor, but the surface size is dominant)
Try a solid, thin wire.

I'm sure you know, a solid, thin wire can still easily be configured in a very bad way. And, we don't know what kind of wire it now is. You can not make assertions about capacitance without knowing how the wire is laid out in 3d space.

I think, it's perfectly fair to ask for images.

Also if the DC voltage goes to 1.8V under these circumstances, capacitance can't be a factor. The actual problem here is the lack of details. That is why a reference to the forum guidelines is not just a knee jerk reaction.

Wiring error. Post a schematic diagram and a clear, focused, close up photo of your setup.

1 Like

I am pretty sure I have the wiring connections connected to the right pins.

/*
Teensy 4.1 SPI pins
10 - CHIP SELECT
11 - MOSI
12 - MISO
13 - CLOCK
*/

/*
Teensy mcu -> ina239 sensor connection
10 -> CS
11 -> SDI
12 -> SDO
13 -> SCK
*/

Below are the photos I took of my setup.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.