This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

PGA460-Q1: PGA460 SPI Problem

Part Number: PGA460-Q1
Other Parts Discussed in Thread: PGA460

Hi all, Hi Akeem,

Since last week I am experimenting with the PGA460. UART communication works fine but in the final circuit there is no UART left so I chose to use SPI/USART instead.

I set up the following test code for UART communication in Arduino IDE and used a Leonardo board:

byte th[] = {0x55, 0x10, 0xB0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xB4, 0xA6, 0x90, 0x07, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8}; // threshold values
byte tn[] = {0x55, 0x04 , 0x00 , 0xFB}; // temperature and noise
byte tnr[] = {0x55, 0x06, 0xF9}; // temperature and noise result

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

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {    
    previousMillis = currentMillis;  
    ms_uart();
    Serial.println("");
  }
  
  while (Serial1.available()) {
    byte b = Serial1.read();
    Serial.print(b, HEX);
    Serial.print(" ");          
  }  
}

void ms_uart(){
    Serial1.write(th, sizeof(th));
    Serial1.write(tn, sizeof(tn));
    delay(10);
    Serial1.write(tnr, sizeof(tnr));
}

This code works fine and gives me the following result which is plausible and has a correct checksum:

40 73 2D 1F

Distance measurements and data dumps are also OK.

Now I modified the code to work via SPI and connected MOSI to RX, MISO to TX and CLK to CLK:

#include <SPI.h>

byte th[] = {0x55, 0x10, 0xB0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xB4, 0xA6, 0x90, 0x07, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8}; // threshold
byte tn[] = {0x55, 0x04 , 0x00 , 0xFB}; // temperature and noise
byte tnr[] = {0x55, 0x06, 0xF9}; // temperature and noise result
byte buf[4];

SPISettings pga460_spi(1000000, LSBFIRST, SPI_MODE2);

void setup() {  
  Serial.begin(115200);
  SPI.begin();
}


void loop() {  
  ms_spi();
  Serial.println("");
  delay(1000);  
}

void ms_spi(){
  SPI.beginTransaction(pga460_spi); 
  SPI.transfer(th, sizeof(th));
  SPI.transfer(tn, sizeof(tn));
  delay(10);
  SPI.transfer(tnr, sizeof(tnr));  
  for(uint8_t i = 0; i < 4; i++){
    buf[i] = SPI.transfer(0xFF);    
  }
  SPI.endTransaction();
  print_buffer();
}

void print_buffer(){
  for(uint8_t i = 0; i < 4; i++){
    Serial.print(buf[i], HEX);
    Serial.print(" ");
  }
}

As a result I get this:

73 2D FE FF

which is not plausible and has a wrong checksum AND only the first time it is executed gives me this result. All following results in the loop are [0 0 0 0].

The hardware is identical, I also tried with other controller boards (ESP32, ESP8366, Arduino Mega, Arduino UNO) , all with the same problem.

Does anyone have an idea what I am doing wrong here? I tried the hole day with different tweaks and tricks but nothing helps.

Thanks a lot,

Peter

  • Hello Peter,

    Akeem Whitehead our PGA460 device application engineer will respond to your question soon.

  • OK, the problem with the above code is that I overwrite my buffers. Sorry for being a fool.

    Trying something different now.

  • Hi Peter,

    I'm glad to hear you were able to debug this issue on your own in such a short time.

    Do you have any additional questions regarding the SPI/USART mode of the PGA460?

  • @Akeem,

    here is my test code for the ESP32 to show you where the problem is. It receives an "s" or an "u" for SPI or UART and sends the an identical code to the PGA460 via one of the lines.

    BTW, an external pullup resistor on the RX pin of the ESP32 is mandatory to make it work with UART.

    #include <SPI.h>
    #include <HardwareSerial.h>
    
    byte th[] = {0x55, 0x10, 0xB0, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC3, 0xB4, 0xA6, 0x90, 0x07, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8};
    byte tn[] = {0x55, 0x04 , 0x00 , 0xFB}; // temperature and noise
    byte tnr[] = {0x55, 0x06, 0xF9}; // temperature and noise result
    
    int count = 0;
    uint8_t port = 0;
    byte buf[4];
    
    HardwareSerial pga460_uart(2);
    SPISettings pga460_spi(1000000, LSBFIRST, SPI_MODE2);
    
    void setup() {
      pinMode(19, INPUT_PULLUP);  
      pinMode(5, OUTPUT);
      pinMode(18, OUTPUT);
      Serial.begin(115200);
    }
    
    void loop() {
      while(Serial.available()){
        char m = Serial.read();
        if(m == 's') port = 1;
        if(m == 'u') port = 2;    
      } 
    
      switch (port){
        case 1: ms_spi();
        break;
        case 2: ms_uart();
        break;
      }
    
      port = 0;  
    }
    
    void ms_spi(){
      Serial.print(count);
      Serial.println(" SPI");
      count++;
      SPI.begin(18,19,23,5);  
      
      digitalWrite(5, HIGH);
      SPI.beginTransaction(pga460_spi);
    
      for(uint8_t i = 0; i < sizeof(th); i++){
        SPI.transfer(th[i]);
      } 
      delay(1);
      for(uint8_t i = 0; i < sizeof(tn); i++){
        SPI.transfer(tn[i]);
      } 
      delay(10);
      for(uint8_t i = 0; i < sizeof(tnr); i++){
        SPI.transfer(tnr[i]);
      } 
      delay(1);
      for(uint8_t i = 0; i < 4; i++){    
        buf[i] = SPI.transfer(0xFF);          
      } 
      
      digitalWrite(5, LOW);
      SPI.endTransaction();
      SPI.end();
      print_buffer();
    }
    
    void ms_uart(){
      digitalWrite(18, LOW);
      pga460_uart.begin(115200, SERIAL_8N2, 19,23);
      Serial.print(count);
      Serial.println(" UART");
      count++;
      pga460_uart.write(th, sizeof(th));    
      pga460_uart.write(tn, sizeof(tn));
      delay(10);
      pga460_uart.write(tnr, sizeof(tnr)); 
      while(!pga460_uart.available()){};  
      while (pga460_uart.available()){
        Serial.print(pga460_uart.read(), HEX);
        Serial.print(" ");
      }
      Serial.println("");
      pga460_uart.end();
    }
    
    void print_buffer(){
      for(uint8_t i = 0; i < 4; i++){
        Serial.print(buf[i], HEX);
        Serial.print(" ");
      }
      Serial.println(""); 
    }

    The result:

    UART:
    44 73 2D 1B

    Nothing susicious here.

    SPI:
    73 2D FE FF

    Wrong values and wrong checksum.

    Doing this with different Arduino boards (UNO, Leonardo, MEGA) leads to the exact same error.

    I ordered an MSP430 board to perform more tests. Do you have any idea why the standard SPI does not work?

    Changing the SPI mode to 0 gives a series of 0x00 back. Different speed settings do not help either.

  • Here is a binary output for comparison. It looks as if the SPI output is shifted by one byte:

    0 UART
    1000100 1110011 101101 11011 
    44 73 2D 1B 
    
    1 SPI
    1110101 101101 11111100 11111111 
    75 2D FC FF 
    
    2 UART
    1000100 1110101 101101 11001 
    44 75 2D 19 
    
    3 SPI
    1110101 101101 11111100 11111111 
    75 2D FC FF 
    

  • OK, I found another hint and skipped the checksum in the last command which is a response command (6).

    With that done I get the following results (UART and SPI):

    UART:
    1000100 1110011 101101 11011 
    44 73 2D 1B 
    
    SPI:
    1000000 1110011 101101 10011111 
    40 73 2D 9F 
    

    Now the data bytes are at the correct position but the diagnostic bytes are different and the checksum is still wrong.

    The diagnostic data field looks fine so I could live with that. But why the wrong checksum?

  • Next test: I increased the baud rate to 2 Mbps and then higher up to 8 Mbps and then the checksum is correct. The checksum error seems to occur only when the baud rate is lower than or equal to 1 Mbps. Strange but not a real problem as long as the master controller can handle it.