67 views
in System Integration by

Hello,

I would like to develop an I/O monitor page of a device to display the status of digital inputs and control the outputs.

Something like:

In the device, the acquisition of the inputs is done by thread as in the DeviceIntegration example.

The status of each input is defined in C as a bool variable.

In Embedded Wizard the status of the inputs is defined as a bool property in the Device class.

Currently, to pass 2 inputs I am using the following code in device integration:

static void InputStartThread( const void* arg )
{
	while ( Machine_Initialized )
	{
	    bool InputStartP1_State = !HAL_GPIO_ReadPin(START_PEDALE_1_GPIO_Port, START_PEDALE_1_Pin);
	    bool InputStartP2_State = !HAL_GPIO_ReadPin(START_PEDALE_2_GPIO_Port, START_PEDALE_2_Pin);
			    		    
	    EwInvokeCopy( GUI_UpdateInputStartP1StateProc, &InputStartP1_State, sizeof( bool));
	    EwInvokeCopy( GUI_UpdateInputStartP2StateProc, &InputStartP2_State, sizeof( bool));

	    /* sleep for a certain period... */
	    EwBspOsDelay( 100 );
	}
  /* terminate the thread */
  InputStart_Check_Thread = 0;
  EwBspOsThreadDestroy( EwBspOsThreadGetHandle());
}

/* Update the GUI value of InputStartP1*/
static void GUI_UpdateInputStartP1StateProc( const void* aData )
{
  bool state = *((bool*)aData);
  ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
  ApplicationDeviceClass__UpdateStartP1( device,  state );
}

/* Update the GUI value of InputStartP2*/
static void GUI_UpdateInputStartP2StateProc( const void* aData )
{
  bool state = *((bool*)aData);
  ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
  ApplicationDeviceClass__UpdateStartP2( device,  state );
}

I would like to know if for each input it is necessary to create a GUI_Updatexxx function to pass as an argument to the EwInvokeCopy command (so for 20 inputs, write 20 functions and que 20 invocations via the EwInvokeCopy command) or if there is a more "efficient" method to synchronize the state of 20 bool variables between native code and GUI.

1 Answer

0 votes
by

Hello Nicola,

in fact, you can implement a single Update() method with 20 parameters and provide all values at once. It is a design detail. You can also pass all values in a single EwInvokeCopy() invocation.

This approach is convenient, when all values change at the same time. The approach with individual Update methods is more useful when the values change independently. See also Update multiple Properties using a common UpdateProperty() method.

I hope it helps you further.

Best regards

Paul Banach

by

Hello Paul,

so you mean I can create in EW a single UpdateAllInput() method and pass 20 parameters, like:

static void InputStartThread( const void* arg )
{
	while ( Machine_Initialized )
	{
	    bool Input1_State = !HAL_GPIO_ReadPin(INPUT_1_GPIO_Port, INPUT_1_Pin);
	    bool Input2_State = !HAL_GPIO_ReadPin(INPUT_2_GPIO_Port, INPUT_2_Pin);
        ....
	    bool Input20_State = !HAL_GPIO_ReadPin(INPUT_20_GPIO_Port, INPUT_20_Pin);
			    		    
	    ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
        ApplicationDeviceClass__UpdateAllInput( device,  Input1_State, Input2_State, ..., Input20_State );

	    /* sleep for a certain period... */
	    EwBspOsDelay( 100 );
	}
  /* terminate the thread */
  InputStart_Check_Thread = 0;
  EwBspOsThreadDestroy( EwBspOsThreadGetHandle());
}

Or do I need to use the command EwInvokeCopy to que te Update procedure?

If so, how can I pass to this function 20 values?

I mean this code (I added ??? where I don't know what to write):

static void InputStartThread( const void* arg )
{
	while ( Machine_Initialized )
	{
	    bool Input1_State = !HAL_GPIO_ReadPin(INPUT_1_GPIO_Port, INPUT_1_Pin);
	    bool Input2_State = !HAL_GPIO_ReadPin(INPUT_2_GPIO_Port, INPUT_2_Pin);
        ....
	    bool Input20_State = !HAL_GPIO_ReadPin(INPUT_20_GPIO_Port, INPUT_20_Pin);

        EwInvokeCopy( GUI_UpdateAllInputStateProc, ???, sizeof( ???)); 

	    /* sleep for a certain period... */
	    EwBspOsDelay( 100 );
	}
  /* terminate the thread */
  InputStart_Check_Thread = 0;
  EwBspOsThreadDestroy( EwBspOsThreadGetHandle());
}

/* Update the GUI value of AllInputs*/
static void GUI_UpdateAllInputStateProc( const void* aData )
{
  bool state1 = ???
  bool state2 = ???
  ...
  bool stare 20 = ???

  ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
  ApplicationDeviceClass__UpdateAllInput( device,  state1, state2, ...., state20 );
}

Another question:

I'm thinking about using a struct in C code for all inputs, something like:

typedef struct _Input
{
	bool Input1;
    bool Input2;
    ...
    bool Input20;
} Input;

In this case, how can I pass the whole structure to EW? Is it advisable to do something like this?

 

Best regards.

Nicola

by

Hello Nicola,

the approach with C struct is the right one. Instead of using local variables Input1_State, Input2_State, ... define a struct with similar members. At runtime inside the thread perform something similar to:

InputStruct data;

data.Input1  = !HAL_GPIO_ReadPin(INPUT_1_GPIO_Port, INPUT_1_Pin);
data.Input2  = !HAL_GPIO_ReadPin(INPUT_1_GPIO_Port, INPUT_2_Pin);
...
data.Input20 = !HAL_GPIO_ReadPin(INPUT_1_GPIO_Port, INPUT_20_Pin);

EwInvokeCopy( GUI_UpdateInputStateProc, &data, sizeof( data ));

In the function GUI_UpdateInputStateProc you access the values as shown below:

InputStruct* data (InputStruct*)aData;

ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
ApplicationDeviceClass__UpdateAllInput( device,  data->Input1, data->Input2, ..., data->Input20 );

I hope it helps you further.

Best regards

Paul Banach

ago by

Hello Paul,

thank you for the reply.

I tried and it works!

The only downside is that I have to pass a variable for each input. Since I have a struct like this in my C code,

typedef struct _input{
	//Ingressi  sulla Lizard
	bool start1_sw;
	bool start2_sw;
	bool ih_tuning_fault;
	bool ih_overcurrent_fault;
	bool ih_check_control;
	bool aux_voltage;
	bool df_encoder1;
	bool df_encoder2;
	//Ingressi sull'IOExpander
	bool start1_ext;
	bool start2_ext;
	bool pwr_bit0_ext;
	bool pwr_bit1_ext;
	bool pwr_bit2_ext;
	bool pwr_bit3_ext;
	bool pwr_bit4_ext;
	bool pwr_bit5_ext;
	bool pwr_bit6_ext;
	bool presssure_sw;
	bool temperature_sw;
	bool slide1_in;
	bool slide1_out;
	bool slide2_in;
	bool slide2_out;
	bool driver1_fault;
	bool driver2_fault;
} input_t;

The function in C to pass all input is:

static void GUI_UpdateInputState( const void* aData )
{
  
  input_t Input = *((input_t*)aData);

  /* only in case that the device driver is still initialized and the worker
     thread is still running, the data should be provided to the device class
     - otherwise, a new autoobject will be created and a new worker thread
     started... */
    ApplicationDeviceClass device = EwGetAutoObject( &ApplicationDevice, ApplicationDeviceClass );
    ApplicationDeviceClass__UpdateInput( device,
      Input.start1_sw,
      Input.start2_sw,
      Input.ih_tuning_fault, 
      Input.ih_overcurrent_fault,
      Input.ih_check_control,
      Input.aux_voltage,
      Input.df_encoder1,
      Input.df_encoder2,
      Input.start1_ext,
      Input.start2_ext,
      Input.pwr_bit0_ext,
      Input.pwr_bit1_ext,
      Input.pwr_bit2_ext,
      Input.pwr_bit3_ext,
      Input.pwr_bit4_ext,
      Input.pwr_bit5_ext,
      Input.pwr_bit6_ext,
      Input.presssure_sw,
      Input.temperature_sw,
      Input.slide1_in,
      Input.slide1_out,
      Input.slide2_in,
      Input.slide2_out,
      Input.driver1_fault,
      Input.driver2_fault);
}

And the corresponding in Embedded Wizard has lot of arguments:

I wondered if it would be possible to replicate the struct in Embedded Wizard, to make passing variables easier and clearer. I currently have a property of type bool for each input.

ago by
Hello Nicola,

such approach is possible but it is not simpler. As first step you would define a new class in Embedded Wizard containing variables for all the values. This class would correspond to the structure in C. Then at the runtime in C code you instantiate an object of the class. Assign all the values to the variables in the object and finally pass the object in the invocation of the Update() method. Inside the Update method you query the values from the object and update the properties.

The code is much more complex and due to the complexity officially not documented. If you are interested in such approach I would recommend to implement the code first in Chora and then analyze/copy the resulting C code.

I hope it helps you further.

Best regards

Paul Banach

Embedded Wizard Website | Privacy Policy | Imprint

...