AFE4300 Weight

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

AFE4300 Weight

Postby OneTwo » Mon Jun 04, 2018 7:05 pm

hello,

i really need your help with the implementation of the AFE4300 chip.
Currently I only got the two values 0 or 65536, I suspected the error was in the SPI communication but I am not sure. The following code was ported from the Arduino community.

Datesheet: http://www.ti.com/lit/ds/symlink/afe4300.pdf
The first question is: do I have to set the CS pin independently?

Code: Select all

#include "AFE4300.h"
#include "SPIbus.h"
#include <cstring>
#include "sdkconfig.h"

const unsigned char ADC_DATA_RESULT       = 0x00;
const unsigned char ADC_CONTROL_REGISTER    = 0x01;
const unsigned char MISC1_REGISTER          = 0x02;
const unsigned char MISC2_REGISTER          = 0x03;
const unsigned char DEVICE_CONTROL_1       = 0x09;
const unsigned char ISW_MATRIX             = 0x0A;
const unsigned char VSW_MATRIX             = 0x0B;
const unsigned char IQ_MODE_ENABLE          = 0x0C;
const unsigned char WEIGHT_SCALE_CONTROL    = 0x0D;
const unsigned char BCM_DAC_FREQ          = 0x0E;
const unsigned char DEVICE_CONTROL_2       = 0x0F;
const unsigned char ADC_CONTROL_REGISTER_2    = 0x10;
const unsigned char MISC3_REGISTER          = 0x1A;

//spi_device_handle_t spi;
//spi_bus_config_t buscfg;

SPI_t &mySPI = vspi;        // vspi and hspi are the default objects
spi_device_handle_t device = nullptr;
#define SPI_MODE 1
#define SPI_CLOCK 1000000     // 1 MHz

AFE4300::AFE4300(int reset, int rdy, int mosi, int miso, int sclk, int cs)
   : PIN_RESET(gpio_num_t(reset))
   , PIN_DRDY(gpio_num_t(rdy))
   , PIN_MOSI(gpio_num_t(mosi))
   , PIN_MISO(gpio_num_t(miso))
   , PIN_SCLK(gpio_num_t(sclk))
   , PIN_CS(gpio_num_t(cs))
   , gain_(1)
   , weightscale_(1)
   , weightoffset(1)
{
   //gpio_set_direction(PIN_CS, GPIO_MODE_OUTPUT);
   gpio_set_direction(PIN_RESET, GPIO_MODE_OUTPUT);
   gpio_set_direction(PIN_DRDY, GPIO_MODE_INPUT);

   ESP_ERROR_CHECK( mySPI.begin(PIN_MOSI, PIN_MISO, PIN_SCLK));
   ESP_ERROR_CHECK( mySPI.addDevice(SPI_MODE, SPI_CLOCK, PIN_CS, &device));
}


void AFE4300::reset()
{
   gpio_set_level(PIN_RESET, 0);
   delayMicroseconds(100000);
   gpio_set_level(PIN_RESET, 1);
}

void AFE4300::init()
{
   writeRegister(ADC_CONTROL_REGISTER,      0x4140);
   writeRegister(MISC1_REGISTER,         0x0000);
   writeRegister(MISC2_REGISTER,         0xFFFF);
   writeRegister(DEVICE_CONTROL_1,         0x0004);
   writeRegister(ISW_MATRIX,            0x0000);
   writeRegister(VSW_MATRIX,            0x0000);
   writeRegister(IQ_MODE_ENABLE,         0x0000);
   writeRegister(WEIGHT_SCALE_CONTROL,      0x0000);
   writeRegister(BCM_DAC_FREQ,            0x0040);
   writeRegister(DEVICE_CONTROL_2,         0x0000);
   writeRegister(ADC_CONTROL_REGISTER_2,   0x0011);
   writeRegister(MISC3_REGISTER,         0x00C0);
}

void AFE4300::initWeightScale()
{
   writeRegister(ADC_CONTROL_REGISTER,      0x4140); //Differential measurement mode, 32 SPS
   writeRegister(DEVICE_CONTROL_1,         0x0005); //Power up weigh scale signal chain
   writeRegister(ADC_CONTROL_REGISTER_2,   0x0000); //ADC selects output of weigh scale
   writeRegister(WEIGHT_SCALE_CONTROL,      0x003F); //Gain = 1 DAC Offset = -1
   writeRegister(BCM_DAC_FREQ,            0x0040); //Frequency = default
   writeRegister(IQ_MODE_ENABLE,         0x0000); //Disable IQ mode
   writeRegister(ISW_MATRIX,            0x0000); //Channels IOUTP1 and IOUTN0
   writeRegister(VSW_MATRIX,            0x0000); //Channels VSENSEP1 and VSENSEN0
}

/**
* @brief  Initializes the BCM Module
*/
void AFE4300::initBCM()
{
   writeRegister(ADC_CONTROL_REGISTER,      0x4120); //Differential measurement mode, 32 SPS
   writeRegister(DEVICE_CONTROL_1,         0x0006); //Power up BCM signal chain
   writeRegister(ISW_MATRIX,            0x0804); //Channels IOUTP1 and IOUTN0
   writeRegister(VSW_MATRIX,            0x0804); //Channels VSENSEP1 and VSENSEN0
   writeRegister(ADC_CONTROL_REGISTER_2,   0x0063); //ADC selects output of BCM-I output
   writeRegister(WEIGHT_SCALE_CONTROL,      0x0000); //Gain = 1 DAC Offset = 0
}

int AFE4300::read()
{
   return readRegister(ADC_DATA_RESULT);
}

void AFE4300::writeRegister(unsigned char address, unsigned int data)
{
   unsigned char firstByte = (unsigned char)(data >> 8);
   unsigned char secondByte = (unsigned char)data;

   uint8_t buffer[2] = {0};
   buffer[0] = firstByte;
   buffer[1] = secondByte;

   ESP_ERROR_CHECK(mySPI.writeBytes(device, address, 2, buffer));
}

int AFE4300::readRegister(unsigned char address)
{
   int spiReceive = 0;

   address = address & 0x1F;
   address = address | 0x20;

   uint8_t buffer[2] = {0};
   ESP_ERROR_CHECK(mySPI.readBytes(device, address, 2, buffer));
   
   unsigned char spiReceiveFirst = 0;
   unsigned char spiReceiveSecond = 0;
   spiReceiveFirst = buffer[0];
   spiReceiveSecond = buffer[1];

   spiReceive = (spiReceiveFirst << 8);
   spiReceive |= spiReceiveSecond;

   return spiReceive;
}

f.h-f.s.
Posts: 199
Joined: Thu Dec 08, 2016 2:53 pm

Re: AFE4300 Weight

Postby f.h-f.s. » Fri Jun 15, 2018 10:10 am

You may drive the CS as a normal GPIO, letting the SPI Driver handle that is possible too. Or just tie it to the ground as the datasheet also mentions(page 21).

I would start with trying to read the registers in the AFE4300. The datasheet contains the default values for these registers. If you can confirm you can read from the registers correctly, then you can try and write to these registers and confirm your values. Then you know your spi bus is working correctly.

If your SPI bus isn't working correctly you can attach a logic analyzer/O-scope and try to see what is going wrong. Or fiddle with the SPI bus settings until you get it right =P.

Goodluck!

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

Re: AFE4300 Weight

Postby OneTwo » Mon Jun 25, 2018 11:20 am

f.h-f.s. wrote:You may drive the CS as a normal GPIO, letting the SPI Driver handle that is possible too. Or just tie it to the ground as the datasheet also mentions(page 21).

I would start with trying to read the registers in the AFE4300. The datasheet contains the default values for these registers. If you can confirm you can read from the registers correctly, then you can try and write to these registers and confirm your values. Then you know your spi bus is working correctly.

If your SPI bus isn't working correctly you can attach a logic analyzer/O-scope and try to see what is going wrong. Or fiddle with the SPI bus settings until you get it right =P.

Goodluck!


Thanks for the feedback!

With the Arduino Framework i think i get "correct" values
due.PNG
due.PNG (58.43 KiB) Viewed 372 times


But with the esp-idf framework i only see that im sending the command byte (0x20) and two data bytes (0x00) but there is nothing shifted inside miso.
esp.PNG
esp.PNG (31.92 KiB) Viewed 372 times


What falls into place is that
- MOSI is low and with Arduino it is high in default state
- transfering with the Arduino Due i see that the clock is for a short time paused between each byte

does anyone have a tip on how I could get this to work with the esp-idf?

I tried the with the spi_master API and currently i try that with the "spi_master" from loboris but actualy without luck.

f.h-f.s.
Posts: 199
Joined: Thu Dec 08, 2016 2:53 pm

Re: AFE4300 Weight

Postby f.h-f.s. » Tue Jun 26, 2018 7:32 am

What I am noticing is that your command bytes are sent right after each other. Try adding a delay in between them? See page 22 of that datasheet, it states you need to have a delay of 8us in between your commands. It actually tells you exactly how the signal should look.

Goodluck!

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

Re: AFE4300 Weight

Postby OneTwo » Tue Jun 26, 2018 9:11 am

f.h-f.s. wrote:What I am noticing is that your command bytes are sent right after each other. Try adding a delay in between them? See page 22 of that datasheet, it states you need to have a delay of 8us in between your commands. It actually tells you exactly how the signal should look.

Goodluck!


Thanks for the response.
Yes thats right and i tried to transfer byte by byte without luck.

Pseudo code:

Code: Select all

set cs: low
1 to 3:
   create and fill transaction with 1 byte
   result = transfer transaction
set cs: high


So may i ask how to achieve a short delay between a transaction?

device_interface_config_t.pre_cb // to soon
device_interface_config_t.post_cb // to late
device_interface_config_t.input_delay_ns // could this help???

device_interface_config_t.cs_ena_posttrans // talks about the cs line


One thing i could try is to modify the spi_master library from loboris.
Maybe something like this:

Code: Select all

// ** Start the transaction ***
host->hw->cmd.usr=1;
// Wait the transaction to finish
while (host->hw->cmd.usr);
delayMicroseconds(8);

f.h-f.s.
Posts: 199
Joined: Thu Dec 08, 2016 2:53 pm

Re: AFE4300 Weight

Postby f.h-f.s. » Tue Jun 26, 2018 10:58 am

The RDY signal asserts when a byte is received and de-asserts when a byte has been processed. Can you show me what this signal is doing in the case of arduino and esp-idf?

In each case watch the signals STE(CS),SCLK(CLK),SDIN(MOSI),SDOUT(MISO), RDY, RST.
I would like to see the signal from startup up to and including the first transaction. Maybe the arduino driver for the AFE4300 resets the device properly(see page 20 of the datasheet)?

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

Re: AFE4300 Weight

Postby OneTwo » Tue Jun 26, 2018 11:12 am

f.h-f.s. wrote:The RDY signal asserts when a byte is received and de-asserts when a byte has been processed. Can you show me what this signal is doing in the case of arduino and esp-idf?

In each case watch the signals STE(CS),SCLK(CLK),SDIN(MOSI),SDOUT(MISO), RDY, RST.
I would like to see the signal from startup up to and including the first transaction. Maybe the arduino driver for the AFE4300 resets the device properly(see page 20 of the datasheet)?


Ok i will prepare my two projects (arduino / esp) later and capture the results.

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

Re: AFE4300 Weight

Postby OneTwo » Tue Jun 26, 2018 6:02 pm

The capture are made with Sale Logic Application (file extension: logicdata)

esp32_byte_by_byte.txt
(8.24 MiB) Downloaded 21 times
use loboris SPI
esp32_24bits_transfer.txt
(8.92 MiB) Downloaded 21 times
use loboris SPI
esp32_24bits_transfer_no_lobo.txt
(10.63 MiB) Downloaded 23 times
not used

OneTwo
Posts: 20
Joined: Mon Jan 15, 2018 9:24 am

Re: AFE4300 Weight

Postby OneTwo » Tue Jun 26, 2018 6:11 pm

And just in case you want to see the implementation files

AFE4301V2.cpp
(7.17 KiB) Downloaded 21 times

AFE4301V2.h
(1.49 KiB) Downloaded 17 times

SPIExt.cpp
(8.53 KiB) Downloaded 22 times

f.h-f.s.
Posts: 199
Joined: Thu Dec 08, 2016 2:53 pm

Re: AFE4300 Weight

Postby f.h-f.s. » Tue Jun 26, 2018 9:28 pm

I'm missing the logicdata for the arduino project(miso always 0 in these files), and missing the RST pin(although the code looks good for resetting).

I also noticed SCLK is at 2mhz, but your code does specify 1mhz for the clock frequency. Can you try halving 1mhz to 500khz?

What I said about the RDY pin asserting and de-asserting is only true if you have it in one-shot or continuous mode.

Who is online

Users browsing this forum: No registered users and 2 guests