Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: platform_drivers
main.cpp
- Committer:
- ssmith73
- Date:
- 2019-09-16
- Revision:
- 1:bd8aea0d51e0
- Parent:
- 0:86671e9c8db0
File content as of revision 1:bd8aea0d51e0:
/*************************************************************************//**
* @file main.cpp
* @brief Main application code for AD5686 firmware example program
* @author ssmith (sean.smith@analog.com)
******************************************************************************
* Copyright (c) 2019 Analog Devices, Inc.
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Modified versions of the software must be conspicuously marked as such.
* - This software is licensed solely and exclusively for use with
* processors/products manufactured by or for Analog Devices, Inc.
* - This software may not be combined or merged with other code in any manner
* that would cause the software to become subject to terms and
* conditions which differ from those listed here.
* - Neither the name of Analog Devices, Inc. nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
* - The use of this software may or may not infringe the patent rights
* of one or more patent holders. This license does not release you from
* the requirement that you obtain separate licenses from these patent
* holders to use this software.
*
* THIS SOFTWARE IS PROVIDED BY ANALOG DEVICES, INC. AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* NON-INFRINGEMENT, TITLE, MERCHANTABILITY AND FITNESS FOR A
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANALOG DEVICES,
* INC. OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, PUNITIVE OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, DAMAGES ARISING OUT OF CLAIMS OF
* INTELLECTUAL PROPERTY RIGHTS INFRINGEMENT; PROCUREMENT OF SUBSTITUTE
* GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* 20180927-7CBSD SLA
*****************************************************************************/
#include <mbed.h>
#include <ctype.h>
#include "app_config.h"
#define NOT_USED 0
//Lower this value if storage becomes a problem
#define MAX_FREQ_INCREMENTS 511
#define TEMP_LIMIT_MIN -40
#define TEMP_LIMIT_MAX 125
static void print_title(void);
static void getMenuSelect(uint8_t *menuSelect);
static void print_prompt();
static uint8_t read_temperature();
static uint8_t set_system_clock();
static uint8_t set_vrange_and_pga_gain();
static int32_t configure_system();
static uint8_t calculate_gain_factor();
static uint8_t guide();
static uint8_t impedance_sweep();
typedef struct ad5933_config_data {
float start_freq;
uint8_t pga_gain;
float output_voltage_range;
int32_t start_frequency;
int32_t frequency_increment;
int32_t number_increments;
int32_t number_settling_cycles;
}ad5933_config_data;
ad5933_config_data config_data;
static double gain_factor = 0;
static double temperature;
/******************************************************************************/
/************************** Variables Declarations ****************************/
/******************************************************************************/
/**
The following definitions are a requirement for the platform_driver
Pin are changed if required in the app_config.h file
***/
mbed::SPI spi(SPI_MOSI, SPI_MISO, SPI_SCK, SPI_CS);
mbed::I2C i2c(I2C_SDA, I2C_SCL);
PinName slave_selects[MAX_SLAVE_SELECTS];
i2c_init_param i2c_params =
{
GENERIC_I2C, // i2c type
0, // i2c id
100000, // i2c max speed (hz)
AD5933_ADDRESS << 1, // i2c slave address //A0 tied high
};
ad5933_init_param init_params = {
i2c_params, // I2C parameters
AD5933_INTERNAL_SYS_CLK, //current_sys_clk frequency (16MHz)
AD5933_CONTROL_INT_SYSCLK, //current_clock_source
AD5933_RANGE_1000mVpp, //current_gain
AD5933_GAIN_X1, //current_range
AD5933_15_CYCLES, //current_settling
};
ad5933_dev *device;
int32_t connected = -1;
Serial pc(USBTX, USBRX, 115200);
int main()
{
uint8_t menu_select = 0;
print_title();
connected = ad5933_init(&device, init_params);
//Do a quick check to ensure basic connectivity is ok
temperature = ad5933_get_temperature(device);
if (temperature >= TEMP_LIMIT_MIN && temperature <= TEMP_LIMIT_MAX) {
pc.printf("\nTemperature: %f, AD5933 initialisation successful!\n",temperature);
}
else {
pc.printf("AD5933 initialisation reported a bad temperature - recommend debug :\n");
}
while (connected == SUCCESS) {
print_prompt();
getMenuSelect(&menu_select);
config_data.start_freq = 10000;
if (menu_select > 12)
print_prompt();
else switch (menu_select)
{
case 0:
guide();
wait(2);
break;
case 1:
read_temperature();
break;
case 2:
configure_system();
break;
case 3:
calculate_gain_factor();
break;
case 4:
impedance_sweep();
break;
default:
pc.printf("Invalid option: Ignored.");
break;
}
wait(0.1);
}
return 0;
}
//! Prints the title block
void print_title()
{
pc.printf("*****************************************************************\n");
pc.printf("* AD5933 Demonstration Program -- (mbed 1.0) *\n");
pc.printf("* *\n");
pc.printf("* This program demonstrates communication with the AD5933 *\n");
pc.printf("* *\n");
pc.printf("* 1 MSPS, 12-Bit Impedance Converter, Network analyser *\n");
pc.printf("* *\n");
pc.printf("* Set the baud rate to 115200 select the newline terminator. *\n");
pc.printf("*****************************************************************\n");
}
void print_prompt()
{
pc.printf("\n\n\rCommand Summary:\n\n");
pc.printf(" 0 -Software Guide\n");
pc.printf(" 1 -Read temperature\n");
pc.printf(" 2 -Configure voltage-range, PGA-Gain and sweep parameters\n");
pc.printf(" 3 -Calculate Gain-Factor\n");
pc.printf(" 4 -Do an impedance sweep\n");
pc.printf("\n\rMake a selection...\n");
}
static void getMenuSelect(uint8_t *menuSelect) {
pc.scanf("%d", (int *)menuSelect);
}
static uint8_t read_temperature()
{
temperature = ad5933_get_temperature(device);
pc.printf("Current temperature:%.3f C", temperature);
return SUCCESS;
}
static uint8_t set_system_clock()
{
pc.printf(" Select Internal (1) or external clock (2): ");
int input = 0;
pc.scanf("%d", &input);
if (isdigit(input) == 0 && (input == 1 || input == 2))
{
input == 1 ? pc.printf("\n You selected Internal clock source\n") :
pc.printf(" You selected external Source clock source\n");
}
else
{
pc.printf("Invalid entry\n");
wait(2);
return FAILURE;
}
if (input == 2)
{
pc.printf(" Enter external clock frequency in Hz ");
pc.scanf("%d", &input);
if (isdigit(input) == 0 && input > 0 && input < 20000000)
{
pc.printf(" External clk-source frequency set to %d \n", input);
}
else
{
pc.printf("Invalid entry\n");
wait(2);
return FAILURE;
}
}
ad5933_set_system_clk(device,
input == 1 ? AD5933_CONTROL_INT_SYSCLK :
AD5933_CONTROL_EXT_SYSCLK,
input);
return 0;
}
static uint8_t set_vrange_and_pga_gain()
{
int input;
uint8_t v_range = AD5933_RANGE_1000mVpp;
pc.printf(" Select output voltage range:\n");
pc.printf(" 0: 2Vpp typical:\n");
pc.printf(" 1: 200mVpp typical:\n");
pc.printf(" 2: 400mVpp typical:\n");
pc.printf(" 3: 1Vpp typical:\n");
pc.scanf("%d", &input);
if (input >= 0 && input < 4)
{
switch (input)
{
case AD5933_RANGE_2000mVpp: {
pc.printf(" Selected 2V pp typical.\n");
break;
}
case AD5933_RANGE_200mVpp: {
pc.printf(" Selected 200mV pp typical.\n");
break;
}
case AD5933_RANGE_400mVpp: {
pc.printf(" Selected 400mV pp typical.\n");
break;
}
case AD5933_RANGE_1000mVpp: {
pc.printf(" Selected 1V pp typical.\n");
break;
}
}
v_range = input;
}
else
{
pc.printf("Invalid entry\n");
wait(2);
return FAILURE;
}
pc.printf("\n Select PGA Gain (0=X5, 1=X1)\n");
pc.scanf("%d", &input);
if (input >= 0 && input < 2)
{
config_data.pga_gain = input;
config_data.output_voltage_range = v_range;
pc.printf("PGA gain set to : ");
input == AD5933_GAIN_X5 ? printf("X5\n\n") : printf("X1\n\n");
ad5933_set_range_and_gain(device,
config_data.output_voltage_range,
config_data.pga_gain);
}
else
{
pc.printf("Invalid entry: write aborted\n");
wait(2);
return FAILURE;
}
return SUCCESS;
}
static int32_t configure_system()
{
pc.printf("Configure the impedance meter\n\n");
set_vrange_and_pga_gain();
set_system_clock();
int start_freq;
int freq_inc;
int num_increments;
int num_settling_cycles;
int multiplier = AD5933_SETTLING_X1;
pc.printf("\n Enter start-frequency as a decimal number: ");
if (pc.scanf("%d", &start_freq) == 1)
{
if (start_freq <= 0)
{
pc.printf(" Invalid entry, write aborted: \n");
return FAILURE;
}
}
pc.printf("\n Enter frequency-increment as a decimal number: ");
pc.scanf("%d", &freq_inc);
if (isdigit(freq_inc) != 0 || freq_inc <= 0)
{
pc.printf(" Invalid entry, write aborted: \n");
return FAILURE;
}
pc.printf("\n Enter the number of increments as a decimal number: ");
pc.printf("\n Number of increments must be less than %d\n", MAX_FREQ_INCREMENTS);
pc.scanf("%d", &num_increments);
if (isdigit(num_increments) != 0 || num_increments > MAX_FREQ_INCREMENTS)
{
pc.printf(" Invalid entry, write aborted: \n");
return FAILURE;
}
pc.printf("Enter the number of settling-time cycles before ADC is triggered.\n");
pc.scanf("%d", &num_settling_cycles);
if (num_settling_cycles > AD5933_MAX_SETTLING_CYCLES )
{
pc.printf(" Invalid entry, write aborted: \n");
return FAILURE;
}
pc.printf("Set the settling time multiplier (X1=0, X2=1, X4=2).\n");
pc.scanf("%d", &multiplier);
if (multiplier > 2)
{
pc.printf(" Invalid entry, write aborted: \n");
return FAILURE;
}
else
{ //adjust X4 option to match memory map
if (multiplier == 2)
multiplier = AD5933_SETTLING_X4;
}
pc.printf("\n Setting start frequency to %d\n\r", (unsigned int)start_freq);
pc.printf(" Setting frequency increment to %d\n\r", (unsigned int)freq_inc);
pc.printf(" Setting the number of increments to %d\n\r", (unsigned int)num_increments);
pc.printf(" Setting the number of settling-cycles to %d\n\r", (unsigned int)num_settling_cycles);
pc.printf(" The multiplier for the settling-cycles %d\n\r", (unsigned int)multiplier+1);
//update device state
config_data.start_freq = start_freq;
config_data.frequency_increment = freq_inc;
config_data.number_increments = num_increments;
config_data.number_settling_cycles = num_settling_cycles;
ad5933_set_settling_time(device,multiplier,num_settling_cycles);
ad5933_set_range_and_gain(device, device->current_range, device->current_gain);
ad5933_config_sweep(device, start_freq, freq_inc, num_increments);
return SUCCESS;
}
static uint8_t calculate_gain_factor()
{
double calibration_impedance;
pc.printf("\n\nCalculate the gain-factor (see datasheet for information)\n");
pc.printf("Calcualted gain-factor will be stored for impedance measurements and\n");
pc.printf("displayed on the terminal screen.\n");
pc.printf("Ensure that the system has been configured before\n");
pc.printf("calculating the gain factor\n");
ad5933_config_sweep(device,
config_data.start_freq,
config_data.frequency_increment,
config_data.number_increments);
// Do standby, init-start freq, start the sweep, and wait for valid data
ad5933_start_sweep(device);
pc.printf("\nEnter calibration resistance in Ohms: ");
pc.scanf("%le", &calibration_impedance);
pc.printf("Calculating gain factor\n\r");
gain_factor = ad5933_calculate_gain_factor(device,
calibration_impedance,
AD5933_FUNCTION_REPEAT_FREQ);
pc.printf("\n\r Calculated gain factor %e\n\r", gain_factor);
return SUCCESS;
}
static uint8_t guide()
{
pc.printf("\n\rAD5933-Demo quick-start guide: \n\n");
pc.printf("This program can be used both as a demo of the AD5933 impedance \n");
pc.printf("measurement system and as a starting point for developing a \n");
pc.printf("more advanced program for prototyping. This program is not \n");
pc.printf("provided as production-quality code, but as a helpful starting point.\n\n");
pc.printf("As a quick start, the following steps can be implemented to ensure\n");
pc.printf("firmware is communcating with the board and measurements taking place.\n\n");
pc.printf("Firstly - use menu option 1 to read the on-chip temperature.\n");
pc.printf("If a realistic temperature comes back - you are good to go :)\n\n");
pc.printf("Step 1\tConnect a 200k Resistor across the SMA terminals of the PMOD 1A\n");
pc.printf("Step 2\tSelect the 100k feedback resistor by pulling the SEL pin high\n");
pc.printf("Step 2\tConfigure the impedance system with Menu Option 2\n");
pc.printf("Step 3\tCalculate the gain factor with menu-item 3\n");
pc.printf("Step 3\tReplace the 200k impedance across the SMA terminals with a \n");
pc.printf("different 'unknown' impedance (300K perhaps)\n");
pc.printf("Step 4\tRun the impedance measurement with menu-item 4\n");
pc.printf("\tresults are dispayed on the terminal\n");
return SUCCESS;
}
static uint8_t impedance_sweep() {
ad5933_result results;
pc.printf("\nPerform a sweep to calculate an unknown impedance (see datasheet for information)\n");
pc.printf("System should have been previously configured (Menu Option 2)\n");
pc.printf("Impedance will be caculated and results shown.\n\r");
int32_t status = FAILURE;
double impedance;
float frequency = config_data.start_freq;
ad5933_config_sweep(device,
config_data.start_freq,
config_data.frequency_increment,
config_data.number_increments);
/*
> program frequency sweep parameters into relevant registerS
> place the ad5933 into standby mode.
> start frequency register
> number of increments register
*/
ad5933_start_sweep(device);
pc.printf("\n FREQUENCY MAGNITUDE PHASE IMPEDANCE\n");
do {
//Fill up the results struct with data
results = ad5933_calculate_impedance(device,
gain_factor,
AD5933_FUNCTION_INC_FREQ);
impedance = 1 / (results.magnitude * gain_factor);
pc.printf(" %.2f,", frequency);
pc.printf(" %.2f", results.magnitude);
pc.printf(" %.2f", results.phase);
pc.printf(" %.2f\n", impedance);
frequency += config_data.frequency_increment;
//poll the status register to check if frequency sweep is complete.
status = ad5933_get_register_value(device, AD5933_REG_STATUS, 1);
} while ((status & AD5933_STAT_SWEEP_DONE) == 0);
return status;
}