Jump to content
  • 0

PmodIA's status register not responding


mecwee

Question

Hi there,

I bought a couple of pmodia boards very recently, and tried to communicate with it using chipkit u32. I carefully read the manual of ad5933 and pmodia as well (i2c communication stuff in particular). Then, I tried to use the demo code to start talking with it via chipkit u32. However, it did not respond. I checked the code, and figured that it stuck since the status register never gives out a "ready" bit to read temperature, etc. Not matter how I command it to initialize sweep or perform temperature measurement. The output from the status register (0x8F) is always 0111 0000.

Then, I switched to an arduino uno. It seems the address pointer can be assigned to different address, and I can write to the desired address, and read them back correctly, e.g., I can send 0x90 to the control register (0x80) for temperature measurement. Then, move the pointer to command register (0x80) to read out "0x90" correctly. Unfortunately, the status register (0x8F) always reads as 0111 0000. I tired many combinations with varying delay time between writing command to 0x80 and reading status register. Unfortunately, the result is the same. It seems to me that the PmodIA is not performing temperature measurement, or frequency sweep at all after my commands.

I had great experiences working with diligent boards (Zedboard and zybo), and typically figured out problems by myself. However, this bug frustrated me for almost 5 days. Please advise!

 

Following is the simple code I used to test the communication, and its response from serial monitor. I hope this can help debug. In addition, 12k pull-up resistor is provided for both SDA and SCL as suggested by the AD5933 user manual.

pde file in Mpide 0150

#include <WireIA.h>
#include <inttypes.h>
#include <Wire.h>
#include <EEPROM.h>
IA testIA;
void setup()
{

    Serial.begin(9600);
    
    Serial.println("PmodIA Demo");
    Serial.println("Press 'r' when ready!!");
    while(Serial.read() != 'r');    
    
    testIA.IA_init();
        testIA.IA_test();
        
        delay(20);
    testIA.setControlRegister(1,1);
    testIA.setControlRegister(9,1);
        
        delay(1000);
        uint8_t disp; 
        disp = testIA.readRegisterValue(0x8F);
        Serial.println(disp,BIN);
}

void loop()
{

}

Respond from serial monitor

PmodIA Demo
Press 'r' when ready!!
IN test
128
**********
96
128
45
**********
128
**********
9
55
75
**********
1110000 (the status register 0x8F always gives this value, meaning "not ready")

 

Link to comment
Share on other sites

16 answers to this question

Recommended Posts

JColvin,

It seems like I just solved the problem. It turned out that the power supply cannot be 5 V. When I switched it from 5 to 3.3 V on the microcontroller. It started to generate correct temperature measurements.

The manual says that voltage supply for PmodIA can be 3.3 - 5 V. However, in my case, 5 V is not working. 

Thanks much for all the time and efforts you put on this problem. I hope this piece of information can help others.

Best regards,

Tom

Link to comment
Share on other sites

Hi Tim,

When I checked with the applications engineers last they said they got the module up and running as is without any modification. I'll ask them to show me what they did so that way I can hopefully identify what I'm doing differently on the module.

Thanks,
JColvin

Link to comment
Share on other sites

Hi @jpeyron,

first of all, thank you very much for your answer. I will explain my context.

I am working with an Arduino Uno rev 3, software 2:1.0.5 +dfsg2-4 under Ubuntu 16.04.6 LTS 64-bit. The PmodIA platform was purchased from Digi-Key and is brand new. I am connecting the SCL and SDA pins of the Uno and the GND and 3.3V outputs from the power section of the UNO into the corresponding pins of the PmodIA. I am connecting the SEL pin to ground.

For the measurements, I am indeed following the instructions given in the datasheet. Here is a little piece of my code that tests the functionality of the PmodIA (I couldn't find any guidelines about posting code in the official forum guidelines, sorry). The Test function (at the end of the code) is being called inside the loop function of the Arduino. I have included the minimum definitions and auxiliary functions that are needed to understand the Test function, but I am not posting all of the code because it would not help.
 

Here is the piece of code:

 

// Device address
const byte PmodIA = 0x0D;  // PmodIA's address as slave in I2C protocol

// Register addresses
const byte reg_Control = 0x80;  // Control register address (R/W), 2 bytes
const byte reg_Status = 0x8F;   // Status register address (read only), 1 byte

// Register sizes
const byte size_Control = 2;  //  Control register size [bytes]
const byte size_Status = 1;   // Status register size [bytes]

// Control register commands (4 MSBits)
const byte val_Standby = 0xB0;           // Standby mode
const byte val_IniStartFreq = 0x10;     // Start with initial frequency
const byte val_IniFreqSweep = 0x20;  // Start frequency sweep
const byte val_IncFreq = 0x30;             // Increment frequency
const byte val_MeasTemp = 0x90;      // Measure temperature
//---------------------------------------------------------------------------------------------------------------------------------
void selReg(byte slave,byte reg_address) // Function that sets the register pointer to a specific register (for block read/write)
{
  Wire.beginTransmission(slave); // Send address byte and set R/W bit for write mode
  
  Wire.write(0xB0);              // Send register pointer command
  Wire.write(reg_address); // Send address of register
  
  Wire.endTransmission(); // Send message
}
//---------------------------------------------------------------------------------------------------------------------------------
void blockWrite(byte slave,byte reg_address,byte numBytes,const byte data[]) // Function that writes a block of bytes into a specific set of consecutive register addresses
{
  selReg(slave,reg_address);         // Set register pointer
  Wire.beginTransmission(slave); // Send address byte and set R/W bit for write mode
  
  Wire.write(0xA0);          // Send block write command
  Wire.write(numBytes); // Number of bytes to be written
  
  for(int i = 0; i < numBytes; i++)
  {
    Wire.write(data[i]);  // Write value into the register
  }
  
  Wire.endTransmission(); // Send message
}
//---------------------------------------------------------------------------------------------------------------------------------
void blockRead(byte slave,byte reg_address,byte numBytes,byte *data) // Function that reads a block of bytes from a specific set of consecutive register addresses
{
  for(int i = 0; i < numBytes; i++)
  {
    selReg(slave,reg_address + i);       // Set register pointer
    Wire.requestFrom(slave,(byte)1);  // Request data from selected register
    data[i] = Wire.read();                        // Read byte i and store its value in variable data
  }
}
//---------------------------------------------------------------------------------------------------------------------------------
void setControlReg(byte slave,const byte data) // Function that modifies only the first 4 bits in the control register (operating modes)
{
  blockRead(slave,reg_Control,size_Control,C);  // Read control register value and store in array C
  C[0] = (C[0] & 0x0F) | data;                                   // Bitwise OR assignment after masking the 4 MSBits (does not modify bits 11-0)
  blockWrite(slave,reg_Control,size_Control,C); // Set new control register value
}
//---------------------------------------------------------------------------------------------------------------------------------
void Test(byte slave) // Function to test PmodIA's functionality
{  
  // Standby mode
  Serial.print("Enter Standby mode, code: ");
  Serial.println(val_Standby,HEX);
  setControlReg(slave,val_Standby); // Set the 4 MSbits of control register
  delay(1000); // Wait one second
  blockRead(slave,reg_Control,size_Control,C); // Read the control register to see if it has changed
  Serial.print("Control register value (MSByte): ");
  Serial.println(C[0],HEX);
  blockRead(slave,reg_Status,size_Status,S);  // Read the status register (should not indicate available data)
  Serial.print("Status register value: ");
  Serial.println(S[0],BIN);
  delay(1000); // Wait one second
  Serial.println("");
  
  // Start with initial frequency
  Serial.print("Start with initial frequency, code: ");
  Serial.println(val_IniStartFreq,HEX);
  setControlReg(slave,val_IniStartFreq); // Set the 4 MSbits of control register
  delay(1000); // Wait one second
  blockRead(slave,reg_Control,size_Control,C); // Read the control register to see if it has changed
  Serial.print("Control register value (MSByte): ");
  Serial.println(C[0],HEX);
  blockRead(slave,reg_Status,size_Status,S);  // Read the status register (should indicate available data in the real and imaginary registers)
  Serial.print("Status register value: ");
  Serial.println(S[0],BIN);
  delay(1000); // Wait one second
  Serial.println("");
  
  // Start frequency sweep
  Serial.print("Start frequency sweep, code: ");
  Serial.println(val_IniFreqSweep,HEX);
  setControlReg(slave,val_IniFreqSweep); // Set the 4 MSbits of control register  
  delay(1000); // Wait one second  
  blockRead(slave,reg_Control,size_Control,C); // Read the control register to see if it has changed
  Serial.print("Control register value (MSByte): ");
  Serial.println(C[0],HEX);
  blockRead(slave,reg_Status,size_Status,S);  // Read the status register (should not indicate available data)
  Serial.print("Status register value: ");
  Serial.println(S[0],BIN);
  delay(1000); // Wait one second
  Serial.println("");
  
  // Increment frequency
  Serial.print("Increment frequency, code: ");
  Serial.println(val_IncFreq,HEX);
  setControlReg(slave,val_IncFreq); // Set the 4 MSbits of control register 
  delay(1000); // Wait one second    
  blockRead(slave,reg_Control,size_Control,C); // Read the control register to see if it has changed
  Serial.print("Control register value (MSByte): ");
  Serial.println(C[0],HEX);
  blockRead(slave,reg_Status,size_Status,S);  // Read the status register (should indicate available data in the real and imaginary registers)
  Serial.print("Status register value: ");
  Serial.println(S[0],BIN);
  delay(1000); // Wait one second
  Serial.println("");
  
  for(int i = 0;i < 10;i++)
  {
    // Measure temperature
    Serial.print("Measure temperature, code: ");
    Serial.println(val_MeasTemp,HEX);
    setControlReg(slave,val_MeasTemp); // Set the 4 MSbits of control register    
    delay(1000); // Wait one second  
    blockRead(slave,reg_Control,size_Control,C); // Read the control register to see if it has changed
    Serial.print("Control register value (MSByte): ");
    Serial.println(C[0],HEX);
    blockRead(slave,reg_Status,size_Status,S);  // Read the status register (should indicate available data in temperature register)
    Serial.print("Status register value: ");
    Serial.println(S[0],BIN);
    delay(1000); // Wait one second
    Serial.println("");
  }
}

The following screenshot shows the serial monitor after executing the code on the Arduino Uno:

image.thumb.png.0ec4b4c8beae63ed558a7caec3b2f0ff.png

The 4 LSBits of the MSByte in the control register correspond to the gain and range settings (not shown in the code), so a constant value 3 is always displayed (and never changed). The 4 MSBits of the MSByte in the control register (corresponding to the operating modes) are being correctly written and the impedance measurements are carried out as expected (although the data is not being read in this code example). The status register correctly indicates that a DFT computation is complete (bit 2) after asking for it (by sending the corresponding control commands to the control register), but it doesn't indicate that a temperature measurement is complete (bit 1) after writing the corresponding control command into the control register.

I have tested frequency sweeps with different configurations and they did work as expected. I also tried a program that only reads (attemps to...) temperature, but nothing changes in the status register. I tried of course reading the temperature register despite of the status register issue, but it's empty. The temperature conversion is not being carried out.

 

Thank you in advance for your help!

F.E.G.

 

Link to comment
Share on other sites

Hi @Fabian,

In the Datasheet here it states on page 16:

"The temperature sensor block defaults to a power-down state.

To perform a measurement, a measure temperature command is issued by the user to the control register (Register Address 0x80 and Register Address 0x81).

After the temperature operation is complete (typically 800 μs later), the block automatically powers down until the next temperature command is issued.

The user can poll the status register (Register Address 0x8F) to see if a valid temperature conversion has taken place, indicating that valid temperature data is available to read at Register Address 0x92 and Register Address 0x93 (see the Register Map section)."

Please attach your code for reading the temperature.

best regards,

Jon

Link to comment
Share on other sites

4 minutes ago, jpeyron said:

Hi @Fabian,

Unfortunately , we haven't had the bandwidth to create a working arduino project for the Pmod IA. 

Here is a forum thread that has a completed Raspberry PI/Pmod IA project that should be a good reference along with the datasheet for your project. They go through some calibration set up as well.

best regards,

Jon

Thank you, Jon. However, the issue should have nothing to do with the arduino platform. I'm using the UNO as an I2C Master and sending standard I2C commands. My code effectively reads from and writes to all the AD5933 registers. Also, the OP says in the accepted answer of this thread that she/he managed to get the device working with an Arduino UNO, but the solution of "using 3.3 V instead of 5 V" doesn't work for me. As I said before, all the functionalities of the PmodIA are behaving properly except for the temperature conversion, which is puzzling me.

Link to comment
Share on other sites

Hi all,

I'm experiencing exactly the same problem as mecwee, namely no temperature conversion is being carried out after sending the corresponing command to the control register.

I am testing the PmodIA with an Arduino UNO rev.3 and I'm using Vcc = 3.3 V from the UNO. The impedance measurement settings are standard (1x gain, amplitude range 2, RFB 100 kOhm), but as far as I understand they shouldn't affect temperature measurements.

I tried writing to the control register and then reading it to verify that it effectively changes... everything seems to be working properly. This same behavior is observed when I send the "measure temperature" command (i.e. setting the value 0x90 in the control register with address 0x80) and then read it (the returned value is effectively 0x90). However, when I read the status register it keeps showing the first bit having the value 0 (which means that a valid temperature reading is not available). I tried a frequency sweep and the status register correctly shows a "valid impedance reading" (bit 1 is set) and "end of sweep" (bit 3 is set). Nevertheless, no matter how much time I wait after asking for a temperature measurement, the status register won't acknowledge a valid temperature conversion. Despite of this, I tried to read the temperature register in order to see if there was something... of course, the register was empty (value 0x0000).

 

I would really appreciate some advice in this matter, for I have tried everything that was proposed in this forum and nothing worked for me.

¡Saludos!

Link to comment
Share on other sites

Hi @jpeyron,
Your linked forum thread is great.  I was working to validate my impedance calibration when I found the temperature response problem - I was hoping to use temperature as a quick comms check since any number around 23 would be correct.  Once I had trouble I used a logic analyzer and attempted to measure temperature using my own code on a Raspberry Pi 3 and well as the following Arduino code:
https://github.com/mjmeli/arduino-ad5933
and got the same behavior, control registers set correctly and status register never signals complete.  I was powering both devices using 5V.  It works fine now back at 3.3V and completes a temperature reading in about 3ms.

I'll read the linked thread regarding IZ calibration with interest.  Analog Devices also has a circuit note that's relevant to the referenced thread I'm hoping to work through as an example:
http://www.analog.com/en/design-center/reference-designs/hardware-reference-design/circuits-from-the-lab/cn0217.html

 

Link to comment
Share on other sites

Hi @periwink,

We have not had time to make a working demo for the Pmod IA.  We will work on verifying the input voltage and limits the excitation voltage maximum. I know there is some calibrations involved in the setup of the Pmod IA. Did you calibrate the Pmod IA? Are you able to share your setup and code used?  Here is a forum thread where a community member was able to get all of the functions working correctly. They also posted some helpful setup and usage hints as well as their code(unverified). Have you had a chance to look at their code?

thank you,

 

Jon

Link to comment
Share on other sites

I experienced the same lack of temperature measurements finishing.  I was running an input voltage VDD=5, a switch to 3.3 has fixed the problem.  Registers maintained reasonable values at 5V, however the status register never cleared the temperature bit.  The AD5933 datasheet says it's fully 3.3-5V capable, I wonder if this is a quirk of the breakout board?  I hope not as this also limits the excitation voltage maximum to 2V peak to peak instead of 3 with VDD=5.

Link to comment
Share on other sites

Hi JColvin,

I found this thread while troubleshooting issues in communicating with my pmodia through an arduino mega2560. Like Tom, I am having an issue with receiving invalid status register responses, however connecting to 3.3 volt supply did not solve the issue for me.  I ran the code he provided here and the response I get is the following, which shows a different but still invalid register status:

Current register status is:
1010001
Current control register is:
10010000

Do you have any follow up information from your applications engineers on what may be the cause of this aside from using a supply voltage of 3.3 volts instead of 5 volts?

I have put in a request to Analog Devices on this issue and am waiting to hear from them, but in the mean time I wanted to check here if any reasons for this behavior had been identified by the Digilent team.

Many thanks,

Tim

Link to comment
Share on other sites

Hi Tom,

In truth, I do not know why the status register is responding as it is. The way you have written your code (which I double checked and confirmed that all of your command codes and addresses are correct as per the AD5933 datasheet) effectively takes any "Pmod" portion out of the equation so you are just communicating with the Analog Devices AD5933 chip. Your I2C connection to the chip appears to be sound considering you were able to change the default state of the control register and read the changed byte value of the control register.

According to the datasheet for the AD5933, temperature conversions can take place without any special modes, when a measure temperature command is sent as you have sent it, the temperature sensor block apparently powers up, takes the measurement, and powers back down, with the temperature conversion process supposedly only taking approximately 800 us: much shorter than the time you allotted for the chip.

Yet, when you poll the Status register, which is a read only register so you would not be able to accidentally (or purposefully) write over it, you are receiving a control word which again according to the AD5933 datasheet is not one of the possible results listed in Table 14, which baffles me.

The only thing I can think of would be that by leaving the "measure temperature" control word in the Control Register, the chip continually takes temperature measurements resulting in the Status register never thinking a valid temperature measurement has been completed. However, I think this is highly unlikely as this same logic would apply to the "increment frequency" or "repeat frequency" command, also resulting in an unreadable Status register; something that I would expect Analog Devices would have avoided during the creation of this chip.

I will ask our applications engineers about this to see if they have encountered something similar or not. 

Let me know if you have any more questions.

Thanks,
JColvin

Link to comment
Share on other sites

JColvin,

Thanks much for the prompt reply! I tried your suggestions, but it did not work. I reorganized the script to try to make it crystal clear. Basically, I avoided using any function from the demo library. Instead, all the codes are generic now. Please help check and debug. Again, the response from serial monitor is provided. In addition, the register address map, command, etc. (from WireIA.h file) are provided.

Since I currently have 2 chips in hand, I tried to replace it with the spare one. However, the result is the same (register status error).

Thanks in advance!

Tom

 

Script:

#include <Wire.h>

void setup()
{
  // initialization
  Wire.begin();
  Serial.begin(9600);  
  Serial.println("PmodIA Demo");
  Serial.println("Press 'r' when ready!!");
  while(Serial.read() != 'r');    

  // send Command to Control Register
  Wire.beginTransmission(0x0D);
  Wire.send(0x80);
  Wire.send(0x90);
  Wire.endTransmission();

  // set Register Pointer to Status Register
  Wire.beginTransmission(0x0D);
  Wire.send(0xB0);  
  Wire.send(0x8F);
  Wire.endTransmission();

  // Read from Status Register
  delay(500);
  Wire.requestFrom(0x0D, 1); 
  uint8_t disp_status;
  disp_status = Wire.read(); 
  Wire.endTransmission();
  Serial.println("Current register status is:");
  Serial.println(disp_status,BIN);

  // set Register Pointer to Control Register
  Wire.beginTransmission(0x0D);
  Wire.send(0xB0);  
  Wire.send(0x80);
  Wire.endTransmission();
  delay(20);

  // Read from Status Register
  delay(500);
  Wire.requestFrom(0x0D, 1); 
  uint8_t disp_control;
  disp_control = Wire.read(); 
  Wire.endTransmission();
  Serial.println("Current control register is:");
  Serial.println(disp_control,BIN);
}

void loop()

{

}

 

Response from serial monitor

PmodIA Demo
Press 'r' when ready!!
Current register status is:
1110000
Current control register is:
10010000

 

 

/*Register Map*/

#define IA_ADDRESS                0x0D  //IA 
#define BLOCK_WRITE_CMD     0xA0  //block write command
#define BLOCK_READ_CMD       0xA1  //block read command
#define ADR_PTR_CMD              0xB0  //address pointer command

/*Register Map*/

#define CONTROL_REG                               0x80
#define START_FREQUENCY_REG              0x82
#define FREQUENCY_INCREMENT_REG      0x85
#define NUM_INCREMENTS_REG                 0x88
#define NUM_SETTLING_TIME_REG             0x8A
#define STATUS_REG                   0x8F
#define TEMP_DATA_REG            0x92
#define REAL_DATA_REG             0x94
#define IMAG_DATA_REG             0x96

/*CONTROL REGISTER COMMANDS*/

#define INIT_START_FREQ              0x10
#define START_FREQ_SWEEP        0x20
#define INC_FREQ                           0x30
#define REPEAT_FREQ                   0x40
#define MEASURE_TEMP                0x90
#define PWR_DOWN                        0xA0
#define STAND_BY                          0xB0

 

Link to comment
Share on other sites

Hi Tom,

So I looked into it (I'm still not receiving anything from my serial monitor, but I'll presume that's an unrelated issue), and came up with a couple of things, but I personally don't know if they will solve your problem. The biggest thing that is throwing me off is the fact that your status register is reading as 0x70 (0111000). When you look at the Analog Devices datasheet for the AD5933 at the Status Register section (pg 26), the chip seemingly would never actually report that code that you are receiving. I'm not sure how interpret it.

Otherwise, within the provided library for the PmodIA inside of the WireIA.cpp file in the setControlRegister function (around line 300), the code sets the control register values by OR'ing the values rather than setting/replacing the byte with a new value, which can easily lead to setting the Control Register into a non-existent mode, or in a mode you don't want to be in. Originally, I thought that this was the source of your problem, but the initialize function sets the ControlData array to all zeros, so the two settings that you set inside of your code will actually still get you your desired control command. :/ What will need to be done (that I will add to the list of things to fix inside of this library) is somewhere to reset the ControlData array back to all 0's before trying to change to control register again.

That being said, I guess I would try removing the "testIA.setControlRegister(1,1);" line from you code to see if that makes a difference, but I don't know if it will or not. I'll keep looking for something such as ending a I2C transmission early, but to me that wouldn't produce the Status Register value that it did, so it's hard to say what might turn up.

Let me know if you have any more questions,

Thanks,
JColvin

Link to comment
Share on other sites

Hi mecwee, 

I'm working on seeing if I can find something. I know when I tried the demo code that is provided with the PmodIA I never got anything out of it since the provided library needs some work, but since you seem to actually have gotten something back from serial monitor, I'm going to try the code you used and see what I find.

Thanks,
JColvin

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...