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.

PGA460PSM-EVM: Energia code library guides adaptation to ESP32 in Arduino IDE

Part Number: PGA460PSM-EVM
Other Parts Discussed in Thread: PGA460, ENERGIA, TEST, PGA460-Q1


I've already evaluated PGA460 with PGA460Q1-EVM and now I'm developing an design where I want ESP32 to control the PGA, so I used PGA460-PSM and connected VPWR to 12 Vdc, TXD to RX ESP32; RXD to TX ESP32; GND to ESP32 GND wich is also conected with the 12 voltage source GND. I could send some simple comands like reading eeprom but I have no response from PGA tx looking on the oscilloscope. ESP32 logic level is 3.3V so it should work fine without pull-up resistors, right?

I'm trying to adapt Energia PGA460_USSC library in Arduino IDE to use with ESP32 but I'm having trouble in doing so. I only use "PGA460_USSC.h", "PGA460_USSC.cpp" and I use pins 22 and 23 as UART rx, tx and the ESP32 UART library for Arduino IDE. I'm sending my files attached. I've taken out all SPI and TCI functions and all references to pins I dont use. 

This is the results so far..


  • I've tryied also this code I found in other post and had no response on PGA's TX.


    //cmd 0 - p1 burst listen
    byte buf0[4] = {0x55, 0x00, 0x01, 0xFE};
    //cmd 1 - p2 burst listen
    byte buf1[4] = {0x55, 0x01, 0x01, 0xFD};
    //cmd 10 - register write decple to time of 4.096ms
    byte buf10[5] = {0x55, 0x0A, 0x26, 0x00, 0xCF};
    //cmd 17 - broadcast p1 burst listen
    byte buf17[4] = {0x55, 0x11, 0x01, 0xED};
    //cmd 19 - broadcast p1 listen only
    byte buf19[4] = {0x55, 0x13, 0x01, 0xEB};
    //cmd 25 - broadcast bulk threshold write
    byte buf25[35] = {0x55, 0x19, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x84, 0x21, 0x08, 0x42, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x84, 0x21, 0x08, 0x42, 0x10, 0x80, 0x80, 0x80, 0x80, 0x00, 0x7C};
    #include <SoftwareSerial.h>
    SoftwareSerial mySerial(22,23);
    //const int buttonPin = PUSH2; // the number of the pushbutton pin
    //const int ledPin = RED_LED; // the number of the LED pin
    int buttonState = 0; // variable for reading the pushbutton status

    void setup() {

    pinMode(22, INPUT);
    pinMode(23, OUTPUT);

    // put your setup code here, to run once:
    mySerial.begin(19200); // initialize PGA460 UART serial channel

    //assume UART_ADDR=0
    //bulk threshold write mid-code values to clear THR_CRC_ERR
    mySerial.write(buf25, sizeof(buf25));

    // [TODO] set p1 rec length to 4.096ms

    // set UART_ADDR=0's time decouple to 4.096ms
    mySerial.write(buf10, sizeof(buf10));

    void loop() {
    // put your main code here, to run repeatedly:

    // check if the pushbutton is pressed.
    //while (digitalRead(buttonPin) == HIGH){}

    // broadcast p1 burst+listen (non-dependent on UART_ADDR)
    mySerial.write(buf17, sizeof(buf17));

    // delay by 100ms

    //[TODO] read back ultrasonic measurement results

    // toggle red LED
    //digitalWrite(ledPin, !(digitalRead(ledPin))); // turn the LED on (HIGH is the voltage level)

    // repeat loop every second
    delay (1000);


  • There's no Ultrasonic Measurement Results command after the P1 Burst and Listen:

    For UART address 0, you should use: 0x55, 0x05, 0xFA

    First of all, try to just write/read addresses with the ESP32. The datasheet (SLASEC8B) on pag. 57 has a couple of examples with the correct checksum. Also the EVM tool has an interface mode where you can generate commands with the correct checksum. That way you can experiment different setups without having to implement checksum calculation first.

    So in your setup, you should write:

    Time varying gain settings

    Threshold settings

    CRC ERR clear command

    Decouple time

    And in your loop:


    Ultrasonic Measurement Results it into bytes and then use it to calculate distance.

    Moreover, SoftwareSerial does not have 2 stopbits implemented in the library. Therefor, you should resort to HardwareSerial library. PGA460 communicates in UART with 2 stopbits.

  • Hi Gabriel,

    Your hardware setup as described is correct. VPWR=12, UART connections, and common GND. This four pin configuration is all you require at a minimum. No pull-up at the TEST pin is required since you are using a 3.3V MCU. In the case of Arduino, you may need to add a pull-up to the PGA460's TXD pin to maintain an idle high logic.

    If this does not resolve the communication error, consider the following:

    I suspect the issue is due to the UART port configuration of your MCU. The UART is standard in all asepcts (8 bits, 1 start, no parity, no flow control), except for the requirement of 2-stop bits. If Arduino does not allow for the option to configure your UART port with 2-stop bits, then you will need to manually update the Arduino UART library to enable 2-stop bits, or add an inter-field wait time holding the UART master TX high for an additional bit width before sending a subsequent UART byte. See section " USART Asynchronous Mode" of the datasheet for full details on the UART master requirements.

    The simplified example snippet you show in your second post is a no-response example. All commands in that example are write-to-slave only commands that do no prompt the PGA460 to respond (i.e. P1 or P1 Burst/Listen, threshold write, TVG write). As Jaatje mentioned, you would need to add byte buf19[4] = {0x55, 0x05}; , which is the ultrasonic measurement results command, and add a command to send and receive UART data where the placeholder //[TODO] read back ultrasonic measurement results is located.

    If you can capture a logic analyzer output of your UART master TX command, I may be able to see where exactly the error is coming from.

  • Another helpfull tip is to read the Serial2 output (since Serial is your Serial Monitor/USB connection). You can just do the following

    unsigned char WriteByteArray[4] = { 0x55, 0x09, 0x1B, 0xDB }

    unsigned char ReadByte1;

    unsigned char ReadByte2;

    unsigned char ReadByte3;


    RX = 13;

    TX = 14;

    void setup()



    Serial2.begin(115200, SERIAL_8N2, RX, TX);


    void loop()


    Serial2.write(WriteByteArray[, 4);


    ReadByte1 =;

    ReadByte2 =;

    ReadByte3 =;

    Serial.println("ReadByte1 = ");


    Serial.println("ReadByte2 = ");


    Serial.println("ReadByte3 = ");



    Or something like that. You send a command in this case a READ (0x09) request to the PGA460. The PGA460 immediatly responds with 3 bytes in return. If you can read these bytes, that means that the communication with the PGA460 is succesfull!

    Btw, the Serial.flush() function is that the Arduino waits until the write function has been completed, therefor ensuring the transfer of the bytes to the PGA460.

  • Thank you Akeem and Jaatje for the helpfull tips.

    This is my logic analyzer output from the Energia codes adaptation:

  • Hello Akeem,

    Thanks again for all the help.

    The communication is working apparently, bit I still could not get distance results. I think it is something about the slave-master communication and my sincronization on readings. Can you recognize the PGA's TX data?

  • Hi Gabriel,

    Based on your last logic analyzer capture of command-5, you were able to capture the distance for one object. You can decode the PGA-TX data as follows:

    Byte0 = 0x40 = UART diagnostic data field (see "Table 4. UART Diagnostic Data Description" of the datasheet to understand this byte). A value of 0x40 indicates the last command was received successfully without error.

    For Bytes1-5, see "Table 3. UART Interface Command List" of the datasheet to decode the ultrasonic measurement results:

    • Byte1= 0x00 = MSB of TOF in microseconds
    • Byte2 = 0x55 = LSB of TOF in microseconds
    • Byte3 = 0x28 = width of echo
    • Byte4 = 0xB7 = amplitude of echo
    • Byte5 = 0x8A = slave generated checksum

    Based on this, your object is at 0x0055 (85) microseconds or a distance of 9mm. This indicates your threshold is detecting the low-to-high transient of the burst energy. See PGA460 FAQ#5.2 (How can I detect more than eight objects? Can I set the threshold to ignore ringing decay ripple or objects for a given time after bursting? How can the Threshold Offset be used?) at for details on avoiding this first false positive. You can also set your number of objects to detect to a value of 2 in your Preset 1/2 burst listen command to use the second object's results as the first real object.

  • Hello Akeem, 

    Thank you for the support so far. I am still unable to properly work with PGA and ESP32. 

    Communication seems to be working fine, but when I tried to implement echo datadump, it would always have the same 128 results. It seems no burst pulse is been generated in the transducer. And now when I do an P1BL command I always get 2 bytes response (0x40, 0xBE). I'm using following configurations in Setup():

    USER_DATA1 = 0x00;
    USER_DATA2 = 0x00;
    USER_DATA3 = 0x00;
    USER_DATA4 = 0x00;
    USER_DATA5 = 0x00;
    USER_DATA6 = 0x00;
    USER_DATA7 = 0x00;
    USER_DATA8 = 0x00;
    USER_DATA9 = 0x00;
    USER_DATA10 = 0x00;
    USER_DATA11 = 0x00;
    USER_DATA12 = 0x00;
    USER_DATA13 = 0x00;
    USER_DATA14 = 0x00;
    USER_DATA15 = 0x00;
    USER_DATA16 = 0x00;
    USER_DATA17 = 0x00;
    USER_DATA18 = 0x00;
    USER_DATA19 = 0x00;
    USER_DATA20 = 0x00;
    TVGAIN0 = 0xAA;
    TVGAIN1 = 0xAA;
    TVGAIN2 = 0xAA;
    TVGAIN3 = 0x82;
    TVGAIN4 = 0x08;
    TVGAIN5 = 0x20;
    TVGAIN6 = 0x80;
    INIT_GAIN = 0x60;
    FREQUENCY = 0x8F;
    DEADTIME = 0xA0;
    PULSE_P1 = 0x10;
    PULSE_P2 = 0x10;
    CURR_LIM_P1 = 0xA5;
    CURR_LIM_P2 = 0x55;
    REC_LENGTH = 0xA9;
    FREQ_DIAG = 0x33;
    SAT_FDIAG_TH = 0xEE;
    FVOLT_DEC = 0x7C;
    DECPL_TEMP = 0x4F;
    DSP_SCALE = 0x00;
    TEMP_TRIM = 0x00;
    P1_GAIN_CTRL = 0x09;
    P2_GAIN_CTRL = 0x09;
    byte buf12[46] = {syncByte, EEBW, USER_DATA1, USER_DATA2, USER_DATA3, USER_DATA4, USER_DATA5, USER_DATA6,
    mySerial.write(buf12, sizeof(buf12)); // serial transmit master data for bulk EEPROM
    //Serial.println("Transmited Transducer Settings!");

    P1_THR_0 = 0x88;
    P1_THR_1 = 0x88;
    P1_THR_2 = 0x88;
    P1_THR_3 = 0x88;
    P1_THR_4 = 0x88;
    P1_THR_5 = 0x88;
    P1_THR_6 = 0x84;
    P1_THR_7 = 0x21;
    P1_THR_8 = 0x08;
    P1_THR_9 = 0x42;
    P1_THR_10 = 0x10;
    P1_THR_11 = 0x80;
    P1_THR_12 = 0x80;
    P1_THR_13 = 0x80;
    P1_THR_14 = 0x80;
    P1_THR_15 = 0x00;
    P2_THR_0 = 0x88;
    P2_THR_1 = 0x88;
    P2_THR_2 = 0x88;
    P2_THR_3 = 0x88;
    P2_THR_4 = 0x88;
    P2_THR_5 = 0x88;
    P2_THR_6 = 0x84;
    P2_THR_7 = 0x21;
    P2_THR_8 = 0x08;
    P2_THR_9 = 0x42;
    P2_THR_10 = 0x10;
    P2_THR_11 = 0x80;
    P2_THR_12 = 0x80;
    P2_THR_13 = 0x80;
    P2_THR_14 = 0x80;
    P2_THR_15 = 0x00;
    byte buf16[35] = {syncByte, THRBW, P1_THR_0, P1_THR_1, P1_THR_2, P1_THR_3, P1_THR_4, P1_THR_5, P1_THR_6,
    P1_THR_7, P1_THR_8, P1_THR_9, P1_THR_10, P1_THR_11, P1_THR_12, P1_THR_13, P1_THR_14, P1_THR_15,
    P2_THR_0, P2_THR_1, P2_THR_2, P2_THR_3, P2_THR_4, P2_THR_5, P2_THR_6,
    P2_THR_7, P2_THR_8, P2_THR_9, P2_THR_10, P2_THR_11, P2_THR_12, P2_THR_13, P2_THR_14, P2_THR_15,
    mySerial.write(buf16, sizeof(buf16)); // serial transmit master data for bulk threhsold
    byte gain_range = 0x4F;
    regAddr = 0x26;
    regData = gain_range;
    byte buf10[5] = {syncByte, SRW, regAddr, regData, calcChecksum(SRW)};
    mySerial.write(buf10, sizeof(buf10));

    TVGAIN0 = 0x48;
    TVGAIN1 = 0x48;
    TVGAIN2 = 0x48;
    TVGAIN3 = 0xC3;
    TVGAIN4 = 0xDC;
    TVGAIN5 = 0xDD;
    TVGAIN6 = 0xDD;
    byte buf14[10] = {syncByte, TVGBW, TVGAIN0, TVGAIN1, TVGAIN2, TVGAIN3, TVGAIN4, TVGAIN5, TVGAIN6, calcChecksum(TVGBW)};
    mySerial.write(buf14, sizeof(buf14)); // serial transmit master data to initiate burst and/or listen command
    byte bufCmd[4] = {syncByte, 0xFF, 4, 0xFF}; // prepare bufCmd with 0xFF placeholders
    bufCmd[1] = P1BL;
    bufCmd[3] = calcChecksum(P1BL);
    mySerial.write(bufCmd, sizeof(bufCmd)); // serial transmit master data to initiate burst and/or listen command

    byte writeType = SRW; // default to single address register write (cmd10)
    //writeType = BC_RW; // cmd22

    byte buf11[5] = {syncByte, writeType, regAddr, regData, calcChecksum(writeType)};

    And in Loop():

    memset(ultraMeasResult, 0, sizeof(ultraMeasResult));
    byte buf5[3] = {syncByte, UMR, calcChecksum(UMR)};
    mySerial.write(buf5, sizeof(buf5)); //serial transmit master data to read ultrasonic measurement results

    Checksum appear to be working fine. Where am I missing? I can send full code and logic analyser outputs.


    Gabriel Onzi

  • Hi Gabriel ,

    When you attempted to capture the echo data dump, did you ensure the DATADUMP_EN in the EE_CNTRL register bit was set to '1'? By default, this value always starts-up as '0' which prevents the echo data dump results from updating. Only either the ultrasonic measurement results can be updated, or the echo data dump results, but not both simultaneously. The result that updates is based on the value of DATADUMP_EN. From the datasheet:

    "The echo data-dump function can be enabled for any of the four BURST/LISTEN or LISTEN ONLY commands
    and is enabled by the DATADUMP_EN bit in the EE_CNTRL register. When enabled, and upon receiving a
    BURST/LISTEN or a LISTEN ONLY command, the PGA460-Q1 device holds the IO pin low for the entire record
    interval thus signaling the master MCU that data-dump cycle is in progress. When the data-dump cycle is
    complete the data can be extracted by the data dump read command."

    If you can provide the echo data dump output, I can confirm if it is updating or not. It should be changing in noise floor alone (even without a burst). Typically, the echo data dump results appear to be random after power-up.

    The only device settings that prevent the driver block from actually generating a burst are:

    • If the THR_CRC_ERR is not cleared after power-up. The threshold must be written to at least once after power-up.
    • If the VPWR_OV_TH is violated. For example, the default condition checks if the VPWR level is below 12.3V to allow excitation. If the VPWR level is above 12V, the driver will be locked/disabled. Detailed description from the datasheet:

    "The input device supply on the VPWR pin defines a fixed UV-threshold level and adjustable OV-threshold level (VPWR_OV_TH) that keeps the device active while disabling the output driver. This feature allows control of power dissipation at high voltage inputs without damaging the driver."