I can't get 2 click boards to operate at the same time

Fully featured PIC compilers available on Windows, Linux, and macOS.
Post Reply
Author
Message
nate@allstrap.com
Posts: 3
Joined: 20 Nov 2023 14:05

I can't get 2 click boards to operate at the same time

#1 Post by nate@allstrap.com » 30 Jan 2024 17:59

I'm running a PIC18F57K42 on the UNI-DS V8 in NECTO using PIC C AI compiler, and I have been unable to get 2 click boards to run at the same time. I casn get the LDC board to operate OR a SoliSwitch, but never both at the same time. I assumed this was an I2C issues, so I specified :

i2c_master_set_slave_address( &ldc.i2c, ldc.slave_address ); //before tried to get LDC data
i2c_master_set_slave_address( &solidswitch.i2c, solidswitch.slave_address );//before I sent SolidSwitch commands

still only one works. I am using the example code as a starting point, and running a simple digital input for each function. Code is below....

#include "board.h"
#include "log.h"
#include "ldc.h"
#include "math.h"
#include "drv_digital_in.h"
#include "drv_digital_out.h"
#include "solidswitch.h"
#include "MikroSDK.Driver.I2C.Master"
static solidswitch_t solidswitch;
static log_t logger;
#include "MikroSDK.mikroSDKVersion"


/**

* @brief Displays all enabled channels on USB UART.
* @details This function reads logic state of outputs and
* displays all enabled channels on USB UART.
*
* @return None.
* @note None.
*/
//static void solidswitch_display_enabled_channels ( void );

static ldc_t ldc;

static digital_in_t input_pin;
static digital_in_t input_pin2;
static digital_out_t output_pin;
//static log_t logger;

uint16_t divider;
uint8_t button;
uint8_t button2;
uint8_t hold;
int Run=0;
int Stop=1;
int finish=1;
int i=0;
int CycleComplete=0;
int ButtonHeld;
const int delay=50;
uint8_t high=1;
uint8_t low=0;
int FirstRun=1;


void application_init ( void )
{
log_cfg_t log_cfg; /**< Logger config object. */
ldc_cfg_t ldc_cfg; /**< Click config object. */
solidswitch_cfg_t solidswitch_cfg; /**< Click config object. */
/**
* Logger initialization.
* Default baud rate: 115200
* Default log level: LOG_LEVEL_DEBUG
* @note If USB_UART_RX and USB_UART_TX
* are defined as HAL_PIN_NC, you will
* need to define them manually for log to work.
* See @b LOG_MAP_USB_UART macro definition for detailed explanation.
*/
LOG_MAP_USB_UART( log_cfg );
log_init( &logger, &log_cfg );
log_info( &logger, " SolidSwitch");
log_info( &logger, " Application Init " );


// LDC Click initialization.
ldc_cfg_setup( &ldc_cfg );
LDC_MAP_MIKROBUS( ldc_cfg, MIKROBUS_1 );
err_t init_flag = ldc_init( &ldc, &ldc_cfg );
if ( I2C_MASTER_ERROR == init_flag )
{
log_error( &logger, " Application Init Error. " );
log_info( &logger, " Please, run program again... " );
for ( ; ; );
}

if ( ldc_default_cfg ( &ldc ) < 0 )
{
log_error( &logger, " Default configuration. " );
for ( ; ; );
}

uint16_t temp_data = 0;
ldc_generic_read( &ldc, LDC_REG_MANUFACTURER_ID, &temp_data );
log_printf( &logger, "> Manufacturer ID: 0x%.4X\r\n", temp_data );
if ( LDC_MANUFACTURER_ID != temp_data )
{
log_error( &logger, " Manufacturer ID. " );
for ( ; ; );
}

ldc_generic_read( &ldc, LDC_REG_DEVICE_ID, &temp_data );
log_printf( &logger, "> Device ID 0x%.4X\r\n", temp_data );
if ( LDC_DEVICE_ID != temp_data )
{
log_error( &logger, " Device ID. " );
for ( ; ; );
}

ldc_generic_read( &ldc, LDC_REG_CLOCK_DIVIDERS_CH0, &temp_data );
divider = temp_data & 0x3FF;

log_info( &logger, " Application Task " );
log_info( &logger, " LDC Ready " );



//SOLIDSWITCH Click initialization.

solidswitch_cfg_setup( &solidswitch_cfg );
SOLIDSWITCH_MAP_MIKROBUS( solidswitch_cfg, MIKROBUS_5 );
err_t init_flag2 = solidswitch_init( &solidswitch, &solidswitch_cfg );
if (init_flag2 == I2C_MASTER_ERROR)
{
log_error(&logger,"Application Init Error.");
log_info(&logger,"Please, run program again...");

//for ( ; ; );
}

solidswitch_default_cfg ( &solidswitch );
log_info( &logger, " Solid Switch Ready " );

//Setup input pins
digital_in_init( &input_pin, PD0 ); //Initialize digital input driver context structure and individual GPIO pin as digital input.
digital_in_init( &input_pin2, PD1 ); //Initialize digital input driver context structure and individual GPIO pin as digital input.
digital_out_init( &output_pin, PD5 ); // Initialize digital output driver context structure and individual GPIO pin as digital output.
solidswitch_write_single ( &solidswitch, SOLIDSWITCH_DISABLE_ALL_OUTPUTS );

}
void application_task ( void )
{
if ( !ldc_get_interrupt( &ldc )&& button2 )
// if ( !ldc_get_interrupt( &ldc ) )
{
if(FirstRun)
{
log_debug( &logger, " LDC READ " );
FirstRun=0;
}
i2c_master_set_slave_address( &ldc.i2c, ldc.slave_address );
float frequency = 0.0;
float inductance = 0.0;
uint16_t status = 0;
ldc_generic_read( &ldc, LDC_REG_STATUS, &status );
if ( status & LDC_STATUS_DRDY )
{
err_t ret_val = ldc_get_frequency( &ldc, LDC_REG_DATA_CH0, divider, &frequency );
if ( !ret_val )
{
log_printf( &logger, "> Freq[MHz]: %.3f\r\n", frequency );
if ( frequency > 0 )
{
inductance = ldc_calculate_inductance( frequency );
}
log_printf( &logger, "> L[uH]: %.3f\r\n", inductance );
log_printf( &logger, "> ************************\r\n" );

Delay_ms( 500 );
}
else
{
log_error( &logger, " Reading data: %ld", ret_val );
}
}
else log_debug( &logger, " Not Status and LDC_STATUS " );

}
i2c_master_set_slave_address( &solidswitch.i2c, solidswitch.slave_address );
button = digital_in_read( &input_pin ); // Read digital input value.
button2 = digital_in_read( &input_pin2 ); // Read digital input value.
hold = Run = button; //

while(hold)
{
Delay_ms(10);
hold = digital_in_read( &input_pin ); // Read digital input value.

ButtonHeld ++;
if(ButtonHeld >= 100)
{
log_printf( &logger, "Button hold fault");
button=0;
Stop=1;
}
}
ButtonHeld=0;


if(Stop)
{
log_printf( &logger, "Armed\r");
Stop=0;
}

if(button)
{
log_printf( &logger, "Auto Running\r");
solidswitch_write_single ( &solidswitch, SOLIDSWITCH_ENABLE_OUT0 | SOLIDSWITCH_ENABLE_OUT1 );
for(i=0;i<50;i++)
{
digital_out_toggle(&output_pin);
Delay_ms(delay);
Stop = digital_in_read( &input_pin ); // Read digital input value.

if(Stop)
{
solidswitch_write_single ( &solidswitch, SOLIDSWITCH_DISABLE_ALL_OUTPUTS );
digital_out_write( &output_pin, 0); /// Write read value to the output pin
button=Run=0;
log_printf( &logger, "Cycle Interrupted\r");

while(Stop) //in case of cycle cancel hold here until button is released
{
Delay_ms(50);
Stop = digital_in_read( &input_pin ); // Read digital input value.
}
break;

}
}
if(Run) log_printf( &logger, "Cycle Complete\r");
Run=0;
solidswitch_write_single ( &solidswitch, SOLIDSWITCH_DISABLE_ALL_OUTPUTS );
Stop=1;
digital_out_write( &output_pin, 0); /// Write read value to the output pin
}
}





int main ( void )
{
application_init( );
for ( ; ; )
{
application_task();
}
}
// ------------------------------------------------------------------------ END
Last edited by nate@allstrap.com on 31 Jan 2024 14:42, edited 1 time in total.

User avatar
IvanJeremic
mikroElektronika team
Posts: 316
Joined: 05 Sep 2022 14:32

Re: I can't get 2 click boards to operate at the same time

#2 Post by IvanJeremic » 31 Jan 2024 13:27

Hi,

You can see how I did it in the code example below where I used 5 click boards (a lot of them used I2C):

Code: Select all

/**
 * @file main.c
 * @brief Main function for Sensor_5 TFT Designer Application.
 */

#include "vtft.h"
#include "gl.h"
#include "main_screen.h"
#include "scr_main_screen.h"
#include "touch_controller.h"
#include "conversions.h"
#include "ndirco2.h"
#include "thermo4.h"
#include "altitude3.h"
#include "temphum6.h"
#include "airquality9.h"
void formatFloatStr( char *s )
{
   uint8_t i;
   uint8_t point;
   uint8_t degree = 0;
   for( i = 0, point = 0; s[i] != '\0'; i++ )
   {
      if( s[i] == '.' ) {
          point = i;
          break;
      }
   }
   for( i = point + 1; s[i] != '\0'; i++ ) {
      if( s[i] == '-' ) {
          i++;
          while( s[i] == '0' ) {
             i++;
          }
          degree = s[i] - '0';
          break;
      }
   }
   if( degree > 4 ) {
      s[point - 1] = '0';
      s[point + 1] = '0';
      s[point + 2] = '0';
      s[point + 3] = '0';
      s[point + 4] = '\0';
   }
   else if( degree == 4 ) {
           if( s[point - 1] >= '5' ) {
              s[point - 1] = '0';
              s[point + 1] = '0';
              s[point + 2] = '0';
              s[point + 3] = '1';
              s[point + 4] = '\0';
           }
           else {
              s[point - 1] = '0';
              s[point + 1] = '0';
              s[point + 2] = '0';
              s[point + 3] = '0';
              s[point + 4] = '\0';
           }
   }
   else {
      switch(degree) {
         case 0: s[point + 4] = '\0';
                 break;
         case 1: s[point + 3] = s[point + 2];
                 s[point + 2] = s[point + 1];
                 s[point + 1] = s[point - 1];
                 s[point - 1] = '0';
                 s[point + 4] = '\0';
                 break;
         case 2: s[point + 3] = s[point + 1];
                 s[point + 2] = s[point - 1];
                 s[point + 1] = '0';
                 s[point - 1] = '0';
                 s[point + 4] = '\0';
                 break;
         case 3: s[point + 3] = s[point - 1];
                 s[point + 2] = '0';
                 s[point + 1] = '0';
                 s[point - 1] = '0';
                 s[point + 4] = '\0';
                 break;
         default: s[point + 4] = '\0';
                  break;
      }

   }
}


static gl_driver_t display_driver;
static tp_t tp;
static vtft_t vtft;
static tp_drv_t tp_interface;
static ndirco2_t ndirco2;
static thermo4_t thermo4;
static float temp_in_faren;
static altitude3_t altitude3;
static temphum6_t temphum6;
static airquality9_t airquality9;



void board_init()
{
    touch_controller_init(&display_driver, TFT8_MAX_BACKLIGHT);
    // Initialize Graphic library.
    gl_set_driver(&display_driver);

    touch_controller_tp_init(&tp, &tp_interface);
}

/**
 * @brief Application initialization function.
 */
void application_init()
{
    board_init();
    uint16_t part_id;

    // Initialize VTFT library.
    vtft_init(&vtft, &tp);
    main_screen_show(&vtft);
    
    ndirco2_cfg_t ndirco2_cfg;
    ndirco2_cfg_setup( &ndirco2_cfg );
    NDIRCO2_MAP_MIKROBUS( ndirco2_cfg, MIKROBUS_2 );
    ndirco2_init( &ndirco2, &ndirco2_cfg );
    Delay_ms( 300 );
    ndirco2_reset( &ndirco2 );
    ndirco2_write_register( &ndirco2, NDIRCO2_AVERAGING_COUNT_REG, 0x03 );
    ndirco2_set_mode( &ndirco2, NDIRCO2_CONTINUOUS_OP_MODE );
    Delay_ms( 200 );
    
    
    thermo4_cfg_t thermo4_cfg;
    thermo4_cfg_setup( &thermo4_cfg );
    THERMO4_MAP_MIKROBUS( thermo4_cfg, MIKROBUS_1 );
    thermo4_init( &thermo4, &thermo4_cfg );
    
    
    altitude3_cfg_t altitude3_cfg;
    altitude3_cfg_setup( &altitude3_cfg );
    ALTITUDE3_MAP_MIKROBUS( altitude3_cfg, MIKROBUS_3 );
    altitude3_init( &altitude3, &altitude3_cfg );
    altitude3_default_cfg ( &altitude3 );
    
    temphum6_cfg_t temphum6_cfg;
    temphum6_cfg_setup( &temphum6_cfg );
    TEMPHUM6_MAP_MIKROBUS( temphum6_cfg, MIKROBUS_4 );
    temphum6_init( &temphum6, &temphum6_cfg );
    temphum6_reset( &temphum6 );
    part_id = temphum6_get_part_id( &temphum6 );
    if ( part_id != TEMPHUM6_PART_ID )
    {
        for ( ; ; );
    }
    
    airquality9_cfg_t airquality9_cfg;
    airquality9_cfg_setup( &airquality9_cfg );
    AIRQUALITY9_MAP_MIKROBUS( airquality9_cfg, MIKROBUS_5 );
    err_t init_flag  = airquality9_init( &airquality9, &airquality9_cfg );
    if ( ( I2C_MASTER_ERROR == init_flag ) || ( SPI_MASTER_ERROR == init_flag ) )
    {
        for ( ; ; );
    }
    
    if ( AIRQUALITY9_ERROR == airquality9_default_cfg ( &airquality9 ) )
    {
        for ( ; ; );
    }
    
}

/**
 * @brief Application task function.
 */
void application_task()
{

        i2c_master_set_slave_address( &ndirco2.i2c, ndirco2.slave_address );
         uint16_t co2_data;
         ndirco2_read_co2( &ndirco2, NDIRCO2_CHECK_EACH_MEASURE, &co2_data );
       
        
            uint8_t temp_str[ 36 ] = { 0 };
            
            uint16_to_str ( co2_data, temp_str );
            
            main_screen.Label_4->text.font.color = 0xfe40;
            vtft_draw_component(&vtft, main_screen.Label_4);
            
            strcpy ( main_screen.Label_4->text.caption, temp_str );
            main_screen.Label_4->text.font.color = 0x0000;
            vtft_draw_component(&vtft, main_screen.Label_4);
           
            Delay_ms(500);
    
       
    
    i2c_master_set_slave_address( &thermo4.i2c, thermo4.slave_address );
    temp_in_faren = thermo4_read_temperature_f( &thermo4 );
    
       
        float_to_str ( temp_in_faren, temp_str );
        formatFloatStr(temp_str);
        temp_str[4] = 0;
        
        main_screen.Label_2->text.font.color = 0xfe40;
        vtft_draw_component(&vtft, main_screen.Label_2);
        
        strcpy ( main_screen.Label_2->text.caption, temp_str );
        main_screen.Label_2->text.font.color = 0x0000;
        vtft_draw_component(&vtft, main_screen.Label_2);
       
        Delay_ms(500);
    
    i2c_master_set_slave_address( &altitude3.i2c, altitude3.slave_address );
    uint8_t response;
    response = altitude3_measurement_mode( &altitude3, ALTITUDE3_NORMAL_T_FIRST );
    Delay_ms( 100 );
    response = altitude3_get_data( &altitude3, response );
       
        uint16_to_str (( uint16_t ) altitude3.sens_data.pressure, temp_str );
       
        main_screen.Label_6->text.font.color = 0xfe40;
        vtft_draw_component(&vtft, main_screen.Label_6);
        
        strcpy ( main_screen.Label_6->text.caption, temp_str );
        main_screen.Label_6->text.font.color = 0x0000;
        vtft_draw_component(&vtft, main_screen.Label_6);
        
        Delay_ms(500);
        
        i2c_master_set_slave_address( &temphum6.i2c, temphum6.slave_address );
        float hum;
        hum = temphum6_read_relative_huminidy( &temphum6 );
    
       
        float_to_str ( hum, temp_str );
        formatFloatStr(temp_str);
        temp_str[4] = 0;
       
        main_screen.Label_8->text.font.color = 0xfe40;
        vtft_draw_component(&vtft, main_screen.Label_8);
        
        strcpy ( main_screen.Label_8->text.caption, temp_str );
        main_screen.Label_8->text.font.color = 0x0000;
        vtft_draw_component(&vtft, main_screen.Label_8);
       
        Delay_ms(500);
        
        i2c_master_set_slave_address( &airquality9.i2c, airquality9.slave_address );
        uint16_t tvoc;
    
         if ( AIRQUALITY9_OK == airquality9_read_tvoc ( &airquality9, &tvoc ) )
        {
        uint16_to_str ( tvoc, temp_str );
       
        main_screen.Label_10->text.font.color = 0xfe40;
        vtft_draw_component(&vtft, main_screen.Label_10);
        
        strcpy ( main_screen.Label_10->text.caption, temp_str );
        main_screen.Label_10->text.font.color = 0x0000;
        vtft_draw_component(&vtft, main_screen.Label_10);
       
        Delay_ms(500);
        }
    
}

/**
  @brief Application main function.
 */
void main()
{
    application_init();

    while (1)
    {
        application_task();
    }
}


Regards,

Ivan.

nate@allstrap.com
Posts: 3
Joined: 20 Nov 2023 14:05

Re: I can't get 2 click boards to operate at the same time

#3 Post by nate@allstrap.com » 31 Jan 2024 13:58

Ivan,
Thanks for your reply. I can't seem to find the difference. I am also using the "i2c_master_set_slave_addres" command, and it didn't fix my issue. it doesn't seem to matter what I do; the last click board declared in my "init" routine is the only one that will work from that point on. I can set up the LDC, read data just fine, then set up the SolidSwitch and never see data from it again whether I use the I2C set slave command or not. I can switch the order and it behaves in the opposite way. It has to be that I'm not getting the commands through to the first board, but I can't see why not..... am I using the I2C set slave incorrectly? any other ideas?

adamretrobow28@gmail.com
Posts: 1
Joined: 17 Apr 2024 11:20

Re: I can't get 2 click boards to operate at the same time

#4 Post by adamretrobow28@gmail.com » 17 Apr 2024 11:21

It seems like you're encountering persistent issues with your I2C communication setup, despite efforts to address them through commands like "i2c_master_set_slave_address." To troubleshoot effectively, ensure correct slave addresses, validate bus initialization, verify pull-up resistors, stabilize power supply, check timing parameters, employ debugging tools, review software implementation, and avoid address conflicts. By methodically addressing each potential issue, you can pinpoint and resolve the root cause of your I2C communication challenges.

nate@allstrap.com
Posts: 3
Joined: 20 Nov 2023 14:05

Re: I can't get 2 click boards to operate at the same time

#5 Post by nate@allstrap.com » 24 Apr 2024 15:57

I got this to work finally. it took quite a bit of investigation, and practice, but I did get 5 click boards working together with an 18F57K22, when I swap it over to other MCUs though, 2 of the boards stop working. I have tried so many things that I'm not sure which change worked, so I started by rebuilding the project. As far as I know all of the settings are the same but it still acts as if it can't talk to the two simplest click boards (Thumbwheel - OneWire, and SolidSwitch - I2C). I also ran the example code for each of these click boards with the new setups, and there was no difference (i.e. thy did not work at all). I'll get back to work on I2C comms and see if I can make the PIC18F97J94 or PIC18F86K22 work with them, but I'm not terribly hopeful at this point... it's not the end of the world, as i can use other devices, but being limited to SPI communications is a drag...

Post Reply

Return to “PIC AI compilers”