AD5933 code example with AVR

Go To Last Post
13 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I wrote code in C for communication between AD5933 and AVR Atmega 16 (please see attachemt).

After mcu and lcd initialization, calibrating is performing with known impedance of 10 kOhms as Z while Rfb is 10 kOhms. With that parameters the Gain factor is calculated and in next steps I am performing only measuring with GF correction. But Result is never true.for example(respectively):10000,51613,12121,12151,2125,785,5412,..

Also when i open circuit it show not valid numbers such 3265,54541,-23526,2121,..

this image is my circuit:

I think no I2C problem happen.But i attach mytwi.c file ,I use in my project.

 

Do you have any suggestion what is wrong with my code? All functions,  written in ANSI C so I believe that there is no problem with syntax because I used Code Vision Avr compiler.

Best regards

 

 

/*Author  : Bashid

Chip type               : ATmega16
Program type            : Application
AVR Core Clock frequency: 16 MHz
Memory model            : Small
External RAM size       : 0
Data Stack size         : 256
*****************************************************/

#include <mega16.h>
#include <alcd.h>
#include <stdlib.h>
#include <delay.h>
#include <math.h>
#include "mytwi.h"



//Command
#define ACK 0xc4


//AD5933 Register addresses
#define Control_high 0x80
#define Control_low 0x81
#define Freq_high 0x82
#define Freq_mid 0x83
#define Freq_low 0x84
#define FreqInc_high 0x85
#define FreqInc_mid 0x86
#define FreqInc_low 0x87
#define NumInc_high 0x88
#define NumInc_low 0x89
#define NumSettle_high 0x8a
#define NumSettle_low 0x8b
#define Status 0x8f
#define Temp_high 0x92
#define Temp_low 0x93
#define Real_high 0x94
#define Real_low 0x95
#define Imag_high 0x96
#define Imag_low 0x97
#define TWINT 0x80

//AD5933 control codes
#define Init 0x10        //Initialize with start Freq
#define Sweep 0x20        //Start Frequency Sweep
#define IncFreq 0x30        //Increment Frequency
#define RepFreq 0x40        //Repeat Frequency
#define MeaTemp 0x90        //Measure Temperature
#define PowerDown 0xa0        //Power down mode
#define Standby 0xb0        //Standby mode
#define Range2V 0x00        //Output Voltage range 2V
#define Range1V 0x06        //Output Voltage range 1V
#define Range400mV 0x04 //Output Voltage range 400mV
#define Range200mV 0x02 //Output Voltage range 200mV
#define gainx5 0x00        //PGA gain x5
#define gainx1 0x01        //PGA gain x1


void main(void)
{

unsigned char* data;
unsigned long int i,kl,R,I;
float GF=0.0,Z=0.0,Result=0.0;
unsigned int numbinc;
int j,count=0;
unsigned char real_high,real_low,im_high,im_low;
char txt1[16];
char txt2[16];
char txt3[16];

i=Init_TWI();



//start of program
lcd_init(16);                        // Initialize LCD

data=(unsigned char*) malloc(10*sizeof(unsigned char));

lcd_puts("Init Done...");
delay_ms(1000);

com:

lcd_clear();
lcd_puts("CALIBRATING...");
delay_ms(1000);

//Setting Start Freq
i=50000*32.0023195;//50KHZ Is Start Frequency
*data=0x000000ff & (i>>16);*(data+1)=0x000000ff & (i>>8);
*(data+2)=0x000000ff & i;//Split for three Register
Block_write(0x82,3,data);


//Setting Freq Increment
i=1000*32.0023195;//1KHZ Is Frequency Incerment
*data=0x000000ff & (i>>16); *(data+1)=0x000000ff & (i>>8);
*(data+2)=0x000000ff & i;
Block_write(0x85, 3, data);


//Setting Number of increments
numbinc=15;
*data=0x000000ff & (numbinc>>8); *(data+1)=0x000000ff & numbinc;
Block_write(0x88, 2, data);

//Settling cycle 50 ta!
Byte_write(0x8A, 0x00);
Byte_write(0x8B, 0x32);


/*if((i=strncmp(val, "V1",2))==0){
j=1;
}*/
//else if((i=strncmp(val, "V2",2))==0){
j=2; //Range 2 =1.515 volt in 5 volt vdd
//}
/*else if((i=strncmp(val, "V3",2))==0){
j=3;
}
else if((i=strncmp(val, "V4",2))==0){
j=4;
}*/

/*PLacing AD5933 in standby mode, see manual p. 20-21*/
if(j==1){
PORTB=0x1F;
Byte_write(Control_high, 0xb1);
}
else if(j==2){
Byte_write(Control_high, 0xb7);
}
else if(j==3){
PORTB=0x4F;
Byte_write(Control_high, 0xb5);
}
else if(j==4){
PORTB=0x8F;
Byte_write(Control_high, 0xb3);
}


//Initialize with start frequency:
if(j==1){
Byte_write(Control_high, 0x11);
}
else if(j==2){
Byte_write(Control_high, 0x17);
}
else if(j==3){
Byte_write(Control_high, 0x15);
}
else if(j==4){
Byte_write(Control_high, 0x13);
}

//Some settling time
for(i=0;i==100;i++);


//Start Sample routine
while(1){

if(j==1){
Byte_write(Control_high, 0x21);
}
else if(j==2){
Byte_write(Control_high, 0x27);
}
else if(j==3){
Byte_write(Control_high, 0x25);
}
else if(j==4){
Byte_write(Control_high, 0x23);
}
break;
}

start:
//Waits until the real and imaginary data in the AD5933 is valid
while(!(Byte_read(Status) & 0x02));


//Reads the two hex values from the real register
real_high=0;real_low=0;
real_high=Byte_read(Real_high);
real_low=Byte_read(Real_low);
//Converting the real value to decimal
R=Data_proc(real_high, real_low);


im_high=0;im_low=0;
im_high=Byte_read(Imag_high);
im_low=Byte_read(Imag_low);
I=Data_proc(im_high, im_low);


Z=sqrt(R*R+I*I);

if(count==0){
GF=1.0/(Z*10000.0);//10 K Calibrating Res
count=1;
lcd_clear();
lcd_puts("Calibrate Done");
delay_ms(1000);
}


if(count!=0){
Result = 1.0/(Z*GF);
itoa(Result,txt3);
lcd_clear();
lcd_puts("Impedance:");
lcd_gotoxy(0,1);
lcd_puts(txt3);
delay_ms(1500);
}




//Test if the sweep is complete, if not complete program increment frequency
if((Byte_read(Status) & 0x04)==0){
for(kl=0; kl==10000; kl++);
if(j==1){
Byte_write(Control_high, 0x31);
}
else if(j==2){
Byte_write(Control_high, 0x37);
}
else if(j==3){
Byte_write(Control_high, 0x35);
}
else if(j==4){
Byte_write(Control_high, 0x33);
}
goto start;
}

//If complete programming power down mode
else{
Byte_write(Control_high, 0xA1);
goto com;
}

}

 

 

 

 

 

 

Attachment(s): 

 

 

 

Last Edited: Sun. Jun 21, 2015 - 09:26 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

That is a lot of code to wade through.  And upon inspection there are commented-out sections.

 

To get the most examining eyes, it is usually best to post the smallest complete test program that exhibits the symptoms.

 

Now, you have given us a bit of the symptoms:

After calibrating I kept 10 kOhms in Z holder and measuring is correct (approximately 10000.65 Ohms) but after that if I change Z  all results are very close to10  kOhms.

...but you don't really help.  With a certain input (show schematic; tell how you are measuring) what output to the AVR are you getting?  And repeat with the "bad" input.  At this point, it could be a problem in TWI comms, right?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello

I change it to a better code with more expression.

smiley

Please Help me what is wrong...blush

 

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

bashid wrote:

Please Help me what is wrong...

I don't see any pull-up resistors on the scl and sda lines.

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

1. Add pull up resistors
2. Use a respected I2C library.
3. Format the code neatly.
The world will become a better place. All your problems will become easier to solve.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Sorryblush

I forget to put pull up resistors in my schematic but in my real circuit,I put them.

About my twi library ,I checked it with several respected library And I Know it's True.

I think problem is when loop repeat another time,Because If you look my first answer is true but I cannot see anything wrong...frown

 

 

 

 

 

 

 

Last Edited: Mon. Jun 22, 2015 - 06:34 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Seriously, of course you can write your own I2C functions if you want. I suggest that you copy the API of a proven library. Then you can do proper testing. And you can use sensible return values.
However you do things, you still need to format the code in your main program. And wrap up your whole AS6 project in a ZIP, then attach it here. You would be surprised how much effort readers may put into your problem. e.g. build and run on real hardware.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ok.Can you guide me a trusted i2c library to rewrite my program,please?.

 

 

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ross McKenzie ValuSoft Melbourne Australia

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

hello

can you send me all files of this project with ad5933?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

did you not spot the dates on this thread ... ?

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi,

have you got all the c files for this ad5933 project for impedance measurement,if yes then please send me "ashusdiggi@gmail.com"...

I am very new to this feild..I want to understand your code ,so please send me...

 

Thankyou..

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

It's just a TWI/I2C device. Did you not read #9? That is a link to one of the most respected software libraries for AVR - it does TWI.

 

If you treat software as "layered"/modular then you can get your TWI code from one source and the higher level AD5933 operating code from another. A quick google for "AD5933 Arduino" (because Arduino library support is often the best support for a given device) leads to:

 

https://github.com/mjmeli/arduino-ad5933

 

Now, sure, that code is using Arduino's own TWI support code (the "Wire" class) to interface to I2C

int AD5933::getByte(byte address, byte *value) {
    // Request to read a byte using the address pointer register
    Wire.beginTransmission(AD5933_ADDR);
    Wire.write(ADDR_PTR);
    Wire.write(address);

    // Ensure transmission worked
    if (byte res = Wire.endTransmission() != I2C_RESULT_SUCCESS) {
        *value = res;
        return false;
    }

    // Read the byte from the written address
    Wire.requestFrom(AD5933_ADDR, 1);
    if (Wire.available()) {
        *value = Wire.read();
        return true;
    } else {
        *value = 0;
        return false;
    }
}

but you could replace those calls with the equivalents from the Peter Fleury I2C code.