Example program for EVAL-TempSense-ARDZ boards.
Dependencies: platform_drivers
app/main.cpp
- Committer:
- Kjansen
- Date:
- 2021-09-24
- Revision:
- 7:3e5f6cca357e
File content as of revision 7:3e5f6cca357e:
/***************************************************************************** * @file main.cpp * @brief EVAL-TempSense-ARDZ example program * @author ssmith (sean.smith@analog.com) ****************************************************************************** * Copyright (c) 2019, 2021 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 <cstdio> #include <mbed.h> #include <cmath> #include "app_config.h" #include "spi.h" #include "i2c.h" #include "error.h" #include "i2c_extra.h" #include "spi_extra.h" #ifdef __cplusplus extern "C" { #endif #include "delay.h" #include "platform_support.h" #include "adt7420.h" #include "adt7xxx_support.h" #ifdef __cplusplus } #endif // __cplusplus #define constrain(amt,low,high) ((amt)<(low)?(low):((amt)>(high)?(high):(amt))) #define TEMP_MIN -40 #define TEMP_MAX 150 #define MAX_HYST_TEMP 15 #define MIN_HYST_TEMP 0 #define RESET_DELAY 500 #define WAIT_MENU_TIME 1000 #define NOT_USED 0 static void print_title(void); static void print_prompt(void); static uint8_t select_device(); static void print_active_device(int ext_int_value); static int get_menu_select(uint8_t *menu_select); static uint8_t read_temperature(); static uint8_t set_resolution(); static uint8_t set_op_mode(); static uint8_t bunch_of_temps(); static uint8_t readback_reg(); static uint8_t reset_interface(); static uint8_t write_to_setpoint_reg(); static uint8_t set_fault_queue(); static uint8_t set_ct_int_config(); static void microcontroller_reset(); static int input_check(int input_val, int lowest_accepted_val, int highest_accepted_val, int invalid_check); /******************************************************************************/ /************************** Variables Declarations ****************************/ /******************************************************************************/ // Initialize the extra parameters for I2C initialization mbed_i2c_init_param i2c_init_extra_params = { .i2c_sda_pin = I2C_SDA, .i2c_scl_pin = I2C_SCL }; i2c_init_param i2c_params = { .max_speed_hz = 100000, // i2c max speed (hz) .slave_address = INT_I2C_ADDRESS, // i2c slave address .extra = &i2c_init_extra_params // I2C extra init parameters }; // Initialize the extra parameters for SPI initialization mbed_spi_init_param spi_init_extra_params = { .spi_miso_pin = SPI_MISO, .spi_mosi_pin = SPI_MOSI, .spi_clk_pin = SPI_SCK }; spi_init_param spi_params = { .max_speed_hz = 1000000, //SPI frequency (Hz) .chip_select = SPI_CS, //Chip Select .mode = SPI_MODE_3, //CPOL/CPHA settings for your device .extra = &spi_init_extra_params // SPI extra init parameters }; adt7420_init_param init_params = { .resolution_setting = NOT_USED, //Resolution setting .active_device = ACTIVE_DEVICE //Set this in app_config.h }; adt7420_dev *device; registers_e registers; int32_t connected = -1; uint8_t device_id = 0; int main() { uint8_t menu_select = 0; print_title(); device_id = select_device(); connected = adt7420_init(&device, init_params); if (connected != SUCCESS) { printf(EOL EOL " Connection to device failed :(" EOL); printf(" ...Restarting application... " EOL); mdelay(WAIT_MENU_TIME); microcontroller_reset(); } else { printf(EOL EOL " Connection to device succeeded!" EOL); } while (connected == SUCCESS) { menu_select = 0; print_active_device(device_id); print_prompt(); if (get_menu_select(&menu_select) == FAILURE) printf(EOL "***** Returning to main menu *****" EOL); else { switch (menu_select) { case 1: read_temperature(); break; case 2: set_resolution(); break; case 3: set_op_mode(); break; case 4: bunch_of_temps(); break; case 5: readback_reg(); break; case 6: reset_interface(); break; case 7: write_to_setpoint_reg(); break; case 8: set_fault_queue(); break; case 9: set_ct_int_config(); break; case 10: /*Restore device registers to default values before restarting microcontroller*/ reset_interface(); microcontroller_reset(); break; default: printf("Invalid option" EOL); break; } } mdelay(WAIT_MENU_TIME); //wait 1 second } } /******************************************************************************* * @brief Prints the title block. *******************************************************************************/ void print_title() { printf("*****************************************************************" EOL); printf("* EVAL-TempeSense-ARDZ Demonstration Program *" EOL); printf("* *" EOL); printf("* This program demonstrates communication with the ADT7xx *" EOL); printf("* High-Accuracy digital temperature sensor family *" EOL); printf("* It works with both SPI & I2C versions *" EOL); printf("* *" EOL); printf("*****************************************************************" EOL); } /******************************************************************************* * @brief Prints the "main menu" prompt to the console. *******************************************************************************/ void print_prompt() { printf(EOL EOL "Command Summary:" EOL); printf(" 1 -Read temperature" EOL); printf(" 2 -Set resolution" EOL); printf(" 3 -Set operation mode" EOL); printf(" 4 -Poll temperature" EOL); printf(" 5 -Read a register" EOL); printf(" 6 -Reset the interface" EOL); printf(" 7 -Write to a setpoint register" EOL); printf(" 8 -Set Fault Queue configuration" EOL); printf(" 9 -Set CT/INT polarity and mode" EOL); printf(" 10 -Full System Reset" EOL); printf(EOL); } static int get_menu_select(uint8_t *menu_select) { int invalid_check = scanf("%d",(int *) menu_select); return input_check(*menu_select, 1, 10, invalid_check); } /******************************************************************************* * @brief - Select the serial interface (SPI/I2C) and device * based on the part family. * - Only one device and interface can be active. * Example: ADT7320 - SPI (Internal or Remote device) * ADT7420 - I2C (Internal or Remote device) * * @param None * * @return new_dev - Return device selected * Example: 1 - Internal(Main PCB) * 2 - Remote (External PCB) *******************************************************************************/ uint8_t select_device() { printf("Please select interface by choosing a device:" EOL); printf(" 1- ADT7320 (SPI)" EOL); printf(" 2- ADT7420 (I2C)" EOL); printf(" Select an option: "); int invalid_check, new_interface = 0; invalid_check = scanf("%d", &new_interface); //Prompts for user input while correct interface is not selected while (input_check(new_interface, 1, 2, invalid_check) == FAILURE) { printf("Please select interface by choosing a device:" EOL); printf(" 1- ADT7320 (SPI)" EOL); printf(" 2- ADT7420 (I2C)" EOL); printf(" Select an option: "); invalid_check = scanf("%d", &new_interface); } printf("%d", new_interface); switch (new_interface) { case 1: printf(" ADT7320 sensor selected!" EOL EOL); init_params.active_device = ID_ADT7320; init_params.interface_init.spi_init = spi_params; break; case 2: printf(" ADT7420 sensor selected!" EOL EOL); init_params.active_device = ID_ADT7420; init_params.interface_init.i2c_init = i2c_params; break; } printf("Available devices:" EOL); printf(" 1- Internal (Main PCB)" EOL); printf(" 2- Remote (External PCB)" EOL); printf(" Select an option: "); int new_dev = 0; invalid_check = scanf("%d", &new_dev); //Prompts for user input while correct device is not selected while (input_check(new_dev, 1, 2, invalid_check) == FAILURE) { printf("Device select:" EOL); printf(" 1- Internal (Main PCB)" EOL); printf(" 2- Remote (External PCB)" EOL); printf(" Select an option: "); invalid_check = scanf("%d", &new_dev); } printf("%d", new_dev); switch (new_dev) { case 1: printf(" Internal sensor selected!"); init_params.interface_init.i2c_init.slave_address = INT_I2C_ADDRESS; init_params.interface_init.spi_init.chip_select = SPI_CS; break; case 2: printf(" External sensor selected!"); init_params.interface_init.i2c_init.slave_address = EXT_I2C_ADDRESS; init_params.interface_init.spi_init.chip_select = SPI_CSE; break; } return new_dev; } /******************************************************************************* * @brief - Reads and prints the temperature in Celsius Degree * * @param None * * @return - Return SUCCESS flag - currently unused. *******************************************************************************/ static uint8_t read_temperature() { float temp = adt7420_get_temperature(device); printf("Current temperature:%.3f C", temp); return SUCCESS; } /******************************************************************************* * @brief -Set the device resolution for 13 or 16 bits * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t set_resolution() { printf(" Available resolutions:" EOL); printf(" 1- 13-bit" EOL); printf(" 2- 16-bit" EOL); printf(" Select an option: "); int new_res, invalid_check = 0; invalid_check = scanf("%d", &new_res); if (input_check(new_res, 1, 2, invalid_check) == FAILURE) { return FAILURE; } else { printf("%d" EOL, new_res); new_res = (new_res == 1) ? 0 : 1; adt7420_set_resolution(device, new_res); printf("Set resolution to %d-bit", (13 + 3 * new_res)); return SUCCESS; } } /******************************************************************************* * @brief - Set the device operation mode * (Continuous conversion, One-shot, SPS, Shutdown). * - Consult datasheet for more information. * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t set_op_mode() { printf(" Available operation modes:" EOL); printf(" 1- Continuous conversion mode (default)" EOL); printf(" 2- One-shot mode" EOL); printf(" 3- 1 SPS mode" EOL); printf(" 4- Shutdown" EOL); printf(" Select a mode: "); int new_mode, invalid_check = 0; invalid_check = scanf("%d", &new_mode); if (input_check(new_mode, 1, 4, invalid_check) == FAILURE) { return FAILURE; } else { printf("%d" EOL, new_mode); switch (new_mode) { case 1: adt7420_set_operation_mode(device, ADT7420_OP_MODE_CONT_CONV); break; case 2: /*When One shot mode is set completes one conversion and immediately goes to shutdown mode*/ adt7420_set_operation_mode(device, ADT7420_OP_MODE_ONE_SHOT); printf( EOL" One Shot mode enabled, device will enter shutdown mode once a conversion is complete." EOL); printf(" See page 10 in datasheet for details." EOL); break; case 3: adt7420_set_operation_mode(device, ADT7420_OP_MODE_1_SPS); break; case 4: adt7420_set_operation_mode(device, ADT7420_OP_MODE_SHUTDOWN); break; default: printf("Invalid option" EOL); break; } return SUCCESS; } } /******************************************************************************* * @brief - Prints poll of temperature based on the frequency of readings and * number of samples. * * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t bunch_of_temps() { printf(" Enter number of desired samples: "); int num_samples, invalid_check = 1; invalid_check = scanf("%d", &num_samples); if (input_check(num_samples, 1, 2000000, invalid_check) == FAILURE) { return FAILURE; } printf("%d" EOL, num_samples); printf(" Enter a desired frequency in samples/sec (max 10): "); int sample_freq = 1; invalid_check = scanf("%d", &sample_freq); if (input_check(sample_freq, 1, 10, invalid_check) == FAILURE) { return FAILURE; } sample_freq = constrain(sample_freq, 1, 10); printf("%d", sample_freq); uint32_t delay_sec = 1000000 / sample_freq; printf(" Gathering %d seconds of samples" EOL, num_samples/sample_freq); printf("Press enter to continue and then press again to quit" EOL); getchar(); for (int i = 0; i < num_samples; i++) { if(getchar_noblock()) { return SUCCESS; } else { printf(" Sample:%d: Temperature:", i + 1); float temp = adt7420_get_temperature(device); printf("%.4f" EOL, temp); udelay(delay_sec); } } return SUCCESS; } /******************************************************************************* * @brief - Reads back data store in device registers * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t readback_reg() { printf(" Available registers:" EOL); printf(" 1- Status" EOL); printf(" 2- Configuration" EOL); printf(" 3- Temperature" EOL); printf(" 4- ID" EOL); printf(" 5- Critical Temperature setpoint" EOL); printf(" 6- Hysteresis Temperature setpoint" EOL); printf(" 7- Temperature high setpoint" EOL); printf(" 8- Temperature low setpoint" EOL); printf(" Select a mode: "); uint16_t read_value = 0; int new_mode, invalid_check = 0; invalid_check = scanf("%d", &new_mode); if (input_check(new_mode, 1, 8, invalid_check) == FAILURE) { return FAILURE; } printf("%d" EOL, new_mode); switch (new_mode) { case 1: read_value = adt7420_get_register_address_and_value(device, REG_STATUS); break; case 2: read_value = adt7420_get_register_address_and_value(device, REG_CONFIG); break; case 3: read_value = adt7420_get_register_address_and_value(device, REG_TEMP); break; case 4: read_value = adt7420_get_register_address_and_value(device, REG_ID); break; case 5: read_value = adt7420_get_register_address_and_value(device, REG_T_CRIT); break; case 6: read_value = adt7420_get_register_address_and_value(device, REG_HIST); break; case 7: read_value = adt7420_get_register_address_and_value(device, REG_T_HIGH); break; case 8: read_value = adt7420_get_register_address_and_value(device, REG_T_LOW); break; default: break; } printf("Read value: 0x%x" EOL, read_value); return SUCCESS; } /******************************************************************************* * @brief - Resets device interface (SPI/I2C) (power-on reset) * * @param None * * @return - Return SUCCESS flag - currently unused. *******************************************************************************/ static uint8_t reset_interface() { printf(" Resetting interface..." EOL); adt7420_reset(device); udelay(RESET_DELAY); return SUCCESS; } /******************************************************************************* * @brief - Write to setpoint registers THIGH, TLOW, TCRIT and THYST. - Values entered in Celsius and rounded to a near integer value. * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t write_to_setpoint_reg() { printf(" Available registers:" EOL); printf(" 1- Critical setpoint" EOL); printf(" 2- Hystersis setpoint" EOL); printf(" 3- Temperature high setpoint" EOL); printf(" 4- Temperature low setpoint" EOL); printf(" Select a mode: "); int new_mode, invalid_check = 0; invalid_check = scanf("%d", &new_mode); if (input_check(new_mode, 1, 4, invalid_check) == FAILURE) { return FAILURE; } printf("%d" EOL, new_mode); float temp_c; if(new_mode == 2) { printf("Enter value to write (0 to 15) Celsius:"); invalid_check = scanf("%f", &temp_c); if(input_check(temp_c, MIN_HYST_TEMP, MAX_HYST_TEMP, invalid_check) == FAILURE) { return FAILURE; } } else { printf("Enter value to write (in Celsius):"); invalid_check = scanf("%f", &temp_c); if(input_check(temp_c, TEMP_MIN, TEMP_MAX, invalid_check) == FAILURE) { return FAILURE; } } printf(" %.2f", temp_c); int16_t write_value; if(new_mode == 2) write_value = round(temp_c); else write_value = round(128 * temp_c); switch (new_mode) { case 1: if (adt7420_wr_setpoint_reg(device, REG_T_CRIT, write_value) == SUCCESS) printf(EOL "0x%x successfuly written" EOL, write_value); else printf(EOL "0x%x NOT successfuly written" EOL, write_value); break; case 2: if (adt7420_wr_setpoint_reg(device, REG_HIST, write_value) == SUCCESS) printf(EOL "0x%x successfuly written (bits 7:4 are fixed at 0)" EOL, write_value); else printf(EOL "0x%x NOT successfuly written" EOL, write_value); break; case 3: if (adt7420_wr_setpoint_reg(device, REG_T_HIGH, write_value) == SUCCESS) printf(EOL "0x%x successfuly written" EOL, write_value); else printf(EOL "0x%x NOT successfuly written" EOL, write_value); break; case 4: if (adt7420_wr_setpoint_reg(device, REG_T_LOW, write_value) == SUCCESS) printf(EOL "0x%x successfuly written" EOL, write_value); else printf(EOL "0x%x NOT successfuly written" EOL, write_value); break; default: printf("Invalid selection - try again." EOL); mdelay(2000); break; } return SUCCESS; } /******************************************************************************* * @brief - Set the number of undertemperature/overtemperature faults * that can occur before setting the INT and CT output pins * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t set_fault_queue() { printf(" Available fault queue options:" EOL); printf(" 1- 1 fault (default) " EOL); printf(" 2- 2 faults" EOL); printf(" 3- 3 faults" EOL); printf(" 4- 4 faults" EOL); printf(" Select a mode: "); int new_fault, invalid_check = 0; invalid_check = scanf("%d", &new_fault); if (input_check(new_fault, 1, 4, invalid_check) == FAILURE) { return FAILURE; } else { printf("%d" EOL, new_fault); switch (new_fault) { case 1: adt7420_set_fault_queue(device, ADT7420_FAULT_QUEUE_1_FAULT); break; case 2: adt7420_set_fault_queue(device, ADT7420_FAULT_QUEUE_2_FAULTS); break; case 3: adt7420_set_fault_queue(device, ADT7420_FAULT_QUEUE_3_FAULTS); break; case 4: adt7420_set_fault_queue(device, ADT7420_FAULT_QUEUE_4_FAULTS); break; default: printf("Invalid option" EOL); break; } return SUCCESS; } } /******************************************************************************* * @brief - Set INT/CT Outputs pins to Comparator or Interrupt mode * * @param None * * @return - Return SUCCESS/FAILURE flags *******************************************************************************/ static uint8_t set_ct_int_config() { int new_polarity = 0; int new_mode, invalid_check = 0; printf(" Choose INT/CT mode:" EOL); printf(" 1- Interrupt (default) " EOL); printf(" 2- Comparator " EOL); printf(" Select a mode: "); invalid_check = scanf("%d", &new_mode); if (input_check(new_mode, 1, 2, invalid_check) == FAILURE) { return FAILURE; } else { printf("%d" EOL, new_mode); new_mode = (new_mode == 1) ? 0 : 1; adt7420_set_ct_int_mode(device, new_mode); } printf(EOL " Set output polarity for Critical and Over/Under Temperature pin:" EOL); printf(" (Feature available only for internal sensors)." EOL); if(init_params.interface_init.i2c_init.slave_address == INT_I2C_ADDRESS || init_params.interface_init.spi_init.chip_select == SPI_CS) { printf(" 1- Active Low (default) " EOL); printf(" 2- Active High" EOL); printf(" Select a mode: "); invalid_check = scanf("%d", &new_polarity); if (input_check(new_polarity, 1, 2, invalid_check) == FAILURE) { return FAILURE; } else { printf("%d" EOL, new_polarity); new_polarity = (new_polarity == 1) ? 0 : 1; adt7420_set_ct_int_polarity(device, new_polarity); } } return SUCCESS; } /******************************************************************************* * @brief Reset microcontroller * * @param None * * @return None. *******************************************************************************/ static void microcontroller_reset() { NVIC_SystemReset(); } /******************************************************************************* * @brief Prints the active device every time the main menu is redrawn * * @param external_internal_selection - External or Internal Chip Selected * * @return None. *******************************************************************************/ static void print_active_device(int external_internal_selection) { const char* devices[7] = {EOL EOL " Active Device: ADT7410 I2C", EOL EOL " Active Device: ADT7420 I2C", EOL EOL " Active Device: ADT7422 I2C", EOL EOL " Active Device: ADT7310 SPI", EOL EOL " Active Device: ADT7311 SPI", EOL EOL " Active Device: ADT7312 SPI", EOL EOL " Active Device: ADT7320 SPI" }; const char* external_internal_print[] = {" - Internal Chip " EOL, " - External Chip " EOL }; printf("%s %s", devices[init_params.active_device], external_internal_print[external_internal_selection - 1]); } /******************************************************************************* * @brief Checks is an input is a digit and within valid range * * @param input_val - Value inputed by user * @param lowest_accepted_val - Lowest acceptable value * @param highest_accepted_val - Highest acceptable value * @param invalid_check - Checks if unexpected type of data was entered in scanf * * @return SUCCESS/FAILURE Flags. *******************************************************************************/ static int input_check(int input_val, int lowest_accepted_val, int highest_accepted_val, int invalid_check) { if(invalid_check == 0 || input_val < lowest_accepted_val || input_val > highest_accepted_val) { printf(EOL EOL "***** Invalid entry: No changes made *****" EOL ); mdelay(WAIT_MENU_TIME); return FAILURE; } return SUCCESS; }